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

JuliaLang / julia / #37918

28 Sep 2024 11:02PM UTC coverage: 86.484% (-0.8%) from 87.243%
#37918

push

local

web-flow
add --trim option for generating smaller binaries (#55047)

This adds a command line option `--trim` that builds images where code
is only included if it is statically reachable from methods marked using
the new function `entrypoint`. Compile-time errors are given for call
sites that are too dynamic to allow trimming the call graph (however
there is an `unsafe` option if you want to try building anyway to see
what happens).

The PR has two other components. One is changes to Base that generally
allow more code to be compiled in this mode. These changes will either
be merged in separate PRs or moved to a separate part of the workflow
(where we will build a custom system image for this purpose). The branch
is set up this way to make it easy to check out and try the
functionality.

The other component is everything in the `juliac/` directory, which
implements a compiler driver script based on this new option, along with
some examples and tests. This will eventually become a package "app"
that depends on PackageCompiler and provides a CLI for all of this
stuff, so it will not be merged here. To try an example:

```
julia contrib/juliac.jl --output-exe hello --trim test/trimming/hello.jl
```

When stripped the resulting executable is currently about 900kb on my
machine.

Also includes a lot of work by @topolarity

---------

Co-authored-by: Gabriel Baraldi <baraldigabriel@gmail.com>
Co-authored-by: Tim Holy <tim.holy@gmail.com>
Co-authored-by: Cody Tapscott <topolarity@tapscott.me>

2 of 10 new or added lines in 4 files covered. (20.0%)

1269 existing lines in 41 files now uncovered.

77375 of 89467 relevant lines covered (86.48%)

15490193.44 hits per line

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

93.31
/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
19,538✔
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}()
567,012✔
159
function vect(X::T...) where T
47,785✔
160
    @_terminates_locally_meta
52,794✔
161
    vec = Vector{T}(undef, length(X))
1,520,870✔
162
    @_safeindex for i = 1:length(X)
188,255✔
163
        vec[i] = X[i]
4,573,362✔
164
    end
6,334,300✔
165
    return vec
136,244✔
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...)
52,583✔
184
    T = promote_typeof(X...)
56,325✔
185
    return T[X...]
56,510✔
186
end
187

188
size(a::Array, d::Integer) = size(a, Int(d)::Int)
×
189
function size(a::Array, d::Int)
4,930✔
190
    d < 1 && error("arraysize: dimension out of range")
65,406,853✔
191
    sz = getfield(a, :size)
65,525,860✔
192
    return d > length(sz) ? 1 : getfield(sz, d, false) # @inbounds
89,725,194✔
193
end
194
size(a::Array) = getfield(a, :size)
2,147,483,647✔
195

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

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

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

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

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

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

216
function _unsetindex!(A::Array, i::Int)
217
    @inline
10,999,612✔
218
    @boundscheck checkbounds(A, i)
2,147,483,647✔
219
    @inbounds _unsetindex!(memoryref(A.ref, i))
2,147,483,647✔
220
    return A
2,147,483,647✔
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)
354,536✔
226
function elsize(::Type{Ptr{T}}) where T
8✔
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})
8✔
230
    T isa DataType || sizeof(Any) # throws
7✔
231
    return LLT_ALIGN(Core.sizeof(T), datatype_alignment(T))
5✔
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
34,994✔
236

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

245
function isassigned(a::Vector, i::Int) # slight compiler simplification for the most common case
165✔
246
    @inline
6,100,646✔
247
    @_noub_if_noinbounds_meta
6,100,646✔
248
    @boundscheck checkbounds(Bool, a, i) || return false
2,147,483,647✔
249
    return @inbounds isassigned(memoryrefnew(a.ref, i, false))
2,147,483,647✔
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))
27,268,238✔
269
    return dest
26,487,564✔
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
12,714,429✔
284
    unsafe_copyto!(memoryref(dest.ref, doffs), memoryref(src.ref, soffs), n)
15,579,846✔
285
    return dest
7,789,926✔
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)
60,966✔
295
copyto!(dest::Array, doffs::Integer, src::Memory, soffs::Integer, n::Integer) = _copyto_impl!(dest, doffs, src, soffs, n)
17✔
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)
250,023,422✔
300

301
function _copyto_impl!(dest::Union{Array,Memory}, doffs::Integer, src::Union{Array,Memory}, soffs::Integer, n::Integer)
11✔
302
    n == 0 && return dest
153,342,035✔
303
    n > 0 || _throw_argerror("Number of elements to copy must be non-negative.")
119,720,507✔
304
    @boundscheck checkbounds(dest, doffs:doffs+n-1)
119,720,526✔
305
    @boundscheck checkbounds(src, soffs:soffs+n-1)
119,720,487✔
306
    @inbounds let dest = memoryref(dest isa Array ? getfield(dest, :ref) : dest, doffs),
119,720,491✔
307
                  src = memoryref(src isa Array ? getfield(src, :ref) : src, soffs)
308
        unsafe_copyto!(dest, src, n)
239,440,923✔
309
    end
310
    return dest
119,720,240✔
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)))
10✔
318

319
copyto!(dest::Array, src::Array) = copyto!(dest, 1, src, 1, length(src))
33,756✔
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))
37,017,549✔
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
996✔
327
    xT = x isa T ? x : convert(T, x)::T
264,474✔
328
    for i in eachindex(dest)
841,046,473✔
329
        @inbounds dest[i] = xT
2,147,483,647✔
330
    end
2,147,483,647✔
331
    return dest
841,046,477✔
332
end
333

334
"""
335
    copy(x)
336

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

341
See also [`copy!`](@ref Base.copy!), [`copyto!`](@ref), [`deepcopy`](@ref).
342
"""
343
copy
344

345
@eval function copy(a::Array{T}) where {T}
152,975✔
346
    # `jl_genericmemory_copy_slice` only throws when the size exceeds the max allocation
347
    # size, but since we're copying an existing array, we're guaranteed that this will not happen.
348
    @_nothrow_meta
280,952✔
349
    ref = a.ref
174,207,176✔
350
    newmem = ccall(:jl_genericmemory_copy_slice, Ref{Memory{T}}, (Any, Ptr{Cvoid}, Int), ref.mem, ref.ptr_or_offset, length(a))
174,207,178✔
351
    return $(Expr(:new, :(typeof(a)), :(memoryref(newmem)), :(a.size)))
174,207,050✔
352
end
353

354
## Constructors ##
355

356
similar(a::Array{T,1}) where {T}                    = Vector{T}(undef, size(a,1))
235,209✔
357
similar(a::Array{T,2}) where {T}                    = Matrix{T}(undef, size(a,1), size(a,2))
8,727✔
358
similar(a::Array{T,1}, S::Type) where {T}           = Vector{S}(undef, size(a,1))
16,049✔
359
similar(a::Array{T,2}, S::Type) where {T}           = Matrix{S}(undef, size(a,1), size(a,2))
26,380✔
360
similar(a::Array{T}, m::Int) where {T}              = Vector{T}(undef, m)
4,035,114✔
361
similar(a::Array, T::Type, dims::Dims{N}) where {N} = Array{T,N}(undef, dims)
103,144,360✔
362
similar(a::Array{T}, dims::Dims{N}) where {T,N}     = Array{T,N}(undef, dims)
607✔
363

364
# T[x...] constructs Array{T,1}
365
"""
366
    getindex(type[, elements...])
367

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

371
# Examples
372
```jldoctest
373
julia> Int8[1, 2, 3]
374
3-element Vector{Int8}:
375
 1
376
 2
377
 3
378

379
julia> getindex(Int8, 1, 2, 3)
380
3-element Vector{Int8}:
381
 1
382
 2
383
 3
384
```
385
"""
386
function getindex(::Type{T}, vals...) where T
56,219✔
387
    @inline
185,707✔
388
    @_effect_free_terminates_locally_meta
185,707✔
389
    a = Vector{T}(undef, length(vals))
919,909,059✔
390
    if vals isa NTuple
185,738✔
391
        @_safeindex for i in 1:length(vals)
128,497✔
392
            a[i] = vals[i]
68,788,934✔
393
        end
215,521✔
394
    else
395
        # use afoldl to avoid type instability inside loop
396
        afoldl(1, vals...) do i, v
59,504✔
397
            @inbounds a[i] = v
125,248✔
398
            return i + 1
125,236✔
399
        end
400
    end
401
    return a
188,054✔
402
end
403

404
function getindex(::Type{Any}, @nospecialize vals...)
22,485,412✔
405
    @_effect_free_terminates_locally_meta
7,292✔
406
    a = Vector{Any}(undef, length(vals))
89,498,978✔
407
    @_safeindex for i = 1:length(vals)
29,029,385✔
408
        a[i] = vals[i]
119,182,372✔
409
    end
113,797,680✔
410
    return a
22,616,747✔
411
end
412
getindex(::Type{Any}) = Vector{Any}()
72,889,624✔
413

414
function fill!(a::Union{Array{UInt8}, Array{Int8}}, x::Integer)
5✔
415
    ref = a.ref
11,500,969✔
416
    t = @_gc_preserve_begin ref
11,500,969✔
417
    p = unsafe_convert(Ptr{Cvoid}, ref)
11,500,969✔
418
    memset(p, x isa eltype(a) ? x : convert(eltype(a), x), length(a))
11,500,972✔
419
    @_gc_preserve_end t
11,500,966✔
420
    return a
11,500,966✔
421
end
422

423
to_dim(d::Integer) = d
×
424
to_dim(d::OneTo) = last(d)
212✔
425

426
"""
427
    fill(value, dims::Tuple)
428
    fill(value, dims...)
429

430
Create an array of size `dims` with every location set to `value`.
431

432
For example, `fill(1.0, (5,5))` returns a 5×5 array of floats,
433
with `1.0` in every location of the array.
434

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

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

448
```jldoctest
449
julia> v = fill([], 3)
450
3-element Vector{Vector{Any}}:
451
 []
452
 []
453
 []
454

455
julia> v[1] === v[2] === v[3]
456
true
457

458
julia> value = v[1]
459
Any[]
460

461
julia> push!(value, 867_5309)
462
1-element Vector{Any}:
463
 8675309
464

465
julia> v
466
3-element Vector{Vector{Any}}:
467
 [8675309]
468
 [8675309]
469
 [8675309]
470
```
471

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

475
```jldoctest
476
julia> v2 = [[] for _ in 1:3]
477
3-element Vector{Vector{Any}}:
478
 []
479
 []
480
 []
481

482
julia> v2[1] === v2[2] === v2[3]
483
false
484

485
julia> push!(v2[1], 8675309)
486
1-element Vector{Any}:
487
 8675309
488

489
julia> v2
490
3-element Vector{Vector{Any}}:
491
 [8675309]
492
 []
493
 []
494
```
495

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

498
# Examples
499
```jldoctest
500
julia> fill(1.0, (2,3))
501
2×3 Matrix{Float64}:
502
 1.0  1.0  1.0
503
 1.0  1.0  1.0
504

505
julia> fill(42)
506
0-dimensional Array{Int64, 0}:
507
42
508

509
julia> A = fill(zeros(2), 2) # sets both elements to the same [0.0, 0.0] vector
510
2-element Vector{Vector{Float64}}:
511
 [0.0, 0.0]
512
 [0.0, 0.0]
513

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

516
julia> A # both A[1] and A[2] are the very same vector
517
2-element Vector{Vector{Float64}}:
518
 [42.0, 0.0]
519
 [42.0, 0.0]
520
```
521
"""
522
function fill end
523

524
fill(v, dims::DimOrInd...) = fill(v, dims)
2,147,483,647✔
525
fill(v, dims::NTuple{N, Union{Integer, OneTo}}) where {N} = fill(v, map(to_dim, dims))
×
526
fill(v, dims::NTuple{N, Integer}) where {N} = (a=Array{typeof(v),N}(undef, dims); fill!(a, v); a)
2,147,483,647✔
527
fill(v, dims::NTuple{N, DimOrInd}) where {N} = (a=similar(Array{typeof(v),N}, dims); fill!(a, v); a)
×
528
fill(v, dims::Tuple{}) = (a=Array{typeof(v),0}(undef, dims); fill!(a, v); a)
137✔
529

530
"""
531
    zeros([T=Float64,] dims::Tuple)
532
    zeros([T=Float64,] dims...)
533

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

537
# Examples
538
```jldoctest
539
julia> zeros(1)
540
1-element Vector{Float64}:
541
 0.0
542

543
julia> zeros(Int8, 2, 3)
544
2×3 Matrix{Int8}:
545
 0  0  0
546
 0  0  0
547
```
548
"""
549
function zeros end
550

551
"""
552
    ones([T=Float64,] dims::Tuple)
553
    ones([T=Float64,] dims...)
554

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

558
# Examples
559
```jldoctest
560
julia> ones(1,2)
561
1×2 Matrix{Float64}:
562
 1.0  1.0
563

564
julia> ones(ComplexF64, 2, 3)
565
2×3 Matrix{ComplexF64}:
566
 1.0+0.0im  1.0+0.0im  1.0+0.0im
567
 1.0+0.0im  1.0+0.0im  1.0+0.0im
568
```
569
"""
570
function ones end
571

572
for (fname, felt) in ((:zeros, :zero), (:ones, :one))
573
    @eval begin
574
        $fname(dims::DimOrInd...) = $fname(dims)
447,087✔
575
        $fname(::Type{T}, dims::DimOrInd...) where {T} = $fname(T, dims)
2,147,483,647✔
576
        $fname(dims::Tuple{Vararg{DimOrInd}}) = $fname(Float64, dims)
452,729✔
577
        $fname(::Type{T}, dims::NTuple{N, Union{Integer, OneTo}}) where {T,N} = $fname(T, map(to_dim, dims))
1,264✔
578
        function $fname(::Type{T}, dims::NTuple{N, Integer}) where {T,N}
12,253✔
579
            a = Array{T,N}(undef, dims)
175,447,385✔
580
            fill!(a, $felt(T))
2,147,483,647✔
581
            return a
121,832,699✔
582
        end
583
        function $fname(::Type{T}, dims::Tuple{}) where {T}
584
            a = Array{T}(undef)
20✔
585
            fill!(a, $felt(T))
20✔
586
            return a
20✔
587
        end
588
        function $fname(::Type{T}, dims::NTuple{N, DimOrInd}) where {T,N}
×
589
            a = similar(Array{T,N}, dims)
×
590
            fill!(a, $felt(T))
×
591
            return a
×
592
        end
593
    end
594
end
595

596
## Conversions ##
597

598
convert(::Type{T}, a::AbstractArray) where {T<:Array} = a isa T ? a : T(a)::T
291,988✔
599

600
promote_rule(a::Type{Array{T,n}}, b::Type{Array{S,n}}) where {T,n,S} = el_same(promote_type(T,S), a, b)
86✔
601

602
## Constructors ##
603

604
if nameof(@__MODULE__) === :Base  # avoid method overwrite
605
# constructors should make copies
606
Array{T,N}(x::AbstractArray{S,N})         where {T,N,S} = copyto_axcheck!(Array{T,N}(undef, size(x)), x)
301,547✔
607
AbstractArray{T,N}(A::AbstractArray{S,N}) where {T,N,S} = copyto_axcheck!(similar(A,T), A)
9,605✔
608
end
609

610
## copying iterators to containers
611

612
"""
613
    collect(element_type, collection)
614

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

618
# Examples
619
```jldoctest
620
julia> collect(Float64, 1:2:5)
621
3-element Vector{Float64}:
622
 1.0
623
 3.0
624
 5.0
625
```
626
"""
627
collect(::Type{T}, itr) where {T} = _collect(T, itr, IteratorSize(itr))
25,793,117✔
628

629
_collect(::Type{T}, itr, isz::Union{HasLength,HasShape}) where {T} =
41,662✔
630
    copyto!(_array_for(T, isz, _similar_shape(itr, isz)), itr)
631
function _collect(::Type{T}, itr, isz::SizeUnknown) where T
25,751,448✔
632
    a = Vector{T}()
25,751,455✔
633
    for x in itr
44,214,100✔
634
        push!(a, x)
129,595,001✔
635
    end
240,727,355✔
636
    return a
25,751,454✔
637
end
638

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

642
_similar_shape(itr, ::SizeUnknown) = nothing
×
643
_similar_shape(itr, ::HasLength) = length(itr)::Integer
51,884,647✔
644
_similar_shape(itr, ::HasShape) = axes(itr)
378,594,863✔
645

646
_similar_for(c::AbstractArray, ::Type{T}, itr, ::SizeUnknown, ::Nothing) where {T} =
1,361,182✔
647
    similar(c, T, 0)
648
_similar_for(c::AbstractArray, ::Type{T}, itr, ::HasLength, len::Integer) where {T} =
13,854,236✔
649
    similar(c, T, len)
650
_similar_for(c::AbstractArray, ::Type{T}, itr, ::HasShape, axs) where {T} =
296,594✔
651
    similar(c, T, axs)
652

653
# make a collection appropriate for collecting `itr::Generator`
654
_array_for(::Type{T}, ::SizeUnknown, ::Nothing) where {T} = Vector{T}(undef, 0)
144✔
655
_array_for(::Type{T}, ::HasLength, len::Integer) where {T} = Vector{T}(undef, Int(len))
61,468,449✔
656
_array_for(::Type{T}, ::HasShape{N}, axs) where {T,N} = similar(Array{T,N}, axs)
1,056,217,424✔
657

658
# used by syntax lowering for simple typed comprehensions
659
_array_for(::Type{T}, itr, isz) where {T} = _array_for(T, isz, _similar_shape(itr, isz))
1,116,026,223✔
660

661

