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

JuliaLang / julia / #37477

pending completion
#37477

push

local

web-flow
Allow external lattice elements to properly union split (#49030)

Currently `MustAlias` is the only lattice element that is allowed
to widen to union types. However, there are others in external
packages. Expand the support we have for this in order to allow
union splitting of lattice elements.

Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com>

26 of 26 new or added lines in 5 files covered. (100.0%)

71476 of 82705 relevant lines covered (86.42%)

34756248.54 hits per line

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

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

3
 ## Basic functions ##
4

5
isreal(x::AbstractArray) = all(isreal,x)
3,777✔
6
iszero(x::AbstractArray) = all(iszero,x)
4,603✔
7
isreal(x::AbstractArray{<:Real}) = true
410✔
8

9
## Constructors ##
10

11
"""
12
    vec(a::AbstractArray) -> AbstractVector
13

14
Reshape the array `a` as a one-dimensional column vector. Return `a` if it is
15
already an `AbstractVector`. The resulting array
16
shares the same underlying data as `a`, so it will only be mutable if `a` is
17
mutable, in which case modifying one will also modify the other.
18

19
# Examples
20
```jldoctest
21
julia> a = [1 2 3; 4 5 6]
22
2×3 Matrix{Int64}:
23
 1  2  3
24
 4  5  6
25

26
julia> vec(a)
27
6-element Vector{Int64}:
28
 1
29
 4
30
 2
31
 5
32
 3
33
 6
34

35
julia> vec(1:3)
36
1:3
37
```
38

39
See also [`reshape`](@ref), [`dropdims`](@ref).
40
"""
41
vec(a::AbstractArray) = reshape(a,length(a))
2,627✔
42
vec(a::AbstractVector) = a
229✔
43

44
_sub(::Tuple{}, ::Tuple{}) = ()
×
45
_sub(t::Tuple, ::Tuple{}) = t
26✔
46
_sub(t::Tuple, s::Tuple) = _sub(tail(t), tail(s))
36✔
47

48
"""
49
    dropdims(A; dims)
50

51
Return an array with the same data as `A`, but with the dimensions specified by
52
`dims` removed. `size(A,d)` must equal 1 for every `d` in `dims`,
53
and repeated dimensions or numbers outside `1:ndims(A)` are forbidden.
54

55
The result shares the same underlying data as `A`, such that the
56
result is mutable if and only if `A` is mutable, and setting elements of one
57
alters the values of the other.
58

59
See also: [`reshape`](@ref), [`vec`](@ref).
60

61
# Examples
62
```jldoctest
63
julia> a = reshape(Vector(1:4),(2,2,1,1))
64
2×2×1×1 Array{Int64, 4}:
65
[:, :, 1, 1] =
66
 1  3
67
 2  4
68

69
julia> b = dropdims(a; dims=3)
70
2×2×1 Array{Int64, 3}:
71
[:, :, 1] =
72
 1  3
73
 2  4
74

75
julia> b[1,1,1] = 5; a
76
2×2×1×1 Array{Int64, 4}:
77
[:, :, 1, 1] =
78
 5  3
79
 2  4
80
```
81
"""
82
dropdims(A; dims) = _dropdims(A, dims)
68✔
83
function _dropdims(A::AbstractArray, dims::Dims)
34✔
84
    for i in eachindex(dims)
34✔
85
        1 <= dims[i] <= ndims(A) || throw(ArgumentError("dropped dims must be in range 1:ndims(A)"))
50✔
86
        length(axes(A, dims[i])) == 1 || throw(ArgumentError("dropped dims must all be size 1"))
49✔
87
        for j = 1:i-1
57✔
88
            dims[j] == dims[i] && throw(ArgumentError("dropped dims must be unique"))
16✔
89
        end
15✔
90
    end
54✔
91
    ax = _foldoneto((ds, d) -> d in dims ? ds : (ds..., axes(A,d)), (), Val(ndims(A)))
150✔
92
    reshape(A, ax::typeof(_sub(axes(A), dims)))
26✔
93
end
94
_dropdims(A::AbstractArray, dim::Integer) = _dropdims(A, (Int(dim),))
16✔
95

96
## Unary operators ##
97

98
"""
99
    conj!(A)
100

101
Transform an array to its complex conjugate in-place.
102

103
See also [`conj`](@ref).
104

105
# Examples
106
```jldoctest
107
julia> A = [1+im 2-im; 2+2im 3+im]
108
2×2 Matrix{Complex{Int64}}:
109
 1+1im  2-1im
110
 2+2im  3+1im
111

112
julia> conj!(A);
113

114
julia> A
115
2×2 Matrix{Complex{Int64}}:
116
 1-1im  2+1im
117
 2-2im  3-1im
118
```
119
"""
120
conj!(A::AbstractArray{<:Number}) = (@inbounds broadcast!(conj, A, A); A)
700✔
121
conj!(x::AbstractArray{<:Real}) = x
1,112✔
122

123
"""
124
    conj(A::AbstractArray)
125

126
Return an array containing the complex conjugate of each entry in array `A`.
127

128
Equivalent to `conj.(A)`, except that when `eltype(A) <: Real`
129
`A` is returned without copying, and that when `A` has zero dimensions,
130
a 0-dimensional array is returned (rather than a scalar).
131

132
# Examples
133
```jldoctest
134
julia> conj([1, 2im, 3 + 4im])
135
3-element Vector{Complex{Int64}}:
136
 1 + 0im
137
 0 - 2im
138
 3 - 4im
139

140
julia> conj(fill(2 - im))
141
0-dimensional Array{Complex{Int64}, 0}:
142
2 + 1im
143
```
144
"""
145
conj(A::AbstractArray) = broadcast_preserving_zero_d(conj, A)
715✔
146
conj(A::AbstractArray{<:Real}) = A
1,166✔
147

148
"""
149
    real(A::AbstractArray)
150

151
Return an array containing the real part of each entry in array `A`.
152

153
Equivalent to `real.(A)`, except that when `eltype(A) <: Real`
154
`A` is returned without copying, and that when `A` has zero dimensions,
155
a 0-dimensional array is returned (rather than a scalar).
156

157
# Examples
158
```jldoctest
159
julia> real([1, 2im, 3 + 4im])
160
3-element Vector{Int64}:
161
 1
162
 0
163
 3
164

165
julia> real(fill(2 - im))
166
0-dimensional Array{Int64, 0}:
167
2
168
```
169
"""
170
real(A::AbstractArray) = broadcast_preserving_zero_d(real, A)
1,333✔
171
real(A::AbstractArray{<:Real}) = A
373✔
172

173
"""
174
    imag(A::AbstractArray)
175

176
Return an array containing the imaginary part of each entry in array `A`.
177

178
Equivalent to `imag.(A)`, except that when `A` has zero dimensions,
179
a 0-dimensional array is returned (rather than a scalar).
180

181
# Examples
182
```jldoctest
183
julia> imag([1, 2im, 3 + 4im])
184
3-element Vector{Int64}:
185
 0
186
 2
187
 4
188

189
julia> imag(fill(2 - im))
190
0-dimensional Array{Int64, 0}:
191
-1
192
```
193
"""
194
imag(A::AbstractArray) = broadcast_preserving_zero_d(imag, A)
830✔
195
imag(A::AbstractArray{<:Real}) = zero(A)
1,490✔
196

197
"""
198
    reim(A::AbstractArray)
199

200
Return a tuple of two arrays containing respectively the real and the imaginary
201
part of each entry in `A`.
202

203
Equivalent to `(real.(A), imag.(A))`, except that when `eltype(A) <: Real`
204
`A` is returned without copying to represent the real part, and that when `A` has
205
zero dimensions, a 0-dimensional array is returned (rather than a scalar).
206

207
# Examples
208
```jldoctest
209
julia> reim([1, 2im, 3 + 4im])
210
([1, 0, 3], [0, 2, 4])
211

212
julia> reim(fill(2 - im))
213
(fill(2), fill(-1))
214
```
215
"""
216
reim(A::AbstractArray)
217

218
-(A::AbstractArray) = broadcast_preserving_zero_d(-, A)
2,503✔
219

220
+(x::AbstractArray{<:Number}) = x
3✔
221
*(x::AbstractArray{<:Number,2}) = x
1✔
222

223
# index A[:,:,...,i,:,:,...] where "i" is in dimension "d"
224

225
"""
226
    selectdim(A, d::Integer, i)
227

228
Return a view of all the data of `A` where the index for dimension `d` equals `i`.
229

230
Equivalent to `view(A,:,:,...,i,:,:,...)` where `i` is in position `d`.
231

232
See also: [`eachslice`](@ref).
233

234
# Examples
235
```jldoctest
236
julia> A = [1 2 3 4; 5 6 7 8]
237
2×4 Matrix{Int64}:
238
 1  2  3  4
239
 5  6  7  8
240

241
julia> selectdim(A, 2, 3)
242
2-element view(::Matrix{Int64}, :, 3) with eltype Int64:
243
 3
244
 7
245

246
julia> selectdim(A, 2, 3:4)
247
2×2 view(::Matrix{Int64}, :, 3:4) with eltype Int64:
248
 3  4
249
 7  8
250
```
251
"""
252
@inline selectdim(A::AbstractArray, d::Integer, i) = _selectdim(A, d, i, _setindex(i, d, map(Slice, axes(A))...))
26✔
253
@noinline function _selectdim(A, d, i, idxs)
26✔
254
    d >= 1 || throw(ArgumentError("dimension must be ≥ 1, got $d"))
26✔
255
    nd = ndims(A)
26✔
256
    d > nd && (i == 1 || throw(BoundsError(A, (ntuple(Returns(Colon()),d-1)..., i))))
26✔
257
    return view(A, idxs...)
26✔
258
end
259

260
function circshift(a::AbstractArray, shiftamt::Real)
57✔
261
    circshift!(similar(a), a, (Integer(shiftamt),))
57✔
262
end
263
circshift(a::AbstractArray, shiftamt::DimsInteger) = circshift!(similar(a), a, shiftamt)
35✔
264
"""
265
    circshift(A, shifts)
266

267
Circularly shift, i.e. rotate, the data in an array. The second argument is a tuple or
268
vector giving the amount to shift in each dimension, or an integer to shift only in the
269
first dimension.
270

271
See also: [`circshift!`](@ref), [`circcopy!`](@ref), [`bitrotate`](@ref), [`<<`](@ref).
272

273
# Examples
274
```jldoctest
275
julia> b = reshape(Vector(1:16), (4,4))
276
4×4 Matrix{Int64}:
277
 1  5   9  13
278
 2  6  10  14
279
 3  7  11  15
280
 4  8  12  16
281

282
julia> circshift(b, (0,2))
283
4×4 Matrix{Int64}:
284
  9  13  1  5
285
 10  14  2  6
286
 11  15  3  7
287
 12  16  4  8
288

289
julia> circshift(b, (-1,0))
290
4×4 Matrix{Int64}:
291
 2  6  10  14
292
 3  7  11  15
293
 4  8  12  16
294
 1  5   9  13
295

296
julia> a = BitArray([true, true, false, false, true])
297
5-element BitVector:
298
 1
299
 1
300
 0
301
 0
302
 1
303

304
julia> circshift(a, 1)
305
5-element BitVector:
306
 1
307
 1
308
 1
309
 0
310
 0
311

312
julia> circshift(a, -1)
313
5-element BitVector:
314
 1
315
 0
316
 0
317
 1
318
 1
319
```
320
"""
321
function circshift(a::AbstractArray, shiftamt)
×
322
    circshift!(similar(a), a, map(Integer, (shiftamt...,)))
×
323
end
324

325
## Other array functions ##
326

327
"""
328
    repeat(A::AbstractArray, counts::Integer...)
329

330
Construct an array by repeating array `A` a given number of times in each dimension, specified by `counts`.
331

332
See also: [`fill`](@ref), [`Iterators.repeated`](@ref), [`Iterators.cycle`](@ref).
333

334
# Examples
335
```jldoctest
336
julia> repeat([1, 2, 3], 2)
337
6-element Vector{Int64}:
338
 1
339
 2
340
 3
341
 1
342
 2
343
 3
344

345
julia> repeat([1, 2, 3], 2, 3)
346
6×3 Matrix{Int64}:
347
 1  1  1
348
 2  2  2
349
 3  3  3
350
 1  1  1
351
 2  2  2
352
 3  3  3
353
```
354
"""
355
function repeat(A::AbstractArray, counts...)
47✔
356
    return _RepeatInnerOuter.repeat(A, outer=counts)
47✔
357
end
358

359
"""
360
    repeat(A::AbstractArray; inner=ntuple(Returns(1), ndims(A)), outer=ntuple(Returns(1), ndims(A)))
361

362
Construct an array by repeating the entries of `A`. The i-th element of `inner` specifies
363
the number of times that the individual entries of the i-th dimension of `A` should be
364
repeated. The i-th element of `outer` specifies the number of times that a slice along the
365
i-th dimension of `A` should be repeated. If `inner` or `outer` are omitted, no repetition
366
is performed.
367

368
# Examples
369
```jldoctest
370
julia> repeat(1:2, inner=2)
371
4-element Vector{Int64}:
372
 1
373
 1
374
 2
375
 2
376

377
julia> repeat(1:2, outer=2)
378
4-element Vector{Int64}:
379
 1
380
 2
381
 1
382
 2
383

384
julia> repeat([1 2; 3 4], inner=(2, 1), outer=(1, 3))
385
4×6 Matrix{Int64}:
386
 1  2  1  2  1  2
387
 1  2  1  2  1  2
388
 3  4  3  4  3  4
389
 3  4  3  4  3  4
390
```
391
"""
392
function repeat(A::AbstractArray; inner = nothing, outer = nothing)
×
393
    return _RepeatInnerOuter.repeat(A, inner=inner, outer=outer)
×
394
end
395

396
module _RepeatInnerOuter
397

398
function repeat(arr; inner=nothing, outer=nothing)
106✔
399
    check(arr, inner, outer)
96✔
400
    arr, inner, outer = resolve(arr, inner, outer)
47✔
401
    repeat_inner_outer(arr, inner, outer)
47✔
402
end
403

404
to_tuple(t::Tuple) = t
47✔
405
to_tuple(x::Integer) = (x,)
×
406
to_tuple(itr) = tuple(itr...)
×
407

408
function pad(a, b)
47✔
409
    N = max(length(a), length(b))
47✔
410
    Base.fill_to_length(a, 1, Val(N)), Base.fill_to_length(b, 1, Val(N))
47✔
411
end
412
function pad(a, b, c)
×
413
    N = max(max(length(a), length(b)), length(c))
×
414
    Base.fill_to_length(a, 1, Val(N)), Base.fill_to_length(b, 1, Val(N)), Base.fill_to_length(c, 1, Val(N))
×
415
end
416

417
function resolve(arr::AbstractArray{<:Any, N}, inner::NTuple{N, Any}, outer::NTuple{N,Any}) where {N}
×
418
    arr, inner, outer
×
419
end
420
function resolve(arr, inner, outer)
×
421
    dims, inner, outer = pad(size(arr), to_tuple(inner), to_tuple(outer))
×
422
    reshape(arr, dims), inner, outer
×
423
end
424
function resolve(arr, inner::Nothing, outer::Nothing)
×
425
    return arr, inner, outer
×
426
end
427
function resolve(arr, inner::Nothing, outer)
47✔
428
    dims, outer = pad(size(arr), to_tuple(outer))
47✔
429
    reshape(arr, dims), inner, outer
47✔
430
end
431
function resolve(arr, inner, outer::Nothing)
×
432
    dims, inner = pad(size(arr), to_tuple(inner))
×
433
    reshape(arr, dims), inner, outer
×
434
end
435

436
function check(arr, inner, outer)
47✔
437
    if inner !== nothing
47✔
438
        # TODO: Currently one based indexing is demanded for inner !== nothing,
439
        # but not for outer !== nothing. Decide for something consistent.
440
        Base.require_one_based_indexing(arr)
×
441
        if any(<(0), inner)
×
442
            throw(ArgumentError("no inner repetition count may be negative; got $inner"))
×
443
        end
444
        if length(inner) < ndims(arr)
×
445
            throw(ArgumentError("number of inner repetitions ($(length(inner))) cannot be less than number of dimensions of input array ($(ndims(arr)))"))
×
446
        end
447
    end
448
    if outer !== nothing
47✔
449
        if any(<(0), outer)
96✔
450
            throw(ArgumentError("no outer repetition count may be negative; got $outer"))
×
451
        end
452
        if (length(outer) < ndims(arr)) && (inner !== nothing)
47✔
453
            throw(ArgumentError("number of outer repetitions ($(length(outer))) cannot be less than number of dimensions of input array ($(ndims(arr)))"))
47✔
454
        end
455
    end
456
end
457

458
repeat_inner_outer(arr, inner::Nothing, outer::Nothing) = arr
×
459
repeat_inner_outer(arr, ::Nothing, outer) = repeat_outer(arr, outer)
47✔
460
repeat_inner_outer(arr, inner, ::Nothing) = repeat_inner(arr, inner)
×
461
repeat_inner_outer(arr, inner, outer) = repeat_outer(repeat_inner(arr, inner), outer)
×
462

463
function repeat_outer(a::AbstractMatrix, (m,n)::NTuple{2, Any})
2✔
464
    o, p = size(a,1), size(a,2)
2✔
465
    b = similar(a, o*m, p*n)
2✔
466
    for j=1:n
4✔
467
        d = (j-1)*p+1
19✔
468
        R = d:d+p-1
19✔
469
        for i=1:m
38✔
470
            c = (i-1)*o+1
19✔
471
            @inbounds b[c:c+o-1, R] = a
19✔
472
        end
19✔
473
    end
36✔
474
    return b
2✔
475
end
476

477
function repeat_outer(a::AbstractVector, (m,)::Tuple{Any})
45✔
478
    o = length(a)
45✔
479
    b = similar(a, o*m)
45✔
480
    for i=1:m
90✔
481
        c = (i-1)*o+1
1,010,652✔
482
        @inbounds b[c:c+o-1] = a
1,018,599✔
483
    end
2,021,259✔
484
    return b
45✔
485
end
486

487
function repeat_outer(arr::AbstractArray{<:Any,N}, dims::NTuple{N,Any}) where {N}
×
488
    insize  = size(arr)
×
489
    outsize = map(*, insize, dims)
×
490
    out = similar(arr, outsize)
×
491
    for I in CartesianIndices(arr)
×
492
        for J in CartesianIndices(dims)
×
493
            TIJ = map(Tuple(I), Tuple(J), insize) do i, j, d
×
494
                i + d * (j-1)
×
495
            end
496
            IJ = CartesianIndex(TIJ)
×
497
            @inbounds out[IJ] = arr[I]
×
498
        end
×
499
    end
×
500
    return out
×
501
end
502

503
function repeat_inner(arr, inner)
×
504
    outsize = map(*, size(arr), inner)
×
505
    out = similar(arr, outsize)
×
506
    for I in CartesianIndices(arr)
×
507
        for J in CartesianIndices(inner)
×
508
            TIJ = map(Tuple(I), Tuple(J), inner) do i, j, d
×
509
                (i-1) * d + j
×
510
            end
511
            IJ = CartesianIndex(TIJ)
×
512
            @inbounds out[IJ] = arr[I]
×
513
        end
×
514
    end
×
515
    return out
×
516
end
517

518
end#module
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