Skip to content

Commit

Permalink
Explicitly compute stride in unaliascopy for SubArray (#54102)
Browse files Browse the repository at this point in the history
Fix #54100 by computing the
stride and offset explicitly. This is unlikely to be a performance
concern, so we don't need to hard-code this.

(cherry picked from commit 159f4d7)
  • Loading branch information
jishnub authored and KristofferC committed Apr 17, 2024
1 parent bf4e638 commit bdc7fb7
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
7 changes: 5 additions & 2 deletions base/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,14 @@ function unaliascopy(V::SubArray{T,N,A,I,LD}) where {T,N,A<:Array,I<:Tuple{Varar
trimmedpind = _trimmedpind(V.indices...)
vdest = trimmedpind isa Tuple{Vararg{Union{Slice,Colon}}} ? dest : view(dest, trimmedpind...)
copyto!(vdest, view(V, _trimmedvind(V.indices...)...))
SubArray{T,N,A,I,LD}(dest, map(_trimmedindex, V.indices), 0, Int(LD))
indices = map(_trimmedindex, V.indices)
stride1 = LD ? compute_stride1(dest, indices) : 0
offset1 = LD ? compute_offset1(dest, stride1, indices) : 0
SubArray{T,N,A,I,LD}(dest, indices, offset1, stride1)
end
# Get the proper trimmed shape
_trimmedshape(::ScalarIndex, rest...) = (1, _trimmedshape(rest...)...)
_trimmedshape(i::AbstractRange, rest...) = (maximum(i), _trimmedshape(rest...)...)
_trimmedshape(i::AbstractRange, rest...) = (isempty(i) ? zero(eltype(i)) : maximum(i), _trimmedshape(rest...)...)
_trimmedshape(i::Union{UnitRange,StepRange,OneTo}, rest...) = (length(i), _trimmedshape(rest...)...)
_trimmedshape(i::AbstractArray{<:ScalarIndex}, rest...) = (length(i), _trimmedshape(rest...)...)
_trimmedshape(i::AbstractArray{<:AbstractCartesianIndex{0}}, rest...) = _trimmedshape(rest...)
Expand Down
19 changes: 19 additions & 0 deletions test/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,25 @@ end
@test @inferred(Base.unaliascopy(V))::typeof(V) == V == A[i1, 1:5, i2, i3]
V = view(A, i1, 1:5, i3, i2)
@test @inferred(Base.unaliascopy(V))::typeof(V) == V == A[i1, 1:5, i3, i2]

@testset "custom ranges" begin
struct MyStepRange{T} <: OrdinalRange{T,T}
r::StepRange{T,T}
end

for f in (:first, :last, :step, :length, :size)
@eval Base.$f(r::MyStepRange) = $f(r.r)
end
Base.getindex(r::MyStepRange, i::Int) = r.r[i]

a = rand(6)
V = view(a, MyStepRange(2:2:4))
@test @inferred(Base.unaliascopy(V))::typeof(V) == V

# empty range
V = view(a, MyStepRange(2:2:1))
@test @inferred(Base.unaliascopy(V))::typeof(V) == V
end
end

@testset "issue #27632" begin
Expand Down

0 comments on commit bdc7fb7

Please sign in to comment.