From bdc7fb7b58d6358fae340dce88ec6baa2df595a2 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Wed, 17 Apr 2024 05:05:27 +0530 Subject: [PATCH] Explicitly compute stride in unaliascopy for SubArray (#54102) Fix https://github.com/JuliaLang/julia/issues/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 159f4d74e63d20c89dcc6c93f7a7e8d01939c130) --- base/subarray.jl | 7 +++++-- test/subarray.jl | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/base/subarray.jl b/base/subarray.jl index 2b8545c2cc226..759b564aade17 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -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...) diff --git a/test/subarray.jl b/test/subarray.jl index 31bd69cccb5ae..337e666da918c 100644 --- a/test/subarray.jl +++ b/test/subarray.jl @@ -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