• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #38032

19 Mar 2025 06:21AM UTC coverage: 20.135% (-2.7%) from 22.851%
#38032

push

local

web-flow
Add a few "See also" entries to `typemax` and friends (#57759)

I would find it helpful to find the names of the related float max
functions from another's docstring.

I kept `maxintfloat` in the `floatmin` and `typemin` docstrings since
there is no `minintfloat` and I still think it would be helpful to have
it there. I also fixed and example in the `typemin` docstring to be
consistent with the `typemax` example.

9813 of 48736 relevant lines covered (20.14%)

119508.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

54.72
/base/array.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
## array.jl: Dense arrays
4

5
"""
6
    DimensionMismatch([msg])
7

8
The objects called do not have matching dimensionality. Optional argument `msg` is a
9
descriptive error string.
10
"""
11
struct DimensionMismatch <: Exception
12
    msg::AbstractString
×
13
end
14
DimensionMismatch() = DimensionMismatch("")
×
15

16
## Type aliases for convenience ##
17
"""
18
    AbstractVector{T}
19

20
Supertype for one-dimensional arrays (or array-like types) with
21
elements of type `T`. Alias for [`AbstractArray{T,1}`](@ref).
22
"""
23
const AbstractVector{T} = AbstractArray{T,1}
24

25
"""
26
    AbstractMatrix{T}
27

28
Supertype for two-dimensional arrays (or array-like types) with
29
elements of type `T`. Alias for [`AbstractArray{T,2}`](@ref).
30
"""
31
const AbstractMatrix{T} = AbstractArray{T,2}
32

33
"""
34
    AbstractVecOrMat{T}
35

36
Union type of [`AbstractVector{T}`](@ref) and [`AbstractMatrix{T}`](@ref).
37
"""
38
const AbstractVecOrMat{T} = Union{AbstractVector{T}, AbstractMatrix{T}}
39
const RangeIndex = Union{<:BitInteger, AbstractRange{<:BitInteger}}
40
const DimOrInd = Union{Integer, AbstractUnitRange}
41
const IntOrInd = Union{Int, AbstractUnitRange}
42
const DimsOrInds{N} = NTuple{N,DimOrInd}
43
const NeedsShaping = Union{Tuple{Integer,Vararg{Integer}}, Tuple{OneTo,Vararg{OneTo}}}
44

45
"""
46
    Array{T,N} <: AbstractArray{T,N}
47

48
`N`-dimensional dense array with elements of type `T`.
49
"""
50
Array
51

52
"""
53
    Vector{T} <: AbstractVector{T}
54

55
One-dimensional dense array with elements of type `T`, often used to represent
56
a mathematical vector. Alias for [`Array{T,1}`](@ref).
57

58
See also [`empty`](@ref), [`similar`](@ref) and [`zero`](@ref) for creating vectors.
59
"""
60
const Vector{T} = Array{T,1}
61

62
"""
63
    Matrix{T} <: AbstractMatrix{T}
64

65
Two-dimensional dense array with elements of type `T`, often used to represent
66
a mathematical matrix. Alias for [`Array{T,2}`](@ref).
67

68
See also [`fill`](@ref), [`zeros`](@ref), [`undef`](@ref) and [`similar`](@ref)
69
for creating matrices.
70
"""
71
const Matrix{T} = Array{T,2}
72

73
"""
74
    VecOrMat{T}
75

76
Union type of [`Vector{T}`](@ref) and [`Matrix{T}`](@ref) which allows functions to accept either a Matrix or a Vector.
77

78
# Examples
79
```jldoctest
80
julia> Vector{Float64} <: VecOrMat{Float64}
81
true
82

83
julia> Matrix{Float64} <: VecOrMat{Float64}
84
true
85

86
julia> Array{Float64, 3} <: VecOrMat{Float64}
87
false
88
```
89
"""
90
const VecOrMat{T} = Union{Vector{T}, Matrix{T}}
91

92
"""
93
    DenseArray{T, N} <: AbstractArray{T,N}
94

95
`N`-dimensional dense array with elements of type `T`.
96
The elements of a dense array are stored contiguously in memory.
97
"""
98
DenseArray
99

100
"""
101
    DenseVector{T}
102

103
One-dimensional [`DenseArray`](@ref) with elements of type `T`. Alias for `DenseArray{T,1}`.
104
"""
105
const DenseVector{T} = DenseArray{T,1}
106

107
"""
108
    DenseMatrix{T}
109

110
Two-dimensional [`DenseArray`](@ref) with elements of type `T`. Alias for `DenseArray{T,2}`.
111
"""
112
const DenseMatrix{T} = DenseArray{T,2}
113

114
"""
115
    DenseVecOrMat{T}
116

117
Union type of [`DenseVector{T}`](@ref) and [`DenseMatrix{T}`](@ref).
118
"""
119
const DenseVecOrMat{T} = Union{DenseVector{T}, DenseMatrix{T}}
120

121
## Basic functions ##
122

123
"""
124
    @_safeindex
125

126
This internal macro converts:
127
- `getindex(xs::Tuple, i::Int)` -> `__safe_getindex(xs, i)`
128
- `setindex!(xs::Vector{T}, x, i::Int)` -> `__safe_setindex!(xs, x, i)`
129
to tell the compiler that indexing operations within the applied expression are always
130
inbounds and do not need to taint `:consistent` and `:nothrow`.
131
"""
132
macro _safeindex(ex)
133
    return esc(_safeindex(ex))
134
end
135
function _safeindex(ex)
×
136
    isa(ex, Expr) || return ex
×
137
    if ex.head === :(=)
×
138
        lhs = ex.args[1]
×
139
        if isa(lhs, Expr) && lhs.head === :ref # xs[i] = x
×
140
            rhs = ex.args[2]
×
141
            xs = lhs.args[1]
×
142
            args = Vector{Any}(undef, length(lhs.args)-1)
×
143
            for i = 2:length(lhs.args)
×
144
                args[i-1] = _safeindex(lhs.args[i])
×
145
            end
×
146
            return Expr(:call, GlobalRef(@__MODULE__, :__safe_setindex!), xs, _safeindex(rhs), args...)
×
147
        end
148
    elseif ex.head === :ref # xs[i]
×
149
        return Expr(:call, GlobalRef(@__MODULE__, :__safe_getindex), ex.args...)
×
150
    end
151
    args = Vector{Any}(undef, length(ex.args))
×
152
    for i = 1:length(ex.args)
×
153
        args[i] = _safeindex(ex.args[i])
×
154
    end
×
155
    return Expr(ex.head, args...)
×
156
end
157

158
vect() = Vector{Any}()
3,494✔
159
function vect(X::T...) where T
20✔
160
    @_terminates_locally_meta
297✔
161
    vec = Vector{T}(undef, length(X))
3,011✔
162
    @_safeindex for i = 1:length(X)
2,080✔
163
        vec[i] = X[i]
5,683✔
164
    end
6,038✔
165
    return vec
713✔
166
end
167

168
"""
169
    vect(X...)
170

171
Create a [`Vector`](@ref) with element type computed from the `promote_typeof` of the argument,
172
containing the argument list.
173

174
# Examples
175
```jldoctest
176
julia> a = Base.vect(UInt8(1), 2.5, 1//2)
177
3-element Vector{Float64}:
178
 1.0
179
 2.5
180
 0.5
181
```
182
"""
183
function vect(X...)
1✔
184
    T = promote_typeof(X...)
1✔
185
    return T[X...]
1✔
186
end
187

188
size(a::Array, d::Integer) = size(a, Int(d)::Int)
×
189
function size(a::Array, d::Int)
190
    d < 1 && error("arraysize: dimension out of range")
11✔
191
    sz = getfield(a, :size)
1,248✔
192
    return d > length(sz) ? 1 : getfield(sz, d, false) # @inbounds
1,248✔
193
end
194
size(a::Array) = getfield(a, :size)
7,086,118✔
195

196
asize_from(a::Array, n) = n > ndims(a) ? () : (size(a,n), asize_from(a, n+1)...)
×
197

198
allocatedinline(@nospecialize T::Type) = (@_total_meta; ccall(:jl_stored_inline, Cint, (Any,), T) != Cint(0))
63✔
199

200
"""
201
    Base.isbitsunion(::Type{T})
202

203
Return whether a type is an "is-bits" Union type, meaning each type included in a Union is [`isbitstype`](@ref).
204

205
# Examples
206
```jldoctest
207
julia> Base.isbitsunion(Union{Float64, UInt8})
208
true
209

210
julia> Base.isbitsunion(Union{Float64, String})
211
false
212
```
213
"""
214
isbitsunion(u::Type) = u isa Union && allocatedinline(u)
×
215

216
function _unsetindex!(A::Array, i::Int)
1,440✔
217
    @inline
33,763✔
218
    @boundscheck checkbounds(A, i)
2,029,079✔
219
    @inbounds _unsetindex!(memoryref(A.ref, i))
2,083,030✔
220
    return A
1,003,013✔
221
end
222

223

224
# TODO: deprecate this (aligned_sizeof and/or elsize and/or sizeof(Some{T}) are more correct)
225
elsize(::Type{A}) where {T,A<:Array{T}} = aligned_sizeof(T)
8✔
226
function elsize(::Type{Ptr{T}}) where T
×
227
    # this only must return something valid for values which satisfy is_valid_intrinsic_elptr(T),
228
    # which includes Any and most concrete datatypes
229
    T === Any && return sizeof(Ptr{Any})
×
230
    T isa DataType || sizeof(Any) # throws
×
231
    return LLT_ALIGN(Core.sizeof(T), datatype_alignment(T))
×
232
end
233
elsize(::Type{Union{}}, slurp...) = 0
×
234

235
sizeof(a::Array) = length(a) * elsize(typeof(a)) # n.b. this ignores bitsunion bytes, as a historical fact
4,043✔
236

237
function isassigned(a::Array, i::Int...)
×
238
    @inline
×
239
    @_noub_if_noinbounds_meta
×
240
    @boundscheck checkbounds(Bool, a, i...) || return false
×
241
    ii = _sub2ind(size(a), i...)
×
242
    return @inbounds isassigned(memoryrefnew(a.ref, ii, false))
×
243
end
244

245
function isassigned(a::Vector, i::Int) # slight compiler simplification for the most common case
406✔
246
    @inline
406✔
247
    @_noub_if_noinbounds_meta
406✔
248
    @boundscheck checkbounds(Bool, a, i) || return false
1,502,610✔
249
    return @inbounds isassigned(memoryrefnew(a.ref, i, false))
1,502,610✔
250
end
251

252

253
## copy ##
254

255
"""
256
    unsafe_copyto!(dest::Ptr{T}, src::Ptr{T}, N)
257

258
Copy `N` elements from a source pointer to a destination, with no checking. The size of an
259
element is determined by the type of the pointers.
260

261
The `unsafe` prefix on this function indicates that no validation is performed on the
262
pointers `dest` and `src` to ensure that they are valid. Incorrect usage may corrupt or
263
segfault your program, in the same manner as C.
264
"""
265
function unsafe_copyto!(dest::Ptr{T}, src::Ptr{T}, n) where T
266
    # Do not use this to copy data between pointer arrays.
267
    # It can't be made safe no matter how carefully you checked.
268
    memmove(dest, src, n * aligned_sizeof(T))
259,848✔
269
    return dest
30,156✔
270
end
271

272
"""
273
    unsafe_copyto!(dest::Array, doffs, src::Array, soffs, n)
274

275
Copy `n` elements from a source array to a destination, starting at the linear index `soffs` in the
276
source and `doffs` in the destination (1-indexed).
277

278
The `unsafe` prefix on this function indicates that no validation is performed to ensure
279
that n is inbounds on either array. Incorrect usage may corrupt or segfault your program, in
280
the same manner as C.
281
"""
282
function unsafe_copyto!(dest::Array, doffs, src::Array, soffs, n)
283
    n == 0 && return dest
8,121✔
284
    unsafe_copyto!(memoryref(dest.ref, doffs), memoryref(src.ref, soffs), n)
5,908✔
285
    return dest
2,954✔
286
end
287

288
"""
289
    copyto!(dest, doffs, src, soffs, n)
290

291
Copy `n` elements from collection `src` starting at the linear index `soffs`, to array `dest` starting at
292
the index `doffs`. Return `dest`.
293
"""
294
copyto!(dest::Array, doffs::Integer, src::Array, soffs::Integer, n::Integer) = _copyto_impl!(dest, doffs, src, soffs, n)
129✔
295
copyto!(dest::Array, doffs::Integer, src::Memory, soffs::Integer, n::Integer) = _copyto_impl!(dest, doffs, src, soffs, n)
×
296
copyto!(dest::Memory, doffs::Integer, src::Array, soffs::Integer, n::Integer) = _copyto_impl!(dest, doffs, src, soffs, n)
×
297

298
# this is only needed to avoid possible ambiguities with methods added in some packages
299
copyto!(dest::Array{T}, doffs::Integer, src::Array{T}, soffs::Integer, n::Integer) where {T} = _copyto_impl!(dest, doffs, src, soffs, n)
595,797✔
300

301
function _copyto_impl!(dest::Union{Array,Memory}, doffs::Integer, src::Union{Array,Memory}, soffs::Integer, n::Integer)
302
    n == 0 && return dest
309,870✔
303
    n > 0 || _throw_argerror("Number of elements to copy must be non-negative.")
295,193✔
304
    @boundscheck checkbounds(dest, doffs:doffs+n-1)
295,193✔
305
    @boundscheck checkbounds(src, soffs:soffs+n-1)
295,193✔
306
    @inbounds let dest = memoryref(dest isa Array ? getfield(dest, :ref) : dest, doffs),
295,193✔
307
                  src = memoryref(src isa Array ? getfield(src, :ref) : src, soffs)
308
        unsafe_copyto!(dest, src, n)
295,802✔
309
    end
310
    return dest
609✔
311
end
312

313

314
# Outlining this because otherwise a catastrophic inference slowdown
315
# occurs, see discussion in #27874.
316
# It is also mitigated by using a constant string.
317
_throw_argerror(s) = (@noinline; throw(ArgumentError(s)))
×
318

319
copyto!(dest::Array, src::Array) = copyto!(dest, 1, src, 1, length(src))
126✔
320

321
# also to avoid ambiguities in packages
322
copyto!(dest::Array{T}, src::Array{T}) where {T} = copyto!(dest, 1, src, 1, length(src))
15,997✔
323

324
# N.B: The generic definition in multidimensional.jl covers, this, this is just here
325
# for bootstrapping purposes.
326
function fill!(dest::Array{T}, x) where T
60✔
327
    @inline
188✔
328
    x = x isa T ? x : convert(T, x)::T
188✔
329
    return _fill!(dest, x)
8,247,126✔
330
end
331
function _fill!(dest::Array{T}, x::T) where T
60✔
332
    for i in eachindex(dest)
423,292✔
333
        @inbounds dest[i] = x
7,996,416✔
334
    end
15,820,250✔
335
    return dest
102,914✔
336
end
337

338
"""
339
    copy(x)
340

341
Create a shallow copy of `x`: the outer structure is copied, but not all internal values.
342
For example, copying an array produces a new array with identically-same elements as the
343
original.
344

345
See also [`copy!`](@ref Base.copy!), [`copyto!`](@ref), [`deepcopy`](@ref).
346
"""
347
copy
348

349
@eval function copy(a::Array)
46✔
350
    # `copy` only throws when the size exceeds the max allocation size,
351
    # but since we're copying an existing array, we're guaranteed that this will not happen.
352
    @_nothrow_meta
46✔
353
    ref = a.ref
253,400✔
354
    newmem = typeof(ref.mem)(undef, length(a))
253,400✔
355
    @inbounds unsafe_copyto!(memoryref(newmem), ref, length(a))
448,974✔
356
    return $(Expr(:new, :(typeof(a)), :(memoryref(newmem)), :(a.size)))
253,400✔
357
end
358

359
# a mutating version of copyto! that results in dst aliasing src afterwards
360
function _take!(dst::Array{T,N}, src::Array{T,N}) where {T,N}
361
    if getfield(dst, :ref) !== getfield(src, :ref)
390✔
362
        setfield!(dst, :ref, getfield(src, :ref))
×
363
    end
364
    if getfield(dst, :size) !== getfield(src, :size)
390✔
365
        setfield!(dst, :size, getfield(src, :size))
179✔
366
    end
367
    return dst
390✔
368
end
369

370
## Constructors ##
371

372
similar(a::Array{T,1}) where {T}                    = Vector{T}(undef, size(a,1))
1,202✔
373
similar(a::Array{T,2}) where {T}                    = Matrix{T}(undef, size(a,1), size(a,2))
×
374
similar(a::Array{T,1}, S::Type) where {T}           = Vector{S}(undef, size(a,1))
43✔
375
similar(a::Array{T,2}, S::Type) where {T}           = Matrix{S}(undef, size(a,1), size(a,2))
×
376
similar(a::Array{T}, m::Int) where {T}              = Vector{T}(undef, m)
439✔
377
similar(a::Array, T::Type, dims::Dims{N}) where {N} = Array{T,N}(undef, dims)
541,478✔
378
similar(a::Array{T}, dims::Dims{N}) where {T,N}     = Array{T,N}(undef, dims)
×
379

380
# T[x...] constructs Array{T,1}
381
"""
382
    getindex(type[, elements...])
383

384
Construct a 1-d array of the specified type. This is usually called with the syntax
385
`Type[]`. Element values can be specified using `Type[a,b,c,...]`.
386

387
# Examples
388
```jldoctest
389
julia> Int8[1, 2, 3]
390
3-element Vector{Int8}:
391
 1
392
 2
393
 3
394

395
julia> getindex(Int8, 1, 2, 3)
396
3-element Vector{Int8}:
397
 1
398
 2
399
 3
400
```
401
"""
402
function getindex(::Type{T}, vals...) where T
51✔
403
    @inline
525✔
404
    @_effect_free_terminates_locally_meta
525✔
405
    a = Vector{T}(undef, length(vals))
595,444✔
406
    if vals isa NTuple
525✔
407
        @_safeindex for i in 1:length(vals)
200✔
408
            a[i] = vals[i]
38,228✔
409
        end
32✔
410
    else
411
        # use afoldl to avoid type instability inside loop
412
        afoldl(1, vals...) do i, v
343✔
413
            @inbounds a[i] = v
1,036✔
414
            return i + 1
1,036✔
415
        end
416
    end
417
    return a
534✔
418
end
419

420
function getindex(::Type{Any}, @nospecialize vals...)
15,252✔
421
    @_effect_free_terminates_locally_meta
47✔
422
    a = Vector{Any}(undef, length(vals))
29,092✔
423
    @_safeindex for i = 1:length(vals)
19,108✔
424
        a[i] = vals[i]
60,090✔
425
    end
76,031✔
426
    return a
15,563✔
427
end
428
getindex(::Type{Any}) = Vector{Any}()
39,169✔
429

430
function fill!(a::Union{Array{UInt8}, Array{Int8}}, x::Integer)
431
    ref = a.ref
66,032✔
432
    t = @_gc_preserve_begin ref
66,032✔
433
    p = unsafe_convert(Ptr{Cvoid}, ref)
66,032✔
434
    memset(p, x isa eltype(a) ? x : convert(eltype(a), x), length(a) % UInt)
66,032✔
435
    @_gc_preserve_end t
66,032✔
436
    return a
61✔
437
end
438

439
to_dim(d::Integer) = d
×
440
to_dim(d::OneTo) = last(d)
×
441

442
"""
443
    fill(value, dims::Tuple)
444
    fill(value, dims...)
445

446
Create an array of size `dims` with every location set to `value`.
447

448
For example, `fill(1.0, (5,5))` returns a 5×5 array of floats,
449
with `1.0` in every location of the array.
450

451
The dimension lengths `dims` may be specified as either a tuple or a sequence of arguments.
452
An `N`-length tuple or `N` arguments following the `value` specify an `N`-dimensional
453
array. Thus, a common idiom for creating a zero-dimensional array with its only location
454
set to `x` is `fill(x)`.
455

456
Every location of the returned array is set to (and is thus [`===`](@ref) to)
457
the `value` that was passed; this means that if the `value` is itself modified,
458
all elements of the `fill`ed array will reflect that modification because they're
459
_still_ that very `value`. This is of no concern with `fill(1.0, (5,5))` as the
460
`value` `1.0` is immutable and cannot itself be modified, but can be unexpected
461
with mutable values like — most commonly — arrays.  For example, `fill([], 3)`
462
places _the very same_ empty array in all three locations of the returned vector:
463

464
```jldoctest
465
julia> v = fill([], 3)
466
3-element Vector{Vector{Any}}:
467
 []
468
 []
469
 []
470

471
julia> v[1] === v[2] === v[3]
472
true
473

474
julia> value = v[1]
475
Any[]
476

477
julia> push!(value, 867_5309)
478
1-element Vector{Any}:
479
 8675309
480

481
julia> v
482
3-element Vector{Vector{Any}}:
483
 [8675309]
484
 [8675309]
485
 [8675309]
486
```
487

488
To create an array of many independent inner arrays, use a [comprehension](@ref man-comprehensions) instead.
489
This creates a new and distinct array on each iteration of the loop:
490

491
```jldoctest
492
julia> v2 = [[] for _ in 1:3]
493
3-element Vector{Vector{Any}}:
494
 []
495
 []
496
 []
497

498
julia> v2[1] === v2[2] === v2[3]
499
false
500

501
julia> push!(v2[1], 8675309)
502
1-element Vector{Any}:
503
 8675309
504

505
julia> v2
506
3-element Vector{Vector{Any}}:
507
 [8675309]
508
 []
509
 []
510
```
511

512
See also: [`fill!`](@ref), [`zeros`](@ref), [`ones`](@ref), [`similar`](@ref).
513

514
# Examples
515
```jldoctest
516
julia> fill(1.0, (2,3))
517
2×3 Matrix{Float64}:
518
 1.0  1.0  1.0
519
 1.0  1.0  1.0
520

521
julia> fill(42)
522
0-dimensional Array{Int64, 0}:
523
42
524

525
julia> A = fill(zeros(2), 2) # sets both elements to the same [0.0, 0.0] vector
526
2-element Vector{Vector{Float64}}:
527
 [0.0, 0.0]
528
 [0.0, 0.0]
529

530
julia> A[1][1] = 42; # modifies the filled value to be [42.0, 0.0]
531

532
julia> A # both A[1] and A[2] are the very same vector
533
2-element Vector{Vector{Float64}}:
534
 [42.0, 0.0]
535
 [42.0, 0.0]
536
```
537
"""
538
function fill end
539

540
fill(v, dims::DimOrInd...) = fill(v, dims)
6,041,569✔
541
fill(v, dims::NTuple{N, Union{Integer, OneTo}}) where {N} = fill(v, map(to_dim, dims))
×
542
fill(v, dims::NTuple{N, Integer}) where {N} = (a=Array{typeof(v),N}(undef, dims); fill!(a, v); a)
6,041,569✔
543
fill(v, dims::NTuple{N, DimOrInd}) where {N} = (a=similar(Array{typeof(v),N}, dims); fill!(a, v); a)
×
544
fill(v, dims::Tuple{}) = (a=Array{typeof(v),0}(undef, dims); fill!(a, v); a)
×
545

546
"""
547
    zeros([T=Float64,] dims::Tuple)
548
    zeros([T=Float64,] dims...)
549

550
Create an `Array`, with element type `T`, of all zeros with size specified by `dims`.
551
See also [`fill`](@ref), [`ones`](@ref), [`zero`](@ref).
552

553
# Examples
554
```jldoctest
555
julia> zeros(1)
556
1-element Vector{Float64}:
557
 0.0
558

559
julia> zeros(Int8, 2, 3)
560
2×3 Matrix{Int8}:
561
 0  0  0
562
 0  0  0
563
```
564
"""
565
function zeros end
566

567
"""
568
    ones([T=Float64,] dims::Tuple)
569
    ones([T=Float64,] dims...)
570

571
Create an `Array`, with element type `T`, of all ones with size specified by `dims`.
572
See also [`fill`](@ref), [`zeros`](@ref).
573

574
# Examples
575
```jldoctest
576
julia> ones(1,2)
577
1×2 Matrix{Float64}:
578
 1.0  1.0
579

580
julia> ones(ComplexF64, 2, 3)
581
2×3 Matrix{ComplexF64}:
582
 1.0+0.0im  1.0+0.0im  1.0+0.0im
583
 1.0+0.0im  1.0+0.0im  1.0+0.0im
584
```
585
"""
586
function ones end
587

588
for (fname, felt) in ((:zeros, :zero), (:ones, :one))
589
    @eval begin
590
        $fname(dims::DimOrInd...) = $fname(dims)
×
591
        $fname(::Type{T}, dims::DimOrInd...) where {T} = $fname(T, dims)
994,209✔
592
        $fname(dims::Tuple{Vararg{DimOrInd}}) = $fname(Float64, dims)
×
593
        $fname(::Type{T}, dims::NTuple{N, Union{Integer, OneTo}}) where {T,N} = $fname(T, map(to_dim, dims))
×
594
        function $fname(::Type{T}, dims::NTuple{N, Integer}) where {T,N}
60✔
595
            a = Array{T,N}(undef, dims)
124,757✔
596
            fill!(a, $felt(T))
994,209✔
597
            return a
58,786✔
598
        end
599
        function $fname(::Type{T}, dims::Tuple{}) where {T}
×
600
            a = Array{T}(undef)
×
601
            fill!(a, $felt(T))
×
602
            return a
×
603
        end
604
        function $fname(::Type{T}, dims::NTuple{N, DimOrInd}) where {T,N}
×
605
            a = similar(Array{T,N}, dims)
×
606
            fill!(a, $felt(T))
×
607
            return a
×
608
        end
609
    end
610
end
611

612
## Conversions ##
613

614
convert(::Type{T}, a::AbstractArray) where {T<:Array} = a isa T ? a : T(a)::T
126✔
615

616
promote_rule(a::Type{Array{T,n}}, b::Type{Array{S,n}}) where {T,n,S} = el_same(promote_type(T,S), a, b)
×
617

618
## Constructors ##
619

620
# constructors should make copies
621
Array{T,N}(x::AbstractArray{S,N})         where {T,N,S} = copyto_axcheck!(Array{T,N}(undef, size(x)), x)
126✔
622
AbstractArray{T,N}(A::AbstractArray{S,N}) where {T,N,S} = copyto_axcheck!(similar(A,T), A)
×
623

624
## copying iterators to containers
625

626
"""
627
    collect(element_type, collection)
628

629
Return an `Array` with the given element type of all items in a collection or iterable.
630
The result has the same shape and number of dimensions as `collection`.
631

632
# Examples
633
```jldoctest
634
julia> collect(Float64, 1:2:5)
635
3-element Vector{Float64}:
636
 1.0
637
 3.0
638
 5.0
639
```
640
"""
641
collect(::Type{T}, itr) where {T} = _collect(T, itr, IteratorSize(itr))
18,756✔
642

643
_collect(::Type{T}, itr, isz::Union{HasLength,HasShape}) where {T} =
×
644
    copyto!(_array_for(T, isz, _similar_shape(itr, isz)), itr)
645
function _collect(::Type{T}, itr, isz::SizeUnknown) where T
18,756✔
646
    a = Vector{T}()
18,756✔
647
    for x in itr
34,788✔
648
        push!(a, x)
78,046✔
649
    end
140,060✔
650
    return a
18,756✔
651
end
652

653
# make a collection similar to `c` and appropriate for collecting `itr`
654
_similar_for(c, ::Type{T}, itr, isz, shp) where {T} = similar(c, T)
×
655

656
_similar_shape(itr, ::SizeUnknown) = nothing
×
657
_similar_shape(itr, ::HasLength) = length(itr)::Integer
32,762✔
658
_similar_shape(itr, ::HasShape) = axes(itr)
234,728✔
659

660
_similar_for(c::AbstractArray, ::Type{T}, itr, ::SizeUnknown, ::Nothing) where {T} =
40✔
661
    similar(c, T, 0)
662
_similar_for(c::AbstractArray, ::Type{T}, itr, ::HasLength, len::Integer) where {T} =
15,030✔
663
    similar(c, T, len)
664
_similar_for(c::AbstractArray, ::Type{T}, itr, ::HasShape, axs) where {T} =
204✔
665
    similar(c, T, axs)
666

667
# make a collection appropriate for collecting `itr::Generator`
668
_array_for(::Type{T}, ::SizeUnknown, ::Nothing) where {T} = Vector{T}(undef, 0)
×
669
_array_for(::Type{T}, ::HasLength, len::Integer) where {T} = Vector{T}(undef, Int(len))
16,158✔
670
_array_for(::Type{T}, ::HasShape{N}, axs) where {T,N} = similar(Array{T,N}, axs)
346,240✔
671

672
# used by syntax lowering for simple typed comprehensions
673
_array_for(::Type{T}, itr, isz) where {T} = _array_for(T, isz, _similar_shape(itr, isz))
362,886✔
674

675

676
"""
677
    collect(iterator)
678

679
Return an `Array` of all items in a collection or iterator. For dictionaries, returns
680
a `Vector` of `key=>value` [Pair](@ref Pair)s. If the argument is array-like or is an iterator
681
with the [`HasShape`](@ref IteratorSize) trait, the result will have the same shape
682
and number of dimensions as the argument.
683

684
Used by [comprehensions](@ref man-comprehensions) to turn a [generator expression](@ref man-generators)
685
into an `Array`. Thus, *on generators*, the square-brackets notation may be used instead of calling `collect`,
686
see second example.
687

688
The element type of the returned array is based on the types of the values collected. However, if the
689
iterator is empty then the element type of the returned (empty) array is determined by type inference.
690

691
# Examples
692

693
Collect items from a `UnitRange{Int64}` collection:
694

695
```jldoctest
696
julia> collect(1:3)
697
3-element Vector{Int64}:
698
 1
699
 2
700
 3
701
```
702

703
Collect items from a generator (same output as `[x^2 for x in 1:3]`):
704

705
```jldoctest
706
julia> collect(x^2 for x in 1:3)
707
3-element Vector{Int64}:
708
 1
709
 4
710
 9
711
```
712

713
Collecting an empty iterator where the result type depends on type inference:
714

715
```jldoctest
716
julia> [rand(Bool) ? 1 : missing for _ in []]
717
Union{Missing, Int64}[]
718
```
719

720
When the iterator is non-empty, the result type depends only on values:
721

722
```julia-repl
723
julia> [rand(Bool) ? 1 : missing for _ in [""]]
724
1-element Vector{Int64}:
725
 1
726
```
727
"""
728
collect(itr) = _collect(1:1 #= Array =#, itr, IteratorEltype(itr), IteratorSize(itr))
272,359✔
729

730
collect(A::AbstractArray) = _collect_indices(axes(A), A)
×
731

732
collect_similar(cont, itr) = _collect(cont, itr, IteratorEltype(itr), IteratorSize(itr))
212✔
733

734
_collect(cont, itr, ::HasEltype, isz::Union{HasLength,HasShape}) =
15,457✔
735
    copyto!(_similar_for(cont, eltype(itr), itr, isz, _similar_shape(itr, isz)), itr)
736

737
function _collect(cont, itr, ::HasEltype, isz::SizeUnknown)
40✔
738
    a = _similar_for(cont, eltype(itr), itr, isz, nothing)
40✔
739
    for x in itr
77✔
740
        push!(a,x)
281✔
741
    end
509✔
742
    return a
40✔
743
end
744

745
_collect_indices(::Tuple{}, A) = copyto!(Array{eltype(A),0}(undef), A)
×
746
_collect_indices(indsA::Tuple{Vararg{OneTo}}, A) =
×
747
    copyto!(Array{eltype(A)}(undef, length.(indsA)), A)
748
function _collect_indices(indsA, A)
×
749
    B = Array{eltype(A)}(undef, length.(indsA))
×
750
    copyto!(B, CartesianIndices(axes(B)), A, CartesianIndices(indsA))
×
751
end
752

753
# NOTE: this function is not meant to be called, only inferred, for the
754
# purpose of bounding the types of values generated by an iterator.
755
function _iterator_upper_bound(itr)
×
756
    x = iterate(itr)
×
757
    while x !== nothing
×
758
        val = getfield(x, 1)
×
759
        if inferencebarrier(nothing)
×
760
            return val
×
761
        end
762
        x = iterate(itr, getfield(x, 2))
×
763
    end
×
764
    throw(nothing)
×
765
end
766

767
# define this as a macro so that the call to Core.Compiler
768
# gets inlined into the caller before recursion detection
769
# gets a chance to see it, so that recursive calls to the caller
770
# don't trigger the inference limiter
771
macro default_eltype(itr)
772
    I = esc(itr)
773
    return quote
774
        if $I isa Generator && ($I).f isa Type
769✔
775
            T = ($I).f
86✔
776
        else
777
            T = Base._return_type(_iterator_upper_bound, Tuple{typeof($I)})
683✔
778
        end
779
        promote_typejoin_union(T)
769✔
780
    end
781
end
782

783
function collect(itr::Generator)
1,105✔
784
    isz = IteratorSize(itr.iter)
490✔
785
    et = @default_eltype(itr)
786
    if isa(isz, SizeUnknown)
490✔
787
        return grow_to!(Vector{et}(), itr)
624✔
788
    else
789
        shp = _similar_shape(itr, isz)
679✔
790
        y = iterate(itr)
1,354✔
791
        if y === nothing
679✔
792
            return _array_for(et, isz, shp)
4✔
793
        end
794
        v1, st = y
486✔
795
        dest = _array_for(typeof(v1), isz, shp)
675✔
796
        # The typeassert gives inference a helping hand on the element type and dimensionality
797
        # (work-around for #28382)
798
        et′ = et <: Type ? Type : et
486✔
799
        RT = dest isa AbstractArray ? AbstractArray{<:et′, ndims(dest)} : Any
486✔
800
        collect_to_with_first!(dest, v1, itr, st)::RT
675✔
801
    end
802
end
803

804
_collect(c, itr, ::EltypeUnknown, isz::SizeUnknown) =
×
805
    grow_to!(_similar_for(c, @default_eltype(itr), itr, isz, nothing), itr)
×
806

807
function _collect(c, itr, ::EltypeUnknown, isz::Union{HasLength,HasShape})
195✔
808
    et = @default_eltype(itr)
197✔
809
    shp = _similar_shape(itr, isz)
204✔
810
    y = iterate(itr)
402✔
811
    if y === nothing
204✔
812
        return _similar_for(c, et, itr, isz, shp)
3✔
813
    end
814
    v1, st = y
197✔
815
    dest = _similar_for(c, typeof(v1), itr, isz, shp)
201✔
816
    # The typeassert gives inference a helping hand on the element type and dimensionality
817
    # (work-around for #28382)
818
    et′ = et <: Type ? Type : et
195✔
819
    RT = dest isa AbstractArray ? AbstractArray{<:et′, ndims(dest)} : Any
195✔
820
    collect_to_with_first!(dest, v1, itr, st)::RT
201✔
821
end
822

823
function collect_to_with_first!(dest::AbstractArray, v1, itr, st)
9✔
824
    i1 = first(LinearIndices(dest))
28✔
825
    dest[i1] = v1
876✔
826
    return collect_to!(dest, itr, i1+1, st)
3,867✔
827
end
828

829
function collect_to_with_first!(dest, v1, itr, st)
×
830
    push!(dest, v1)
×
831
    return grow_to!(dest, itr, st)
×
832
end
833

834
function setindex_widen_up_to(dest::AbstractArray{T}, el, i) where T
×
835
    @inline
×
836
    new = similar(dest, promote_typejoin(T, typeof(el)))
×
837
    f = first(LinearIndices(dest))
×
838
    copyto!(new, first(LinearIndices(new)), dest, f, i-f)
×
839
    @inbounds new[i] = el
×
840
    return new
×
841
end
842

843
function collect_to!(dest::AbstractArray{T}, itr, offs, st) where T
402✔
844
    # collect to dest array, checking the type of each result. if a result does not
845
    # match, widen the result type and re-dispatch.
846
    i = offs
414✔
847
    while true
8,014✔
848
        y = iterate(itr, st)
15,138✔
849
        y === nothing && break
8,014✔
850
        el, st = y
4,147✔
851
        if el isa T
4,142✔
852
            @inbounds dest[i] = el
7,138✔
853
            i += 1
7,138✔
854
        else
855
            new = setindex_widen_up_to(dest, el, i)
×
856
            return collect_to!(new, itr, i+1, st)
×
857
        end
858
    end
7,138✔
859
    return dest
876✔
860
end
861

862
function grow_to!(dest, itr)
2✔
863
    y = iterate(itr)
2✔
864
    y === nothing && return dest
2✔
865
    dest2 = empty(dest, typeof(y[1]))
×
866
    push!(dest2, y[1])
×
867
    grow_to!(dest2, itr, y[2])
×
868
end
869

870
function push_widen(dest, el)
871
    @inline
×
872
    new = sizehint!(empty(dest, promote_typejoin(eltype(dest), typeof(el))), length(dest))
×
873
    if new isa AbstractSet
×
874
        # TODO: merge back these two branches when copy! is re-enabled for sets/vectors
875
        union!(new, dest)
×
876
    else
877
        append!(new, dest)
×
878
    end
879
    push!(new, el)
×
880
    return new
×
881
end
882

883
function grow_to!(dest, itr, st)
×
884
    T = eltype(dest)
×
885
    y = iterate(itr, st)
×
886
    while y !== nothing
×
887
        el, st = y
×
888
        if el isa T
×
889
            push!(dest, el)
×
890
        else
891
            new = push_widen(dest, el)
×
892
            return grow_to!(new, itr, st)
×
893
        end
894
        y = iterate(itr, st)
×
895
    end
×
896
    return dest
×
897
end
898

899
## Iteration ##
900

901
iterate(A::Array, i=1) = (@inline; (i - 1)%UInt < length(A)%UInt ? (@inbounds A[i], i + 1) : nothing)
12,017,989✔
902

903
## Indexing: getindex ##
904

905
"""
906
    getindex(collection, key...)
907

908
Retrieve the value(s) stored at the given key or index within a collection. The syntax
909
`a[i,j,...]` is converted by the compiler to `getindex(a, i, j, ...)`.
910

911
See also [`get`](@ref), [`keys`](@ref), [`eachindex`](@ref).
912

913
# Examples
914
```jldoctest
915
julia> A = Dict("a" => 1, "b" => 2)
916
Dict{String, Int64} with 2 entries:
917
  "b" => 2
918
  "a" => 1
919

920
julia> getindex(A, "a")
921
1
922
```
923
"""
924
function getindex end
925

926
function getindex(A::Array, i1::Int, i2::Int, I::Int...)
×
927
    @inline
×
928
    @boundscheck checkbounds(A, i1, i2, I...) # generally _to_linear_index requires bounds checking
×
929
    return @inbounds A[_to_linear_index(A, i1, i2, I...)]
×
930
end
931

932
# Faster contiguous indexing using copyto! for AbstractUnitRange and Colon
933
function getindex(A::Array, I::AbstractUnitRange{<:Integer})
70✔
934
    @inline
×
935
    @boundscheck checkbounds(A, I)
541,008✔
936
    lI = length(I)
541,008✔
937
    X = similar(A, axes(I))
541,008✔
938
    if lI > 0
541,008✔
939
        copyto!(X, firstindex(X), A, first(I), lI)
538,620✔
940
    end
941
    return X
540,699✔
942
end
943

944
# getindex for carrying out logical indexing for AbstractUnitRange{Bool} as Bool <: Integer
945
getindex(a::Array, r::AbstractUnitRange{Bool}) = getindex(a, to_index(r))
×
946

947
function getindex(A::Array, c::Colon)
948
    lI = length(A)
439✔
949
    X = similar(A, lI)
439✔
950
    if lI > 0
439✔
951
        unsafe_copyto!(X, 1, A, 1, lI)
878✔
952
    end
953
    return X
439✔
954
end
955

956
# This is redundant with the abstract fallbacks, but needed for bootstrap
957
function getindex(A::Array{S}, I::AbstractRange{Int}) where S
958
    return S[ A[i] for i in I ]
2✔
959
end
960

961
## Indexing: setindex! ##
962

963
"""
964
    setindex!(collection, value, key...)
965

966
Store the given value at the given key or index within a collection. The syntax `a[i,j,...] =
967
x` is converted by the compiler to `(setindex!(a, x, i, j, ...); x)`.
968

969
# Examples
970
```jldoctest
971
julia> a = Dict("a"=>1)
972
Dict{String, Int64} with 1 entry:
973
  "a" => 1
974

975
julia> setindex!(a, 2, "b")
976
Dict{String, Int64} with 2 entries:
977
  "b" => 2
978
  "a" => 1
979
```
980
"""
981
function setindex! end
982

983
function setindex!(A::Array{T}, x, i::Int) where {T}
4,488✔
984
    @_propagate_inbounds_meta
275,601✔
985
    x = x isa T ? x : convert(T, x)::T
550,117✔
986
    return _setindex!(A, x, i)
48,252,820✔
987
end
988
function _setindex!(A::Array{T}, x::T, i::Int) where {T}
3,988✔
989
    @_noub_if_noinbounds_meta
275,476✔
990
    @boundscheck (i - 1)%UInt < length(A)%UInt || throw_boundserror(A, (i,))
48,253,230✔
991
    memoryrefset!(memoryrefnew(A.ref, i, false), x, :not_atomic, false)
48,253,230✔
992
    return A
37,374,368✔
993
end
994
function setindex!(A::Array{T}, x, i1::Int, i2::Int, I::Int...) where {T}
×
995
    @_propagate_inbounds_meta
×
996
    x = x isa T ? x : convert(T, x)::T
×
997
    return _setindex!(A, x, i1, i2, I...)
×
998
end
999
function _setindex!(A::Array{T}, x::T, i1::Int, i2::Int, I::Int...) where {T}
×
1000
    @inline
×
1001
    @_noub_if_noinbounds_meta
×
1002
    @boundscheck checkbounds(A, i1, i2, I...) # generally _to_linear_index requires bounds checking
×
1003
    memoryrefset!(memoryrefnew(A.ref, _to_linear_index(A, i1, i2, I...), false), x, :not_atomic, false)
×
1004
    return A
×
1005
end
1006

1007
__safe_setindex!(A::Vector{Any}, @nospecialize(x), i::Int) = (@inline; @_nothrow_noub_meta;
194✔
1008
    memoryrefset!(memoryrefnew(A.ref, i, false), x, :not_atomic, false); return A)
218,614✔
1009
__safe_setindex!(A::Vector{T}, x::T, i::Int) where {T} = (@inline; @_nothrow_noub_meta;
2,069✔
1010
    memoryrefset!(memoryrefnew(A.ref, i, false), x, :not_atomic, false); return A)
1,858,187✔
1011
__safe_setindex!(A::Vector{T}, x,    i::Int) where {T} = (@inline;
×
1012
    __safe_setindex!(A, convert(T, x)::T, i))
×
1013

1014
# This is redundant with the abstract fallbacks but needed and helpful for bootstrap
1015
function setindex!(A::Array, X::AbstractArray, I::AbstractVector{Int})
1016
    @_propagate_inbounds_meta
1✔
1017
    @boundscheck setindex_shape_check(X, length(I))
4,306✔
1018
    @boundscheck checkbounds(A, I)
4,306✔
1019
    require_one_based_indexing(X)
1✔
1020
    X′ = unalias(A, X)
1✔
1021
    I′ = unalias(A, I)
1✔
1022
    count = 1
1✔
1023
    for i in I′
4,306✔
1024
        @inbounds A[i] = X′[count]
13,994✔
1025
        count += 1
13,994✔
1026
    end
24,188✔
1027
    return A
4,306✔
1028
end
1029

1030
# Faster contiguous setindex! with copyto!
1031
function setindex!(A::Array{T}, X::Array{T}, I::AbstractUnitRange{Int}) where T
1032
    @inline
3✔
1033
    @boundscheck checkbounds(A, I)
82✔
1034
    lI = length(I)
82✔
1035
    @boundscheck setindex_shape_check(X, lI)
82✔
1036
    if lI > 0
82✔
1037
        unsafe_copyto!(A, first(I), X, 1, lI)
42✔
1038
    end
1039
    return A
82✔
1040
end
1041
function setindex!(A::Array{T}, X::Array{T}, c::Colon) where T
×
1042
    @inline
×
1043
    lI = length(A)
×
1044
    @boundscheck setindex_shape_check(X, lI)
×
1045
    if lI > 0
×
1046
        unsafe_copyto!(A, 1, X, 1, lI)
×
1047
    end
1048
    return A
×
1049
end
1050

1051
# Pick new memory size for efficiently growing an array
1052
# TODO: This should know about the size of our GC pools
1053
# Specifically we are wasting ~10% of memory for small arrays
1054
# by not picking memory sizes that max out a GC pool
1055
function overallocation(maxsize)
4✔
1056
    maxsize < 8 && return 8;
592,716✔
1057
    # compute maxsize = maxsize + 4*maxsize^(7/8) + maxsize/8
1058
    # for small n, we grow faster than O(n)
1059
    # for large n, we grow at O(n/8)
1060
    # and as we reach O(memory) for memory>>1MB,
1061
    # this means we end by adding about 10% of memory each time
1062
    exp2 = sizeof(maxsize) * 8 - Core.Intrinsics.ctlz_int(maxsize)
45,169✔
1063
    maxsize += (1 << div(exp2 * 7, 8)) * 4 + div(maxsize, 8)
45,169✔
1064
    return maxsize
45,169✔
1065
end
1066

1067
array_new_memory(mem::Memory, newlen::Int) = typeof(mem)(undef, newlen) # when implemented, this should attempt to first expand mem
592,655✔
1068

1069
function _growbeg!(a::Vector, delta::Integer)
1070
    @_noub_meta
×
1071
    delta = Int(delta)
×
1072
    delta == 0 && return # avoid attempting to index off the end
10,252✔
1073
    delta >= 0 || throw(ArgumentError("grow requires delta >= 0"))
10,250✔
1074
    ref = a.ref
49,184✔
1075
    mem = ref.mem
49,184✔
1076
    len = length(a)
49,184✔
1077
    offset = memoryrefoffset(ref)
49,184✔
1078
    newlen = len + delta
49,184✔
1079
    setfield!(a, :size, (newlen,))
49,184✔
1080
    # if offset is far enough advanced to fit data in existing memory without copying
1081
    if delta <= offset - 1
49,184✔
1082
        setfield!(a, :ref, @inbounds memoryref(ref, 1 - delta))
37,193✔
1083
    else
1084
        @noinline (function()
23,982✔
1085
        @_terminates_locally_meta
1✔
1086
        memlen = length(mem)
11,991✔
1087
        if offset + len - 1 > memlen || offset < 1
23,982✔
1088
            throw(ConcurrencyViolationError("Vector has invalid state. Don't modify internal fields incorrectly, or resize without correct locks"))
×
1089
        end
1090
        # since we will allocate the array in the middle of the memory we need at least 2*delta extra space
1091
        # the +1 is because I didn't want to have an off by 1 error.
1092
        newmemlen = max(overallocation(len), len + 2 * delta + 1)
18,962✔
1093
        newoffset = div(newmemlen - newlen, 2) + 1
11,991✔
1094
        # If there is extra data after the end of the array we can use that space so long as there is enough
1095
        # space at the end that there won't be quadratic behavior with a mix of growth from both ends.
1096
        # Specifically, we want to ensure that we will only do this operation once before
1097
        # increasing the size of the array, and that we leave enough space at both the beginning and the end.
1098
        if newoffset + newlen < memlen
11,991✔
1099
            newoffset = div(memlen - newlen, 2) + 1
18✔
1100
            newmem = mem
18✔
1101
            unsafe_copyto!(newmem, newoffset + delta, mem, offset, len)
36✔
1102
            for j in offset:newoffset+delta-1
18✔
1103
                @inbounds _unsetindex!(mem, j)
195✔
1104
            end
372✔
1105
        else
1106
            newmem = array_new_memory(mem, newmemlen)
11,973✔
1107
            unsafe_copyto!(newmem, newoffset + delta, mem, offset, len)
11,973✔
1108
        end
1109
        if ref !== a.ref
11,991✔
1110
            @noinline throw(ConcurrencyViolationError("Vector can not be resized concurrently"))
×
1111
        end
1112
        setfield!(a, :ref, @inbounds memoryref(newmem, newoffset))
11,991✔
1113
        end)()
1114
    end
1115
    return
48,941✔
1116
end
1117

1118
function _growend!(a::Vector, delta::Integer)
1,431✔
1119
    @_noub_meta
2,164✔
1120
    delta = Int(delta)
2,164✔
1121
    delta >= 0 || throw(ArgumentError("grow requires delta >= 0"))
406,784✔
1122
    ref = a.ref
2,339,095✔
1123
    mem = ref.mem
2,339,095✔
1124
    memlen = length(mem)
2,339,095✔
1125
    len = length(a)
2,339,095✔
1126
    newlen = len + delta
2,339,095✔
1127
    offset = memoryrefoffset(ref)
2,339,095✔
1128
    setfield!(a, :size, (newlen,))
2,339,095✔
1129
    newmemlen = offset + newlen - 1
2,339,095✔
1130
    if memlen < newmemlen
2,339,095✔
1131
        @noinline (function()
1,159,418✔
1132
        if offset + len - 1 > memlen || offset < 1
1,155,440✔
1133
            throw(ConcurrencyViolationError("Vector has invalid state. Don't modify internal fields incorrectly, or resize without correct locks"))
×
1134
        end
1135

1136
        if offset - 1 > div(5 * newlen, 4)
577,720✔
1137
            # If the offset is far enough that we can copy without resizing
1138
            # while maintaining proportional spacing on both ends of the array
1139
            # note that this branch prevents infinite growth when doing combinations
1140
            # of push! and popfirst! (i.e. when using a Vector as a queue)
1141
            newmem = mem
977✔
1142
            newoffset = div(newlen, 8) + 1
977✔
1143
        else
1144
            # grow either by our computed overallocation factor
1145
            # or exactly the requested size, whichever is larger
1146
            # TODO we should possibly increase the offset if the current offset is nonzero.
1147
            newmemlen2 = max(overallocation(memlen), newmemlen)
613,398✔
1148
            newmem = array_new_memory(mem, newmemlen2)
576,743✔
1149
            newoffset = offset
576,743✔
1150
        end
1151
        newref = @inbounds memoryref(newmem, newoffset)
577,720✔
1152
        unsafe_copyto!(newref, ref, len)
633,594✔
1153
        if ref !== a.ref
577,720✔
1154
            @noinline throw(ConcurrencyViolationError("Vector can not be resized concurrently"))
×
1155
        end
1156
        setfield!(a, :ref, newref)
577,720✔
1157
        end)()
1158
    end
1159
    return
1,865,590✔
1160
end
1161

1162
function _growat!(a::Vector, i::Integer, delta::Integer)
71,980✔
1163
    @_terminates_globally_noub_meta
×
1164
    delta = Int(delta)
×
1165
    i = Int(i)
×
1166
    i == 1 && return _growbeg!(a, delta)
71,980✔
1167
    len = length(a)
62,615✔
1168
    i == len + 1 && return _growend!(a, delta)
62,615✔
1169
    delta >= 0 || throw(ArgumentError("grow requires delta >= 0"))
62,615✔
1170
    1 < i <= len || throw(BoundsError(a, i))
62,615✔
1171
    ref = a.ref
62,615✔
1172
    mem = ref.mem
62,615✔
1173
    memlen = length(mem)
62,615✔
1174
    newlen = len + delta
62,615✔
1175
    offset = memoryrefoffset(ref)
62,615✔
1176
    setfield!(a, :size, (newlen,))
62,615✔
1177
    newmemlen = offset + newlen - 1
62,615✔
1178

1179
    # which side would we rather grow into?
1180
    prefer_start = i <= div(len, 2)
62,615✔
1181
    # if offset is far enough advanced to fit data in beginning of the memory
1182
    if prefer_start && delta <= offset - 1
62,615✔
1183
        newref = @inbounds memoryref(mem, offset - delta)
27,402✔
1184
        unsafe_copyto!(newref, ref, i)
54,804✔
1185
        setfield!(a, :ref, newref)
27,402✔
1186
        for j in i:i+delta-1
27,402✔
1187
            @inbounds _unsetindex!(a, j)
38,470✔
1188
        end
38,470✔
1189
    elseif !prefer_start && memlen >= newmemlen
35,213✔
1190
        unsafe_copyto!(mem, offset - 1 + delta + i, mem, offset - 1 + i, len - i + 1)
62,686✔
1191
        for j in i:i+delta-1
31,343✔
1192
            @inbounds _unsetindex!(a, j)
43,773✔
1193
        end
43,773✔
1194
    else
1195
        # since we will allocate the array in the middle of the memory we need at least 2*delta extra space
1196
        # the +1 is because I didn't want to have an off by 1 error.
1197
        newmemlen = max(overallocation(memlen), len+2*delta+1)
5,364✔
1198
        newoffset = (newmemlen - newlen) ÷ 2 + 1
3,870✔
1199
        newmem = array_new_memory(mem, newmemlen)
3,870✔
1200
        newref = @inbounds memoryref(newmem, newoffset)
3,870✔
1201
        unsafe_copyto!(newref, ref, i-1)
7,740✔
1202
        unsafe_copyto!(newmem, newoffset + delta + i - 1, mem, offset + i - 1, len - i + 1)
7,740✔
1203
        setfield!(a, :ref, newref)
3,870✔
1204
    end
1205
end
1206

1207
# efficiently delete part of an array
1208
function _deletebeg!(a::Vector, delta::Integer)
12,552✔
1209
    delta = Int(delta)
32,401✔
1210
    len = length(a)
130,654✔
1211
    0 <= delta <= len || throw(ArgumentError("_deletebeg! requires delta in 0:length(a)"))
130,654✔
1212
    for i in 1:delta
45,237✔
1213
        @inbounds _unsetindex!(a, i)
143,209✔
1214
    end
45,255✔
1215
    newlen = len - delta
130,654✔
1216
    if newlen != 0 # if newlen==0 we could accidentally index past the memory
130,654✔
1217
        newref = @inbounds memoryref(a.ref, delta + 1)
113,856✔
1218
        setfield!(a, :ref, newref)
113,856✔
1219
    end
1220
    setfield!(a, :size, (newlen,))
130,654✔
1221
    return
130,654✔
1222
end
1223
function _deleteend!(a::Vector, delta::Integer)
21,029✔
1224
    delta = Int(delta)
1,372✔
1225
    len = length(a)
1,113,670✔
1226
    0 <= delta <= len || throw(ArgumentError("_deleteend! requires delta in 0:length(a)"))
1,113,670✔
1227
    newlen = len - delta
1,113,670✔
1228
    for i in newlen+1:len
1,131,038✔
1229
        @inbounds _unsetindex!(a, i)
1,857,578✔
1230
    end
2,535,960✔
1231
    setfield!(a, :size, (newlen,))
1,113,670✔
1232
    return
1,113,670✔
1233
end
1234
function _deleteat!(a::Vector, i::Integer, delta::Integer)
7,169✔
1235
    i = Int(i)
61✔
1236
    len = length(a)
7,169✔
1237
    0 <= delta || throw(ArgumentError("_deleteat! requires delta >= 0"))
7,169✔
1238
    1 <= i <= len || throw(BoundsError(a, i))
7,169✔
1239
    i + delta <= len + 1 || throw(BoundsError(a, i + delta - 1))
7,169✔
1240
    newa = a
61✔
1241
    if 2*i + delta <= len
7,169✔
1242
        unsafe_copyto!(newa, 1 + delta, a, 1, i - 1)
376✔
1243
        _deletebeg!(a, delta)
367✔
1244
    else
1245
        unsafe_copyto!(newa, i, a, i + delta, len + 1 - delta - i)
9,045✔
1246
        _deleteend!(a, delta)
6,802✔
1247
    end
1248
    return
7,169✔
1249
end
1250
## Dequeue functionality ##
1251

1252
"""
1253
    push!(collection, items...) -> collection
1254

1255
Insert one or more `items` in `collection`. If `collection` is an ordered container,
1256
the items are inserted at the end (in the given order).
1257

1258
# Examples
1259
```jldoctest
1260
julia> push!([1, 2, 3], 4, 5, 6)
1261
6-element Vector{Int64}:
1262
 1
1263
 2
1264
 3
1265
 4
1266
 5
1267
 6
1268
```
1269

1270
If `collection` is ordered, use [`append!`](@ref) to add all the elements of another
1271
collection to it. The result of the preceding example is equivalent to `append!([1, 2, 3], [4,
1272
5, 6])`. For `AbstractSet` objects, [`union!`](@ref) can be used instead.
1273

1274
See [`sizehint!`](@ref) for notes about the performance model.
1275

1276
See also [`pushfirst!`](@ref).
1277
"""
1278
function push! end
1279

1280
function push!(a::Vector{T}, item) where T
1,543✔
1281
    @inline
2,058✔
1282
    # convert first so we don't grow the array if the assignment won't work
1283
    # and also to avoid a dynamic dynamic dispatch in the common case that
1284
    # `item` is poorly-typed and `a` is well-typed
1285
    item = item isa T ? item : convert(T, item)::T
36,161✔
1286
    return _push!(a, item)
1,814,271✔
1287
end
1288
function _push!(a::Vector{T}, item::T) where T
1,388✔
1289
    _growend!(a, 1)
1,814,271✔
1290
    @_safeindex a[length(a)] = item
1,814,271✔
1291
    return a
1,506,432✔
1292
end
1293

1294
# specialize and optimize the single argument case
1295
function push!(a::Vector{Any}, @nospecialize x)
36✔
1296
    _growend!(a, 1)
119,979✔
1297
    @_safeindex a[length(a)] = x
119,979✔
1298
    return a
119,979✔
1299
end
1300
function push!(a::Vector{Any}, @nospecialize x...)
1301
    @_terminates_locally_meta
×
1302
    na = length(a)
71✔
1303
    nx = length(x)
×
1304
    _growend!(a, nx)
71✔
1305
    @_safeindex for i = 1:nx
142✔
1306
        a[na+i] = x[i]
142✔
1307
    end
213✔
1308
    return a
71✔
1309
end
1310

1311
"""
1312
    append!(collection, collections...) -> collection.
1313

1314
For an ordered container `collection`, add the elements of each `collections`
1315
to the end of it.
1316

1317
!!! compat "Julia 1.6"
1318
    Specifying multiple collections to be appended requires at least Julia 1.6.
1319

1320
# Examples
1321
```jldoctest
1322
julia> append!([1], [2, 3])
1323
3-element Vector{Int64}:
1324
 1
1325
 2
1326
 3
1327

1328
julia> append!([1, 2, 3], [4, 5], [6])
1329
6-element Vector{Int64}:
1330
 1
1331
 2
1332
 3
1333
 4
1334
 5
1335
 6
1336
```
1337

1338
Use [`push!`](@ref) to add individual items to `collection` which are not already
1339
themselves in another collection. The result of the preceding example is equivalent to
1340
`push!([1, 2, 3], 4, 5, 6)`.
1341

1342
See [`sizehint!`](@ref) for notes about the performance model.
1343

1344
See also [`vcat`](@ref) for vectors, [`union!`](@ref) for sets,
1345
and [`prepend!`](@ref) and [`pushfirst!`](@ref) for the opposite order.
1346
"""
1347
function append! end
1348

1349
function append!(a::Vector{T}, items::Union{AbstractVector{<:T},Tuple}) where T
1350
    items isa Tuple && (items = map(x -> convert(T, x), items))
3✔
1351
    n = Int(length(items))::Int
27,255✔
1352
    _growend!(a, n)
27,402✔
1353
    copyto!(a, length(a)-n+1, items, firstindex(items), n)
40,106✔
1354
    return a
27,256✔
1355
end
1356

1357
append!(a::AbstractVector, iter) = _append!(a, IteratorSize(iter), iter)
88,577✔
1358
push!(a::AbstractVector, iter...) = append!(a, iter)
147✔
1359
append!(a::AbstractVector, iter...) = (foreach(v -> append!(a, v), iter); a)
×
1360

1361
function _append!(a::AbstractVector, ::Union{HasLength,HasShape}, iter)
14,954✔
1362
    n = Int(length(iter))::Int
15,459✔
1363
    i = lastindex(a)
4✔
1364
    sizehint!(a, length(a) + n; shrink=false)
14,954✔
1365
    for item in iter
28,774✔
1366
        push!(a, item)
68,886✔
1367
    end
69,417✔
1368
    a
4✔
1369
end
1370
function _append!(a::AbstractVector, ::IteratorSize, iter)
73,623✔
1371
    for item in iter
84,088✔
1372
        push!(a, item)
81,506✔
1373
    end
81,506✔
1374
    a
×
1375
end
1376

1377
"""
1378
    prepend!(a::Vector, collections...) -> collection
1379

1380
Insert the elements of each `collections` to the beginning of `a`.
1381

1382
When `collections` specifies multiple collections, order is maintained:
1383
elements of `collections[1]` will appear leftmost in `a`, and so on.
1384

1385
!!! compat "Julia 1.6"
1386
    Specifying multiple collections to be prepended requires at least Julia 1.6.
1387

1388
# Examples
1389
```jldoctest
1390
julia> prepend!([3], [1, 2])
1391
3-element Vector{Int64}:
1392
 1
1393
 2
1394
 3
1395

1396
julia> prepend!([6], [1, 2], [3, 4, 5])
1397
6-element Vector{Int64}:
1398
 1
1399
 2
1400
 3
1401
 4
1402
 5
1403
 6
1404
```
1405
"""
1406
function prepend! end
1407

1408
function prepend!(a::Vector{T}, items::Union{AbstractVector{<:T},Tuple}) where T
2✔
1409
    items isa Tuple && (items = map(x -> convert(T, x), items))
2✔
1410
    n = length(items)
4✔
1411
    _growbeg!(a, n)
6✔
1412
    # in case of aliasing, the _growbeg might have shifted our data, so copy
1413
    # just the last n elements instead of all of them from the first
1414
    copyto!(a, 1, items, lastindex(items)-n+1, n)
6✔
1415
    return a
4✔
1416
end
1417

1418
prepend!(a::AbstractVector, iter) = _prepend!(a, IteratorSize(iter), iter)
×
1419
pushfirst!(a::AbstractVector, iter...) = prepend!(a, iter)
×
1420
prepend!(a::AbstractVector, iter...) = (for v = reverse(iter); prepend!(a, v); end; return a)
×
1421

1422
function _prepend!(a::Vector, ::Union{HasLength,HasShape}, iter)
×
1423
    @_terminates_locally_meta
×
1424
    require_one_based_indexing(a)
×
1425
    n = Int(length(iter))::Int
×
1426
    sizehint!(a, length(a) + n; first=true, shrink=false)
×
1427
    n = 0
×
1428
    for item in iter
×
1429
        n += 1
×
1430
        pushfirst!(a, item)
×
1431
    end
×
1432
    reverse!(a, 1, n)
×
1433
    a
×
1434
end
1435
function _prepend!(a::Vector, ::IteratorSize, iter)
×
1436
    n = 0
×
1437
    for item in iter
×
1438
        n += 1
×
1439
        pushfirst!(a, item)
×
1440
    end
×
1441
    reverse!(a, 1, n)
×
1442
    a
×
1443
end
1444

1445
"""
1446
    resize!(a::Vector, n::Integer) -> Vector
1447

1448
Resize `a` to contain `n` elements. If `n` is smaller than the current collection
1449
length, the first `n` elements will be retained. If `n` is larger, the new elements are not
1450
guaranteed to be initialized.
1451

1452
# Examples
1453
```jldoctest
1454
julia> resize!([6, 5, 4, 3, 2, 1], 3)
1455
3-element Vector{Int64}:
1456
 6
1457
 5
1458
 4
1459

1460
julia> a = resize!([6, 5, 4, 3, 2, 1], 8);
1461

1462
julia> length(a)
1463
8
1464

1465
julia> a[1:6]
1466
6-element Vector{Int64}:
1467
 6
1468
 5
1469
 4
1470
 3
1471
 2
1472
 1
1473
```
1474
"""
1475
function resize!(a::Vector, nl_::Integer)
426,207✔
1476
    nl = Int(nl_)::Int
3,681✔
1477
    l = length(a)
449,385✔
1478
    if nl > l
449,385✔
1479
        _growend!(a, nl-l)
257,841✔
1480
    elseif nl != l
191,544✔
1481
        if nl < 0
48,580✔
1482
            _throw_argerror("new length must be ≥ 0")
×
1483
        end
1484
        _deleteend!(a, l-nl)
48,580✔
1485
    end
1486
    return a
449,385✔
1487
end
1488

1489
"""
1490
    sizehint!(s, n; first::Bool=false, shrink::Bool=true) -> s
1491

1492
Suggest that collection `s` reserve capacity for at least `n` elements. That is, if
1493
you expect that you're going to have to push a lot of values onto `s`, you can avoid
1494
the cost of incremental reallocation by doing it once up front; this can improve
1495
performance.
1496

1497
If `first` is `true`, then any additional space is reserved before the start of the collection.
1498
This way, subsequent calls to `pushfirst!` (instead of `push!`) may become faster.
1499
Supplying this keyword may result in an error if the collection is not ordered
1500
or if `pushfirst!` is not supported for this collection.
1501

1502
If `shrink=true` (the default), the collection's capacity may be reduced if its current
1503
capacity is greater than `n`.
1504

1505
See also [`resize!`](@ref).
1506

1507
# Notes on the performance model
1508

1509
For types that support `sizehint!`,
1510

1511
1. `push!` and `append!` methods generally may (but are not required to) preallocate extra
1512
   storage. For types implemented in `Base`, they typically do, using a heuristic optimized for
1513
   a general use case.
1514

1515
2. `sizehint!` may control this preallocation. Again, it typically does this for types in
1516
   `Base`.
1517

1518
3. `empty!` is nearly costless (and O(1)) for types that support this kind of preallocation.
1519

1520
!!! compat "Julia 1.11"
1521
    The `shrink` and `first` arguments were added in Julia 1.11.
1522
"""
1523
function sizehint! end
1524

1525
function sizehint!(a::Vector, sz::Integer; first::Bool=false, shrink::Bool=true)
36,384✔
1526
    len = length(a)
17,365✔
1527
    ref = a.ref
17,365✔
1528
    mem = ref.mem
17,365✔
1529
    memlen = length(mem)
17,365✔
1530
    sz = max(Int(sz), len)
17,365✔
1531
    inc = sz - len
17,365✔
1532
    if sz <= memlen
17,365✔
1533
        # if we don't save at least 1/8th memlen then its not worth it to shrink
1534
        if !shrink || memlen - sz <= div(memlen, 8)
11,769✔
1535
            return a
11,627✔
1536
        end
1537
        newmem = array_new_memory(mem, sz)
69✔
1538
        if first
69✔
1539
            newref = memoryref(newmem, inc + 1)
×
1540
        else
1541
            newref = memoryref(newmem)
69✔
1542
        end
1543
        unsafe_copyto!(newref, ref, len)
84✔
1544
        setfield!(a, :ref, newref)
69✔
1545
    elseif first
5,669✔
1546
        _growbeg!(a, inc)
×
1547
        newref = getfield(a, :ref)
×
1548
        newref = memoryref(newref, inc + 1)
×
1549
        setfield!(a, :size, (len,)) # undo the size change from _growbeg!
×
1550
        setfield!(a, :ref, newref) # undo the offset change from _growbeg!
×
1551
    else # last
1552
        _growend!(a, inc)
5,669✔
1553
        setfield!(a, :size, (len,)) # undo the size change from _growend!
5,669✔
1554
    end
1555
    a
51✔
1556
end
1557

1558
# Fall-back implementation for non-shrinkable collections
1559
# avoid defining this the normal way to avoid avoid infinite recursion
1560
function Core.kwcall(kwargs::NamedTuple{names}, ::typeof(sizehint!), a, sz) where names
×
1561
    get(kwargs, :first, false)::Bool
×
1562
    get(kwargs, :shrink, true)::Bool
×
1563
    isempty(diff_names(names, (:first, :shrink))) || kwerr(kwargs, sizehint!, a, sz)
×
1564
    sizehint!(a, sz)
×
1565
end
1566

1567
"""
1568
    pop!(collection) -> item
1569

1570
Remove an item in `collection` and return it. If `collection` is an
1571
ordered container, the last item is returned; for unordered containers,
1572
an arbitrary element is returned.
1573

1574
See also: [`popfirst!`](@ref), [`popat!`](@ref), [`delete!`](@ref), [`deleteat!`](@ref), [`splice!`](@ref), and [`push!`](@ref).
1575

1576
# Examples
1577
```jldoctest
1578
julia> A=[1, 2, 3]
1579
3-element Vector{Int64}:
1580
 1
1581
 2
1582
 3
1583

1584
julia> pop!(A)
1585
3
1586

1587
julia> A
1588
2-element Vector{Int64}:
1589
 1
1590
 2
1591

1592
julia> S = Set([1, 2])
1593
Set{Int64} with 2 elements:
1594
  2
1595
  1
1596

1597
julia> pop!(S)
1598
2
1599

1600
julia> S
1601
Set{Int64} with 1 element:
1602
  1
1603

1604
julia> pop!(Dict(1=>2))
1605
1 => 2
1606
```
1607
"""
1608
function pop!(a::Vector)
1,359✔
1609
    if isempty(a)
1,023,096✔
1610
        _throw_argerror("array must be non-empty")
×
1611
    end
1612
    item = a[end]
1,023,096✔
1613
    _deleteend!(a, 1)
1,023,096✔
1614
    return item
1,023,096✔
1615
end
1616

1617
"""
1618
    popat!(a::Vector, i::Integer, [default])
1619

1620
Remove the item at the given `i` and return it. Subsequent items
1621
are shifted to fill the resulting gap.
1622
When `i` is not a valid index for `a`, return `default`, or throw an error if
1623
`default` is not specified.
1624

1625
See also: [`pop!`](@ref), [`popfirst!`](@ref), [`deleteat!`](@ref), [`splice!`](@ref).
1626

1627
!!! compat "Julia 1.5"
1628
    This function is available as of Julia 1.5.
1629

1630
# Examples
1631
```jldoctest
1632
julia> a = [4, 3, 2, 1]; popat!(a, 2)
1633
3
1634

1635
julia> a
1636
3-element Vector{Int64}:
1637
 4
1638
 2
1639
 1
1640

1641
julia> popat!(a, 4, missing)
1642
missing
1643

1644
julia> popat!(a, 4)
1645
ERROR: BoundsError: attempt to access 3-element Vector{Int64} at index [4]
1646
[...]
1647
```
1648
"""
1649
function popat!(a::Vector, i::Integer)
×
1650
    @_propagate_inbounds_meta
×
1651
    x = a[i]
×
1652
    _deleteat!(a, i, 1)
×
1653
    x
×
1654
end
1655

1656
function popat!(a::Vector, i::Integer, default)
×
1657
    if 1 <= i <= length(a)
×
1658
        x = @inbounds a[i]
×
1659
        _deleteat!(a, i, 1)
×
1660
        x
×
1661
    else
1662
        default
×
1663
    end
1664
end
1665

1666
"""
1667
    pushfirst!(collection, items...) -> collection
1668

1669
Insert one or more `items` at the beginning of `collection`.
1670

1671
This function is called `unshift` in many other programming languages.
1672

1673
# Examples
1674
```jldoctest
1675
julia> pushfirst!([1, 2, 3, 4], 5, 6)
1676
6-element Vector{Int64}:
1677
 5
1678
 6
1679
 1
1680
 2
1681
 3
1682
 4
1683
```
1684
"""
1685
function pushfirst!(a::Vector{T}, item) where T
1686
    @inline
×
1687
    item = item isa T ? item : convert(T, item)::T
×
1688
    return _pushfirst!(a, item)
6✔
1689
end
1690
function _pushfirst!(a::Vector{T}, item::T) where T
1691
    _growbeg!(a, 1)
6✔
1692
    @_safeindex a[1] = item
5✔
1693
    return a
5✔
1694
end
1695

1696
# specialize and optimize the single argument case
1697
function pushfirst!(a::Vector{Any}, @nospecialize x)
1698
    _growbeg!(a, 1)
40,912✔
1699
    @_safeindex a[1] = x
38,929✔
1700
    return a
38,929✔
1701
end
1702
function pushfirst!(a::Vector{Any}, @nospecialize x...)
1703
    @_terminates_locally_meta
×
1704
    na = length(a)
×
1705
    nx = length(x)
×
1706
    _growbeg!(a, nx)
×
1707
    @_safeindex for i = 1:nx
×
1708
        a[i] = x[i]
×
1709
    end
×
1710
    return a
×
1711
end
1712

1713
"""
1714
    popfirst!(collection) -> item
1715

1716
Remove the first `item` from `collection`.
1717

1718
This function is called `shift` in many other programming languages.
1719

1720
See also: [`pop!`](@ref), [`popat!`](@ref), [`delete!`](@ref).
1721

1722
# Examples
1723
```jldoctest
1724
julia> A = [1, 2, 3, 4, 5, 6]
1725
6-element Vector{Int64}:
1726
 1
1727
 2
1728
 3
1729
 4
1730
 5
1731
 6
1732

1733
julia> popfirst!(A)
1734
1
1735

1736
julia> A
1737
5-element Vector{Int64}:
1738
 2
1739
 3
1740
 4
1741
 5
1742
 6
1743
```
1744
"""
1745
function popfirst!(a::Vector)
45✔
1746
    if isempty(a)
130,286✔
1747
        _throw_argerror("array must be non-empty")
×
1748
    end
1749
    item = a[1]
130,286✔
1750
    _deletebeg!(a, 1)
130,286✔
1751
    return item
130,286✔
1752
end
1753

1754
"""
1755
    insert!(a::Vector, index::Integer, item)
1756

1757
Insert an `item` into `a` at the given `index`. `index` is the index of `item` in
1758
the resulting `a`.
1759

1760
See also: [`push!`](@ref), [`replace`](@ref), [`popat!`](@ref), [`splice!`](@ref).
1761

1762
# Examples
1763
```jldoctest
1764
julia> insert!(Any[1:6;], 3, "here")
1765
7-element Vector{Any}:
1766
 1
1767
 2
1768
  "here"
1769
 3
1770
 4
1771
 5
1772
 6
1773
```
1774
"""
1775
function insert!(a::Array{T,1}, i::Integer, item) where T
1776
    @_propagate_inbounds_meta
×
1777
    item = item isa T ? item : convert(T, item)::T
×
1778
    return _insert!(a, i, item)
57,584✔
1779
end
1780
function _insert!(a::Array{T,1}, i::Integer, item::T) where T
1781
    @_noub_meta
×
1782
    # Throw convert error before changing the shape of the array
1783
    _growat!(a, i, 1)
57,584✔
1784
    # :noub, because _growat! already did bound check
1785
    @inbounds a[i] = item
57,584✔
1786
    return a
42,928✔
1787
end
1788

1789
"""
1790
    deleteat!(a::Vector, i::Integer)
1791

1792
Remove the item at the given `i` and return the modified `a`. Subsequent items
1793
are shifted to fill the resulting gap.
1794

1795
See also: [`keepat!`](@ref), [`delete!`](@ref), [`popat!`](@ref), [`splice!`](@ref).
1796

1797
# Examples
1798
```jldoctest
1799
julia> deleteat!([6, 5, 4, 3, 2, 1], 2)
1800
5-element Vector{Int64}:
1801
 6
1802
 4
1803
 3
1804
 2
1805
 1
1806
```
1807
"""
1808
function deleteat!(a::Vector, i::Integer)
1809
    i isa Bool && depwarn("passing Bool as an index is deprecated", :deleteat!)
×
1810
    _deleteat!(a, i, 1)
7,154✔
1811
    return a
×
1812
end
1813

1814
function deleteat!(a::Vector, r::AbstractUnitRange{<:Integer})
1815
    if eltype(r) === Bool
1✔
1816
        return invoke(deleteat!, Tuple{Vector, AbstractVector{Bool}}, a, r)
×
1817
    else
1818
        n = length(a)
1✔
1819
        f = first(r)
1✔
1820
        f isa Bool && depwarn("passing Bool as an index is deprecated", :deleteat!)
1✔
1821
        isempty(r) || _deleteat!(a, f, length(r))
31✔
1822
        return a
16✔
1823
    end
1824
end
1825

1826
"""
1827
    deleteat!(a::Vector, inds)
1828

1829
Remove the items at the indices given by `inds`, and return the modified `a`.
1830
Subsequent items are shifted to fill the resulting gap.
1831

1832
`inds` can be either an iterator or a collection of sorted and unique integer indices,
1833
or a boolean vector of the same length as `a` with `true` indicating entries to delete.
1834

1835
# Examples
1836
```jldoctest
1837
julia> deleteat!([6, 5, 4, 3, 2, 1], 1:2:5)
1838
3-element Vector{Int64}:
1839
 5
1840
 3
1841
 1
1842

1843
julia> deleteat!([6, 5, 4, 3, 2, 1], [true, false, true, false, true, false])
1844
3-element Vector{Int64}:
1845
 5
1846
 3
1847
 1
1848

1849
julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2))
1850
ERROR: ArgumentError: indices must be unique and sorted
1851
Stacktrace:
1852
[...]
1853
```
1854
"""
1855
deleteat!(a::Vector, inds) = _deleteat!(a, inds)
×
1856
deleteat!(a::Vector, inds::AbstractVector) = _deleteat!(a, to_indices(a, (inds,))[1])
90✔
1857

1858
struct Nowhere; end
1859
push!(::Nowhere, _) = nothing
×
1860
_growend!(::Nowhere, _) = nothing
×
1861

1862
function _push_deleted!(dltd, a::Vector, ind)
1863
    @_propagate_inbounds_meta
×
1864
    if isassigned(a, ind)
86✔
1865
        push!(dltd, a[ind])
86✔
1866
    else
1867
        _growend!(dltd, 1)
×
1868
    end
1869
end
1870

1871
function _copy_item!(a::Vector, p, q)
1872
    @_propagate_inbounds_meta
×
1873
    if isassigned(a, q)
48✔
1874
        a[p] = a[q]
48✔
1875
    else
1876
        _unsetindex!(a, p)
×
1877
    end
1878
end
1879

1880
function _deleteat!(a::Vector, inds, dltd=Nowhere())
90✔
1881
    n = length(a)
180✔
1882
    y = iterate(inds)
90✔
1883
    y === nothing && return a
90✔
1884
    (p, s) = y
×
1885
    checkbounds(a, p)
86✔
1886
    @inbounds _push_deleted!(dltd, a, p)
86✔
1887
    q = p+1
86✔
1888
    while true
86✔
1889
        y = iterate(inds, s)
86✔
1890
        y === nothing && break
86✔
1891
        (i,s) = y
×
1892
        if !(q <= i <= n)
×
1893
            if i < q
×
1894
                _throw_argerror("indices must be unique and sorted")
×
1895
            else
1896
                throw(BoundsError())
×
1897
            end
1898
        end
1899
        while q < i
×
1900
            @inbounds _copy_item!(a, p, q)
×
1901
            p += 1; q += 1
×
1902
        end
×
1903
        @inbounds _push_deleted!(dltd, a, i)
×
1904
        q = i+1
×
1905
    end
×
1906
    while q <= n
134✔
1907
        @inbounds _copy_item!(a, p, q)
48✔
1908
        p += 1; q += 1
48✔
1909
    end
48✔
1910
    _deleteend!(a, n-p+1)
86✔
1911
    return a
86✔
1912
end
1913

1914
# Simpler and more efficient version for logical indexing
1915
function deleteat!(a::Vector, inds::AbstractVector{Bool})
×
1916
    n = length(a)
×
1917
    length(inds) == n || throw(BoundsError(a, inds))
×
1918
    p = 1
×
1919
    for (q, i) in enumerate(inds)
×
1920
        @inbounds _copy_item!(a, p, q)
×
1921
        p += !i
×
1922
    end
×
1923
    _deleteend!(a, n-p+1)
×
1924
    return a
×
1925
end
1926

1927
const _default_splice = []
1928

1929
"""
1930
    splice!(a::Vector, index::Integer, [replacement]) -> item
1931

1932
Remove the item at the given index, and return the removed item.
1933
Subsequent items are shifted left to fill the resulting gap.
1934
If specified, replacement values from an ordered
1935
collection will be spliced in place of the removed item.
1936

1937
See also: [`replace`](@ref), [`delete!`](@ref), [`deleteat!`](@ref), [`pop!`](@ref), [`popat!`](@ref).
1938

1939
# Examples
1940
```jldoctest
1941
julia> A = [6, 5, 4, 3, 2, 1]; splice!(A, 5)
1942
2
1943

1944
julia> A
1945
5-element Vector{Int64}:
1946
 6
1947
 5
1948
 4
1949
 3
1950
 1
1951

1952
julia> splice!(A, 5, -1)
1953
1
1954

1955
julia> A
1956
5-element Vector{Int64}:
1957
  6
1958
  5
1959
  4
1960
  3
1961
 -1
1962

1963
julia> splice!(A, 1, [-1, -2, -3])
1964
6
1965

1966
julia> A
1967
7-element Vector{Int64}:
1968
 -1
1969
 -2
1970
 -3
1971
  5
1972
  4
1973
  3
1974
 -1
1975
```
1976

1977
To insert `replacement` before an index `n` without removing any items, use
1978
`splice!(collection, n:n-1, replacement)`.
1979
"""
1980
function splice!(a::Vector, i::Integer, ins=_default_splice)
×
1981
    v = a[i]
×
1982
    m = length(ins)
×
1983
    if m == 0
×
1984
        _deleteat!(a, i, 1)
×
1985
    elseif m == 1
×
1986
        a[i] = only(ins)
×
1987
    else
1988
        _growat!(a, i, m-1)
×
1989
        k = 1
×
1990
        for x in ins
×
1991
            a[i+k-1] = x
×
1992
            k += 1
×
1993
        end
×
1994
    end
1995
    return v
×
1996
end
1997

1998
"""
1999
    splice!(a::Vector, indices, [replacement]) -> items
2000

2001
Remove items at specified indices, and return a collection containing
2002
the removed items.
2003
Subsequent items are shifted left to fill the resulting gaps.
2004
If specified, replacement values from an ordered collection will be spliced in
2005
place of the removed items; in this case, `indices` must be a `AbstractUnitRange`.
2006

2007
To insert `replacement` before an index `n` without removing any items, use
2008
`splice!(collection, n:n-1, replacement)`.
2009

2010
$(_DOCS_ALIASING_WARNING)
2011

2012
!!! compat "Julia 1.5"
2013
    Prior to Julia 1.5, `indices` must always be a `UnitRange`.
2014

2015
!!! compat "Julia 1.8"
2016
    Prior to Julia 1.8, `indices` must be a `UnitRange` if splicing in replacement values.
2017

2018
# Examples
2019
```jldoctest
2020
julia> A = [-1, -2, -3, 5, 4, 3, -1]; splice!(A, 4:3, 2)
2021
Int64[]
2022

2023
julia> A
2024
8-element Vector{Int64}:
2025
 -1
2026
 -2
2027
 -3
2028
  2
2029
  5
2030
  4
2031
  3
2032
 -1
2033
```
2034
"""
2035
function splice!(a::Vector, r::AbstractUnitRange{<:Integer}, ins=_default_splice)
14,396✔
2036
    v = a[r]
14,396✔
2037
    m = length(ins)
×
2038
    if m == 0
×
2039
        deleteat!(a, r)
×
2040
        return v
×
2041
    end
2042

2043
    n = length(a)
14,396✔
2044
    f = first(r)
14,396✔
2045
    l = last(r)
14,396✔
2046
    d = length(r)
14,396✔
2047

2048
    if m < d
14,396✔
2049
        delta = d - m
×
2050
        _deleteat!(a, (f - 1 < n - l) ? f : (l - delta + 1), delta)
×
2051
    elseif m > d
14,396✔
2052
        _growat!(a, (f - 1 < n - l) ? f : (l + 1), m - d)
14,396✔
2053
    end
2054

2055
    k = 1
×
2056
    for x in ins
14,396✔
2057
        a[f+k-1] = x
43,188✔
2058
        k += 1
43,188✔
2059
    end
57,584✔
2060
    return v
14,396✔
2061
end
2062

2063
splice!(a::Vector, inds) = (dltds = eltype(a)[]; _deleteat!(a, inds, dltds); dltds)
×
2064

2065
function empty!(a::Vector)
3✔
2066
    _deleteend!(a, length(a))
108,244✔
2067
    return a
96,988✔
2068
end
2069

2070
# use memcmp for cmp on byte arrays
2071
function cmp(a::Array{UInt8,1}, b::Array{UInt8,1})
×
2072
    aref = a.ref
×
2073
    bref = b.ref
×
2074
    ta = @_gc_preserve_begin aref
×
2075
    tb = @_gc_preserve_begin bref
×
2076
    pa = unsafe_convert(Ptr{Cvoid}, aref)
×
2077
    pb = unsafe_convert(Ptr{Cvoid}, bref)
×
2078
    c = memcmp(pa, pb, min(length(a),length(b)))
×
2079
    @_gc_preserve_end ta
×
2080
    @_gc_preserve_end tb
×
2081
    return c < 0 ? -1 : c > 0 ? +1 : cmp(length(a),length(b))
×
2082
end
2083

2084
const BitIntegerArray{N} = Union{map(T->Array{T,N}, BitInteger_types)...} where N
×
2085
# use memcmp for == on bit integer types
2086
function ==(a::Arr, b::Arr) where {Arr <: BitIntegerArray}
×
2087
    if size(a) == size(b)
×
2088
        aref = a.ref
×
2089
        bref = b.ref
×
2090
        ta = @_gc_preserve_begin aref
×
2091
        tb = @_gc_preserve_begin bref
×
2092
        pa = unsafe_convert(Ptr{Cvoid}, aref)
×
2093
        pb = unsafe_convert(Ptr{Cvoid}, bref)
×
2094
        c = memcmp(pa, pb, sizeof(eltype(Arr)) * length(a))
×
2095
        @_gc_preserve_end ta
×
2096
        @_gc_preserve_end tb
×
2097
        return c == 0
×
2098
    else
2099
        return false
×
2100
    end
2101
end
2102

2103
function ==(a::Arr, b::Arr) where Arr <: BitIntegerArray{1}
2104
    len = length(a)
20,230✔
2105
    if len == length(b)
20,230✔
2106
        aref = a.ref
20,230✔
2107
        bref = b.ref
20,230✔
2108
        ta = @_gc_preserve_begin aref
20,230✔
2109
        tb = @_gc_preserve_begin bref
20,230✔
2110
        T = eltype(Arr)
×
2111
        pa = unsafe_convert(Ptr{T}, aref)
20,230✔
2112
        pb = unsafe_convert(Ptr{T}, bref)
20,230✔
2113
        c = memcmp(pa, pb, sizeof(T) * len)
20,230✔
2114
        @_gc_preserve_end ta
20,230✔
2115
        @_gc_preserve_end tb
20,230✔
2116
        return c == 0
20,230✔
2117
    else
2118
        return false
×
2119
    end
2120
end
2121

2122
"""
2123
    reverse(v [, start=firstindex(v) [, stop=lastindex(v) ]] )
2124

2125
Return a copy of `v` reversed from start to stop.  See also [`Iterators.reverse`](@ref)
2126
for reverse-order iteration without making a copy, and in-place [`reverse!`](@ref).
2127

2128
# Examples
2129
```jldoctest
2130
julia> A = Vector(1:5)
2131
5-element Vector{Int64}:
2132
 1
2133
 2
2134
 3
2135
 4
2136
 5
2137

2138
julia> reverse(A)
2139
5-element Vector{Int64}:
2140
 5
2141
 4
2142
 3
2143
 2
2144
 1
2145

2146
julia> reverse(A, 1, 4)
2147
5-element Vector{Int64}:
2148
 4
2149
 3
2150
 2
2151
 1
2152
 5
2153

2154
julia> reverse(A, 3, 5)
2155
5-element Vector{Int64}:
2156
 1
2157
 2
2158
 5
2159
 4
2160
 3
2161
```
2162
"""
2163
function reverse(A::AbstractVector, start::Integer, stop::Integer=lastindex(A))
×
2164
    s, n = Int(start), Int(stop)
×
2165
    B = similar(A)
×
2166
    for i = firstindex(A):s-1
×
2167
        B[i] = A[i]
×
2168
    end
×
2169
    for i = s:n
×
2170
        B[i] = A[n+s-i]
×
2171
    end
×
2172
    for i = n+1:lastindex(A)
×
2173
        B[i] = A[i]
×
2174
    end
×
2175
    return B
×
2176
end
2177

2178
# 1d special cases of reverse(A; dims) and reverse!(A; dims):
2179
for (f,_f) in ((:reverse,:_reverse), (:reverse!,:_reverse!))
2180
    @eval begin
2181
        $f(A::AbstractVector; dims=:) = $_f(A, dims)
110,614✔
2182
        $_f(A::AbstractVector, ::Colon) = $f(A, firstindex(A), lastindex(A))
7,672✔
2183
        $_f(A::AbstractVector, dim::Tuple{Integer}) = $_f(A, first(dim))
×
2184
        function $_f(A::AbstractVector, dim::Integer)
×
2185
            dim == 1 || _throw_argerror(LazyString("invalid dimension ", dim, " ≠ 1"))
×
2186
            return $_f(A, :)
×
2187
        end
2188
    end
2189
end
2190

2191
function reverseind(a::AbstractVector, i::Integer)
×
2192
    li = LinearIndices(a)
×
2193
    first(li) + last(li) - i
×
2194
end
2195

2196
# This implementation of `midpoint` is performance-optimized but safe
2197
# only if `lo <= hi`.
2198
midpoint(lo::T, hi::T) where T<:Integer = lo + ((hi - lo) >>> 0x01)
29,024✔
2199
midpoint(lo::Integer, hi::Integer) = midpoint(promote(lo, hi)...)
×
2200

2201
"""
2202
    reverse!(v [, start=firstindex(v) [, stop=lastindex(v) ]]) -> v
2203

2204
In-place version of [`reverse`](@ref).
2205

2206
# Examples
2207
```jldoctest
2208
julia> A = Vector(1:5)
2209
5-element Vector{Int64}:
2210
 1
2211
 2
2212
 3
2213
 4
2214
 5
2215

2216
julia> reverse!(A);
2217

2218
julia> A
2219
5-element Vector{Int64}:
2220
 5
2221
 4
2222
 3
2223
 2
2224
 1
2225
```
2226
"""
2227
function reverse!(v::AbstractVector, start::Integer, stop::Integer=lastindex(v))
71,902✔
2228
    s, n = Int(start), Int(stop)
64,244✔
2229
    if n > s # non-empty and non-trivial
71,902✔
2230
        liv = LinearIndices(v)
20,710✔
2231
        if !(first(liv) ≤ s ≤ last(liv))
20,710✔
2232
            throw(BoundsError(v, s))
×
2233
        elseif !(first(liv) ≤ n ≤ last(liv))
20,710✔
2234
            throw(BoundsError(v, n))
×
2235
        end
2236
        r = n
549✔
2237
        @inbounds for i in s:midpoint(s, n-1)
20,710✔
2238
            v[i], v[r] = v[r], v[i]
23,397✔
2239
            r -= 1
23,397✔
2240
        end
26,084✔
2241
    end
2242
    return v
71,902✔
2243
end
2244

2245
# concatenations of (in)homogeneous combinations of vectors, horizontal and vertical
2246

2247
vcat() = Vector{Any}()
×
2248
hcat() = Vector{Any}()
×
2249

2250
function hcat(V::Vector{T}...) where T
×
2251
    height = length(V[1])
×
2252
    for j = 2:length(V)
×
2253
        if length(V[j]) != height
×
2254
            throw(DimensionMismatch("vectors must have same lengths"))
×
2255
        end
2256
    end
×
2257
    return [ V[j][i]::T for i=1:length(V[1]), j=1:length(V) ]
×
2258
end
2259
hcat(A::Vector...) = cat(A...; dims=Val(2)) # more special than SparseArrays's hcat
×
2260

2261
function vcat(arrays::Vector{T}...) where T
168✔
2262
    n = 0
168✔
2263
    for a in arrays
168✔
2264
        n += length(a)
492✔
2265
    end
658✔
2266
    arr = Vector{T}(undef, n)
168✔
2267
    nd = 1
168✔
2268
    for a in arrays
168✔
2269
        na = length(a)
492✔
2270
        @assert nd + na <= 1 + length(arr) # Concurrent modification of arrays?
492✔
2271
        unsafe_copyto!(arr, nd, a, 1, na)
734✔
2272
        nd += na
492✔
2273
    end
658✔
2274
    return arr
168✔
2275
end
2276
vcat(A::Vector...) = cat(A...; dims=Val(1)) # more special than SparseArrays's vcat
1✔
2277

2278
_cat(n::Integer, x::Integer...) = reshape([x...], (ntuple(Returns(1), n-1)..., length(x)))
×
2279

2280
## find ##
2281

2282
"""
2283
    findnext(A, i)
2284

2285
Find the next index after or including `i` of a `true` element of `A`,
2286
or `nothing` if not found.
2287

2288
Indices are of the same type as those returned by [`keys(A)`](@ref)
2289
and [`pairs(A)`](@ref).
2290

2291
# Examples
2292
```jldoctest
2293
julia> A = [false, false, true, false]
2294
4-element Vector{Bool}:
2295
 0
2296
 0
2297
 1
2298
 0
2299

2300
julia> findnext(A, 1)
2301
3
2302

2303
julia> findnext(A, 4) # returns nothing, but not printed in the REPL
2304

2305
julia> A = [false false; true false]
2306
2×2 Matrix{Bool}:
2307
 0  0
2308
 1  0
2309

2310
julia> findnext(A, CartesianIndex(1, 1))
2311
CartesianIndex(2, 1)
2312
```
2313
"""
2314
findnext(A, start) = findnext(identity, A, start)
×
2315

2316
"""
2317
    findfirst(A)
2318

2319
Return the index or key of the first `true` value in `A`.
2320
Return `nothing` if no such value is found.
2321
To search for other kinds of values, pass a predicate as the first argument.
2322

2323
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
2324
and [`pairs(A)`](@ref).
2325

2326
See also: [`findall`](@ref), [`findnext`](@ref), [`findlast`](@ref), [`searchsortedfirst`](@ref).
2327

2328
# Examples
2329
```jldoctest
2330
julia> A = [false, false, true, false]
2331
4-element Vector{Bool}:
2332
 0
2333
 0
2334
 1
2335
 0
2336

2337
julia> findfirst(A)
2338
3
2339

2340
julia> findfirst(falses(3)) # returns nothing, but not printed in the REPL
2341

2342
julia> A = [false false; true false]
2343
2×2 Matrix{Bool}:
2344
 0  0
2345
 1  0
2346

2347
julia> findfirst(A)
2348
CartesianIndex(2, 1)
2349
```
2350
"""
2351
findfirst(A) = findfirst(identity, A)
×
2352

2353
# Needed for bootstrap, and allows defining only an optimized findnext method
2354
findfirst(A::AbstractArray) = findnext(A, first(keys(A)))
74✔
2355

2356
"""
2357
    findnext(predicate::Function, A, i)
2358

2359
Find the next index after or including `i` of an element of `A`
2360
for which `predicate` returns `true`, or `nothing` if not found. This works for
2361
Arrays, Strings, and most other collections that support [`getindex`](@ref),
2362
[`keys(A)`](@ref), and [`nextind`](@ref).
2363

2364
Indices are of the same type as those returned by [`keys(A)`](@ref)
2365
and [`pairs(A)`](@ref).
2366

2367
# Examples
2368
```jldoctest
2369
julia> A = [1, 4, 2, 2];
2370

2371
julia> findnext(isodd, A, 1)
2372
1
2373

2374
julia> findnext(isodd, A, 2) # returns nothing, but not printed in the REPL
2375

2376
julia> A = [1 4; 2 2];
2377

2378
julia> findnext(isodd, A, CartesianIndex(1, 1))
2379
CartesianIndex(1, 1)
2380

2381
julia> findnext(isspace, "a b c", 3)
2382
4
2383
```
2384
"""
2385
function findnext(testf::Function, A, start)
×
2386
    i = oftype(first(keys(A)), start)
×
2387
    l = last(keys(A))
97,592✔
2388
    i > l && return nothing
97,592✔
2389
    while true
99,229✔
2390
        testf(A[i]) && return i
112,959✔
2391
        i == l && break
90,721✔
2392
        # nextind(A, l) can throw/overflow
2393
        i = nextind(A, i)
50,004✔
2394
    end
50,004✔
2395
    return nothing
40,717✔
2396
end
2397

2398
"""
2399
    findfirst(predicate::Function, A)
2400

2401
Return the index or key of the first element of `A` for which `predicate` returns `true`.
2402
Return `nothing` if there is no such element.
2403

2404
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
2405
and [`pairs(A)`](@ref).
2406

2407
# Examples
2408
```jldoctest
2409
julia> A = [1, 4, 2, 2]
2410
4-element Vector{Int64}:
2411
 1
2412
 4
2413
 2
2414
 2
2415

2416
julia> findfirst(iseven, A)
2417
2
2418

2419
julia> findfirst(x -> x>10, A) # returns nothing, but not printed in the REPL
2420

2421
julia> findfirst(isequal(4), A)
2422
2
2423

2424
julia> A = [1 4; 2 2]
2425
2×2 Matrix{Int64}:
2426
 1  4
2427
 2  2
2428

2429
julia> findfirst(iseven, A)
2430
CartesianIndex(2, 1)
2431
```
2432
"""
2433
function findfirst(testf::Function, A)
1✔
2434
    for (i, a) in pairs(A)
1✔
2435
        testf(a) && return i
×
2436
    end
×
2437
    return nothing
1✔
2438
end
2439

2440
# Needed for bootstrap, and allows defining only an optimized findnext method
2441
findfirst(testf::Function, A::Union{AbstractArray, AbstractString}) =
582,005✔
2442
    findnext(testf, A, first(keys(A)))
2443

2444
findfirst(p::Union{Fix2{typeof(isequal),T},Fix2{typeof(==),T}}, r::OneTo) where {T<:Integer} =
×
2445
    1 <= p.x <= r.stop ? convert(keytype(r), p.x) : nothing
2446

2447
findfirst(::typeof(iszero), ::OneTo) = nothing
×
2448
findfirst(::typeof(isone), r::OneTo) = isempty(r) ? nothing : oneunit(keytype(r))
×
2449

2450
function findfirst(p::Union{Fix2{typeof(isequal),T},Fix2{typeof(==),T}}, r::AbstractUnitRange{<:Integer}) where {T<:Integer}
×
2451
    first(r) <= p.x <= last(r) || return nothing
×
2452
    i1 = first(keys(r))
×
2453
    return i1 + oftype(i1, p.x - first(r))
×
2454
end
2455

2456
function findfirst(p::Union{Fix2{typeof(isequal),T},Fix2{typeof(==),T}}, r::StepRange{T,S}) where {T,S}
×
2457
    isempty(r) && return nothing
×
2458
    minimum(r) <= p.x <= maximum(r) || return nothing
×
2459
    d = p.x - first(r)
×
2460
    iszero(d % step(r)) || return nothing
×
2461
    return convert(keytype(r), d ÷ step(r) + 1)
×
2462
end
2463

2464
findfirst(::typeof(iszero), r::AbstractRange) = findfirst(==(zero(first(r))), r)
×
2465
findfirst(::typeof(isone), r::AbstractRange) = findfirst(==(one(first(r))), r)
×
2466

2467
"""
2468
    findprev(A, i)
2469

2470
Find the previous index before or including `i` of a `true` element of `A`,
2471
or `nothing` if not found.
2472

2473
Indices are of the same type as those returned by [`keys(A)`](@ref)
2474
and [`pairs(A)`](@ref).
2475

2476
See also: [`findnext`](@ref), [`findfirst`](@ref), [`findall`](@ref).
2477

2478
# Examples
2479
```jldoctest
2480
julia> A = [false, false, true, true]
2481
4-element Vector{Bool}:
2482
 0
2483
 0
2484
 1
2485
 1
2486

2487
julia> findprev(A, 3)
2488
3
2489

2490
julia> findprev(A, 1) # returns nothing, but not printed in the REPL
2491

2492
julia> A = [false false; true true]
2493
2×2 Matrix{Bool}:
2494
 0  0
2495
 1  1
2496

2497
julia> findprev(A, CartesianIndex(2, 1))
2498
CartesianIndex(2, 1)
2499
```
2500
"""
2501
findprev(A, start) = findprev(identity, A, start)
×
2502

2503
"""
2504
    findlast(A)
2505

2506
Return the index or key of the last `true` value in `A`.
2507
Return `nothing` if there is no `true` value in `A`.
2508

2509
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
2510
and [`pairs(A)`](@ref).
2511

2512
See also: [`findfirst`](@ref), [`findprev`](@ref), [`findall`](@ref).
2513

2514
# Examples
2515
```jldoctest
2516
julia> A = [true, false, true, false]
2517
4-element Vector{Bool}:
2518
 1
2519
 0
2520
 1
2521
 0
2522

2523
julia> findlast(A)
2524
3
2525

2526
julia> A = falses(2,2);
2527

2528
julia> findlast(A) # returns nothing, but not printed in the REPL
2529

2530
julia> A = [true false; true false]
2531
2×2 Matrix{Bool}:
2532
 1  0
2533
 1  0
2534

2535
julia> findlast(A)
2536
CartesianIndex(2, 1)
2537
```
2538
"""
2539
findlast(A) = findlast(identity, A)
×
2540

2541
# Needed for bootstrap, and allows defining only an optimized findprev method
2542
findlast(A::AbstractArray) = findprev(A, last(keys(A)))
241✔
2543

2544
"""
2545
    findprev(predicate::Function, A, i)
2546

2547
Find the previous index before or including `i` of an element of `A`
2548
for which `predicate` returns `true`, or `nothing` if not found. This works for
2549
Arrays, Strings, and most other collections that support [`getindex`](@ref),
2550
[`keys(A)`](@ref), and [`nextind`](@ref).
2551

2552
Indices are of the same type as those returned by [`keys(A)`](@ref)
2553
and [`pairs(A)`](@ref).
2554

2555
# Examples
2556
```jldoctest
2557
julia> A = [4, 6, 1, 2]
2558
4-element Vector{Int64}:
2559
 4
2560
 6
2561
 1
2562
 2
2563

2564
julia> findprev(isodd, A, 1) # returns nothing, but not printed in the REPL
2565

2566
julia> findprev(isodd, A, 3)
2567
3
2568

2569
julia> A = [4 6; 1 2]
2570
2×2 Matrix{Int64}:
2571
 4  6
2572
 1  2
2573

2574
julia> findprev(isodd, A, CartesianIndex(1, 2))
2575
CartesianIndex(2, 1)
2576

2577
julia> findprev(isspace, "a b c", 3)
2578
2
2579
```
2580
"""
2581
function findprev(testf::Function, A, start)
92✔
2582
    f = first(keys(A))
92✔
2583
    i = oftype(f, start)
92✔
2584
    i < f && return nothing
153✔
2585
    while true
552✔
2586
        testf(A[i]) && return i
817✔
2587
        i == f && break
400✔
2588
        # prevind(A, f) can throw/underflow
2589
        i = prevind(A, i)
399✔
2590
    end
399✔
2591
    return nothing
1✔
2592
end
2593

2594
"""
2595
    findlast(predicate::Function, A)
2596

2597
Return the index or key of the last element of `A` for which `predicate` returns `true`.
2598
Return `nothing` if there is no such element.
2599

2600
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
2601
and [`pairs(A)`](@ref).
2602

2603
# Examples
2604
```jldoctest
2605
julia> A = [1, 2, 3, 4]
2606
4-element Vector{Int64}:
2607
 1
2608
 2
2609
 3
2610
 4
2611

2612
julia> findlast(isodd, A)
2613
3
2614

2615
julia> findlast(x -> x > 5, A) # returns nothing, but not printed in the REPL
2616

2617
julia> A = [1 2; 3 4]
2618
2×2 Matrix{Int64}:
2619
 1  2
2620
 3  4
2621

2622
julia> findlast(isodd, A)
2623
CartesianIndex(2, 1)
2624
```
2625
"""
2626
function findlast(testf::Function, A)
×
2627
    for (i, a) in Iterators.reverse(pairs(A))
×
2628
        testf(a) && return i
×
2629
    end
×
2630
    return nothing
×
2631
end
2632

2633
# Needed for bootstrap, and allows defining only an optimized findprev method
2634
findlast(testf::Function, A::Union{AbstractArray, AbstractString}) =
403✔
2635
    findprev(testf, A, last(keys(A)))
2636

2637
# for monotonic ranges, there is a unique index corresponding to a value, so findfirst and findlast are identical
2638
function findlast(p::Union{Fix2{typeof(isequal),<:Integer},Fix2{typeof(==),<:Integer},typeof(iszero),typeof(isone)},
×
2639
        r::AbstractUnitRange{<:Integer})
2640
    findfirst(p, r)
×
2641
end
2642

2643
function findlast(p::Union{Fix2{typeof(isequal),T},Fix2{typeof(==),T},typeof(iszero),typeof(isone)},
×
2644
        r::StepRange{T,S}) where {T,S}
2645
    findfirst(p, r)
×
2646
end
2647

2648
"""
2649
    findall(f::Function, A)
2650

2651
Return a vector `I` of the indices or keys of `A` where `f(A[I])` returns `true`.
2652
If there are no such elements of `A`, return an empty array.
2653

2654
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
2655
and [`pairs(A)`](@ref).
2656

2657
# Examples
2658
```jldoctest
2659
julia> x = [1, 3, 4]
2660
3-element Vector{Int64}:
2661
 1
2662
 3
2663
 4
2664

2665
julia> findall(isodd, x)
2666
2-element Vector{Int64}:
2667
 1
2668
 2
2669

2670
julia> A = [1 2 0; 3 4 0]
2671
2×3 Matrix{Int64}:
2672
 1  2  0
2673
 3  4  0
2674
julia> findall(isodd, A)
2675
2-element Vector{CartesianIndex{2}}:
2676
 CartesianIndex(1, 1)
2677
 CartesianIndex(2, 1)
2678

2679
julia> findall(!iszero, A)
2680
4-element Vector{CartesianIndex{2}}:
2681
 CartesianIndex(1, 1)
2682
 CartesianIndex(2, 1)
2683
 CartesianIndex(1, 2)
2684
 CartesianIndex(2, 2)
2685

2686
julia> d = Dict(:A => 10, :B => -1, :C => 0)
2687
Dict{Symbol, Int64} with 3 entries:
2688
  :A => 10
2689
  :B => -1
2690
  :C => 0
2691

2692
julia> findall(≥(0), d)
2693
2-element Vector{Symbol}:
2694
 :A
2695
 :C
2696

2697
```
2698
"""
2699
function findall(testf::Function, A)
×
2700
    gen = (first(p) for p in pairs(A) if testf(last(p)))
×
2701
    @default_eltype(gen) === Union{} ? collect(@default_eltype(keys(A)), gen) : collect(gen)
×
2702
end
2703

2704
# Broadcasting is much faster for small testf, and computing
2705
# integer indices from logical index using findall has a negligible cost
2706
findall(testf::F, A::AbstractArray) where {F<:Function} = findall(testf.(A))
9✔
2707

2708
"""
2709
    findall(A)
2710

2711
Return a vector `I` of the `true` indices or keys of `A`.
2712
If there are no such elements of `A`, return an empty array.
2713
To search for other kinds of values, pass a predicate as the first argument.
2714

2715
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
2716
and [`pairs(A)`](@ref).
2717

2718
See also: [`findfirst`](@ref), [`searchsorted`](@ref).
2719

2720
# Examples
2721
```jldoctest
2722
julia> A = [true, false, false, true]
2723
4-element Vector{Bool}:
2724
 1
2725
 0
2726
 0
2727
 1
2728

2729
julia> findall(A)
2730
2-element Vector{Int64}:
2731
 1
2732
 4
2733

2734
julia> A = [true false; false true]
2735
2×2 Matrix{Bool}:
2736
 1  0
2737
 0  1
2738

2739
julia> findall(A)
2740
2-element Vector{CartesianIndex{2}}:
2741
 CartesianIndex(1, 1)
2742
 CartesianIndex(2, 2)
2743

2744
julia> findall(falses(3))
2745
Int64[]
2746
```
2747
"""
2748
function findall(A)
×
2749
    collect(first(p) for p in pairs(A) if last(p))
×
2750
end
2751

2752
# Allocating result upfront is faster (possible only when collection can be iterated twice)
2753
function findall(A::AbstractArray{Bool})
×
2754
    n = count(A)
×
2755
    I = Vector{eltype(keys(A))}(undef, n)
×
2756
    cnt = 1
×
2757
    for (i,a) in pairs(A)
×
2758
        if a
×
2759
            I[cnt] = i
×
2760
            cnt += 1
×
2761
        end
2762
    end
×
2763
    I
×
2764
end
2765

2766
findall(x::Bool) = x ? [1] : Vector{Int}()
×
2767
findall(testf::Function, x::Number) = testf(x) ? [1] : Vector{Int}()
×
2768
findall(p::Fix2{typeof(in)}, x::Number) = x in p.x ? [1] : Vector{Int}()
×
2769

2770
# similar to Matlab's ismember
2771
"""
2772
    indexin(a, b)
2773

2774
Return an array containing the first index in `b` for
2775
each value in `a` that is a member of `b`. The output
2776
array contains `nothing` wherever `a` is not a member of `b`.
2777

2778
See also: [`sortperm`](@ref), [`findfirst`](@ref).
2779

2780
# Examples
2781
```jldoctest
2782
julia> a = ['a', 'b', 'c', 'b', 'd', 'a'];
2783

2784
julia> b = ['a', 'b', 'c'];
2785

2786
julia> indexin(a, b)
2787
6-element Vector{Union{Nothing, Int64}}:
2788
 1
2789
 2
2790
 3
2791
 2
2792
  nothing
2793
 1
2794

2795
julia> indexin(b, a)
2796
3-element Vector{Union{Nothing, Int64}}:
2797
 1
2798
 2
2799
 3
2800
```
2801
"""
2802
function indexin(a, b::AbstractArray)
×
2803
    inds = keys(b)
×
2804
    bdict = Dict{eltype(b),eltype(inds)}()
×
2805
    for (val, ind) in zip(b, inds)
×
2806
        get!(bdict, val, ind)
×
2807
    end
×
2808
    return Union{eltype(inds), Nothing}[
×
2809
        get(bdict, i, nothing) for i in a
2810
    ]
2811
end
2812

2813
function _findin(a::Union{AbstractArray, Tuple}, b::AbstractSet)
×
2814
    ind  = Vector{eltype(keys(a))}()
×
2815
    @inbounds for (i,ai) in pairs(a)
×
2816
        ai in b && push!(ind, i)
×
2817
    end
×
2818
    ind
×
2819
end
2820
_findin(a::Union{AbstractArray, Tuple}, b) = _findin(a, Set(b))
×
2821

2822
# If two collections are already sorted, _findin can be computed with
2823
# a single traversal of the two collections. This is much faster than
2824
# using a hash table (although it has the same complexity).
2825
function _sortedfindin(v::Union{AbstractArray, Tuple}, w)
×
2826
    viter, witer = keys(v), eachindex(w)
×
2827
    out  = eltype(viter)[]
×
2828
    vy, wy = iterate(viter), iterate(witer)
×
2829
    if vy === nothing || wy === nothing
×
2830
        return out
×
2831
    end
2832
    viteri, i = vy
×
2833
    witerj, j = wy
×
2834
    @inbounds begin
×
2835
        vi, wj = v[viteri], w[witerj]
×
2836
        while true
×
2837
            if isless(vi, wj)
×
2838
                vy = iterate(viter, i)
×
2839
                if vy === nothing
×
2840
                    break
×
2841
                end
2842
                viteri, i = vy
×
2843
                vi        = v[viteri]
×
2844
            elseif isless(wj, vi)
×
2845
                wy = iterate(witer, j)
×
2846
                if wy === nothing
×
2847
                    break
×
2848
                end
2849
                witerj, j = wy
×
2850
                wj        = w[witerj]
×
2851
            else
2852
                push!(out, viteri)
×
2853
                vy = iterate(viter, i)
×
2854
                if vy === nothing
×
2855
                    break
×
2856
                end
2857
                # We only increment the v iterator because v can have
2858
                # repeated matches to a single value in w
2859
                viteri, i = vy
×
2860
                vi        = v[viteri]
×
2861
            end
2862
        end
×
2863
    end
2864
    return out
×
2865
end
2866

2867
function findall(pred::Fix2{typeof(in),<:Union{Array{<:Real},Real}}, x::Array{<:Real})
×
2868
    if issorted(x, Sort.Forward) && issorted(pred.x, Sort.Forward)
×
2869
        return _sortedfindin(x, pred.x)
×
2870
    else
2871
        return _findin(x, pred.x)
×
2872
    end
2873
end
2874
# issorted fails for some element types so the method above has to be restricted
2875
# to element with isless/< defined.
2876
findall(pred::Fix2{typeof(in)}, x::AbstractArray) = _findin(x, pred.x)
×
2877
findall(pred::Fix2{typeof(in)}, x::Tuple) = _findin(x, pred.x)
×
2878

2879
# Copying subregions
2880
function indcopy(sz::Dims, I::Vector)
×
2881
    n = length(I)
×
2882
    s = sz[n]
×
2883
    for i = n+1:length(sz)
×
2884
        s *= sz[i]
×
2885
    end
×
2886
    dst = eltype(I)[_findin(I[i], i < n ? (1:sz[i]) : (1:s)) for i = 1:n]
×
2887
    src = eltype(I)[I[i][_findin(I[i], i < n ? (1:sz[i]) : (1:s))] for i = 1:n]
×
2888
    dst, src
×
2889
end
2890

2891
function indcopy(sz::Dims, I::Tuple{Vararg{RangeIndex}})
×
2892
    n = length(I)
×
2893
    s = sz[n]
×
2894
    for i = n+1:length(sz)
×
2895
        s *= sz[i]
×
2896
    end
×
2897
    dst::typeof(I) = ntuple(i-> _findin(I[i], i < n ? (1:sz[i]) : (1:s)), n)::typeof(I)
×
2898
    src::typeof(I) = ntuple(i-> I[i][_findin(I[i], i < n ? (1:sz[i]) : (1:s))], n)::typeof(I)
×
2899
    dst, src
×
2900
end
2901

2902
## Filter ##
2903

2904
"""
2905
    filter(f, a)
2906

2907
Return a copy of collection `a`, removing elements for which `f` is `false`.
2908
The function `f` is passed one argument.
2909

2910
!!! compat "Julia 1.4"
2911
    Support for `a` as a tuple requires at least Julia 1.4.
2912

2913
See also: [`filter!`](@ref), [`Iterators.filter`](@ref).
2914

2915
# Examples
2916
```jldoctest
2917
julia> a = 1:10
2918
1:10
2919

2920
julia> filter(isodd, a)
2921
5-element Vector{Int64}:
2922
 1
2923
 3
2924
 5
2925
 7
2926
 9
2927
```
2928
"""
2929
function filter(f, a::Array{T, N}) where {T, N}
116✔
2930
    j = 1
116✔
2931
    b = Vector{T}(undef, length(a))
116✔
2932
    for ai in a
116✔
2933
        @inbounds b[j] = ai
615✔
2934
        j = ifelse(f(ai)::Bool, j+1, j)
633✔
2935
    end
615✔
2936
    resize!(b, j-1)
116✔
2937
    sizehint!(b, length(b))
116✔
2938
    b
116✔
2939
end
2940

2941
function filter(f, a::AbstractArray)
×
2942
    (IndexStyle(a) != IndexLinear()) && return a[map(f, a)::AbstractArray{Bool}]
×
2943

2944
    j = 1
×
2945
    idxs = Vector{Int}(undef, length(a))
×
2946
    for idx in eachindex(a)
×
2947
        @inbounds idxs[j] = idx
×
2948
        ai = @inbounds a[idx]
×
2949
        j = ifelse(f(ai)::Bool, j+1, j)
×
2950
    end
×
2951
    resize!(idxs, j-1)
×
2952
    res = a[idxs]
×
2953
    empty!(idxs)
×
2954
    sizehint!(idxs, 0)
×
2955
    return res
×
2956
end
2957

2958
"""
2959
    filter!(f, a)
2960

2961
Update collection `a`, removing elements for which `f` is `false`.
2962
The function `f` is passed one argument.
2963

2964
# Examples
2965
```jldoctest
2966
julia> filter!(isodd, Vector(1:10))
2967
5-element Vector{Int64}:
2968
 1
2969
 3
2970
 5
2971
 7
2972
 9
2973
```
2974
"""
2975
function filter!(f, a::AbstractVector)
38,062✔
2976
    j = firstindex(a)
143✔
2977
    for ai in a
99,193✔
2978
        @inbounds a[j] = ai
186,828✔
2979
        j = ifelse(f(ai)::Bool, nextind(a, j), j)
186,900✔
2980
    end
186,828✔
2981
    j > lastindex(a) && return a
99,193✔
2982
    if a isa Vector
42✔
2983
        resize!(a, j-1)
135✔
2984
        sizehint!(a, j-1)
135✔
2985
    else
2986
        deleteat!(a, j:lastindex(a))
×
2987
    end
2988
    return a
135✔
2989
end
2990

2991
"""
2992
    filter(f)
2993

2994
Create a function that filters its arguments with function `f` using [`filter`](@ref), i.e.
2995
a function equivalent to `x -> filter(f, x)`.
2996

2997
The returned function is of type `Base.Fix1{typeof(filter)}`, which can be
2998
used to implement specialized methods.
2999

3000
# Examples
3001
```jldoctest
3002
julia> (1, 2, Inf, 4, NaN, 6) |> filter(isfinite)
3003
(1, 2, 4, 6)
3004

3005
julia> map(filter(iseven), [1:3, 2:4, 3:5])
3006
3-element Vector{Vector{Int64}}:
3007
 [2]
3008
 [2, 4]
3009
 [4]
3010
```
3011
!!! compat "Julia 1.9"
3012
    This method requires at least Julia 1.9.
3013
"""
3014
function filter(f)
×
3015
    Fix1(filter, f)
×
3016
end
3017

3018
"""
3019
    keepat!(a::Vector, inds)
3020
    keepat!(a::BitVector, inds)
3021

3022
Remove the items at all the indices which are not given by `inds`,
3023
and return the modified `a`.
3024
Items which are kept are shifted to fill the resulting gaps.
3025

3026
$(_DOCS_ALIASING_WARNING)
3027

3028
`inds` must be an iterator of sorted and unique integer indices.
3029
See also [`deleteat!`](@ref).
3030

3031
!!! compat "Julia 1.7"
3032
    This function is available as of Julia 1.7.
3033

3034
# Examples
3035
```jldoctest
3036
julia> keepat!([6, 5, 4, 3, 2, 1], 1:2:5)
3037
3-element Vector{Int64}:
3038
 6
3039
 4
3040
 2
3041
```
3042
"""
3043
keepat!(a::Vector, inds) = _keepat!(a, inds)
×
3044

3045
"""
3046
    keepat!(a::Vector, m::AbstractVector{Bool})
3047
    keepat!(a::BitVector, m::AbstractVector{Bool})
3048

3049
The in-place version of logical indexing `a = a[m]`. That is, `keepat!(a, m)` on
3050
vectors of equal length `a` and `m` will remove all elements from `a` for which
3051
`m` at the corresponding index is `false`.
3052

3053
# Examples
3054
```jldoctest
3055
julia> a = [:a, :b, :c];
3056

3057
julia> keepat!(a, [true, false, true])
3058
2-element Vector{Symbol}:
3059
 :a
3060
 :c
3061

3062
julia> a
3063
2-element Vector{Symbol}:
3064
 :a
3065
 :c
3066
```
3067
"""
3068
keepat!(a::Vector, m::AbstractVector{Bool}) = _keepat!(a, m)
×
3069

3070
# set-like operators for vectors
3071
# These are moderately efficient, preserve order, and remove dupes.
3072

3073
_unique_filter!(pred::P, update!::U, state) where {P,U} = function (x)
98✔
3074
    # P, U force specialization
3075
    if pred(x, state)
314✔
3076
        update!(state, x)
81✔
3077
        true
3078
    else
3079
        false
3080
    end
3081
end
3082

3083
_grow_filter!(seen) = _unique_filter!(∉, push!, seen)
2✔
3084
_shrink_filter!(keep) = _unique_filter!(∈, pop!, keep)
85✔
3085

3086
function _grow!(pred!, v::AbstractVector, itrs)
×
3087
    filter!(pred!, v) # uniquify v
2✔
3088
    for itr in itrs
2✔
3089
        mapfilter(pred!, push!, itr, v)
4✔
3090
    end
6✔
3091
    return v
2✔
3092
end
3093

3094
union!(v::AbstractVector{T}, itrs...) where {T} =
2✔
3095
    _grow!(_grow_filter!(sizehint!(Set{T}(), length(v))), v, itrs)
3096

3097
symdiff!(v::AbstractVector{T}, itrs...) where {T} =
×
3098
    _grow!(_shrink_filter!(symdiff!(Set{T}(), v, itrs...)), v, itrs)
3099

3100
function _shrink!(shrinker!::F, v::AbstractVector, itrs) where F
×
3101
    seen = Set{eltype(v)}()
×
3102
    filter!(_grow_filter!(seen), v)
×
3103
    shrinker!(seen, itrs...)
×
3104
    filter!(in(seen), v)
×
3105
end
3106

3107
intersect!(v::AbstractVector, itrs...) = _shrink!(intersect!, v, itrs)
×
3108
setdiff!(  v::AbstractVector, itrs...) = _shrink!(setdiff!, v, itrs)
×
3109

3110
vectorfilter(T::Type, f, v) = T[x for x in v if f(x)]
85✔
3111

3112
function _shrink(shrinker!::F, itr, itrs) where F
85✔
3113
    T = promote_eltype(itr, itrs...)
85✔
3114
    keep = shrinker!(Set{T}(itr), itrs...)
85✔
3115
    vectorfilter(T, _shrink_filter!(keep), itr)
85✔
3116
end
3117

3118
intersect(itr, itrs...) = _shrink(intersect!, itr, itrs)
80✔
3119
setdiff(  itr, itrs...) = _shrink(setdiff!, itr, itrs)
5✔
3120

3121
function intersect(v::AbstractVector, r::AbstractRange)
×
3122
    T = promote_eltype(v, r)
×
3123
    common = Iterators.filter(in(r), v)
×
3124
    seen = Set{T}(common)
×
3125
    return vectorfilter(T, _shrink_filter!(seen), common)
×
3126
end
3127
intersect(r::AbstractRange, v::AbstractVector) = intersect(v, r)
×
3128

3129
# Here instead of range.jl for bootstrapping because `@propagate_inbounds` depends on Vectors.
3130
@propagate_inbounds function getindex(v::AbstractRange, i::Integer)
50✔
3131
    if i isa Bool # Not via dispatch to avoid ambiguities
114✔
3132
        throw(ArgumentError("invalid index: $i of type Bool"))
×
3133
    else
3134
        _getindex(v, i)
789,418✔
3135
    end
3136
end
3137

3138
"""
3139
    wrap(Array, m::Union{Memory{T}, MemoryRef{T}}, dims)
3140

3141
Create an array of size `dims` using `m` as the underlying memory. This can be thought of as a safe version
3142
of [`unsafe_wrap`](@ref) utilizing `Memory` or `MemoryRef` instead of raw pointers.
3143
"""
3144
function wrap end
3145

3146
# validity checking for _wrap calls, separate from allocation of Array so that it can be more likely to inline into the caller
3147
function _wrap(ref::MemoryRef{T}, dims::NTuple{N, Int}) where {T, N}
3148
    mem = ref.mem
5,545✔
3149
    mem_len = length(mem) + 1 - memoryrefoffset(ref)
5,545✔
3150
    len = Core.checked_dims(dims...)
×
3151
    @boundscheck mem_len >= len || invalid_wrap_err(mem_len, dims, len)
5,545✔
3152
    return ref
×
3153
end
3154

3155
@noinline invalid_wrap_err(len, dims, proddims) = throw(DimensionMismatch(LazyString(
×
3156
    "Attempted to wrap a MemoryRef of length ", len, " with an Array of size dims=", dims,
3157
    " which is invalid because prod(dims) = ", proddims, " > ", len,
3158
    " so that the array would have more elements than the underlying memory can store.")))
3159

3160
@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, dims::NTuple{N, Integer}) where {T, N}
×
3161
    dims = convert(Dims, dims)
×
3162
    ref = _wrap(m, dims)
×
3163
    $(Expr(:new, :(Array{T, N}), :ref, :dims))
×
3164
end
3165

3166
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, dims::NTuple{N, Integer}) where {T, N}
×
3167
    dims = convert(Dims, dims)
×
3168
    ref = _wrap(memoryref(m), dims)
×
3169
    $(Expr(:new, :(Array{T, N}), :ref, :dims))
×
3170
end
3171
@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, l::Integer) where {T}
3172
    dims = (Int(l),)
5,545✔
3173
    ref = _wrap(m, dims)
5,545✔
3174
    $(Expr(:new, :(Array{T, 1}), :ref, :dims))
60✔
3175
end
3176
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, l::Integer) where {T}
×
3177
    dims = (Int(l),)
×
3178
    ref = _wrap(memoryref(m), (l,))
×
3179
    $(Expr(:new, :(Array{T, 1}), :ref, :dims))
×
3180
end
3181
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}) where {T}
3182
    ref = memoryref(m)
1,379✔
3183
    dims = (length(m),)
1,379✔
3184
    $(Expr(:new, :(Array{T, 1}), :ref, :dims))
1,379✔
3185
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc