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

JuliaLang / julia / #37999

02 Feb 2025 07:22AM UTC coverage: 17.218% (-8.3%) from 25.515%
#37999

push

local

web-flow
bpart: Start tracking backedges for bindings (#57213)

This PR adds limited backedge support for Bindings. There are two
classes of bindings that get backedges:

1. Cross-module `GlobalRef` bindings (new in this PR)
2. Any globals accesses through intrinsics (i.e. those with forward
edges from #57009)

This is a time/space trade-off for invalidation. As a result of the
first category, invalidating a binding now only needs to scan all the
methods defined in the same module as the binding. At the same time, it
is anticipated that most binding references are to bindings in the same
module, keeping the list of bindings that need explicit (back)edges
small.

7 of 30 new or added lines in 3 files covered. (23.33%)

4235 existing lines in 124 files now uncovered.

7882 of 45779 relevant lines covered (17.22%)

98289.89 hits per line

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

43.97
/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}()
410✔
159
function vect(X::T...) where T
20✔
160
    @_terminates_locally_meta
295✔
161
    vec = Vector{T}(undef, length(X))
2,764✔
162
    @_safeindex for i = 1:length(X)
2,237✔
163
        vec[i] = X[i]
5,515✔
164
    end
6,273✔
165
    return vec
790✔
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,177✔
192
    return d > length(sz) ? 1 : getfield(sz, d, false) # @inbounds
1,177✔
193
end
194
size(a::Array) = getfield(a, :size)
1,985,563✔
195

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

UNCOV
198
allocatedinline(@nospecialize T::Type) = (@_total_meta; ccall(:jl_stored_inline, Cint, (Any,), T) != Cint(0))
×
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
"""
UNCOV
214
isbitsunion(u::Type) = u isa Union && allocatedinline(u)
×
215

UNCOV
216
function _unsetindex!(A::Array, i::Int)
×
217
    @inline
37,686✔
218
    @boundscheck checkbounds(A, i)
147,284✔
219
    @inbounds _unsetindex!(memoryref(A.ref, i))
149,784✔
220
    return A
147,284✔
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,035✔
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

UNCOV
245
function isassigned(a::Vector, i::Int) # slight compiler simplification for the most common case
×
246
    @inline
1✔
247
    @_noub_if_noinbounds_meta
1✔
248
    @boundscheck checkbounds(Bool, a, i) || return false
60✔
249
    return @inbounds isassigned(memoryrefnew(a.ref, i, false))
60✔
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))
255,836✔
269
    return dest
29,802✔
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
574✔
284
    unsafe_copyto!(memoryref(dest.ref, doffs), memoryref(src.ref, soffs), n)
598✔
285
    return dest
299✔
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)
131✔
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)
511,351✔
300

301
function _copyto_impl!(dest::Union{Array,Memory}, doffs::Integer, src::Union{Array,Memory}, soffs::Integer, n::Integer)
302
    n == 0 && return dest
255,846✔
303
    n > 0 || _throw_argerror("Number of elements to copy must be non-negative.")
255,637✔
304
    @boundscheck checkbounds(dest, doffs:doffs+n-1)
255,637✔
305
    @boundscheck checkbounds(src, soffs:soffs+n-1)
255,637✔
306
    @inbounds let dest = memoryref(dest isa Array ? getfield(dest, :ref) : dest, doffs),
255,637✔
307
                  src = memoryref(src isa Array ? getfield(src, :ref) : src, soffs)
308
        unsafe_copyto!(dest, src, n)
511,274✔
309
    end
310
    return dest
255,637✔
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))
1,573✔
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
327
    @inline
126✔
328
    x = x isa T ? x : convert(T, x)::T
126✔
329
    return _fill!(dest, x)
1,272✔
330
end
331
function _fill!(dest::Array{T}, x::T) where T
332
    for i in eachindex(dest)
126✔
333
        @inbounds dest[i] = x
1,272✔
334
    end
2,418✔
335
    return dest
126✔
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)
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
×
353
    ref = a.ref
65,402✔
354
    newmem = typeof(ref.mem)(undef, length(a))
65,402✔
355
    @inbounds unsafe_copyto!(memoryref(newmem), ref, length(a))
130,700✔
356
    return $(Expr(:new, :(typeof(a)), :(memoryref(newmem)), :(a.size)))
65,402✔
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)
387✔
362
        setfield!(dst, :ref, getfield(src, :ref))
×
363
    end
364
    if getfield(dst, :size) !== getfield(src, :size)
387✔
365
        setfield!(dst, :size, getfield(src, :size))
177✔
366
    end
367
    return dst
387✔
368
end
369

370
## Constructors ##
371

372
similar(a::Array{T,1}) where {T}                    = Vector{T}(undef, size(a,1))
1,134✔
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))
40✔
375
similar(a::Array{T,2}, S::Type) where {T}           = Matrix{S}(undef, size(a,1), size(a,2))
×
UNCOV
376
similar(a::Array{T}, m::Int) where {T}              = Vector{T}(undef, m)
×
377
similar(a::Array, T::Type, dims::Dims{N}) where {N} = Array{T,N}(undef, dims)
504,967✔
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
1✔
403
    @inline
475✔
404
    @_effect_free_terminates_locally_meta
475✔
405
    a = Vector{T}(undef, length(vals))
132,198✔
406
    if vals isa NTuple
475✔
407
        @_safeindex for i in 1:length(vals)
132✔
408
            a[i] = vals[i]
521✔
409
        end
5✔
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
475✔
418
end
419

420
function getindex(::Type{Any}, @nospecialize vals...)
421
    @_effect_free_terminates_locally_meta
1✔
422
    a = Vector{Any}(undef, length(vals))
136✔
423
    @_safeindex for i = 1:length(vals)
45✔
424
        a[i] = vals[i]
216✔
425
    end
85✔
426
    return a
5✔
427
end
428
getindex(::Type{Any}) = Vector{Any}()
249✔
429

430
function fill!(a::Union{Array{UInt8}, Array{Int8}}, x::Integer)
431
    ref = a.ref
65,161✔
432
    t = @_gc_preserve_begin ref
65,161✔
433
    p = unsafe_convert(Ptr{Cvoid}, ref)
65,161✔
434
    memset(p, x isa eltype(a) ? x : convert(eltype(a), x), length(a) % UInt)
65,161✔
435
    @_gc_preserve_end t
65,161✔
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)
1,272✔
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)
1,272✔
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)
65,161✔
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}
595
            a = Array{T,N}(undef, dims)
65,161✔
596
            fill!(a, $felt(T))
65,161✔
597
            return a
61✔
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
127✔
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)
127✔
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))
100✔
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
100✔
646
    a = Vector{T}()
100✔
647
    for x in itr
117✔
648
        push!(a, x)
30✔
649
    end
43✔
650
    return a
100✔
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
13,109✔
658
_similar_shape(itr, ::HasShape) = axes(itr)
986✔
659

660
_similar_for(c::AbstractArray, ::Type{T}, itr, ::SizeUnknown, ::Nothing) where {T} =
3✔
661
    similar(c, T, 0)
662
_similar_for(c::AbstractArray, ::Type{T}, itr, ::HasLength, len::Integer) where {T} =
13,091✔
663
    similar(c, T, len)
664
_similar_for(c::AbstractArray, ::Type{T}, itr, ::HasShape, axs) where {T} =
182✔
665
    similar(c, T, axs)
666

667
# make a collection appropriate for collecting `itr::Generator`
UNCOV
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))
18✔
670
_array_for(::Type{T}, ::HasShape{N}, axs) where {T,N} = similar(Array{T,N}, axs)
804✔
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))
143✔
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))
266,422✔
729

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

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

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

737
function _collect(cont, itr, ::HasEltype, isz::SizeUnknown)
3✔
738
    a = _similar_for(cont, eltype(itr), itr, isz, nothing)
3✔
739
    for x in itr
3✔
740
        push!(a,x)
16✔
741
    end
16✔
742
    return a
3✔
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
751✔
775
            T = ($I).f
78✔
776
        else
777
            T = Base._return_type(_iterator_upper_bound, Tuple{typeof($I)})
673✔
778
        end
779
        promote_typejoin_union(T)
751✔
780
    end
781
end
782

783
function collect(itr::Generator)
1,104✔
784
    isz = IteratorSize(itr.iter)
489✔
785
    et = @default_eltype(itr)
786
    if isa(isz, SizeUnknown)
489✔
787
        return grow_to!(Vector{et}(), itr)
626✔
788
    else
789
        shp = _similar_shape(itr, isz)
679✔
790
        y = iterate(itr)
1,355✔
791
        if y === nothing
679✔
792
            return _array_for(et, isz, shp)
3✔
793
        end
794
        v1, st = y
486✔
795
        dest = _array_for(typeof(v1), isz, shp)
676✔
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
676✔
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})
180✔
808
    et = @default_eltype(itr)
178✔
809
    shp = _similar_shape(itr, isz)
182✔
810
    y = iterate(itr)
361✔
811
    if y === nothing
182✔
UNCOV
812
        return _similar_for(c, et, itr, isz, shp)
×
813
    end
814
    v1, st = y
180✔
815
    dest = _similar_for(c, typeof(v1), itr, isz, shp)
182✔
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
178✔
819
    RT = dest isa AbstractArray ? AbstractArray{<:et′, ndims(dest)} : Any
178✔
820
    collect_to_with_first!(dest, v1, itr, st)::RT
182✔
821
end
822

823
function collect_to_with_first!(dest::AbstractArray, v1, itr, st)
7✔
824
    i1 = first(LinearIndices(dest))
24✔
825
    dest[i1] = v1
858✔
826
    return collect_to!(dest, itr, i1+1, st)
2,639✔
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

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

843
function collect_to!(dest::AbstractArray{T}, itr, offs, st) where T
400✔
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
408✔
847
    while true
6,529✔
848
        y = iterate(itr, st)
12,185✔
849
        y === nothing && break
6,529✔
850
        el, st = y
3,890✔
851
        if el isa T
3,884✔
852
            @inbounds dest[i] = el
5,671✔
853
            i += 1
5,671✔
854
        else
UNCOV
855
            new = setindex_widen_up_to(dest, el, i)
×
UNCOV
856
            return collect_to!(new, itr, i+1, st)
×
857
        end
858
    end
5,671✔
859
    return dest
858✔
860
end
861

862
function grow_to!(dest, itr)
2✔
863
    y = iterate(itr)
4✔
864
    y === nothing && return dest
3✔
865
    dest2 = empty(dest, typeof(y[1]))
1✔
866
    push!(dest2, y[1])
1✔
867
    grow_to!(dest2, itr, y[2])
1✔
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)
3,041,243✔
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})
934
    @inline
×
935
    @boundscheck checkbounds(A, I)
504,521✔
936
    lI = length(I)
504,521✔
937
    X = similar(A, axes(I))
504,521✔
938
    if lI > 0
504,521✔
939
        copyto!(X, firstindex(X), A, first(I), lI)
505,456✔
940
    end
941
    return X
504,521✔
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

UNCOV
947
function getindex(A::Array, c::Colon)
×
UNCOV
948
    lI = length(A)
×
UNCOV
949
    X = similar(A, lI)
×
UNCOV
950
    if lI > 0
×
UNCOV
951
        unsafe_copyto!(X, 1, A, 1, lI)
×
952
    end
UNCOV
953
    return X
×
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}
383✔
984
    @_propagate_inbounds_meta
267,465✔
985
    x = x isa T ? x : convert(T, x)::T
267,475✔
986
    return _setindex!(A, x, i)
23,183,895✔
987
end
988
function _setindex!(A::Array{T}, x::T, i::Int) where {T}
989
    @_noub_if_noinbounds_meta
267,465✔
990
    @boundscheck (i - 1)%UInt < length(A)%UInt || throw_boundserror(A, (i,))
23,184,310✔
991
    memoryrefset!(memoryrefnew(A.ref, i, false), x, :not_atomic, false)
23,184,310✔
992
    return A
23,184,310✔
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;
24✔
1008
    memoryrefset!(memoryrefnew(A.ref, i, false), x, :not_atomic, false); return A)
1,276✔
1009
__safe_setindex!(A::Vector{T}, x::T, i::Int) where {T} = (@inline; @_nothrow_noub_meta;
679✔
1010
    memoryrefset!(memoryrefnew(A.ref, i, false), x, :not_atomic, false); return A)
173,601✔
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))
1✔
1018
    @boundscheck checkbounds(A, I)
1✔
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′
1✔
UNCOV
1024
        @inbounds A[i] = X′[count]
×
UNCOV
1025
        count += 1
×
UNCOV
1026
    end
×
1027
    return A
1✔
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)
1056
    maxsize < 8 && return 8;
1,990✔
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)
240✔
1063
    maxsize += (1 << div(exp2 * 7, 8)) * 4 + div(maxsize, 8)
240✔
1064
    return maxsize
240✔
1065
end
1066

1067
array_new_memory(mem::Memory, newlen::Int) = typeof(mem)(undef, newlen) # when implemented, this should attempt to first expand mem
2,037✔
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
2✔
UNCOV
1073
    delta >= 0 || throw(ArgumentError("grow requires delta >= 0"))
×
1074
    ref = a.ref
1✔
1075
    mem = ref.mem
1✔
1076
    len = length(a)
1✔
1077
    offset = memoryrefoffset(ref)
1✔
1078
    newlen = len + delta
1✔
1079
    setfield!(a, :size, (newlen,))
1✔
1080
    # if offset is far enough advanced to fit data in existing memory without copying
1081
    if delta <= offset - 1
1✔
UNCOV
1082
        setfield!(a, :ref, @inbounds memoryref(ref, 1 - delta))
×
1083
    else
1084
        @noinline (function()
2✔
1085
        @_terminates_locally_meta
1✔
1086
        memlen = length(mem)
1✔
1087
        if offset + len - 1 > memlen || offset < 1
2✔
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)
1✔
1093
        newoffset = div(newmemlen - newlen, 2) + 1
1✔
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
1✔
UNCOV
1099
            newoffset = div(memlen - newlen, 2) + 1
×
UNCOV
1100
            newmem = mem
×
UNCOV
1101
            unsafe_copyto!(newmem, newoffset + delta, mem, offset, len)
×
UNCOV
1102
            for j in offset:newoffset+delta-1
×
UNCOV
1103
                @inbounds _unsetindex!(mem, j)
×
UNCOV
1104
            end
×
1105
        else
1106
            newmem = array_new_memory(mem, newmemlen)
1✔
1107
            unsafe_copyto!(newmem, newoffset + delta, mem, offset, len)
1✔
1108
        end
1109
        if ref !== a.ref
1✔
1110
            @noinline throw(ConcurrencyViolationError("Vector can not be resized concurrently"))
×
1111
        end
1112
        setfield!(a, :ref, @inbounds memoryref(newmem, newoffset))
1✔
1113
        end)()
1114
    end
1115
    return
1✔
1116
end
1117

1118
function _growend!(a::Vector, delta::Integer)
3✔
1119
    @_noub_meta
693✔
1120
    delta = Int(delta)
693✔
1121
    delta >= 0 || throw(ArgumentError("grow requires delta >= 0"))
2,292✔
1122
    ref = a.ref
170,266✔
1123
    mem = ref.mem
170,266✔
1124
    memlen = length(mem)
170,266✔
1125
    len = length(a)
170,266✔
1126
    newlen = len + delta
170,266✔
1127
    offset = memoryrefoffset(ref)
170,266✔
1128
    setfield!(a, :size, (newlen,))
170,266✔
1129
    newmemlen = offset + newlen - 1
170,266✔
1130
    if memlen < newmemlen
170,266✔
1131
        @noinline (function()
10,070✔
1132
        if offset + len - 1 > memlen || offset < 1
6,080✔
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)
3,040✔
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
1,051✔
1142
            newoffset = div(newlen, 8) + 1
1,051✔
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)
2,229✔
1148
            newmem = array_new_memory(mem, newmemlen2)
1,989✔
1149
            newoffset = offset
1,989✔
1150
        end
1151
        newref = @inbounds memoryref(newmem, newoffset)
3,040✔
1152
        unsafe_copyto!(newref, ref, len)
4,332✔
1153
        if ref !== a.ref
3,040✔
1154
            @noinline throw(ConcurrencyViolationError("Vector can not be resized concurrently"))
×
1155
        end
1156
        setfield!(a, :ref, newref)
3,040✔
1157
        end)()
1158
    end
1159
    return
170,266✔
1160
end
1161

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

1179
    # which side would we rather grow into?
UNCOV
1180
    prefer_start = i <= div(len, 2)
×
1181
    # if offset is far enough advanced to fit data in beginning of the memory
UNCOV
1182
    if prefer_start && delta <= offset - 1
×
UNCOV
1183
        newref = @inbounds memoryref(mem, offset - delta)
×
UNCOV
1184
        unsafe_copyto!(newref, ref, i)
×
UNCOV
1185
        setfield!(a, :ref, newref)
×
UNCOV
1186
        for j in i:i+delta-1
×
UNCOV
1187
            @inbounds _unsetindex!(a, j)
×
UNCOV
1188
        end
×
UNCOV
1189
    elseif !prefer_start && memlen >= newmemlen
×
UNCOV
1190
        unsafe_copyto!(mem, offset - 1 + delta + i, mem, offset - 1 + i, len - i + 1)
×
UNCOV
1191
        for j in i:i+delta-1
×
UNCOV
1192
            @inbounds _unsetindex!(a, j)
×
UNCOV
1193
        end
×
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.
UNCOV
1197
        newmemlen = max(overallocation(memlen), len+2*delta+1)
×
UNCOV
1198
        newoffset = (newmemlen - newlen) ÷ 2 + 1
×
UNCOV
1199
        newmem = array_new_memory(mem, newmemlen)
×
UNCOV
1200
        newref = @inbounds memoryref(newmem, newoffset)
×
UNCOV
1201
        unsafe_copyto!(newref, ref, i-1)
×
UNCOV
1202
        unsafe_copyto!(newmem, newoffset + delta + i - 1, mem, offset + i - 1, len - i + 1)
×
UNCOV
1203
        setfield!(a, :ref, newref)
×
1204
    end
1205
end
1206

1207
# efficiently delete part of an array
1208
function _deletebeg!(a::Vector, delta::Integer)
38✔
1209
    delta = Int(delta)
37,720✔
1210
    len = length(a)
75,972✔
1211
    0 <= delta <= len || throw(ArgumentError("_deletebeg! requires delta in 0:length(a)"))
75,972✔
1212
    for i in 1:delta
37,741✔
1213
        @inbounds _unsetindex!(a, i)
76,048✔
1214
    end
37,741✔
1215
    newlen = len - delta
75,972✔
1216
    if newlen != 0 # if newlen==0 we could accidentally index past the memory
75,972✔
1217
        newref = @inbounds memoryref(a.ref, delta + 1)
65,066✔
1218
        setfield!(a, :ref, newref)
65,066✔
1219
    end
1220
    setfield!(a, :size, (newlen,))
75,972✔
1221
    return
75,972✔
1222
end
1223
function _deleteend!(a::Vector, delta::Integer)
53✔
1224
    delta = Int(delta)
60✔
1225
    len = length(a)
70,899✔
1226
    0 <= delta <= len || throw(ArgumentError("_deleteend! requires delta in 0:length(a)"))
70,899✔
1227
    newlen = len - delta
70,899✔
1228
    for i in newlen+1:len
71,334✔
1229
        @inbounds _unsetindex!(a, i)
73,736✔
1230
    end
72,160✔
1231
    setfield!(a, :size, (newlen,))
70,899✔
1232
    return
70,899✔
1233
end
1234
function _deleteat!(a::Vector, i::Integer, delta::Integer)
61✔
1235
    i = Int(i)
61✔
1236
    len = length(a)
61✔
1237
    0 <= delta || throw(ArgumentError("_deleteat! requires delta >= 0"))
61✔
1238
    1 <= i <= len || throw(BoundsError(a, i))
61✔
1239
    i + delta <= len + 1 || throw(BoundsError(a, i + delta - 1))
61✔
1240
    newa = a
61✔
1241
    if 2*i + delta <= len
61✔
1242
        unsafe_copyto!(newa, 1 + delta, a, 1, i - 1)
31✔
1243
        _deletebeg!(a, delta)
21✔
1244
    else
1245
        unsafe_copyto!(newa, i, a, i + delta, len + 1 - delta - i)
66✔
1246
        _deleteend!(a, delta)
40✔
1247
    end
1248
    return
61✔
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
155✔
1281
    @inline
669✔
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
2,303✔
1286
    return _push!(a, item)
167,564✔
1287
end
1288
function _push!(a::Vector{T}, item::T) where T
1289
    _growend!(a, 1)
167,564✔
1290
    @_safeindex a[length(a)] = item
167,564✔
1291
    return a
167,564✔
1292
end
1293

1294
# specialize and optimize the single argument case
1295
function push!(a::Vector{Any}, @nospecialize x)
1296
    _growend!(a, 1)
1,100✔
1297
    @_safeindex a[length(a)] = x
1,100✔
1298
    return a
1,100✔
1299
end
UNCOV
1300
function push!(a::Vector{Any}, @nospecialize x...)
×
1301
    @_terminates_locally_meta
×
UNCOV
1302
    na = length(a)
×
1303
    nx = length(x)
×
UNCOV
1304
    _growend!(a, nx)
×
UNCOV
1305
    @_safeindex for i = 1:nx
×
UNCOV
1306
        a[na+i] = x[i]
×
UNCOV
1307
    end
×
UNCOV
1308
    return a
×
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))
1✔
1351
    n = length(items)
1,581✔
1352
    _growend!(a, n)
1,581✔
1353
    copyto!(a, length(a)-n+1, items, firstindex(items), n)
3,079✔
1354
    return a
1,581✔
1355
end
1356

1357
append!(a::AbstractVector, iter) = _append!(a, IteratorSize(iter), iter)
1✔
UNCOV
1358
push!(a::AbstractVector, iter...) = append!(a, iter)
×
1359
append!(a::AbstractVector, iter...) = (for v in iter; append!(a, v); end; return a)
×
1360

UNCOV
1361
function _append!(a::AbstractVector, ::Union{HasLength,HasShape}, iter)
×
UNCOV
1362
    n = Int(length(iter))::Int
×
UNCOV
1363
    i = lastindex(a)
×
UNCOV
1364
    sizehint!(a, length(a) + n; shrink=false)
×
UNCOV
1365
    for item in iter
×
UNCOV
1366
        push!(a, item)
×
UNCOV
1367
    end
×
UNCOV
1368
    a
×
1369
end
UNCOV
1370
function _append!(a::AbstractVector, ::IteratorSize, iter)
×
UNCOV
1371
    for item in iter
×
UNCOV
1372
        push!(a, item)
×
UNCOV
1373
    end
×
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)
2✔
1411
    _growbeg!(a, n)
2✔
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)
2✔
1415
    return a
2✔
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)
934✔
1476
    l = length(a)
978✔
1477
    if nl > l
978✔
1478
        _growend!(a, nl-l)
12✔
1479
    elseif nl != l
966✔
1480
        if nl < 0
52✔
1481
            _throw_argerror("new length must be ≥ 0")
×
1482
        end
1483
        _deleteend!(a, l-nl)
52✔
1484
    end
1485
    return a
978✔
1486
end
1487

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

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

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

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

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

1506
# Notes on the performance model
1507

1508
For types that support `sizehint!`,
1509

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

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

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

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

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

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

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

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

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

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

1583
julia> pop!(A)
1584
3
1585

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

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

1596
julia> pop!(S)
1597
2
1598

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1732
julia> popfirst!(A)
1733
1
1734

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1926
const _default_splice = []
1927

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

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

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

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

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

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

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

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

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

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

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

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

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

2009
$(_DOCS_ALIASING_WARNING)
2010

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

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

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

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

UNCOV
2042
    n = length(a)
×
UNCOV
2043
    f = first(r)
×
UNCOV
2044
    l = last(r)
×
UNCOV
2045
    d = length(r)
×
2046

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

2054
    k = 1
×
UNCOV
2055
    for x in ins
×
UNCOV
2056
        a[f+k-1] = x
×
UNCOV
2057
        k += 1
×
UNCOV
2058
    end
×
UNCOV
2059
    return v
×
2060
end
2061

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

2064
function empty!(a::Vector)
3✔
2065
    _deleteend!(a, length(a))
70,828✔
2066
    return a
70,618✔
2067
end
2068

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2215
julia> reverse!(A);
2216

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

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

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

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

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

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

2279
## find ##
2280

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

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

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

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

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

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

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

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

2315
"""
2316
    findfirst(A)
2317

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

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

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

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

2336
julia> findfirst(A)
2337
3
2338

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

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

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

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

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

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

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

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

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

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

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

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

2380
julia> findnext(isspace, "a b c", 3)
2381
4
2382
```
2383
"""
2384
function findnext(testf::Function, A, start)
2✔
2385
    i = oftype(first(keys(A)), start)
2✔
2386
    l = last(keys(A))
1,464✔
2387
    i > l && return nothing
1,464✔
2388
    while true
13,183✔
2389
        testf(A[i]) && return i
26,855✔
2390
        i == l && break
12,033✔
2391
        # nextind(A, l) can throw/overflow
2392
        i = nextind(A, i)
11,804✔
2393
    end
11,804✔
2394
    return nothing
229✔
2395
end
2396

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2502
"""
2503
    findlast(A)
2504

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

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

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

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

2522
julia> findlast(A)
2523
3
2524

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

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

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

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

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

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

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

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

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

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

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

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

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

2576
julia> findprev(isspace, "a b c", 3)
2577
2
2578
```
2579
"""
2580
function findprev(testf::Function, A, start)
88✔
2581
    f = first(keys(A))
88✔
2582
    i = oftype(f, start)
88✔
2583
    i < f && return nothing
149✔
2584
    while true
526✔
2585
        testf(A[i]) && return i
788✔
2586
        i == f && break
377✔
2587
        # prevind(A, f) can throw/underflow
2588
        i = prevind(A, i)
377✔
2589
    end
377✔
UNCOV
2590
    return nothing
×
2591
end
2592

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2707
"""
2708
    findall(A)
2709

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2901
## Filter ##
2902

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

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

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

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

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

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

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

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

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

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

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

2990
"""
2991
    filter(f)
2992

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

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

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

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

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

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

3025
$(_DOCS_ALIASING_WARNING)
3026

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3165
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, dims::NTuple{N, Integer}) where {T, N}
×
3166
    dims = convert(Dims, dims)
×
3167
    ref = _wrap(memoryref(m), dims)
×
3168
    $(Expr(:new, :(Array{T, N}), :ref, :dims))
×
3169
end
3170
@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, l::Integer) where {T}
3171
    dims = (Int(l),)
5,430✔
3172
    ref = _wrap(m, dims)
5,430✔
UNCOV
3173
    $(Expr(:new, :(Array{T, 1}), :ref, :dims))
×
3174
end
3175
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, l::Integer) where {T}
×
3176
    dims = (Int(l),)
×
3177
    ref = _wrap(memoryref(m), (l,))
×
3178
    $(Expr(:new, :(Array{T, 1}), :ref, :dims))
×
3179
end
3180
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}) where {T}
3181
    ref = memoryref(m)
1,348✔
3182
    dims = (length(m),)
1,348✔
3183
    $(Expr(:new, :(Array{T, 1}), :ref, :dims))
1,348✔
3184
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