Skip to content

Commit a939998

Browse files
committed
Extend trimming optimization to all range type.
1 parent cdd5fe3 commit a939998

File tree

2 files changed

+33
-19
lines changed

2 files changed

+33
-19
lines changed

base/subarray.jl

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -110,27 +110,35 @@ unaliascopy(A::SubArray) = typeof(A)(unaliascopy(A.parent), map(unaliascopy, A.i
110110

111111
# When the parent is an Array we can trim the size down a bit. In the future this
112112
# could possibly be extended to any mutable array.
113-
function unaliascopy(V::SubArray{T,N,A,I,LD}) where {T,N,A<:Array,I<:Tuple{Vararg{Union{Real,AbstractRange,Array}}},LD}
114-
dest = Array{T}(undef, _trimmed_shape(V.indices...))
115-
copyto!(dest, view(V, _trimmed_vind(V.indices...)...))
113+
function unaliascopy(V::SubArray{T,N,A,I,LD}) where {T,N,A<:Array,I<:Tuple{Vararg{Union{ScalarIndex,AbstractRange{<:ScalarIndex},Array{<:Union{ScalarIndex,AbstractCartesianIndex}}}}},LD}
114+
dest = Array{T}(undef, _trimmedshape(V.indices...))
115+
trimmedpind = _trimmedpind(V.indices...)
116+
vdest = trimmedpind isa Tuple{Vararg{Union{Slice,Colon}}} ? dest : view(dest, trimmedpind...)
117+
copyto!(vdest, view(V, _trimmedvind(V.indices...)...))
116118
SubArray{T,N,A,I,LD}(dest, map(_trimmedindex, V.indices), 0, Int(LD))
117119
end
118-
# We can avoid the repeation from `AbstractArray{CartesianIndex{0}}`
119-
@inline _trimmed_vind(A, rest...) = (_trimmed_vind1(A)..., _trimmed_vind(rest...)...)
120-
_trimmed_vind() = ()
121-
_trimmed_vind1(i::AbstractArray{<:AbstractCartesianIndex{0}}) = map(firstindex, axes(i))
122-
_trimmed_vind1(i) = axes(i)
123120
# Get the proper trimmed shape
124-
@inline _trimmed_shape(A, rest...) = (_trimmed_shape1(A)..., _trimmed_shape(rest...)...)
125-
_trimmed_shape() = ()
126-
_trimmed_shape1(::Real) = (1,)
127-
_trimmed_shape1(i::AbstractArray{<:Integer}) = (length(i),)
128-
_trimmed_shape1(i::AbstractArray{<:AbstractCartesianIndex{0}}) = ()
129-
_trimmed_shape1(i::AbstractArray{<:AbstractCartesianIndex{N}}) where {N} = (length(i), ntuple(Returns(1), Val(N - 1))...)
121+
_trimmedshape(::ScalarIndex, rest...) = (1, _trimmedshape(rest...)...)
122+
_trimmedshape(i::AbstractRange, rest...) = (maximum(i), _trimmedshape(rest...)...)
123+
_trimmedshape(i::Union{UnitRange,StepRange,OneTo}, rest...) = (length(i), _trimmedshape(rest...)...)
124+
_trimmedshape(i::AbstractArray{<:ScalarIndex}, rest...) = (length(i), _trimmedshape(rest...)...)
125+
_trimmedshape(i::AbstractArray{<:AbstractCartesianIndex{0}}, rest...) = _trimmedshape(rest...)
126+
_trimmedshape(i::AbstractArray{<:AbstractCartesianIndex{N}}, rest...) where {N} = (length(i), ntuple(Returns(1), Val(N - 1))..., _trimmedshape(rest...)...)
127+
_trimmedshape() = ()
128+
# We can avoid the repeation from `AbstractArray{CartesianIndex{0}}`
129+
_trimmedpind(i, rest...) = (map(Returns(:), axes(i))..., _trimmedpind(rest...)...)
130+
_trimmedpind(i::AbstractRange, rest...) = (i, _trimmedpind(rest...)...)
131+
_trimmedpind(i::Union{UnitRange,StepRange,OneTo}, rest...) = ((:), _trimmedpind(rest...)...)
132+
_trimmedpind(i::AbstractArray{<:AbstractCartesianIndex{0}}, rest...) = _trimmedpind(rest...)
133+
_trimmedpind() = ()
134+
_trimmedvind(i, rest...) = (map(Returns(:), axes(i))..., _trimmedvind(rest...)...)
135+
_trimmedvind(i::AbstractArray{<:AbstractCartesianIndex{0}}, rest...) = (map(first, axes(i))..., _trimmedvind(rest...)...)
136+
_trimmedvind() = ()
130137
# Transform indices to be "dense"
131-
_trimmedindex(i::Real) = oftype(i, 1)
132-
_trimmedindex(i::AbstractUnitRange{<:Integer}) = oftype(i, oneto(length(i)))
133-
_trimmedindex(i::AbstractArray{<:Integer}) = oftype(i, reshape(eachindex(IndexLinear(), i), axes(i)))
138+
_trimmedindex(i::ScalarIndex) = oftype(i, 1)
139+
_trimmedindex(i::AbstractRange) = i
140+
_trimmedindex(i::Union{UnitRange,StepRange,OneTo}) = oftype(i, oneto(length(i)))
141+
_trimmedindex(i::AbstractArray{<:ScalarIndex}) = oftype(i, reshape(eachindex(IndexLinear(), i), axes(i)))
134142
_trimmedindex(i::AbstractArray{<:AbstractCartesianIndex{0}}) = oftype(i, copy(i))
135143
function _trimmedindex(i::AbstractArray{<:AbstractCartesianIndex{N}}) where {N}
136144
padding = ntuple(Returns(1), Val(N - 1))

test/subarray.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,8 +660,14 @@ end
660660
@testset "unaliascopy trimming; Issue #26263" begin
661661
A = rand(5,5,5,5)
662662
V = view(A, 2:5, :, 2:5, 1:2:5)
663-
@test @inferred(Base.unaliascopy(V))::typeof(V) == V == A[2:5, :, 2:5, 1:2:5]
664-
@test @inferred(sum(Base.unaliascopy(V))) sum(V) sum(A[2:5, :, 2:5, 1:2:5])
663+
V′ = @inferred(Base.unaliascopy(V))
664+
@test size(V′.parent) == size(V)
665+
@test V′::typeof(V) == V == A[2:5, :, 2:5, 1:2:5]
666+
@test @inferred(sum(V′)) sum(V) sum(A[2:5, :, 2:5, 1:2:5])
667+
V = view(A, Base.IdentityUnitRange(2:4), :, Base.StepRangeLen(1,1,3), 1:2:5)
668+
V′ = @inferred(Base.unaliascopy(V))
669+
@test size(V.parent) != size(V′.parent)
670+
@test V′ == V && V′ isa typeof(V)
665671
i1 = collect(CartesianIndices((2:5)))
666672
i2 = [CartesianIndex(), CartesianIndex()]
667673
i3 = collect(CartesianIndices((2:5, 1:2:5)))

0 commit comments

Comments
 (0)