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

JuliaLang / julia / #37997

29 Jan 2025 02:08AM UTC coverage: 17.283% (-68.7%) from 85.981%
#37997

push

local

web-flow
bpart: Start enforcing min_world for global variable definitions (#57150)

This is the analog of #57102 for global variables. Unlike for consants,
there is no automatic global backdate mechanism. The reasoning for this
is that global variables can be declared at any time, unlike constants
which can only be decalared once their value is available. As a result
code patterns using `Core.eval` to declare globals are rarer and likely
incorrect.

1 of 22 new or added lines in 3 files covered. (4.55%)

31430 existing lines in 188 files now uncovered.

7903 of 45728 relevant lines covered (17.28%)

98663.7 hits per line

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

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

3
using  Base.MultiplicativeInverses: SignedMultiplicativeInverse
4

5
struct ReshapedArray{T,N,P<:AbstractArray,MI<:Tuple{Vararg{SignedMultiplicativeInverse{Int}}}} <: AbstractArray{T,N}
6
    parent::P
7
    dims::NTuple{N,Int}
8
    mi::MI
9
end
UNCOV
10
ReshapedArray(parent::AbstractArray{T}, dims::NTuple{N,Int}, mi) where {T,N} = ReshapedArray{T,N,typeof(parent),typeof(mi)}(parent, dims, mi)
×
11

12
# IndexLinear ReshapedArray
13
const ReshapedArrayLF{T,N,P<:AbstractArray} = ReshapedArray{T,N,P,Tuple{}}
14

15
# Fast iteration on ReshapedArrays: use the parent iterator
16
struct ReshapedArrayIterator{I,M}
17
    iter::I
18
    mi::NTuple{M,SignedMultiplicativeInverse{Int}}
19
end
20
ReshapedArrayIterator(A::ReshapedArray) = _rs_iterator(parent(A), A.mi)
×
21
function _rs_iterator(P, mi::NTuple{M}) where M
×
22
    iter = eachindex(P)
×
23
    ReshapedArrayIterator{typeof(iter),M}(iter, mi)
×
24
end
25

26
struct ReshapedIndex{T}
27
    parentindex::T
28
end
29

30
# eachindex(A::ReshapedArray) = ReshapedArrayIterator(A)  # TODO: uncomment this line
31
@inline function iterate(R::ReshapedArrayIterator, i...)
×
32
    item, inext = iterate(R.iter, i...)
×
33
    ReshapedIndex(item), inext
×
34
end
35
length(R::ReshapedArrayIterator) = length(R.iter)
×
36
eltype(::Type{<:ReshapedArrayIterator{I}}) where {I} = @isdefined(I) ? ReshapedIndex{eltype(I)} : Any
×
37

UNCOV
38
@noinline throw_dmrsa(dims, len) =
×
39
    throw(DimensionMismatch("new dimensions $(dims) must be consistent with array length $len"))
40

41
## reshape(::Array, ::Dims) returns a new Array (to avoid conditionally aliasing the structure, only the data)
42
# reshaping to same # of dimensions
UNCOV
43
@eval function reshape(a::Array{T,M}, dims::NTuple{N,Int}) where {T,N,M}
×
UNCOV
44
    len = Core.checked_dims(dims...) # make sure prod(dims) doesn't overflow (and because of the comparison to length(a))
×
UNCOV
45
    if len != length(a)
×
UNCOV
46
        throw_dmrsa(dims, length(a))
×
47
    end
UNCOV
48
    ref = a.ref
×
49
    # or we could use `a = Array{T,N}(undef, ntuple(i->0, Val(N))); a.ref = ref; a.size = dims; return a` here to avoid the eval
UNCOV
50
    return $(Expr(:new, :(Array{T,N}), :ref, :dims))
×
51
end
52

53
## reshape!(::Array, ::Dims) returns the original array, but must have the same dimensions and length as the original
54
# see also resize! for a similar operation that can change the length
55
function reshape!(a::Array{T,N}, dims::NTuple{N,Int}) where {T,N}
×
56
    len = Core.checked_dims(dims...) # make sure prod(dims) doesn't overflow (and because of the comparison to length(a))
×
57
    if len != length(a)
×
58
        throw_dmrsa(dims, length(a))
×
59
    end
60
    setfield!(a, :dims, dims)
×
61
    return a
×
62
end
63

64

65

66
"""
67
    reshape(A, dims...) -> AbstractArray
68
    reshape(A, dims) -> AbstractArray
69

70
Return an array with the same data as `A`, but with different
71
dimension sizes or number of dimensions. The two arrays share the same
72
underlying data, so that the result is mutable if and only if `A` is
73
mutable, and setting elements of one alters the values of the other.
74

75
The new dimensions may be specified either as a list of arguments or
76
as a shape tuple. At most one dimension may be specified with a `:`,
77
in which case its length is computed such that its product with all
78
the specified dimensions is equal to the length of the original array
79
`A`. The total number of elements must not change.
80

81
# Examples
82
```jldoctest
83
julia> A = Vector(1:16)
84
16-element Vector{Int64}:
85
  1
86
  2
87
  3
88
  4
89
  5
90
  6
91
  7
92
  8
93
  9
94
 10
95
 11
96
 12
97
 13
98
 14
99
 15
100
 16
101

102
julia> reshape(A, (4, 4))
103
4×4 Matrix{Int64}:
104
 1  5   9  13
105
 2  6  10  14
106
 3  7  11  15
107
 4  8  12  16
108

109
julia> reshape(A, 2, :)
110
2×8 Matrix{Int64}:
111
 1  3  5  7   9  11  13  15
112
 2  4  6  8  10  12  14  16
113

114
julia> reshape(1:6, 2, 3)
115
2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:
116
 1  3  5
117
 2  4  6
118
```
119
"""
120
reshape
121

UNCOV
122
reshape(parent::AbstractArray, dims::IntOrInd...) = reshape(parent, dims)
×
UNCOV
123
reshape(parent::AbstractArray, shp::Tuple{Union{Integer,OneTo}, Vararg{Union{Integer,OneTo}}}) = reshape(parent, to_shape(shp))
×
UNCOV
124
reshape(parent::AbstractArray, dims::Tuple{Integer, Vararg{Integer}}) = reshape(parent, map(Int, dims))
×
UNCOV
125
reshape(parent::AbstractArray, dims::Dims)        = _reshape(parent, dims)
×
126

127
# Allow missing dimensions with Colon():
UNCOV
128
reshape(parent::AbstractVector, ::Colon) = parent
×
UNCOV
129
reshape(parent::AbstractVector, ::Tuple{Colon}) = parent
×
UNCOV
130
reshape(parent::AbstractArray, dims::Int...) = reshape(parent, dims)
×
UNCOV
131
reshape(parent::AbstractArray, dims::Integer...) = reshape(parent, dims)
×
UNCOV
132
reshape(parent::AbstractArray, dims::Union{Integer,Colon}...) = reshape(parent, dims)
×
UNCOV
133
reshape(parent::AbstractArray, dims::Tuple{Vararg{Union{Integer,Colon}}}) = reshape(parent, _reshape_uncolon(parent, dims))
×
134

UNCOV
135
@noinline throw1(dims) = throw(DimensionMismatch(LazyString("new dimensions ", dims,
×
136
        " may have at most one omitted dimension specified by `Colon()`")))
UNCOV
137
@noinline throw2(lenA, dims) = throw(DimensionMismatch(string("array size ", lenA,
×
138
    " must be divisible by the product of the new dimensions ", dims)))
139

UNCOV
140
@inline function _reshape_uncolon(A, _dims::Tuple{Vararg{Union{Integer, Colon}}})
×
141
    # promote the dims to `Int` at least
UNCOV
142
    dims = map(x -> x isa Colon ? x : promote_type(typeof(x), Int)(x), _dims)
×
UNCOV
143
    pre = _before_colon(dims...)
×
UNCOV
144
    post = _after_colon(dims...)
×
UNCOV
145
    _any_colon(post...) && throw1(dims)
×
UNCOV
146
    len = length(A)
×
UNCOV
147
    _reshape_uncolon_computesize(len, dims, pre, post)
×
148
end
UNCOV
149
@inline function _reshape_uncolon_computesize(len::Int, dims, pre::Tuple{Vararg{Int}}, post::Tuple{Vararg{Int}})
×
UNCOV
150
    sz = if iszero(len)
×
UNCOV
151
        0
×
152
    else
UNCOV
153
        let pr = Core.checked_dims(pre..., post...)  # safe product
×
UNCOV
154
            quo = _reshape_uncolon_computesize_nonempty(len, dims, pr)
×
UNCOV
155
            convert(Int, quo)
×
156
        end
157
    end
UNCOV
158
    (pre..., sz, post...)
×
159
end
UNCOV
160
@inline function _reshape_uncolon_computesize(len, dims, pre, post)
×
UNCOV
161
    pr = prod((pre..., post...))
×
UNCOV
162
    sz = if iszero(len)
×
UNCOV
163
        promote(len, pr)[1] # zero of the correct type
×
164
    else
UNCOV
165
        _reshape_uncolon_computesize_nonempty(len, dims, pr)
×
166
    end
UNCOV
167
    (pre..., sz, post...)
×
168
end
UNCOV
169
@inline function _reshape_uncolon_computesize_nonempty(len, dims, pr)
×
UNCOV
170
    iszero(pr) && throw2(len, dims)
×
UNCOV
171
    (quo, rem) = divrem(len, pr)
×
UNCOV
172
    iszero(rem) || throw2(len, dims)
×
UNCOV
173
    quo
×
174
end
175
@inline _any_colon() = false
×
176
@inline _any_colon(dim::Colon, tail...) = true
×
UNCOV
177
@inline _any_colon(dim::Any, tail...) = _any_colon(tail...)
×
UNCOV
178
@inline _before_colon(dim::Any, tail...) = (dim, _before_colon(tail...)...)
×
UNCOV
179
@inline _before_colon(dim::Colon, tail...) = ()
×
UNCOV
180
@inline _after_colon(dim::Any, tail...) =  _after_colon(tail...)
×
UNCOV
181
@inline _after_colon(dim::Colon, tail...) = tail
×
182

183
reshape(parent::AbstractArray{T,N}, ndims::Val{N}) where {T,N} = parent
1✔
UNCOV
184
function reshape(parent::AbstractArray, ndims::Val{N}) where N
×
UNCOV
185
    reshape(parent, rdims(Val(N), axes(parent)))
×
186
end
187

188
# Move elements from inds to out until out reaches the desired
189
# dimensionality N, either filling with OneTo(1) or collapsing the
190
# product of trailing dims into the last element
UNCOV
191
rdims_trailing(l, inds...) = length(l) * rdims_trailing(inds...)
×
UNCOV
192
rdims_trailing(l) = length(l)
×
UNCOV
193
rdims(out::Val{N}, inds::Tuple) where {N} = rdims(ntuple(Returns(OneTo(1)), Val(N)), inds)
×
194
rdims(out::Tuple{}, inds::Tuple{}) = () # N == 0, M == 0
×
UNCOV
195
rdims(out::Tuple{}, inds::Tuple{Any}) = ()
×
196
rdims(out::Tuple{}, inds::NTuple{M,Any}) where {M} = ()
×
UNCOV
197
rdims(out::Tuple{Any}, inds::Tuple{}) = out # N == 1, M == 0
×
UNCOV
198
rdims(out::NTuple{N,Any}, inds::Tuple{}) where {N} = out # N > 1, M == 0
×
199
rdims(out::Tuple{Any}, inds::Tuple{Any}) = inds # N == 1, M == 1
×
UNCOV
200
rdims(out::Tuple{Any}, inds::NTuple{M,Any}) where {M} = (oneto(rdims_trailing(inds...)),) # N == 1, M > 1
×
201
rdims(out::NTuple{N,Any}, inds::NTuple{N,Any}) where {N} = inds # N > 1, M == N
×
UNCOV
202
rdims(out::NTuple{N,Any}, inds::NTuple{M,Any}) where {N,M} = (first(inds), rdims(tail(out), tail(inds))...) # N > 1, M > 1, M != N
×
203

204

205
# _reshape on Array returns an Array
UNCOV
206
_reshape(parent::Vector, dims::Dims{1}) = parent
×
207
_reshape(parent::Array, dims::Dims{1}) = reshape(parent, dims)
×
208
_reshape(parent::Array, dims::Dims) = reshape(parent, dims)
×
209

210
# When reshaping Vector->Vector, don't wrap with a ReshapedArray
UNCOV
211
function _reshape(v::AbstractVector, dims::Dims{1})
×
UNCOV
212
    require_one_based_indexing(v)
×
UNCOV
213
    len = dims[1]
×
UNCOV
214
    len == length(v) || _throw_dmrs(length(v), "length", len)
×
UNCOV
215
    v
×
216
end
217
# General reshape
UNCOV
218
function _reshape(parent::AbstractArray, dims::Dims)
×
UNCOV
219
    n = length(parent)
×
UNCOV
220
    prod(dims) == n || _throw_dmrs(n, "size", dims)
×
UNCOV
221
    __reshape((parent, IndexStyle(parent)), dims)
×
222
end
223

UNCOV
224
@noinline function _throw_dmrs(n, str, dims)
×
UNCOV
225
    throw(DimensionMismatch("parent has $n elements, which is incompatible with $str $dims"))
×
226
end
227

228
# Reshaping a ReshapedArray
UNCOV
229
_reshape(v::ReshapedArray{<:Any,1}, dims::Dims{1}) = _reshape(v.parent, dims)
×
UNCOV
230
_reshape(R::ReshapedArray, dims::Dims) = _reshape(R.parent, dims)
×
231

UNCOV
232
function __reshape(p::Tuple{AbstractArray,IndexStyle}, dims::Dims)
×
UNCOV
233
    parent = p[1]
×
UNCOV
234
    strds = front(size_to_strides(map(length, axes(parent))..., 1))
×
UNCOV
235
    strds1 = map(s->max(1,Int(s)), strds)  # for resizing empty arrays
×
UNCOV
236
    mi = map(SignedMultiplicativeInverse, strds1)
×
UNCOV
237
    ReshapedArray(parent, dims, reverse(mi))
×
238
end
239

UNCOV
240
function __reshape(p::Tuple{AbstractArray{<:Any,0},IndexCartesian}, dims::Dims)
×
UNCOV
241
    parent = p[1]
×
UNCOV
242
    ReshapedArray(parent, dims, ())
×
243
end
244

UNCOV
245
function __reshape(p::Tuple{AbstractArray,IndexLinear}, dims::Dims)
×
UNCOV
246
    parent = p[1]
×
UNCOV
247
    ReshapedArray(parent, dims, ())
×
248
end
249

UNCOV
250
size(A::ReshapedArray) = A.dims
×
UNCOV
251
length(A::ReshapedArray) = length(parent(A))
×
UNCOV
252
similar(A::ReshapedArray, eltype::Type, dims::Dims) = similar(parent(A), eltype, dims)
×
UNCOV
253
IndexStyle(::Type{<:ReshapedArrayLF}) = IndexLinear()
×
UNCOV
254
parent(A::ReshapedArray) = A.parent
×
UNCOV
255
parentindices(A::ReshapedArray) = map(oneto, size(parent(A)))
×
256
reinterpret(::Type{T}, A::ReshapedArray, dims::Dims) where {T} = reinterpret(T, parent(A), dims)
×
UNCOV
257
elsize(::Type{<:ReshapedArray{<:Any,<:Any,P}}) where {P} = elsize(P)
×
258

UNCOV
259
unaliascopy(A::ReshapedArray) = typeof(A)(unaliascopy(A.parent), A.dims, A.mi)
×
UNCOV
260
dataids(A::ReshapedArray) = dataids(A.parent)
×
261
# forward the aliasing check the parent in case there are specializations
UNCOV
262
mightalias(A::ReshapedArray, B::ReshapedArray) = mightalias(parent(A), parent(B))
×
263
# special handling for reshaped SubArrays that dispatches to the subarray aliasing check
UNCOV
264
mightalias(A::ReshapedArray, B::SubArray) = mightalias(parent(A), B)
×
UNCOV
265
mightalias(A::SubArray, B::ReshapedArray) = mightalias(A, parent(B))
×
266

UNCOV
267
@inline ind2sub_rs(ax, ::Tuple{}, i::Int) = (i,)
×
UNCOV
268
@inline ind2sub_rs(ax, strds, i) = _ind2sub_rs(ax, strds, i - 1)
×
UNCOV
269
@inline _ind2sub_rs(ax, ::Tuple{}, ind) = (ind + first(ax[end]),)
×
UNCOV
270
@inline function _ind2sub_rs(ax, strds, ind)
×
UNCOV
271
    d, r = divrem(ind, strds[1])
×
UNCOV
272
    (_ind2sub_rs(front(ax), tail(strds), r)..., d + first(ax[end]))
×
273
end
UNCOV
274
offset_if_vec(i::Integer, axs::Tuple{<:AbstractUnitRange}) = i + first(axs[1]) - 1
×
UNCOV
275
offset_if_vec(i::Integer, axs::Tuple) = i
×
276

277
@inline function isassigned(A::ReshapedArrayLF, index::Int)
×
278
    @boundscheck checkbounds(Bool, A, index) || return false
×
279
    indexparent = index - firstindex(A) + firstindex(parent(A))
×
280
    @inbounds ret = isassigned(parent(A), indexparent)
×
281
    ret
×
282
end
UNCOV
283
@inline function isassigned(A::ReshapedArray{T,N}, indices::Vararg{Int, N}) where {T,N}
×
UNCOV
284
    @boundscheck checkbounds(Bool, A, indices...) || return false
×
UNCOV
285
    axp = axes(A.parent)
×
UNCOV
286
    i = offset_if_vec(_sub2ind(size(A), indices...), axp)
×
UNCOV
287
    I = ind2sub_rs(axp, A.mi, i)
×
UNCOV
288
    @inbounds isassigned(A.parent, I...)
×
289
end
290

UNCOV
291
@inline function getindex(A::ReshapedArrayLF, index::Int)
×
UNCOV
292
    @boundscheck checkbounds(A, index)
×
UNCOV
293
    indexparent = index - firstindex(A) + firstindex(parent(A))
×
UNCOV
294
    @inbounds ret = parent(A)[indexparent]
×
UNCOV
295
    ret
×
296
end
UNCOV
297
@inline function getindex(A::ReshapedArray{T,N}, indices::Vararg{Int,N}) where {T,N}
×
UNCOV
298
    @boundscheck checkbounds(A, indices...)
×
UNCOV
299
    _unsafe_getindex(A, indices...)
×
300
end
UNCOV
301
@inline function getindex(A::ReshapedArray, index::ReshapedIndex)
×
UNCOV
302
    @boundscheck checkbounds(parent(A), index.parentindex)
×
UNCOV
303
    @inbounds ret = parent(A)[index.parentindex]
×
UNCOV
304
    ret
×
305
end
306

UNCOV
307
@inline function _unsafe_getindex(A::ReshapedArray{T,N}, indices::Vararg{Int,N}) where {T,N}
×
UNCOV
308
    axp = axes(A.parent)
×
UNCOV
309
    i = offset_if_vec(_sub2ind(size(A), indices...), axp)
×
UNCOV
310
    I = ind2sub_rs(axp, A.mi, i)
×
UNCOV
311
    _unsafe_getindex_rs(parent(A), I)
×
312
end
313
@inline _unsafe_getindex_rs(A, i::Integer) = (@inbounds ret = A[i]; ret)
×
UNCOV
314
@inline _unsafe_getindex_rs(A, I) = (@inbounds ret = A[I...]; ret)
×
315

UNCOV
316
@inline function setindex!(A::ReshapedArrayLF, val, index::Int)
×
UNCOV
317
    @boundscheck checkbounds(A, index)
×
UNCOV
318
    indexparent = index - firstindex(A) + firstindex(parent(A))
×
UNCOV
319
    @inbounds parent(A)[indexparent] = val
×
UNCOV
320
    val
×
321
end
UNCOV
322
@inline function setindex!(A::ReshapedArray{T,N}, val, indices::Vararg{Int,N}) where {T,N}
×
UNCOV
323
    @boundscheck checkbounds(A, indices...)
×
UNCOV
324
    _unsafe_setindex!(A, val, indices...)
×
325
end
UNCOV
326
@inline function setindex!(A::ReshapedArray, val, index::ReshapedIndex)
×
UNCOV
327
    @boundscheck checkbounds(parent(A), index.parentindex)
×
UNCOV
328
    @inbounds parent(A)[index.parentindex] = val
×
UNCOV
329
    val
×
330
end
331

UNCOV
332
@inline function _unsafe_setindex!(A::ReshapedArray{T,N}, val, indices::Vararg{Int,N}) where {T,N}
×
UNCOV
333
    axp = axes(A.parent)
×
UNCOV
334
    i = offset_if_vec(_sub2ind(size(A), indices...), axp)
×
UNCOV
335
    @inbounds parent(A)[ind2sub_rs(axes(A.parent), A.mi, i)...] = val
×
UNCOV
336
    val
×
337
end
338

339
# helpful error message for a common failure case
340
const ReshapedRange{T,N,A<:AbstractRange} = ReshapedArray{T,N,A,Tuple{}}
UNCOV
341
setindex!(A::ReshapedRange, val, index::Int) = _rs_setindex!_err()
×
UNCOV
342
setindex!(A::ReshapedRange{T,N}, val, indices::Vararg{Int,N}) where {T,N} = _rs_setindex!_err()
×
UNCOV
343
setindex!(A::ReshapedRange, val, index::ReshapedIndex) = _rs_setindex!_err()
×
344

UNCOV
345
@noinline _rs_setindex!_err() = error("indexed assignment fails for a reshaped range; consider calling collect")
×
346

UNCOV
347
cconvert(::Type{Ptr{T}}, a::ReshapedArray{T}) where {T} = cconvert(Ptr{T}, parent(a))
×
UNCOV
348
unsafe_convert(::Type{Ptr{T}}, a::ReshapedArray{T}) where {T} = unsafe_convert(Ptr{T}, a.parent)
×
349

350
# Add a few handy specializations to further speed up views of reshaped ranges
351
const ReshapedUnitRange{T,N,A<:AbstractUnitRange} = ReshapedArray{T,N,A,Tuple{}}
UNCOV
352
viewindexing(I::Tuple{Slice, ReshapedUnitRange, Vararg{ScalarIndex}}) = IndexLinear()
×
UNCOV
353
viewindexing(I::Tuple{ReshapedRange, Vararg{ScalarIndex}}) = IndexLinear()
×
UNCOV
354
compute_stride1(s, inds, I::Tuple{ReshapedRange, Vararg{Any}}) = s*step(I[1].parent)
×
UNCOV
355
compute_offset1(parent::AbstractVector, stride1::Integer, I::Tuple{ReshapedRange}) =
×
UNCOV
356
    (@inline; first(I[1]) - first(axes1(I[1]))*stride1)
×
UNCOV
357
substrides(strds::NTuple{N,Int}, I::Tuple{ReshapedUnitRange, Vararg{Any}}) where N =
×
358
    (size_to_strides(strds[1], size(I[1])...)..., substrides(tail(strds), tail(I))...)
359

360
# cconvert(::Type{<:Ptr}, V::SubArray{T,N,P,<:Tuple{Vararg{Union{RangeIndex,ReshapedUnitRange}}}}) where {T,N,P} = V
361
function unsafe_convert(::Type{Ptr{S}}, V::SubArray{T,N,P,<:Tuple{Vararg{Union{RangeIndex,ReshapedUnitRange}}}}) where {S,T,N,P}
362
    parent = V.parent
355,226✔
363
    p = cconvert(Ptr{T}, parent) # XXX: this should occur in cconvert, the result is not GC-rooted
355,226✔
364
    Δmem = if _checkcontiguous(Bool, parent)
355,226✔
365
        (first_index(V) - firstindex(parent)) * elsize(parent)
355,226✔
366
    else
UNCOV
367
        _memory_offset(parent, map(first, V.indices)...)
×
368
    end
369
    return Ptr{S}(unsafe_convert(Ptr{T}, p) + Δmem)
355,226✔
370
end
371

372
_checkcontiguous(::Type{Bool}, A::AbstractArray) = false
×
373
# `strides(A::DenseArray)` calls `size_to_strides` by default.
374
# Thus it's OK to assume all `DenseArray`s are contiguously stored.
375
_checkcontiguous(::Type{Bool}, A::DenseArray) = true
×
UNCOV
376
_checkcontiguous(::Type{Bool}, A::ReshapedArray) = _checkcontiguous(Bool, parent(A))
×
UNCOV
377
_checkcontiguous(::Type{Bool}, A::FastContiguousSubArray) = _checkcontiguous(Bool, parent(A))
×
378

UNCOV
379
function strides(a::ReshapedArray)
×
UNCOV
380
    _checkcontiguous(Bool, a) && return size_to_strides(1, size(a)...)
×
UNCOV
381
    apsz::Dims = size(a.parent)
×
UNCOV
382
    apst::Dims = strides(a.parent)
×
UNCOV
383
    msz, mst, n = merge_adjacent_dim(apsz, apst) # Try to perform "lazy" reshape
×
UNCOV
384
    n == ndims(a.parent) && return size_to_strides(mst, size(a)...) # Parent is stridevector like
×
UNCOV
385
    return _reshaped_strides(size(a), 1, msz, mst, n, apsz, apst)
×
386
end
387

UNCOV
388
function _reshaped_strides(::Dims{0}, reshaped::Int, msz::Int, ::Int, ::Int, ::Dims, ::Dims)
×
UNCOV
389
    reshaped == msz && return ()
×
UNCOV
390
    throw(ArgumentError("Input is not strided."))
×
391
end
UNCOV
392
function _reshaped_strides(sz::Dims, reshaped::Int, msz::Int, mst::Int, n::Int, apsz::Dims, apst::Dims)
×
UNCOV
393
    st = reshaped * mst
×
UNCOV
394
    reshaped = reshaped * sz[1]
×
UNCOV
395
    if length(sz) > 1 && reshaped == msz && sz[2] != 1
×
UNCOV
396
        msz, mst, n = merge_adjacent_dim(apsz, apst, n + 1)
×
UNCOV
397
        reshaped = 1
×
398
    end
UNCOV
399
    sts = _reshaped_strides(tail(sz), reshaped, msz, mst, n, apsz, apst)
×
UNCOV
400
    return (st, sts...)
×
401
end
402

403
merge_adjacent_dim(::Dims{0}, ::Dims{0}) = 1, 1, 0
×
UNCOV
404
merge_adjacent_dim(apsz::Dims{1}, apst::Dims{1}) = apsz[1], apst[1], 1
×
UNCOV
405
function merge_adjacent_dim(apsz::Dims{N}, apst::Dims{N}, n::Int = 1) where {N}
×
UNCOV
406
    sz, st = apsz[n], apst[n]
×
UNCOV
407
    while n < N
×
UNCOV
408
        szₙ, stₙ = apsz[n+1], apst[n+1]
×
UNCOV
409
        if sz == 1
×
UNCOV
410
            sz, st = szₙ, stₙ
×
UNCOV
411
        elseif stₙ == st * sz || szₙ == 1
×
UNCOV
412
            sz *= szₙ
×
413
        else
UNCOV
414
            break
×
415
        end
UNCOV
416
        n += 1
×
UNCOV
417
    end
×
UNCOV
418
    return sz, st, n
×
419
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