From 7f1b4546b80f5254fd133aa76538f013dcd15c2c Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 16 Apr 2024 16:36:52 +0530 Subject: [PATCH 1/3] Explicitly compute stride in unaliascopy for SubArray --- 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 e9660b9dee639..029e73af1e647 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...) = (maximum(i, init=0), _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 eedf28539d72b..0c29c6a784efd 100644 --- a/test/subarray.jl +++ b/test/subarray.jl @@ -827,6 +827,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 From 7dd2f629149d723dd6dfb2b3343ef69ce5339ac2 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 16 Apr 2024 18:46:17 +0530 Subject: [PATCH 2/3] Use zero of the eltype in _trimmedshape --- base/subarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/subarray.jl b/base/subarray.jl index 029e73af1e647..6636d1e969316 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -122,7 +122,7 @@ function unaliascopy(V::SubArray{T,N,A,I,LD}) where {T,N,A<:Array,I<:Tuple{Varar end # Get the proper trimmed shape _trimmedshape(::ScalarIndex, rest...) = (1, _trimmedshape(rest...)...) -_trimmedshape(i::AbstractRange, rest...) = (maximum(i, init=0), _trimmedshape(rest...)...) +_trimmedshape(i::AbstractRange, rest...) = (maximum(i, init=zero(eltype(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...) From b39b0393878b1a0c1a11f60d9dd8958330b8ee66 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 16 Apr 2024 19:14:16 +0530 Subject: [PATCH 3/3] Branch on empty range in _trimmedshape --- base/subarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/subarray.jl b/base/subarray.jl index 6636d1e969316..656628bb40382 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -122,7 +122,7 @@ function unaliascopy(V::SubArray{T,N,A,I,LD}) where {T,N,A<:Array,I<:Tuple{Varar end # Get the proper trimmed shape _trimmedshape(::ScalarIndex, rest...) = (1, _trimmedshape(rest...)...) -_trimmedshape(i::AbstractRange, rest...) = (maximum(i, init=zero(eltype(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...)