662
"""
663
    collect(iterator)
664

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

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

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

677
# Examples
678

679
Collect items from a `UnitRange{Int64}` collection:
680

681
```jldoctest
682
julia> collect(1:3)
683
3-element Vector{Int64}:
684
 1
685
 2
686
 3
687
```
688

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

691
```jldoctest
692
julia> collect(x^2 for x in 1:3)
693
3-element Vector{Int64}:
694
 1
695
 4
696
 9
697
```
698

699
Collecting an empty iterator where the result type depends on type inference:
700

701
```jldoctest
702
julia> [rand(Bool) ? 1 : missing for _ in []]
703
Union{Missing, Int64}[]
704
```
705

706
When the iterator is non-empty, the result type depends only on values:
707

708
```julia-repl
709
julia> [rand(Bool) ? 1 : missing for _ in [""]]
710
1-element Vector{Int64}:
711
 1
712
```
713
"""
714
collect(itr) = _collect(1:1 #= Array =#, itr, IteratorEltype(itr), IteratorSize(itr))
15,445,777✔
715

716
collect(A::AbstractArray) = _collect_indices(axes(A), A)
135,976✔
717

718
collect_similar(cont, itr) = _collect(cont, itr, IteratorEltype(itr), IteratorSize(itr))
189,602✔
719

720
_collect(cont, itr, ::HasEltype, isz::Union{HasLength,HasShape}) =
13,840,755✔
721
    copyto!(_similar_for(cont, eltype(itr), itr, isz, _similar_shape(itr, isz)), itr)
722

723
function _collect(cont, itr, ::HasEltype, isz::SizeUnknown)
1,361,082✔
724
    a = _similar_for(cont, eltype(itr), itr, isz, nothing)
1,361,114✔
725
    for x in itr
2,720,269✔
726
        push!(a,x)
10,476,797✔
727
    end
17,950,495✔
728
    return a
1,361,113✔
729
end
730

731
_collect_indices(::Tuple{}, A) = copyto!(Array{eltype(A),0}(undef), A)
26✔
732
_collect_indices(indsA::Tuple{Vararg{OneTo}}, A) =
137,352✔
733
    copyto!(Array{eltype(A)}(undef, length.(indsA)), A)
734
function _collect_indices(indsA, A)
36✔
735
    B = Array{eltype(A)}(undef, length.(indsA))
237✔
736
    copyto!(B, CartesianIndices(axes(B)), A, CartesianIndices(indsA))
121✔
737
end
738

739
# NOTE: this function is not meant to be called, only inferred, for the
740
# purpose of bounding the types of values generated by an iterator.
741
function _iterator_upper_bound(itr)
×
742
    x = iterate(itr)
×
743
    while x !== nothing
×
744
        val = getfield(x, 1)
×
745
        if inferencebarrier(nothing)
×
746
            return val
×
747
        end
748
        x = iterate(itr, getfield(x, 2))
×
749
    end
×
750
    throw(nothing)
×
751
end
752

753
# define this as a macro so that the call to Core.Compiler
754
# gets inlined into the caller before recursion detection
755
# gets a chance to see it, so that recursive calls to the caller
756
# don't trigger the inference limiter
757
if isdefined(Core, :Compiler)
758
    macro default_eltype(itr)
759
        I = esc(itr)
760
        return quote
761
            if $I isa Generator && ($I).f isa Type
542,096✔
762
                T = ($I).f
12,745✔
763
            else
764
                T = Core.Compiler.return_type(_iterator_upper_bound, Tuple{typeof($I)})
529,351✔
765
            end
766
            promote_typejoin_union(T)
542,097✔
767
        end
768
    end
769
else
770
    macro default_eltype(itr)
771
        I = esc(itr)
772
        return quote
773
            if $I isa Generator && ($I).f isa Type
774
                promote_typejoin_union($I.f)
775
            else
776
                Any
777
            end
778
        end
779
    end
780
end
781

782
function collect(itr::Generator)
906,586✔
783
    isz = IteratorSize(itr.iter)
393,701✔
784
    et = @default_eltype(itr)
785
    if isa(isz, SizeUnknown)
393,701✔
786
        return grow_to!(Vector{et}(), itr)
95,699✔
787
    else
788
        shp = _similar_shape(itr, isz)
822,100✔
789
        y = iterate(itr)
1,631,661✔
790
        if y === nothing
821,473✔
791
            return _array_for(et, isz, shp)
912✔
792
        end
793
        v1, st = y
391,800✔
794
        dest = _array_for(typeof(v1), isz, shp)
1,629,280✔
795
        # The typeassert gives inference a helping hand on the element type and dimensionality
796
        # (work-around for #28382)
797
        et′ = et <: Type ? Type : et
391,800✔
798
        RT = dest isa AbstractArray ? AbstractArray{<:et′, ndims(dest)} : Any
391,907✔
799
        collect_to_with_first!(dest, v1, itr, st)::RT
10,810,565✔
800
    end
801
end
802

803
_collect(c, itr, ::EltypeUnknown, isz::SizeUnknown) =
68✔
804
    grow_to!(_similar_for(c, @default_eltype(itr), itr, isz, nothing), itr)
805

806
function _collect(c, itr, ::EltypeUnknown, isz::Union{HasLength,HasShape})
189,623✔
807
    et = @default_eltype(itr)
125,829✔
808
    shp = _similar_shape(itr, isz)
189,630✔
809
    y = iterate(itr)
377,797✔
810
    if y === nothing
189,628✔
811
        return _similar_for(c, et, itr, isz, shp)
1,436✔
812
    end
813
    v1, st = y
124,680✔
814
    dest = _similar_for(c, typeof(v1), itr, isz, shp)
293,533✔
815
    # The typeassert gives inference a helping hand on the element type and dimensionality
816
    # (work-around for #28382)
817
    et′ = et <: Type ? Type : et
124,658✔
818
    RT = dest isa AbstractArray ? AbstractArray{<:et′, ndims(dest)} : Any
124,671✔
819
    collect_to_with_first!(dest, v1, itr, st)::RT
188,192✔
820
end
821

822
function collect_to_with_first!(dest::AbstractArray, v1, itr, st)
85,692✔
823
    i1 = first(LinearIndices(dest))
516,458✔
824
    dest[i1] = v1
1,008,753✔
825
    return collect_to!(dest, itr, i1+1, st)
11,657,401✔
826
end
827

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

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

842
function collect_to!(dest::AbstractArray{T}, itr, offs, st) where T
126,834✔
843
    # collect to dest array, checking the type of each result. if a result does not
844
    # match, widen the result type and re-dispatch.
845
    i = offs
516,814✔
846
    while true
92,395,033✔
847
        y = iterate(itr, st)
183,781,283✔
848
        y === nothing && break
92,395,023✔
849
        el, st = y
90,413,328✔
850
        if el isa T
90,423,490✔
851
            @inbounds dest[i] = el
91,385,879✔
852
            i += 1
91,385,879✔
853
        else
854
            new = setindex_widen_up_to(dest, el, i)
401✔
855
            return collect_to!(new, itr, i+1, st)
401✔
856
        end
857
    end
91,385,879✔
858
    return dest
1,008,743✔
859
end
860

861
function grow_to!(dest, itr)
1,228✔
862
    y = iterate(itr)
1,560✔
863
    y === nothing && return dest
1,261✔
864
    dest2 = empty(dest, typeof(y[1]))
326✔
865
    push!(dest2, y[1])
402✔
866
    grow_to!(dest2, itr, y[2])
305✔
867
end
868

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

882
function grow_to!(dest, itr, st)
300✔
883
    T = eltype(dest)
194✔
884
    y = iterate(itr, st)
536✔
885
    while y !== nothing
3,232✔
886
        el, st = y
1,597✔
887
        if el isa T
1,599✔
888
            push!(dest, el)
2,920✔
889
        else
890
            new = push_widen(dest, el)
11✔
891
            return grow_to!(new, itr, st)
9✔
892
        end
893
        y = iterate(itr, st)
4,772✔
894
    end
2,918✔
895
    return dest
305✔
896
end
897

898
## Iteration ##
899

900
iterate(A::Array, i=1) = (@inline; (i - 1)%UInt < length(A)%UInt ? (@inbounds A[i], i + 1) : nothing)
2,147,483,647✔
901

902
## Indexing: getindex ##
903

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

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

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

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

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

925
function getindex(A::Array, i1::Int, i2::Int, I::Int...)
120,845✔
926
    @inline
200,469,689✔
927
    @boundscheck checkbounds(A, i1, i2, I...) # generally _to_linear_index requires bounds checking
213,020,875✔
928
    return @inbounds A[_to_linear_index(A, i1, i2, I...)]
213,021,243✔
929
end
930

931
# Faster contiguous indexing using copyto! for AbstractUnitRange and Colon
932
function getindex(A::Array, I::AbstractUnitRange{<:Integer})
7,955,973✔
933
    @inline
869,256✔
934
    @boundscheck checkbounds(A, I)
64,764,867✔
935
    lI = length(I)
64,764,875✔
936
    X = similar(A, axes(I))
102,089,314✔
937
    if lI > 0
64,764,865✔
938
        copyto!(X, firstindex(X), A, first(I), lI)
74,648,886✔
939
    end
940
    return X
64,764,865✔
941
end
942

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

946
function getindex(A::Array, c::Colon)
4,450✔
947
    lI = length(A)
2,015,424✔
948
    X = similar(A, lI)
4,030,846✔
949
    if lI > 0
2,015,424✔
950
        unsafe_copyto!(X, 1, A, 1, lI)
4,030,844✔
951
    end
952
    return X
2,015,424✔
953
end
954

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

960
## Indexing: setindex! ##
961

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

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

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

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

982
function setindex!(A::Array{T}, x, i::Int) where {T}
4,664,843✔
983
    @_noub_if_noinbounds_meta
696,087,001✔
984
    @boundscheck (i - 1)%UInt < length(A)%UInt || throw_boundserror(A, (i,))
2,147,483,647✔
985
    memoryrefset!(memoryrefnew(A.ref, i, false), x isa T ? x : convert(T,x)::T, :not_atomic, false)
2,147,483,647✔
986
    return A
2,147,483,647✔
987
end
988
function setindex!(A::Array{T}, x, i1::Int, i2::Int, I::Int...) where {T}
845,509✔
989
    @inline
72,684,647✔
990
    @_noub_if_noinbounds_meta
72,684,647✔
991
    @boundscheck checkbounds(A, i1, i2, I...) # generally _to_linear_index requires bounds checking
75,859,552✔
992
    memoryrefset!(memoryrefnew(A.ref, _to_linear_index(A, i1, i2, I...), false), x isa T ? x : convert(T,x)::T, :not_atomic, false)
75,860,428✔
993
    return A
75,859,528✔
994
end
995

996
__safe_setindex!(A::Vector{Any}, @nospecialize(x), i::Int) = (@inline; @_nothrow_noub_meta;
1,412,975✔
997
    memoryrefset!(memoryrefnew(A.ref, i, false), x, :not_atomic, false); return A)
294,526,598✔
998
__safe_setindex!(A::Vector{T}, x::T, i::Int) where {T} = (@inline; @_nothrow_noub_meta;
373,970✔
999
    memoryrefset!(memoryrefnew(A.ref, i, false), x, :not_atomic, false); return A)
2,147,483,647✔
1000
__safe_setindex!(A::Vector{T}, x,    i::Int) where {T} = (@inline;
1001
    __safe_setindex!(A, convert(T, x)::T, i))
23,409✔
1002

1003
# This is redundant with the abstract fallbacks but needed and helpful for bootstrap
1004
function setindex!(A::Array, X::AbstractArray, I::AbstractVector{Int})
88✔
1005
    @_propagate_inbounds_meta
814,132✔
1006
    @boundscheck setindex_shape_check(X, length(I))
8,752,141✔
1007
    @boundscheck checkbounds(A, I)
8,752,141✔
1008
    require_one_based_indexing(X)
814,132✔
1009
    X′ = unalias(A, X)
814,132✔
1010
    I′ = unalias(A, I)
814,132✔
1011
    count = 1
814,132✔
1012
    for i in I′
8,752,375✔
1013
        @inbounds A[i] = X′[count]
20,273,565✔
1014
        count += 1
20,273,564✔
1015
    end
33,138,881✔
1016
    return A
8,752,141✔
1017
end
1018

1019
# Faster contiguous setindex! with copyto!
1020
function setindex!(A::Array{T}, X::Array{T}, I::AbstractUnitRange{Int}) where T
100✔
1021
    @inline
1,007,709✔
1022
    @boundscheck checkbounds(A, I)
1,008,018✔
1023
    lI = length(I)
1,008,018✔
1024
    @boundscheck setindex_shape_check(X, lI)
1,008,018✔
1025
    if lI > 0
1,008,018✔
1026
        unsafe_copyto!(A, first(I), X, 1, lI)
2,015,700✔
1027
    end
1028
    return A
1,008,018✔
1029
end
1030
function setindex!(A::Array{T}, X::Array{T}, c::Colon) where T
40✔
1031
    @inline
73✔
1032
    lI = length(A)
73✔
1033
    @boundscheck setindex_shape_check(X, lI)
73✔
1034
    if lI > 0
73✔
1035
        unsafe_copyto!(A, 1, X, 1, lI)
146✔
1036
    end
1037
    return A
73✔
1038
end
1039

1040
# Pick new memory size for efficiently growing an array
1041
# TODO: This should know about the size of our GC pools
1042
# Specifically we are wasting ~10% of memory for small arrays
1043
# by not picking memory sizes that max out a GC pool
1044
function overallocation(maxsize)
1045
    maxsize < 8 && return 8;
1,202,623,333✔
1046
    # compute maxsize = maxsize + 4*maxsize^(7/8) + maxsize/8
1047
    # for small n, we grow faster than O(n)
1048
    # for large n, we grow at O(n/8)
1049
    # and as we reach O(memory) for memory>>1MB,
1050
    # this means we end by adding about 10% of memory each time
1051
    exp2 = sizeof(maxsize) * 8 - Core.Intrinsics.ctlz_int(maxsize)
84,885,334✔
1052
    maxsize += (1 << div(exp2 * 7, 8)) * 4 + div(maxsize, 8)
84,885,334✔
1053
    return maxsize
84,885,335✔
1054
end
1055

1056
array_new_memory(mem::Memory, newlen::Int) = typeof(mem)(undef, newlen) # when implemented, this should attempt to first expand mem
2,147,483,647✔
1057

1058
function _growbeg!(a::Vector, delta::Integer)
38✔
1059
    @_noub_meta
19,312✔
1060
    delta = Int(delta)
19,312✔
1061
    delta == 0 && return # avoid attempting to index off the end
22,108,140✔
1062
    delta >= 0 || throw(ArgumentError("grow requires delta >= 0"))
22,107,568✔
1063
    ref = a.ref
69,001,623✔
1064
    mem = ref.mem
69,001,623✔
1065
    len = length(a)
69,001,623✔
1066
    offset = memoryrefoffset(ref)
69,001,623✔
1067
    newlen = len + delta
69,001,623✔
1068
    setfield!(a, :size, (newlen,))
69,001,623✔
1069
    # if offset is far enough advanced to fit data in existing memory without copying
1070
    if delta <= offset - 1
69,001,623✔
1071
        setfield!(a, :ref, @inbounds memoryref(ref, 1 - delta))
45,980,176✔
1072
    else
1073
        @noinline (function()
46,044,104✔
1074
        memlen = length(mem)
23,022,658✔
1075
        if offset + len - 1 > memlen || offset < 1
46,045,316✔
1076
            throw(ConcurrencyViolationError("Vector has invalid state. Don't modify internal fields incorrectly, or resize without correct locks"))
×
1077
        end
1078
        # since we will allocate the array in the middle of the memory we need at least 2*delta extra space
1079
        # the +1 is because I didn't want to have an off by 1 error.
1080
        newmemlen = max(overallocation(memlen), len + 2 * delta + 1)
35,233,453✔
1081
        newoffset = div(newmemlen - newlen, 2) + 1
23,022,658✔
1082
        # If there is extra data after the end of the array we can use that space so long as there is enough
1083
        # space at the end that there won't be quadratic behavior with a mix of growth from both ends.
1084
        # Specifically, we want to ensure that we will only do this operation once before
1085
        # increasing the size of the array, and that we leave enough space at both the beginning and the end.
1086
        if newoffset + newlen < memlen
23,022,658✔
1087
            newoffset = div(memlen - newlen, 2) + 1
×
1088
            newmem = mem
×
1089
        else
1090
            newmem = array_new_memory(mem, newmemlen)
23,022,658✔
1091
        end
1092
        unsafe_copyto!(newmem, newoffset + delta, mem, offset, len)
46,032,492✔
1093
        if ref !== a.ref
23,022,658✔
1094
            @noinline throw(ConcurrencyViolationError("Vector can not be resized concurrently"))
×
1095
        end
1096
        setfield!(a, :ref, @inbounds memoryref(newmem, newoffset))
23,022,658✔
1097
        end)()
1098
    end
1099
    return
69,001,623✔
1100
end
1101

1102
function _growend!(a::Vector, delta::Integer)
26✔
1103
    @_noub_meta
12,192,896✔
1104
    delta = Int(delta)
12,211,888✔
1105
    delta >= 0 || throw(ArgumentError("grow requires delta >= 0"))
1,211,758,541✔
1106
    ref = a.ref
2,147,483,647✔
1107
    mem = ref.mem
2,147,483,647✔
1108
    memlen = length(mem)
2,147,483,647✔
1109
    len = length(a)
2,147,483,647✔
1110
    newlen = len + delta
2,147,483,647✔
1111
    offset = memoryrefoffset(ref)
2,147,483,647✔
1112
    setfield!(a, :size, (newlen,))
2,147,483,647✔
1113
    newmemlen = offset + newlen - 1
2,147,483,647✔
1114
    if memlen < newmemlen
2,147,483,647✔
1115
        @noinline (function()
2,147,483,647✔
1116
        if offset + len - 1 > memlen || offset < 1
2,147,483,647✔
1117
            throw(ConcurrencyViolationError("Vector has invalid state. Don't modify internal fields incorrectly, or resize without correct locks"))
×
1118
        end
1119

1120
        if offset - 1 > div(5 * newlen, 4)
1,159,101,804✔
1121
            # If the offset is far enough that we can copy without resizing
1122
            # while maintaining proportional spacing on both ends of the array
1123
            # note that this branch prevents infinite growth when doing combinations
1124
            # of push! and popfirst! (i.e. when using a Vector as a queue)
1125
            newmem = mem
21,104✔
1126
            newoffset = div(newlen, 8) + 1
21,104✔
1127
        else
1128
            # grow either by our computed overallocation factor
1129
            # or exactly the requested size, whichever is larger
1130
            # TODO we should possibly increase the offset if the current offset is nonzero.
1131
            newmemlen2 = max(overallocation(memlen), newmemlen)
1,223,771,317✔
1132
            newmem = array_new_memory(mem, newmemlen2)
2,147,483,647✔
1133
            newoffset = offset
1,159,080,685✔
1134
        end
1135
        newref = @inbounds memoryref(newmem, newoffset)
1,159,101,790✔
1136
        unsafe_copyto!(newref, ref, len)
1,264,131,602✔
1137
        if ref !== a.ref
1,159,101,797✔
1138
            @noinline throw(ConcurrencyViolationError("Vector can not be resized concurrently"))
×
1139
        end
1140
        setfield!(a, :ref, newref)
1,159,101,794✔
1141
        end)()
1142
    end
1143
    return
2,147,483,647✔
1144
end
1145

1146
function _growat!(a::Vector, i::Integer, delta::Integer)
98,258,504✔
1147
    @_terminates_globally_noub_meta
183,799✔
1148
    delta = Int(delta)
183,799✔
1149
    i = Int(i)
183,799✔
1150
    i == 1 && return _growbeg!(a, delta)
98,258,504✔
1151
    len = length(a)
76,547,844✔
1152
    i == len + 1 && return _growend!(a, delta)
76,547,844✔
1153
    delta >= 0 || throw(ArgumentError("grow requires delta >= 0"))
75,448,657✔
1154
    1 < i <= len || throw(BoundsError(a, i))
75,448,659✔
1155
    ref = a.ref
75,448,657✔
1156
    mem = ref.mem
75,448,657✔
1157
    memlen = length(mem)
75,448,657✔
1158
    newlen = len + delta
75,448,656✔
1159
    offset = memoryrefoffset(ref)
75,448,655✔
1160
    setfield!(a, :size, (newlen,))
75,448,655✔
1161
    newmemlen = offset + newlen - 1
75,448,656✔
1162

1163
    # which side would we rather grow into?
1164
    prefer_start = i <= div(len, 2)
75,448,657✔
1165
    # if offset is far enough advanced to fit data in beginning of the memory
1166
    if prefer_start && delta <= offset - 1
75,448,657✔
1167
        newref = @inbounds memoryref(mem, offset - delta)
30,925,859✔
1168
        unsafe_copyto!(newref, ref, i)
61,851,718✔
1169
        setfield!(a, :ref, newref)
30,925,859✔
1170
        for j in i:i+delta-1
30,925,859✔
1171
            @inbounds _unsetindex!(a, j)
43,595,077✔
1172
        end
43,588,297✔
1173
    elseif !prefer_start && memlen >= newmemlen
44,522,796✔
1174
        unsafe_copyto!(mem, offset - 1 + delta + i, mem, offset - 1 + i, len - i + 1)
63,078,746✔
1175
        for j in i:i+delta-1
31,539,373✔
1176
            @inbounds _unsetindex!(a, j)
43,757,821✔
1177
        end
43,748,655✔
1178
    else
1179
        # since we will allocate the array in the middle of the memory we need at least 2*delta extra space
1180
        # the +1 is because I didn't want to have an off by 1 error.
1181
        newmemlen = max(overallocation(memlen), len+2*delta+1)
19,113,437✔
1182
        newoffset = (newmemlen - newlen) ÷ 2 + 1
12,983,425✔
1183
        newmem = array_new_memory(mem, newmemlen)
25,966,846✔
1184
        newref = @inbounds memoryref(newmem, newoffset)
12,983,422✔
1185
        unsafe_copyto!(newref, ref, i-1)
25,966,850✔
1186
        unsafe_copyto!(newmem, newoffset + delta + i - 1, mem, offset + i - 1, len - i + 1)
25,966,847✔
1187
        setfield!(a, :ref, newref)
12,983,424✔
1188
    end
1189
end
1190

1191
# efficiently delete part of an array
1192
function _deletebeg!(a::Vector, delta::Integer)
19,520,045✔
1193
    delta = Int(delta)
1,081,272✔
1194
    len = length(a)
72,431,628✔
1195
    0 <= delta <= len || throw(ArgumentError("_deletebeg! requires delta in 0:length(a)"))
72,431,628✔
1196
    for i in 1:delta
20,694,310✔
1197
        @inbounds _unsetindex!(a, i)
97,777,132✔
1198
    end
32,263,778✔
1199
    newlen = len - delta
72,431,627✔
1200
    if newlen != 0 # if newlen==0 we could accidentally index past the memory
72,431,626✔
1201
        newref = @inbounds memoryref(a.ref, delta + 1)
65,807,014✔
1202
        setfield!(a, :ref, newref)
65,807,015✔
1203
    end
1204
    setfield!(a, :size, (newlen,))
72,431,627✔
1205
    return
72,431,627✔
1206
end
1207
function _deleteend!(a::Vector, delta::Integer)
21,378,254✔
1208
    delta = Int(delta)
6,221,201✔
1209
    len = length(a)
1,523,838,635✔
1210
    0 <= delta <= len || throw(ArgumentError("_deleteend! requires delta in 0:length(a)"))
1,523,838,634✔
1211
    newlen = len - delta
1,523,838,635✔
1212
    for i in newlen+1:len
1,563,944,139✔
1213
        @inbounds _unsetindex!(a, i)
2,147,483,647✔
1214
    end
2,147,483,647✔
1215
    setfield!(a, :size, (newlen,))
1,523,838,633✔
1216
    return
1,523,838,633✔
1217
end
1218
function _deleteat!(a::Vector, i::Integer, delta::Integer)
7,617,986✔
1219
    i = Int(i)
100,865✔
1220
    len = length(a)
7,617,986✔
1221
    0 <= delta || throw(ArgumentError("_deleteat! requires delta >= 0"))
7,617,986✔
1222
    1 <= i <= len || throw(BoundsError(a, i))
7,617,989✔
1223
    i + delta <= len + 1 || throw(BoundsError(a, i + delta - 1))
7,617,983✔
1224
    newa = a
100,852✔
1225
    if 2*i + delta <= len
7,617,983✔
1226
        unsafe_copyto!(newa, 1 + delta, a, 1, i - 1)
163,421✔
1227
        _deletebeg!(a, delta)
3,534,685✔
1228
    else
1229
        unsafe_copyto!(newa, i, a, i + delta, len + 1 - delta - i)
10,152,385✔
1230
        _deleteend!(a, delta)
7,500,873✔
1231
    end
1232
    return
7,617,983✔
1233
end
1234
## Dequeue functionality ##
1235

1236
"""
1237
    push!(collection, items...) -> collection
1238

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

1242
# Examples
1243
```jldoctest
1244
julia> push!([1, 2, 3], 4, 5, 6)
1245
6-element Vector{Int64}:
1246
 1
1247
 2
1248
 3
1249
 4
1250
 5
1251
 6
1252
```
1253

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

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

1260
See also [`pushfirst!`](@ref).
1261
"""
1262
function push! end
1263

1264
function push!(a::Vector{T}, item) where T
64,067✔
1265
    # convert first so we don't grow the array if the assignment won't work
1266
    itemT = item isa T ? item : convert(T, item)::T
44,657,032✔
1267
    _growend!(a, 1)
2,147,483,647✔
1268
    @_safeindex a[length(a)] = itemT
2,147,483,647✔
1269
    return a
2,147,483,647✔
1270
end
1271

1272
# specialize and optimize the single argument case
1273
function push!(a::Vector{Any}, @nospecialize x)
7,443✔
1274
    _growend!(a, 1)
128,093,827✔
1275
    @_safeindex a[length(a)] = x
128,093,827✔
1276
    return a
128,093,825✔
1277
end
1278
function push!(a::Vector{Any}, @nospecialize x...)
16✔
1279
    @_terminates_locally_meta
17✔
1280
    na = length(a)
280,345✔
1281
    nx = length(x)
17✔
1282
    _growend!(a, nx)
280,345✔
1283
    @_safeindex for i = 1:nx
560,673✔
1284
        a[na+i] = x[i]
740,614✔
1285
    end
841,149✔
1286
    return a
280,345✔
1287
end
1288

1289
"""
1290
    append!(collection, collections...) -> collection.
1291

1292
For an ordered container `collection`, add the elements of each `collections`
1293
to the end of it.
1294

1295
!!! compat "Julia 1.6"
1296
    Specifying multiple collections to be appended requires at least Julia 1.6.
1297

1298
# Examples
1299
```jldoctest
1300
julia> append!([1], [2, 3])
1301
3-element Vector{Int64}:
1302
 1
1303
 2
1304
 3
1305

1306
julia> append!([1, 2, 3], [4, 5], [6])
1307
6-element Vector{Int64}:
1308
 1
1309
 2
1310
 3
1311
 4
1312
 5
1313
 6
1314
```
1315

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

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

1322
See also [`vcat`](@ref) for vectors, [`union!`](@ref) for sets,
1323
and [`prepend!`](@ref) and [`pushfirst!`](@ref) for the opposite order.
1324
"""
1325
function append! end
1326

1327
function append!(a::Vector{T}, items::Union{AbstractVector{<:T},Tuple}) where T
7,970✔
1328
    items isa Tuple && (items = map(x -> convert(T, x), items))
44,403✔
1329
    n = length(items)
76,608,769✔
1330
    _growend!(a, n)
77,112,227✔
1331
    copyto!(a, length(a)-n+1, items, firstindex(items), n)
120,098,797✔
1332
    return a
77,112,227✔
1333
end
1334

1335
append!(a::AbstractVector, iter) = _append!(a, IteratorSize(iter), iter)
79,932,881✔
1336
push!(a::AbstractVector, iter...) = append!(a, iter)
506,451✔
1337
append!(a::AbstractVector, iter...) = (for v in iter; append!(a, v); end; return a)
7✔
1338

1339
function _append!(a::AbstractVector, ::Union{HasLength,HasShape}, iter)
24,947,362✔
1340
    n = Int(length(iter))::Int
25,175,018✔
1341
    i = lastindex(a)
38✔
1342
    sizehint!(a, length(a) + n; shrink=false)
24,947,375✔
1343
    for item in iter
41,475,649✔
1344
        push!(a, item)
46,836,403✔
1345
    end
47,063,153✔
1346
    a
21✔
1347
end
1348
function _append!(a::AbstractVector, ::IteratorSize, iter)
54,985,503✔
1349
    for item in iter
66,810,709✔
1350
        push!(a, item)
55,740,986✔
1351
    end
55,740,992✔
1352
    a
4✔
1353
end
1354

1355
"""
1356
    prepend!(a::Vector, collections...) -> collection
1357

1358
Insert the elements of each `collections` to the beginning of `a`.
1359

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

1363
!!! compat "Julia 1.6"
1364
    Specifying multiple collections to be prepended requires at least Julia 1.6.
1365

1366
# Examples
1367
```jldoctest
1368
julia> prepend!([3], [1, 2])
1369
3-element Vector{Int64}:
1370
 1
1371
 2
1372
 3
1373

1374
julia> prepend!([6], [1, 2], [3, 4, 5])
1375
6-element Vector{Int64}:
1376
 1
1377
 2
1378
 3
1379
 4
1380
 5
1381
 6
1382
```
1383
"""
1384
function prepend! end
1385

1386
function prepend!(a::Vector{T}, items::Union{AbstractVector{<:T},Tuple}) where T
2,154✔
1387
    items isa Tuple && (items = map(x -> convert(T, x), items))
5,122✔
1388
    n = length(items)
6,186✔
1389
    _growbeg!(a, n)
11,799✔
1390
    # in case of aliasing, the _growbeg might have shifted our data, so copy
1391
    # just the last n elements instead of all of them from the first
1392
    copyto!(a, 1, items, lastindex(items)-n+1, n)
11,794✔
1393
    return a
6,186✔
1394
end
1395

1396
prepend!(a::AbstractVector, iter) = _prepend!(a, IteratorSize(iter), iter)
481✔
1397
pushfirst!(a::AbstractVector, iter...) = prepend!(a, iter)
15✔
1398
prepend!(a::AbstractVector, iter...) = (for v = reverse(iter); prepend!(a, v); end; return a)
7✔
1399

1400
function _prepend!(a::Vector, ::Union{HasLength,HasShape}, iter)
461✔
1401
    @_terminates_locally_meta
462✔
1402
    require_one_based_indexing(a)
462✔
1403
    n = Int(length(iter))::Int
462✔
1404
    sizehint!(a, length(a) + n; first=true, shrink=false)
462✔
1405
    n = 0
462✔
1406
    for item in iter
463✔
1407
        n += 1
761✔
1408
        pushfirst!(a, item)
761✔
1409
    end
757✔
1410
    reverse!(a, 1, n)
456✔
1411
    a
456✔
1412
end
1413
function _prepend!(a::Vector, ::IteratorSize, iter)
3✔
1414
    n = 0
3✔
1415
    for item in iter
5✔
1416
        n += 1
8✔
1417
        pushfirst!(a, item)
11✔
1418
    end
13✔
1419
    reverse!(a, 1, n)
2✔
1420
    a
2✔
1421
end
1422

1423
"""
1424
    resize!(a::Vector, n::Integer) -> Vector
1425

1426
Resize `a` to contain `n` elements. If `n` is smaller than the current collection
1427
length, the first `n` elements will be retained. If `n` is larger, the new elements are not
1428
guaranteed to be initialized.
1429

1430
# Examples
1431
```jldoctest
1432
julia> resize!([6, 5, 4, 3, 2, 1], 3)
1433
3-element Vector{Int64}:
1434
 6
1435
 5
1436
 4
1437

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

1440
julia> length(a)
1441
8
1442

1443
julia> a[1:6]
1444
6-element Vector{Int64}:
1445
 6
1446
 5
1447
 4
1448
 3
1449
 2
1450
 1
1451
```
1452
"""
1453
function resize!(a::Vector, nl::Integer)
1,303,546,520✔
1454
    l = length(a)
1,359,451,022✔
1455
    if nl > l
1,359,451,020✔
1456
        _growend!(a, nl-l)
934,327,475✔
1457
    elseif nl != l
425,123,542✔
1458
        if nl < 0
106,098,358✔
1459
            _throw_argerror("new length must be ≥ 0")
2✔
1460
        end
1461
        _deleteend!(a, l-nl)
106,098,356✔
1462
    end
1463
    return a
1,359,451,016✔
1464
end
1465

1466
"""
1467
    sizehint!(s, n; first::Bool=false, shrink::Bool=true) -> s
1468

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

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

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

1482
See also [`resize!`](@ref).
1483

1484
# Notes on the performance model
1485

1486
For types that support `sizehint!`,
1487

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

1492
2. `sizehint!` may control this preallocation. Again, it typically does this for types in
1493
   `Base`.
1494

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

1497
!!! compat "Julia 1.11"
1498
    The `shrink` and `first` arguments were added in Julia 1.11.
1499
"""
1500
function sizehint! end
1501

1502
function sizehint!(a::Vector, sz::Integer; first::Bool=false, shrink::Bool=true)
50,107,418✔
1503
    len = length(a)
25,052,933✔
1504
    ref = a.ref
25,052,933✔
1505
    mem = ref.mem
25,052,933✔
1506
    memlen = length(mem)
25,052,933✔
1507
    sz = max(Int(sz), len)
25,052,933✔
1508
    inc = sz - len
25,052,933✔
1509
    if sz <= memlen
25,052,933✔
1510
        # if we don't save at least 1/8th memlen then its not worth it to shrink
1511
        if !shrink || memlen - sz <= div(memlen, 8)
21,866,446✔
1512
            return a
21,686,208✔
1513
        end
1514
        newmem = array_new_memory(mem, sz)
132,241✔
1515
        if first
88,474✔
1516
            newref = memoryref(newmem, inc + 1)
×
1517
        else
1518
            newref = memoryref(newmem)
88,474✔
1519
        end
1520
        unsafe_copyto!(newref, ref, len)
151,309✔
1521
        setfield!(a, :ref, newref)
88,474✔
1522
    elseif first
3,278,251✔
1523
        _growbeg!(a, inc)
914✔
1524
        newref = getfield(a, :ref)
457✔
1525
        newref = memoryref(newref, inc + 1)
457✔
1526
        setfield!(a, :size, (len,)) # undo the size change from _growbeg!
457✔
1527
        setfield!(a, :ref, newref) # undo the offset change from _growbeg!
457✔
1528
    else # last
1529
        _growend!(a, inc)
3,277,794✔
1530
        setfield!(a, :size, (len,)) # undo the size change from _growend!
3,277,794✔
1531
    end
1532
    a
5,986✔
1533
end
1534

1535
# Fall-back implementation for non-shrinkable collections
1536
# avoid defining this the normal way to avoid avoid infinite recursion
1537
function Core.kwcall(kwargs::NamedTuple{names}, ::typeof(sizehint!), a, sz) where names
1538
    get(kwargs, :first, false)::Bool
16✔
1539
    get(kwargs, :shrink, true)::Bool
16✔
1540
    isempty(diff_names(names, (:first, :shrink))) || kwerr(kwargs, sizehint!, a, sz)
16✔
1541
    sizehint!(a, sz)
16✔
1542
end
1543

1544
"""
1545
    pop!(collection) -> item
1546

1547
Remove an item in `collection` and return it. If `collection` is an
1548
ordered container, the last item is returned; for unordered containers,
1549
an arbitrary element is returned.
1550

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

1553
# Examples
1554
```jldoctest
1555
julia> A=[1, 2, 3]
1556
3-element Vector{Int64}:
1557
 1
1558
 2
1559
 3
1560

1561
julia> pop!(A)
1562
3
1563

1564
julia> A
1565
2-element Vector{Int64}:
1566
 1
1567
 2
1568

1569
julia> S = Set([1, 2])
1570
Set{Int64} with 2 elements:
1571
  2
1572
  1
1573

1574
julia> pop!(S)
1575
2
1576

1577
julia> S
1578
Set{Int64} with 1 element:
1579
  1
1580

1581
julia> pop!(Dict(1=>2))
1582
1 => 2
1583
```
1584
"""
1585
function pop!(a::Vector)
23,726✔
1586
    if isempty(a)
1,332,615,935✔
1587
        _throw_argerror("array must be non-empty")
1✔
1588
    end
1589
    item = a[end]
1,332,615,933✔
1590
    _deleteend!(a, 1)
1,332,615,934✔
1591
    return item
1,332,615,936✔
1592
end
1593

1594
"""
1595
    popat!(a::Vector, i::Integer, [default])
1596

1597
Remove the item at the given `i` and return it. Subsequent items
1598
are shifted to fill the resulting gap.
1599
When `i` is not a valid index for `a`, return `default`, or throw an error if
1600
`default` is not specified.
1601

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

1604
!!! compat "Julia 1.5"
1605
    This function is available as of Julia 1.5.
1606

1607
# Examples
1608
```jldoctest
1609
julia> a = [4, 3, 2, 1]; popat!(a, 2)
1610
3
1611

1612
julia> a
1613
3-element Vector{Int64}:
1614
 4
1615
 2
1616
 1
1617

1618
julia> popat!(a, 4, missing)
1619
missing
1620

1621
julia> popat!(a, 4)
1622
ERROR: BoundsError: attempt to access 3-element Vector{Int64} at index [4]
1623
[...]
1624
```
1625
"""
1626
function popat!(a::Vector, i::Integer)
4✔
1627
    x = a[i]
10✔
1628
    _deleteat!(a, i, 1)
4✔
1629
    x
4✔
1630
end
1631

1632
function popat!(a::Vector, i::Integer, default)
2✔
1633
    if 1 <= i <= length(a)
2✔
1634
        x = @inbounds a[i]
1✔
1635
        _deleteat!(a, i, 1)
1✔
1636
        x
1✔
1637
    else
1638
        default
1✔
1639
    end
1640
end
1641

1642
"""
1643
    pushfirst!(collection, items...) -> collection
1644

1645
Insert one or more `items` at the beginning of `collection`.
1646

1647
This function is called `unshift` in many other programming languages.
1648

1649
# Examples
1650
```jldoctest
1651
julia> pushfirst!([1, 2, 3, 4], 5, 6)
1652
6-element Vector{Int64}:
1653
 5
1654
 6
1655
 1
1656
 2
1657
 3
1658
 4
1659
```
1660
"""
1661
function pushfirst!(a::Vector{T}, item) where T
316✔
1662
    item = item isa T ? item : convert(T, item)::T
2,938✔
1663
    _growbeg!(a, 1)
39,702✔
1664
    @_safeindex a[1] = item
37,711✔
1665
    return a
37,711✔
1666
end
1667

1668
# specialize and optimize the single argument case
1669
function pushfirst!(a::Vector{Any}, @nospecialize x)
12✔
1670
    _growbeg!(a, 1)
47,840,503✔
1671
    @_safeindex a[1] = x
46,858,294✔
1672
    return a
46,858,293✔
1673
end
1674
function pushfirst!(a::Vector{Any}, @nospecialize x...)
1✔
1675
    @_terminates_locally_meta
2✔
1676
    na = length(a)
2✔
1677
    nx = length(x)
2✔
1678
    _growbeg!(a, nx)
1,382✔
1679
    @_safeindex for i = 1:nx
1,380✔
1680
        a[i] = x[i]
1,384✔
1681
    end
2,077✔
1682
    return a
691✔
1683
end
1684

1685
"""
1686
    popfirst!(collection) -> item
1687

1688
Remove the first `item` from `collection`.
1689

1690
This function is called `shift` in many other programming languages.
1691

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

1694
# Examples
1695
```jldoctest
1696
julia> A = [1, 2, 3, 4, 5, 6]
1697
6-element Vector{Int64}:
1698
 1
1699
 2
1700
 3
1701
 4
1702
 5
1703
 6
1704

1705
julia> popfirst!(A)
1706
1
1707

1708
julia> A
1709
5-element Vector{Int64}:
1710
 2
1711
 3
1712
 4
1713
 5
1714
 6
1715
```
1716
"""
1717
function popfirst!(a::Vector)
321✔
1718
    if isempty(a)
72,289,178✔
1719
        _throw_argerror("array must be non-empty")
1✔
1720
    end
1721
    item = a[1]
72,289,177✔
1722
    _deletebeg!(a, 1)
72,289,177✔
1723
    return item
72,289,176✔
1724
end
1725

1726
"""
1727
    insert!(a::Vector, index::Integer, item)
1728

1729
Insert an `item` into `a` at the given `index`. `index` is the index of `item` in
1730
the resulting `a`.
1731

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

1734
# Examples
1735
```jldoctest
1736
julia> insert!(Any[1:6;], 3, "here")
1737
7-element Vector{Any}:
1738
 1
1739
 2
1740
  "here"
1741
 3
1742
 4
1743
 5
1744
 6
1745
```
1746
"""
1747
function insert!(a::Array{T,1}, i::Integer, item) where T
297✔
1748
    @_noub_meta
1,207,376✔
1749
    # Throw convert error before changing the shape of the array
1750
    _item = item isa T ? item : convert(T, item)::T
1,207,428✔
1751
    _growat!(a, i, 1)
78,871,350✔
1752
    # :noub, because _growat! already did bound check
1753
    @inbounds a[i] = _item
78,871,349✔
1754
    return a
78,871,348✔
1755
end
1756

1757
"""
1758
    deleteat!(a::Vector, i::Integer)
1759

1760
Remove the item at the given `i` and return the modified `a`. Subsequent items
1761
are shifted to fill the resulting gap.
1762

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

1765
# Examples
1766
```jldoctest
1767
julia> deleteat!([6, 5, 4, 3, 2, 1], 2)
1768
5-element Vector{Int64}:
1769
 6
1770
 4
1771
 3
1772
 2
1773
 1
1774
```
1775
"""
1776
function deleteat!(a::Vector, i::Integer)
290✔
1777
    i isa Bool && depwarn("passing Bool as an index is deprecated", :deleteat!)
16,701✔
1778
    _deleteat!(a, i, 1)
7,408,201✔
1779
    return a
16,704✔
1780
end
1781

1782
function deleteat!(a::Vector, r::AbstractUnitRange{<:Integer})
34,068✔
1783
    if eltype(r) === Bool
72,054✔
1784
        return invoke(deleteat!, Tuple{Vector, AbstractVector{Bool}}, a, r)
6✔
1785
    else
1786
        n = length(a)
72,048✔
1787
        f = first(r)
72,141✔
1788
        f isa Bool && depwarn("passing Bool as an index is deprecated", :deleteat!)
72,048✔
1789
        isempty(r) || _deleteat!(a, f, length(r))
391,978✔
1790
        return a
196,199✔
1791
    end
1792
end
1793

1794
"""
1795
    deleteat!(a::Vector, inds)
1796

1797
Remove the items at the indices given by `inds`, and return the modified `a`.
1798
Subsequent items are shifted to fill the resulting gap.
1799

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

1803
# Examples
1804
```jldoctest
1805
julia> deleteat!([6, 5, 4, 3, 2, 1], 1:2:5)
1806
3-element Vector{Int64}:
1807
 5
1808
 3
1809
 1
1810

1811
julia> deleteat!([6, 5, 4, 3, 2, 1], [true, false, true, false, true, false])
1812
3-element Vector{Int64}:
1813
 5
1814
 3
1815
 1
1816

1817
julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2))
1818
ERROR: ArgumentError: indices must be unique and sorted
1819
Stacktrace:
1820
[...]
1821
```
1822
"""
1823
deleteat!(a::Vector, inds) = _deleteat!(a, inds)
19✔
1824
deleteat!(a::Vector, inds::AbstractVector) = _deleteat!(a, to_indices(a, (inds,))[1])
103,603✔
1825

1826
struct Nowhere; end
1827
push!(::Nowhere, _) = nothing
×
1828
_growend!(::Nowhere, _) = nothing
×
1829

1830
function _push_deleted!(dltd, a::Vector, ind)
1831
    @_propagate_inbounds_meta
1,492,546✔
1832
    if isassigned(a, ind)
1,567,194✔
1833
        push!(dltd, a[ind])
1,567,193✔
1834
    else
1835
        _growend!(dltd, 1)
×
1836
    end
1837
end
1838

1839
function _copy_item!(a::Vector, p, q)
1840
    @_propagate_inbounds_meta
4,380,105✔
1841
    if isassigned(a, q)
4,418,700✔
1842
        a[p] = a[q]
4,418,699✔
1843
    else
1844
        _unsetindex!(a, p)
1✔
1845
    end
1846
end
1847

1848
function _deleteat!(a::Vector, inds, dltd=Nowhere())
103,623✔
1849
    n = length(a)
207,245✔
1850
    y = iterate(inds)
103,633✔
1851
    y === nothing && return a
103,623✔
1852
    (p, s) = y
35,482✔
1853
    checkbounds(a, p)
103,402✔
1854
    @inbounds _push_deleted!(dltd, a, p)
103,390✔
1855
    q = p+1
103,390✔
1856
    while true
1,567,194✔
1857
        y = iterate(inds, s)
1,567,205✔
1858
        y === nothing && break
1,567,194✔
1859
        (i,s) = y
1,457,070✔
1860
        if !(q <= i <= n)
1,463,806✔
1861
            if i < q
2✔
1862
                _throw_argerror("indices must be unique and sorted")
1✔
1863
            else
1864
                throw(BoundsError())
1✔
1865
            end
1866
        end
1867
        while q < i
2,888,648✔
1868
            @inbounds _copy_item!(a, p, q)
1,424,844✔
1869
            p += 1; q += 1
1,424,844✔
1870
        end
1,424,844✔
1871
        @inbounds _push_deleted!(dltd, a, i)
1,463,804✔
1872
        q = i+1
1,463,804✔
1873
    end
1,463,804✔
1874
    while q <= n
3,055,050✔
1875
        @inbounds _copy_item!(a, p, q)
2,951,662✔
1876
        p += 1; q += 1
2,951,662✔
1877
    end
2,951,662✔
1878
    _deleteend!(a, n-p+1)
1,567,192✔
1879
    return a
103,388✔
1880
end
1881

1882
# Simpler and more efficient version for logical indexing
1883
function deleteat!(a::Vector, inds::AbstractVector{Bool})
4,029✔
1884
    n = length(a)
4,029✔
1885
    length(inds) == n || throw(BoundsError(a, inds))
4,034✔
1886
    p = 1
4,024✔
1887
    for (q, i) in enumerate(inds)
8,047✔
1888
        @inbounds _copy_item!(a, p, q)
42,194✔
1889
        p += !i
42,194✔
1890
    end
80,365✔
1891
    _deleteend!(a, n-p+1)
21,353✔
1892
    return a
4,024✔
1893
end
1894

1895
const _default_splice = []
1896

1897
"""
1898
    splice!(a::Vector, index::Integer, [replacement]) -> item
1899

1900
Remove the item at the given index, and return the removed item.
1901
Subsequent items are shifted left to fill the resulting gap.
1902
If specified, replacement values from an ordered
1903
collection will be spliced in place of the removed item.
1904

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

1907
# Examples
1908
```jldoctest
1909
julia> A = [6, 5, 4, 3, 2, 1]; splice!(A, 5)
1910
2
1911

1912
julia> A
1913
5-element Vector{Int64}:
1914
 6
1915
 5
1916
 4
1917
 3
1918
 1
1919

1920
julia> splice!(A, 5, -1)
1921
1
1922

1923
julia> A
1924
5-element Vector{Int64}:
1925
  6
1926
  5
1927
  4
1928
  3
1929
 -1
1930

1931
julia> splice!(A, 1, [-1, -2, -3])
1932
6
1933

1934
julia> A
1935
7-element Vector{Int64}:
1936
 -1
1937
 -2
1938
 -3
1939
  5
1940
  4
1941
  3
1942
 -1
1943
```
1944

1945
To insert `replacement` before an index `n` without removing any items, use
1946
`splice!(collection, n:n-1, replacement)`.
1947
"""
1948
function splice!(a::Vector, i::Integer, ins=_default_splice)
3,695✔
1949
    v = a[i]
3,712✔
1950
    m = length(ins)
3,426✔
1951
    if m == 0
3,426✔
1952
        _deleteat!(a, i, 1)
551✔
1953
    elseif m == 1
2,875✔
1954
        a[i] = only(ins)
265✔
1955
    else
1956
        _growat!(a, i, m-1)
2,610✔
1957
        k = 1
2,610✔
1958
        for x in ins
2,610✔
1959
            a[i+k-1] = x
333,695✔
1960
            k += 1
333,695✔
1961
        end
333,695✔
1962
    end
1963
    return v
3,426✔
1964
end
1965

1966
"""
1967
    splice!(a::Vector, indices, [replacement]) -> items
1968

1969
Remove items at specified indices, and return a collection containing
1970
the removed items.
1971
Subsequent items are shifted left to fill the resulting gaps.
1972
If specified, replacement values from an ordered collection will be spliced in
1973
place of the removed items; in this case, `indices` must be a `AbstractUnitRange`.
1974

1975
To insert `replacement` before an index `n` without removing any items, use
1976
`splice!(collection, n:n-1, replacement)`.
1977

1978
$(_DOCS_ALIASING_WARNING)
1979

1980
!!! compat "Julia 1.5"
1981
    Prior to Julia 1.5, `indices` must always be a `UnitRange`.
1982

1983
!!! compat "Julia 1.8"
1984
    Prior to Julia 1.8, `indices` must be a `UnitRange` if splicing in replacement values.
1985

1986
# Examples
1987
```jldoctest
1988
julia> A = [-1, -2, -3, 5, 4, 3, -1]; splice!(A, 4:3, 2)
1989
Int64[]
1990

1991
julia> A
1992
8-element Vector{Int64}:
1993
 -1
1994
 -2
1995
 -3
1996
  2
1997
  5
1998
  4
1999
  3
2000
 -1
2001
```
2002
"""
2003
function splice!(a::Vector, r::AbstractUnitRange{<:Integer}, ins=_default_splice)
19,468,288✔
2004
    v = a[r]
19,538,518✔
2005
    m = length(ins)
71,650✔
2006
    if m == 0
71,650✔
2007
        deleteat!(a, r)
74,059✔
2008
        return v
37,090✔
2009
    end
2010

2011
    n = length(a)
19,397,260✔
2012
    f = first(r)
19,397,259✔
2013
    l = last(r)
19,397,259✔
2014
    d = length(r)
19,397,259✔
2015

2016
    if m < d
19,397,260✔
2017
        delta = d - m
12,627✔
2018
        _deleteat!(a, (f - 1 < n - l) ? f : (l - delta + 1), delta)
19,035✔
2019
    elseif m > d
19,384,633✔
2020
        _growat!(a, (f - 1 < n - l) ? f : (l + 1), m - d)
19,384,524✔
2021
    end
2022

2023
    k = 1
34,560✔
2024
    for x in ins
19,408,766✔
2025
        a[f+k-1] = x
63,459,750✔
2026
        k += 1
62,117,743✔
2027
    end
82,823,619✔
2028
    return v
19,397,260✔
2029
end
2030

2031
splice!(a::Vector, inds) = (dltds = eltype(a)[]; _deleteat!(a, inds, dltds); dltds)
1✔
2032

2033
function empty!(a::Vector)
56✔
2034
    _deleteend!(a, length(a))
90,693,572✔
2035
    return a
77,455,757✔
2036
end
2037

2038
# use memcmp for cmp on byte arrays
2039
function cmp(a::Array{UInt8,1}, b::Array{UInt8,1})
3✔
2040
    aref = a.ref
3✔
2041
    bref = b.ref
3✔
2042
    ta = @_gc_preserve_begin aref
3✔
2043
    tb = @_gc_preserve_begin bref
3✔
2044
    pa = unsafe_convert(Ptr{Cvoid}, aref)
3✔
2045
    pb = unsafe_convert(Ptr{Cvoid}, bref)
3✔
2046
    c = memcmp(pa, pb, min(length(a),length(b)))
3✔
2047
    @_gc_preserve_end ta
3✔
2048
    @_gc_preserve_end tb
3✔
2049
    return c < 0 ? -1 : c > 0 ? +1 : cmp(length(a),length(b))
3✔
2050
end
2051

2052
const BitIntegerArray{N} = Union{map(T->Array{T,N}, BitInteger_types)...} where N
×
2053
# use memcmp for == on bit integer types
2054
function ==(a::Arr, b::Arr) where {Arr <: BitIntegerArray}
1,438✔
2055
    if size(a) == size(b)
4,071✔
2056
        aref = a.ref
2,066✔
2057
        bref = b.ref
2,066✔
2058
        ta = @_gc_preserve_begin aref
2,066✔
2059
        tb = @_gc_preserve_begin bref
2,066✔
2060
        pa = unsafe_convert(Ptr{Cvoid}, aref)
2,066✔
2061
        pb = unsafe_convert(Ptr{Cvoid}, bref)
2,066✔
2062
        c = memcmp(pa, pb, sizeof(eltype(Arr)) * length(a))
2,066✔
2063
        @_gc_preserve_end ta
2,066✔
2064
        @_gc_preserve_end tb
2,066✔
2065
        return c == 0
2,066✔
2066
    else
2067
        return false
×
2068
    end
2069
end
2070

2071
function ==(a::Arr, b::Arr) where Arr <: BitIntegerArray{1}
4,449✔
2072
    len = length(a)
64,662✔
2073
    if len == length(b)
64,662✔
2074
        aref = a.ref
64,538✔
2075
        bref = b.ref
31,626✔
2076
        ta = @_gc_preserve_begin aref
64,538✔
2077
        tb = @_gc_preserve_begin bref
64,538✔
2078
        T = eltype(Arr)
12,706✔
2079
        pa = unsafe_convert(Ptr{T}, aref)
64,538✔
2080
        pb = unsafe_convert(Ptr{T}, bref)
64,538✔
2081
        c = memcmp(pa, pb, sizeof(T) * len)
64,538✔
2082
        @_gc_preserve_end ta
64,538✔
2083
        @_gc_preserve_end tb
64,538✔
2084
        return c == 0
64,538✔
2085
    else
2086
        return false
124✔
2087
    end
2088
end
2089

2090
"""
2091
    reverse(v [, start=firstindex(v) [, stop=lastindex(v) ]] )
2092

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

2096
# Examples
2097
```jldoctest
2098
julia> A = Vector(1:5)
2099
5-element Vector{Int64}:
2100
 1
2101
 2
2102
 3
2103
 4
2104
 5
2105

2106
julia> reverse(A)
2107
5-element Vector{Int64}:
2108
 5
2109
 4
2110
 3
2111
 2
2112
 1
2113

2114
julia> reverse(A, 1, 4)
2115
5-element Vector{Int64}:
2116
 4
2117
 3
2118
 2
2119
 1
2120
 5
2121

2122
julia> reverse(A, 3, 5)
2123
5-element Vector{Int64}:
2124
 1
2125
 2
2126
 5
2127
 4
2128
 3
2129
```
2130
"""
2131
function reverse(A::AbstractVector, start::Integer, stop::Integer=lastindex(A))
7,509✔
2132
    s, n = Int(start), Int(stop)
928✔
2133
    B = similar(A)
14,745✔
2134
    for i = firstindex(A):s-1
7,510✔
2135
        B[i] = A[i]
1,684✔
2136
    end
3,078✔
2137
    for i = s:n
7,522✔
2138
        B[i] = A[n+s-i]
289,218✔
2139
    end
570,940✔
2140
    for i = n+1:lastindex(A)
14,728✔
2141
        B[i] = A[i]
1,690✔
2142
    end
3,090✔
2143
    return B
7,509✔
2144
end
2145

2146
# 1d special cases of reverse(A; dims) and reverse!(A; dims):
2147
for (f,_f) in ((:reverse,:_reverse), (:reverse!,:_reverse!))
2148
    @eval begin
2149
        $f(A::AbstractVector; dims=:) = $_f(A, dims)
161,951,999✔
2150
        $_f(A::AbstractVector, ::Colon) = $f(A, firstindex(A), lastindex(A))
10,946✔
2151
        $_f(A::AbstractVector, dim::Tuple{Integer}) = $_f(A, first(dim))
×
2152
        function $_f(A::AbstractVector, dim::Integer)
2153
            dim == 1 || _throw_argerror(LazyString("invalid dimension ", dim, " ≠ 1"))
11✔
2154
            return $_f(A, :)
4✔
2155
        end
2156
    end
2157
end
2158

2159
function reverseind(a::AbstractVector, i::Integer)
3✔
2160
    li = LinearIndices(a)
3✔
2161
    first(li) + last(li) - i
3✔
2162
end
2163

2164
# This implementation of `midpoint` is performance-optimized but safe
2165
# only if `lo <= hi`.
2166
midpoint(lo::T, hi::T) where T<:Integer = lo + ((hi - lo) >>> 0x01)
16,957,358✔
2167
midpoint(lo::Integer, hi::Integer) = midpoint(promote(lo, hi)...)
×
2168

2169
"""
2170
    reverse!(v [, start=firstindex(v) [, stop=lastindex(v) ]]) -> v
2171

2172
In-place version of [`reverse`](@ref).
2173

2174
# Examples
2175
```jldoctest
2176
julia> A = Vector(1:5)
2177
5-element Vector{Int64}:
2178
 1
2179
 2
2180
 3
2181
 4
2182
 5
2183

2184
julia> reverse!(A);
2185

2186
julia> A
2187
5-element Vector{Int64}:
2188
 5
2189
 4
2190
 3
2191
 2
2192
 1
2193
```
2194
"""
2195
function reverse!(v::AbstractVector, start::Integer, stop::Integer=lastindex(v))
145,603✔
2196
    s, n = Int(start), Int(stop)
119,402✔
2197
    if n > s # non-empty and non-trivial
145,600✔
2198
        liv = LinearIndices(v)
138,279✔
2199
        if !(first(liv) ≤ s ≤ last(liv))
138,279✔
2200
            throw(BoundsError(v, s))
3✔
2201
        elseif !(first(liv) ≤ n ≤ last(liv))
138,276✔
2202
            throw(BoundsError(v, n))
1✔
2203
        end
2204
        r = n
113,262✔
2205
        @inbounds for i in s:midpoint(s, n-1)
138,275✔
2206
            v[i], v[r] = v[r], v[i]
1,978,847✔
2207
            r -= 1
1,978,847✔
2208
        end
3,819,419✔
2209
    end
2210
    return v
145,596✔
2211
end
2212

2213
# concatenations of (in)homogeneous combinations of vectors, horizontal and vertical
2214

2215
vcat() = Vector{Any}()
10,242✔
2216
hcat() = Vector{Any}()
1✔
2217

2218
function hcat(V::Vector{T}...) where T
61✔
2219
    height = length(V[1])
569✔
2220
    for j = 2:length(V)
569✔
2221
        if length(V[j]) != height
635✔
2222
            throw(DimensionMismatch("vectors must have same lengths"))
1✔
2223
        end
2224
    end
732✔
2225
    return [ V[j][i]::T for i=1:length(V[1]), j=1:length(V) ]
568✔
2226
end
2227
hcat(A::Vector...) = cat(A...; dims=Val(2)) # more special than SparseArrays's hcat
6✔
2228

2229
function vcat(arrays::Vector{T}...) where T
36,121✔
2230
    n = 0
4,153✔
2231
    for a in arrays
36,121✔
2232
        n += length(a)
2,072,588✔
2233
    end
2,108,704✔
2234
    arr = Vector{T}(undef, n)
72,219✔
2235
    nd = 1
4,153✔
2236
    for a in arrays
36,121✔
2237
        na = length(a)
2,072,588✔
2238
        @assert nd + na <= 1 + length(arr) # Concurrent modification of arrays?
2,072,588✔
2239
        unsafe_copyto!(arr, nd, a, 1, na)
4,140,833✔
2240
        nd += na
2,072,588✔
2241
    end
2,108,704✔
2242
    return arr
36,121✔
2243
end
2244
vcat(A::Vector...) = cat(A...; dims=Val(1)) # more special than SparseArrays's vcat
28✔
2245

2246
_cat(n::Integer, x::Integer...) = reshape([x...], (ntuple(Returns(1), n-1)..., length(x)))
1✔
2247

2248
## find ##
2249

2250
"""
2251
    findnext(A, i)
2252

2253
Find the next index after or including `i` of a `true` element of `A`,
2254
or `nothing` if not found.
2255

2256
Indices are of the same type as those returned by [`keys(A)`](@ref)
2257
and [`pairs(A)`](@ref).
2258

2259
# Examples
2260
```jldoctest
2261
julia> A = [false, false, true, false]
2262
4-element Vector{Bool}:
2263
 0
2264
 0
2265
 1
2266
 0
2267

2268
julia> findnext(A, 1)
2269
3
2270

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

2273
julia> A = [false false; true false]
2274
2×2 Matrix{Bool}:
2275
 0  0
2276
 1  0
2277

2278
julia> findnext(A, CartesianIndex(1, 1))
2279
CartesianIndex(2, 1)
2280
```
2281
"""
2282
findnext(A, start) = findnext(identity, A, start)
43,236✔
2283

2284
"""
2285
    findfirst(A)
2286

2287
Return the index or key of the first `true` value in `A`.
2288
Return `nothing` if no such value is found.
2289
To search for other kinds of values, pass a predicate as the first argument.
2290

2291
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
2292
and [`pairs(A)`](@ref).
2293

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

2296
# Examples
2297
```jldoctest
2298
julia> A = [false, false, true, false]
2299
4-element Vector{Bool}:
2300
 0
2301
 0
2302
 1
2303
 0
2304

2305
julia> findfirst(A)
2306
3
2307

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

2310
julia> A = [false false; true false]
2311
2×2 Matrix{Bool}:
2312
 0  0
2313
 1  0
2314

2315
julia> findfirst(A)
2316
CartesianIndex(2, 1)
2317
```
2318
"""
2319
findfirst(A) = findfirst(identity, A)
2✔
2320

2321
# Needed for bootstrap, and allows defining only an optimized findnext method
2322
findfirst(A::AbstractArray) = findnext(A, first(keys(A)))
11,978✔
2323

2324
"""
2325
    findnext(predicate::Function, A, i)
2326

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

2332
Indices are of the same type as those returned by [`keys(A)`](@ref)
2333
and [`pairs(A)`](@ref).
2334

2335
# Examples
2336
```jldoctest
2337
julia> A = [1, 4, 2, 2];
2338

2339
julia> findnext(isodd, A, 1)
2340
1
2341

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

2344
julia> A = [1 4; 2 2];
2345

2346
julia> findnext(isodd, A, CartesianIndex(1, 1))
2347
CartesianIndex(1, 1)
2348

2349
julia> findnext(isspace, "a b c", 3)
2350
4
2351
```
2352
"""
2353
function findnext(testf::Function, A, start)
19,395✔
2354
    i = oftype(first(keys(A)), start)
45,025✔
2355
    l = last(keys(A))
80,964,829✔
2356
    i > l && return nothing
80,964,829✔
2357
    while true
196,562,894✔
2358
        testf(A[i]) && return i
196,584,010✔
2359
        i == l && break
189,122,127✔
2360
        # nextind(A, l) can throw/overflow
2361
        i = nextind(A, i)
184,739,123✔
2362
    end
184,739,122✔
2363
    return nothing
4,383,003✔
2364
end
2365

2366
"""
2367
    findfirst(predicate::Function, A)
2368

2369
Return the index or key of the first element of `A` for which `predicate` returns `true`.
2370
Return `nothing` if there is no such element.
2371

2372
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
2373
and [`pairs(A)`](@ref).
2374

2375
# Examples
2376
```jldoctest
2377
julia> A = [1, 4, 2, 2]
2378
4-element Vector{Int64}:
2379
 1
2380
 4
2381
 2
2382
 2
2383

2384
julia> findfirst(iseven, A)
2385
2
2386

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

2389
julia> findfirst(isequal(4), A)
2390
2
2391

2392
julia> A = [1 4; 2 2]
2393
2×2 Matrix{Int64}:
2394
 1  4
2395
 2  2
2396

2397
julia> findfirst(iseven, A)
2398
CartesianIndex(2, 1)
2399
```
2400
"""
2401
function findfirst(testf::Function, A)
15✔
2402
    for (i, a) in pairs(A)
22✔
2403
        testf(a) && return i
14✔
2404
    end
11✔
2405
    return nothing
8✔
2406
end
2407

2408
# Needed for bootstrap, and allows defining only an optimized findnext method
2409
findfirst(testf::Function, A::Union{AbstractArray, AbstractString}) =
278,391,751✔
2410
    findnext(testf, A, first(keys(A)))
2411

2412
findfirst(p::Union{Fix2{typeof(isequal),Int},Fix2{typeof(==),Int}}, r::OneTo{Int}) =
3✔
2413
    1 <= p.x <= r.stop ? p.x : nothing
2414

2415
findfirst(p::Union{Fix2{typeof(isequal),T},Fix2{typeof(==),T}}, r::AbstractUnitRange) where {T<:Integer} =
4✔
2416
    first(r) <= p.x <= last(r) ? firstindex(r) + Int(p.x - first(r)) : nothing
2417

2418
function findfirst(p::Union{Fix2{typeof(isequal),T},Fix2{typeof(==),T}}, r::StepRange{T,S}) where {T,S}
6✔
2419
    isempty(r) && return nothing
6✔
2420
    minimum(r) <= p.x <= maximum(r) || return nothing
7✔
2421
    d = convert(S, p.x - first(r))::S
3✔
2422
    iszero(d % step(r)) || return nothing
3✔
2423
    return d ÷ step(r) + 1
3✔
2424
end
2425

2426
"""
2427
    findprev(A, i)
2428

2429
Find the previous index before or including `i` of a `true` element of `A`,
2430
or `nothing` if not found.
2431

2432
Indices are of the same type as those returned by [`keys(A)`](@ref)
2433
and [`pairs(A)`](@ref).
2434

2435
See also: [`findnext`](@ref), [`findfirst`](@ref), [`findall`](@ref).
2436

2437
# Examples
2438
```jldoctest
2439
julia> A = [false, false, true, true]
2440
4-element Vector{Bool}:
2441
 0
2442
 0
2443
 1
2444
 1
2445

2446
julia> findprev(A, 3)
2447
3
2448

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

2451
julia> A = [false false; true true]
2452
2×2 Matrix{Bool}:
2453
 0  0
2454
 1  1
2455

2456
julia> findprev(A, CartesianIndex(2, 1))
2457
CartesianIndex(2, 1)
2458
```
2459
"""
2460
findprev(A, start) = findprev(identity, A, start)
8,326✔
2461

2462
"""
2463
    findlast(A)
2464

2465
Return the index or key of the last `true` value in `A`.
2466
Return `nothing` if there is no `true` value in `A`.
2467

2468
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
2469
and [`pairs(A)`](@ref).
2470

2471
See also: [`findfirst`](@ref), [`findprev`](@ref), [`findall`](@ref).
2472

2473
# Examples
2474
```jldoctest
2475
julia> A = [true, false, true, false]
2476
4-element Vector{Bool}:
2477
 1
2478
 0
2479
 1
2480
 0
2481

2482
julia> findlast(A)
2483
3
2484

2485
julia> A = falses(2,2);
2486

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

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

2494
julia> findlast(A)
2495
CartesianIndex(2, 1)
2496
```
2497
"""
2498
findlast(A) = findlast(identity, A)
23✔
2499

2500
# Needed for bootstrap, and allows defining only an optimized findprev method
2501
findlast(A::AbstractArray) = findprev(A, last(keys(A)))
248✔
2502

2503
"""
2504
    findprev(predicate::Function, A, i)
2505

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

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

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

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

2525
julia> findprev(isodd, A, 3)
2526
3
2527

2528
julia> A = [4 6; 1 2]
2529
2×2 Matrix{Int64}:
2530
 4  6
2531
 1  2
2532

2533
julia> findprev(isodd, A, CartesianIndex(1, 2))
2534
CartesianIndex(2, 1)
2535

2536
julia> findprev(isspace, "a b c", 3)
2537
2
2538
```
2539
"""
2540
function findprev(testf::Function, A, start)
155✔
2541
    f = first(keys(A))
36,778✔
2542
    i = oftype(f, start)
36,783✔
2543
    i < f && return nothing
38,475✔
2544
    while true
181,795✔
2545
        testf(A[i]) && return i
182,097✔
2546
        i == f && break
143,418✔
2547
        # prevind(A, f) can throw/underflow
2548
        i = prevind(A, i)
143,323✔
2549
    end
143,321✔
2550
    return nothing
94✔
2551
end
2552

2553
"""
2554
    findlast(predicate::Function, A)
2555

2556
Return the index or key of the last element of `A` for which `predicate` returns `true`.
2557
Return `nothing` if there is no such element.
2558

2559
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
2560
and [`pairs(A)`](@ref).
2561

2562
# Examples
2563
```jldoctest
2564
julia> A = [1, 2, 3, 4]
2565
4-element Vector{Int64}:
2566
 1
2567
 2
2568
 3
2569
 4
2570

2571
julia> findlast(isodd, A)
2572
3
2573

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

2576
julia> A = [1 2; 3 4]
2577
2×2 Matrix{Int64}:
2578
 1  2
2579
 3  4
2580

2581
julia> findlast(isodd, A)
2582
CartesianIndex(2, 1)
2583
```
2584
"""
2585
function findlast(testf::Function, A)
3✔
2586
    for (i, a) in Iterators.reverse(pairs(A))
4✔
2587
        testf(a) && return i
6✔
2588
    end
6✔
2589
    return nothing
2✔
2590
end
2591

2592
# Needed for bootstrap, and allows defining only an optimized findprev method
2593
findlast(testf::Function, A::Union{AbstractArray, AbstractString}) =
15,654✔
2594
    findprev(testf, A, last(keys(A)))
2595

2596
"""
2597
    findall(f::Function, A)
2598

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

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

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

2613
julia> findall(isodd, x)
2614
2-element Vector{Int64}:
2615
 1
2616
 2
2617

2618
julia> A = [1 2 0; 3 4 0]
2619
2×3 Matrix{Int64}:
2620
 1  2  0
2621
 3  4  0
2622
julia> findall(isodd, A)
2623
2-element Vector{CartesianIndex{2}}:
2624
 CartesianIndex(1, 1)
2625
 CartesianIndex(2, 1)
2626

2627
julia> findall(!iszero, A)
2628
4-element Vector{CartesianIndex{2}}:
2629
 CartesianIndex(1, 1)
2630
 CartesianIndex(2, 1)
2631
 CartesianIndex(1, 2)
2632
 CartesianIndex(2, 2)
2633

2634
julia> d = Dict(:A => 10, :B => -1, :C => 0)
2635
Dict{Symbol, Int64} with 3 entries:
2636
  :A => 10
2637
  :B => -1
2638
  :C => 0
2639

2640
julia> findall(≥(0), d)
2641
2-element Vector{Symbol}:
2642
 :A
2643
 :C
2644

2645
```
2646
"""
2647
function findall(testf::Function, A)
24✔
2648
    gen = (first(p) for p in pairs(A) if testf(last(p)))
36✔
2649
    @default_eltype(gen) === Union{} ? collect(@default_eltype(keys(A)), gen) : collect(gen)
36✔
2650
end
2651

2652
# Broadcasting is much faster for small testf, and computing
2653
# integer indices from logical index using findall has a negligible cost
2654
findall(testf::F, A::AbstractArray) where {F<:Function} = findall(testf.(A))
267✔
2655

2656
"""
2657
    findall(A)
2658

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

2663
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
2664
and [`pairs(A)`](@ref).
2665

2666
See also: [`findfirst`](@ref), [`searchsorted`](@ref).
2667

2668
# Examples
2669
```jldoctest
2670
julia> A = [true, false, false, true]
2671
4-element Vector{Bool}:
2672
 1
2673
 0
2674
 0
2675
 1
2676

2677
julia> findall(A)
2678
2-element Vector{Int64}:
2679
 1
2680
 4
2681

2682
julia> A = [true false; false true]
2683
2×2 Matrix{Bool}:
2684
 1  0
2685
 0  1
2686

2687
julia> findall(A)
2688
2-element Vector{CartesianIndex{2}}:
2689
 CartesianIndex(1, 1)
2690
 CartesianIndex(2, 2)
2691

2692
julia> findall(falses(3))
2693
Int64[]
2694
```
2695
"""
2696
function findall(A)
4✔
2697
    collect(first(p) for p in pairs(A) if last(p))
4✔
2698
end
2699

2700
# Allocating result upfront is faster (possible only when collection can be iterated twice)
2701
function findall(A::AbstractArray{Bool})
823✔
2702
    n = count(A)
3,689✔
2703
    I = Vector{eltype(keys(A))}(undef, n)
6,994✔
2704
    cnt = 1
3,684✔
2705
    for (i,a) in pairs(A)
7,360✔
2706
        if a
208,878✔
2707
            I[cnt] = i
130,561✔
2708
            cnt += 1
130,561✔
2709
        end
2710
    end
414,077✔
2711
    I
3,684✔
2712
end
2713

2714
findall(x::Bool) = x ? [1] : Vector{Int}()
2✔
2715
findall(testf::Function, x::Number) = testf(x) ? [1] : Vector{Int}()
2✔
2716
findall(p::Fix2{typeof(in)}, x::Number) = x in p.x ? [1] : Vector{Int}()
2✔
2717

2718
# similar to Matlab's ismember
2719
"""
2720
    indexin(a, b)
2721

2722
Return an array containing the first index in `b` for
2723
each value in `a` that is a member of `b`. The output
2724
array contains `nothing` wherever `a` is not a member of `b`.
2725

2726
See also: [`sortperm`](@ref), [`findfirst`](@ref).
2727

2728
# Examples
2729
```jldoctest
2730
julia> a = ['a', 'b', 'c', 'b', 'd', 'a'];
2731

2732
julia> b = ['a', 'b', 'c'];
2733

2734
julia> indexin(a, b)
2735
6-element Vector{Union{Nothing, Int64}}:
2736
 1
2737
 2
2738
 3
2739
 2
2740
  nothing
2741
 1
2742

2743
julia> indexin(b, a)
2744
3-element Vector{Union{Nothing, Int64}}:
2745
 1
2746
 2
2747
 3
2748
```
2749
"""
2750
function indexin(a, b::AbstractArray)
7✔
2751
    inds = keys(b)
7✔
2752
    bdict = Dict{eltype(b),eltype(inds)}()
7✔
2753
    for (val, ind) in zip(b, inds)
14✔
2754
        get!(bdict, val, ind)
30✔
2755
    end
53✔
2756
    return Union{eltype(inds), Nothing}[
7✔
2757
        get(bdict, i, nothing) for i in a
2758
    ]
2759
end
2760

2761
function _findin(a::Union{AbstractArray, Tuple}, b)
375✔
2762
    ind  = Vector{eltype(keys(a))}()
561✔
2763
    bset = Set(b)
377✔
2764
    @inbounds for (i,ai) in pairs(a)
606✔
2765
        ai in bset && push!(ind, i)
90,559✔
2766
    end
180,565✔
2767
    ind
375✔
2768
end
2769

2770
# If two collections are already sorted, _findin can be computed with
2771
# a single traversal of the two collections. This is much faster than
2772
# using a hash table (although it has the same complexity).
2773
function _sortedfindin(v::Union{AbstractArray, Tuple}, w)
9✔
2774
    viter, witer = keys(v), eachindex(w)
9✔
2775
    out  = eltype(viter)[]
9✔
2776
    vy, wy = iterate(viter), iterate(witer)
11✔
2777
    if vy === nothing || wy === nothing
17✔
2778
        return out
2✔
2779
    end
2780
    viteri, i = vy
7✔
2781
    witerj, j = wy
7✔
2782
    @inbounds begin
7✔
2783
        vi, wj = v[viteri], w[witerj]
7✔
2784
        while true
54✔
2785
            if isless(vi, wj)
56✔
2786
                vy = iterate(viter, i)
25✔
2787
                if vy === nothing
14✔
2788
                    break
2✔
2789
                end
2790
                viteri, i = vy
12✔
2791
                vi        = v[viteri]
12✔
2792
            elseif isless(wj, vi)
40✔
2793
                wy = iterate(witer, j)
44✔
2794
                if wy === nothing
24✔
2795
                    break
4✔
2796
                end
2797
                witerj, j = wy
20✔
2798
                wj        = w[witerj]
20✔
2799
            else
2800
                push!(out, viteri)
16✔
2801
                vy = iterate(viter, i)
25✔
2802
                if vy === nothing
16✔
2803
                    break
1✔
2804
                end
2805
                # We only increment the v iterator because v can have
2806
                # repeated matches to a single value in w
2807
                viteri, i = vy
15✔
2808
                vi        = v[viteri]
15✔
2809
            end
2810
        end
47✔
2811
    end
2812
    return out
7✔
2813
end
2814

2815
function findall(pred::Fix2{typeof(in),<:Union{Array{<:Real},Real}}, x::Array{<:Real})
15✔
2816
    if issorted(x, Sort.Forward) && issorted(pred.x, Sort.Forward)
25✔
2817
        return _sortedfindin(x, pred.x)
9✔
2818
    else
2819
        return _findin(x, pred.x)
6✔
2820
    end
2821
end
2822
# issorted fails for some element types so the method above has to be restricted
2823
# to element with isless/< defined.
2824
findall(pred::Fix2{typeof(in)}, x::AbstractArray) = _findin(x, pred.x)
373✔
2825
findall(pred::Fix2{typeof(in)}, x::Tuple) = _findin(x, pred.x)
×
2826

2827
# Copying subregions
2828
function indcopy(sz::Dims, I::Vector)
1✔
2829
    n = length(I)
1✔
2830
    s = sz[n]
1✔
2831
    for i = n+1:length(sz)
2✔
2832
        s *= sz[i]
×
2833
    end
×
2834
    dst = eltype(I)[_findin(I[i], i < n ? (1:sz[i]) : (1:s)) for i = 1:n]
2✔
2835
    src = eltype(I)[I[i][_findin(I[i], i < n ? (1:sz[i]) : (1:s))] for i = 1:n]
2✔
2836
    dst, src
1✔
2837
end
2838

2839
function indcopy(sz::Dims, I::Tuple{Vararg{RangeIndex}})
1✔
2840
    n = length(I)
1✔
2841
    s = sz[n]
1✔
2842
    for i = n+1:length(sz)
1✔
2843
        s *= sz[i]
×
2844
    end
×
2845
    dst::typeof(I) = ntuple(i-> _findin(I[i], i < n ? (1:sz[i]) : (1:s)), n)::typeof(I)
3✔
2846
    src::typeof(I) = ntuple(i-> I[i][_findin(I[i], i < n ? (1:sz[i]) : (1:s))], n)::typeof(I)
3✔
2847
    dst, src
1✔
2848
end
2849

2850
## Filter ##
2851

2852
"""
2853
    filter(f, a)
2854

2855
Return a copy of collection `a`, removing elements for which `f` is `false`.
2856
The function `f` is passed one argument.
2857

2858
!!! compat "Julia 1.4"
2859
    Support for `a` as a tuple requires at least Julia 1.4.
2860

2861
See also: [`filter!`](@ref), [`Iterators.filter`](@ref).
2862

2863
# Examples
2864
```jldoctest
2865
julia> a = 1:10
2866
1:10
2867

2868
julia> filter(isodd, a)
2869
5-element Vector{Int64}:
2870
 1
2871
 3
2872
 5
2873
 7
2874
 9
2875
```
2876
"""
2877
function filter(f, a::Array{T, N}) where {T, N}
4,714✔
2878
    j = 1
2,178✔
2879
    b = Vector{T}(undef, length(a))
9,309✔
2880
    for ai in a
4,714✔
2881
        @inbounds b[j] = ai
1,816,719✔
2882
        j = ifelse(f(ai)::Bool, j+1, j)
1,817,899✔
2883
    end
1,816,719✔
2884
    resize!(b, j-1)
4,714✔
2885
    sizehint!(b, length(b))
4,714✔
2886
    b
2,178✔
2887
end
2888

2889
function filter(f, a::AbstractArray)
450✔
2890
    (IndexStyle(a) != IndexLinear()) && return a[map(f, a)::AbstractArray{Bool}]
450✔
2891

2892
    j = 1
450✔
2893
    idxs = Vector{Int}(undef, length(a))
738✔
2894
    for idx in eachindex(a)
453✔
2895
        @inbounds idxs[j] = idx
103,297✔
2896
        ai = @inbounds a[idx]
103,297✔
2897
        j = ifelse(f(ai)::Bool, j+1, j)
104,830✔
2898
    end
206,305✔
2899
    resize!(idxs, j-1)
449✔
2900
    res = a[idxs]
449✔
2901
    empty!(idxs)
4,032✔
2902
    sizehint!(idxs, 0)
449✔
2903
    return res
449✔
2904
end
2905

2906
"""
2907
    filter!(f, a)
2908

2909
Update collection `a`, removing elements for which `f` is `false`.
2910
The function `f` is passed one argument.
2911

2912
# Examples
2913
```jldoctest
2914
julia> filter!(isodd, Vector(1:10))
2915
5-element Vector{Int64}:
2916
 1
2917
 3
2918
 5
2919
 7
2920
 9
2921
```
2922
"""
2923
function filter!(f, a::AbstractVector)
995,811✔
2924
    j = firstindex(a)
882✔
2925
    for ai in a
115,863,621✔
2926
        @inbounds a[j] = ai
134,157,403✔
2927
        j = ifelse(f(ai)::Bool, nextind(a, j), j)
136,012,228✔
2928
    end
134,157,412✔
2929
    j > lastindex(a) && return a
115,863,619✔
2930
    if a isa Vector
383✔
2931
        resize!(a, j-1)
67,290✔
2932
        sizehint!(a, j-1)
67,290✔
2933
    else
2934
        deleteat!(a, j:lastindex(a))
1✔
2935
    end
2936
    return a
67,291✔
2937
end
2938

2939
"""
2940
    filter(f)
2941

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

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

2948
# Examples
2949
```jldoctest
2950
julia> (1, 2, Inf, 4, NaN, 6) |> filter(isfinite)
2951
(1, 2, 4, 6)
2952

2953
julia> map(filter(iseven), [1:3, 2:4, 3:5])
2954
3-element Vector{Vector{Int64}}:
2955
 [2]
2956
 [2, 4]
2957
 [4]
2958
```
2959
!!! compat "Julia 1.9"
2960
    This method requires at least Julia 1.9.
2961
"""
2962
function filter(f)
1✔
2963
    Fix1(filter, f)
1✔
2964
end
2965

2966
"""
2967
    keepat!(a::Vector, inds)
2968
    keepat!(a::BitVector, inds)
2969

2970
Remove the items at all the indices which are not given by `inds`,
2971
and return the modified `a`.
2972
Items which are kept are shifted to fill the resulting gaps.
2973

2974
$(_DOCS_ALIASING_WARNING)
2975

2976
`inds` must be an iterator of sorted and unique integer indices.
2977
See also [`deleteat!`](@ref).
2978

2979
!!! compat "Julia 1.7"
2980
    This function is available as of Julia 1.7.
2981

2982
# Examples
2983
```jldoctest
2984
julia> keepat!([6, 5, 4, 3, 2, 1], 1:2:5)
2985
3-element Vector{Int64}:
2986
 6
2987
 4
2988
 2
2989
```
2990
"""
2991
keepat!(a::Vector, inds) = _keepat!(a, inds)
9✔
2992

2993
"""
2994
    keepat!(a::Vector, m::AbstractVector{Bool})
2995
    keepat!(a::BitVector, m::AbstractVector{Bool})
2996

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

3001
# Examples
3002
```jldoctest
3003
julia> a = [:a, :b, :c];
3004

3005
julia> keepat!(a, [true, false, true])
3006
2-element Vector{Symbol}:
3007
 :a
3008
 :c
3009

3010
julia> a
3011
2-element Vector{Symbol}:
3012
 :a
3013
 :c
3014
```
3015
"""
3016
keepat!(a::Vector, m::AbstractVector{Bool}) = _keepat!(a, m)
4✔
3017

3018
# set-like operators for vectors
3019
# These are moderately efficient, preserve order, and remove dupes.
3020

3021
_unique_filter!(pred::P, update!::U, state) where {P,U} = function (x)
17,798✔
3022
    # P, U force specialization
3023
    if pred(x, state)
32,579✔
3024
        update!(state, x)
7,501✔
3025
        true
3026
    else
3027
        false
3028
    end
3029
end
3030

3031
_grow_filter!(seen) = _unique_filter!(∉, push!, seen)
178✔
3032
_shrink_filter!(keep) = _unique_filter!(∈, pop!, keep)
1,039✔
3033

3034
function _grow!(pred!, v::AbstractVector, itrs)
78✔
3035
    filter!(pred!, v) # uniquify v
188✔
3036
    for itr in itrs
188✔
3037
        mapfilter(pred!, push!, itr, v)
379✔
3038
    end
561✔
3039
    return v
188✔
3040
end
3041

3042
union!(v::AbstractVector{T}, itrs...) where {T} =
178✔
3043
    _grow!(_grow_filter!(sizehint!(Set{T}(), length(v))), v, itrs)
3044

3045
symdiff!(v::AbstractVector{T}, itrs...) where {T} =
10✔
3046
    _grow!(_shrink_filter!(symdiff!(Set{T}(), v, itrs...)), v, itrs)
3047

UNCOV
3048
function _shrink!(shrinker!::F, v::AbstractVector, itrs) where F
×
UNCOV
3049
    seen = Set{eltype(v)}()
×
UNCOV
3050
    filter!(_grow_filter!(seen), v)
×
UNCOV
3051
    shrinker!(seen, itrs...)
×
UNCOV
3052
    filter!(in(seen), v)
×
3053
end
3054

UNCOV
3055
intersect!(v::AbstractVector, itrs...) = _shrink!(intersect!, v, itrs)
×
UNCOV
3056
setdiff!(  v::AbstractVector, itrs...) = _shrink!(setdiff!, v, itrs)
×
3057

3058
vectorfilter(T::Type, f, v) = T[x for x in v if f(x)]
1,029✔
3059

3060
function _shrink(shrinker!::F, itr, itrs) where F
959✔
3061
    T = promote_eltype(itr, itrs...)
882✔
3062
    keep = shrinker!(Set{T}(itr), itrs...)
1,986✔
3063
    vectorfilter(T, _shrink_filter!(keep), itr)
975✔
3064
end
3065

3066
intersect(itr, itrs...) = _shrink(intersect!, itr, itrs)
395✔
3067
setdiff(  itr, itrs...) = _shrink(setdiff!, itr, itrs)
580✔
3068

3069
function intersect(v::AbstractVector, r::AbstractRange)
4✔
3070
    T = promote_eltype(v, r)
6✔
3071
    common = Iterators.filter(in(r), v)
54✔
3072
    seen = Set{T}(common)
54✔
3073
    return vectorfilter(T, _shrink_filter!(seen), common)
54✔
3074
end
3075
intersect(r::AbstractRange, v::AbstractVector) = intersect(v, r)
2✔
3076

3077
# Here instead of range.jl for bootstrapping because `@propagate_inbounds` depends on Vectors.
3078
@propagate_inbounds function getindex(v::AbstractRange, i::Integer)
2,646✔
3079
    if i isa Bool # Not via dispatch to avoid ambiguities
28,471,182✔
3080
        throw(ArgumentError("invalid index: $i of type Bool"))
6✔
3081
    else
3082
        _getindex(v, i)
541,976,610✔
3083
    end
3084
end
3085

3086
"""
3087
    wrap(Array, m::Union{Memory{T}, MemoryRef{T}}, dims)
3088

3089
Create an array of size `dims` using `m` as the underlying memory. This can be thought of as a safe version
3090
of [`unsafe_wrap`](@ref) utilizing `Memory` or `MemoryRef` instead of raw pointers.
3091
"""
3092
function wrap end
3093

3094
# validity checking for _wrap calls, separate from allocation of Array so that it can be more likely to inline into the caller
3095
function _wrap(ref::MemoryRef{T}, dims::NTuple{N, Int}) where {T, N}
211✔
3096
    mem = ref.mem
5,773,637✔
3097
    mem_len = length(mem) + 1 - memoryrefoffset(ref)
5,773,637✔
3098
    len = Core.checked_dims(dims...)
221✔
3099
    @boundscheck mem_len >= len || invalid_wrap_err(mem_len, dims, len)
5,773,640✔
3100
    if N != 1 && !(ref === GenericMemoryRef(mem) && len === mem_len)
9✔
3101
        mem = ccall(:jl_genericmemory_slice, Memory{T}, (Any, Ptr{Cvoid}, Int), mem, ref.ptr_or_offset, len)
3✔
3102
        ref = memoryref(mem)
3✔
3103
    end
3104
    return ref
5,773,634✔
3105
end
3106

3107
@noinline invalid_wrap_err(len, dims, proddims) = throw(DimensionMismatch(LazyString(
3✔
3108
    "Attempted to wrap a MemoryRef of length ", len, " with an Array of size dims=", dims,
3109
    " which is invalid because prod(dims) = ", proddims, " > ", len,
3110
    " so that the array would have more elements than the underlying memory can store.")))
3111

3112
@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, dims::NTuple{N, Integer}) where {T, N}
4✔
3113
    dims = convert(Dims, dims)
4✔
3114
    ref = _wrap(m, dims)
4✔
3115
    $(Expr(:new, :(Array{T, N}), :ref, :dims))
4✔
3116
end
3117

3118
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, dims::NTuple{N, Integer}) where {T, N}
3✔
3119
    dims = convert(Dims, dims)
3✔
3120
    ref = _wrap(memoryref(m), dims)
4✔
3121
    $(Expr(:new, :(Array{T, N}), :ref, :dims))
2✔
3122
end
3123
@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, l::Integer) where {T}
4✔
3124
    dims = (Int(l),)
5,773,420✔
3125
    ref = _wrap(m, dims)
5,773,422✔
3126
    $(Expr(:new, :(Array{T, 1}), :ref, :dims))
624,743✔
3127
end
3128
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, l::Integer) where {T}
1✔
3129
    dims = (Int(l),)
1✔
3130
    ref = _wrap(memoryref(m), (l,))
1✔
3131
    $(Expr(:new, :(Array{T, 1}), :ref, :dims))
1✔
3132
end
3133
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}) where {T}
3134
    ref = memoryref(m)
1,572,611✔
3135
    dims = (length(m),)
1,572,611✔
3136
    $(Expr(:new, :(Array{T, 1}), :ref, :dims))
1,548,645✔
3137
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