Skip to content

Commit b6c957b

Browse files
jishnubKristofferC
authored andcommitted
Fix linear indexing for ReshapedArray if the parent has offset axes (#41232)
This PR fixes ```julia julia> r = reshape(Base.IdentityUnitRange(3:4), 2, 1) 2×1 reshape(::Base.IdentityUnitRange{UnitRange{Int64}}, 2, 1) with eltype Int64: 3 4 julia> collect(r) == r false julia> collect(r) 2×1 Matrix{Int64}: 3258125826116431922 3688512103538242609 ``` After this PR, ```julia julia> collect(r) 2×1 Matrix{Int64}: 3 4 ``` (cherry picked from commit 6e3044d)
1 parent f54bb4c commit b6c957b

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

base/reshapedarray.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ offset_if_vec(i::Integer, axs::Tuple) = i
238238

239239
@inline function isassigned(A::ReshapedArrayLF, index::Int)
240240
@boundscheck checkbounds(Bool, A, index) || return false
241-
@inbounds ret = isassigned(parent(A), index)
241+
indexparent = index - firstindex(A) + firstindex(parent(A))
242+
@inbounds ret = isassigned(parent(A), indexparent)
242243
ret
243244
end
244245
@inline function isassigned(A::ReshapedArray{T,N}, indices::Vararg{Int, N}) where {T,N}
@@ -251,7 +252,8 @@ end
251252

252253
@inline function getindex(A::ReshapedArrayLF, index::Int)
253254
@boundscheck checkbounds(A, index)
254-
@inbounds ret = parent(A)[index]
255+
indexparent = index - firstindex(A) + firstindex(parent(A))
256+
@inbounds ret = parent(A)[indexparent]
255257
ret
256258
end
257259
@inline function getindex(A::ReshapedArray{T,N}, indices::Vararg{Int,N}) where {T,N}
@@ -275,7 +277,8 @@ end
275277

276278
@inline function setindex!(A::ReshapedArrayLF, val, index::Int)
277279
@boundscheck checkbounds(A, index)
278-
@inbounds parent(A)[index] = val
280+
indexparent = index - firstindex(A) + firstindex(parent(A))
281+
@inbounds parent(A)[indexparent] = val
279282
val
280283
end
281284
@inline function setindex!(A::ReshapedArray{T,N}, val, indices::Vararg{Int,N}) where {T,N}

test/abstractarray.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,3 +2029,33 @@ end
20292029
@test B == A
20302030
end
20312031
end
2032+
2033+
@testset "reshape for offset arrays" begin
2034+
p = Base.IdentityUnitRange(3:4)
2035+
r = reshape(p, :, 1)
2036+
@test r[eachindex(r)] == UnitRange(p)
2037+
@test collect(r) == r
2038+
2039+
struct ZeroBasedArray{T,N,A<:AbstractArray{T,N}} <: AbstractArray{T,N}
2040+
a :: A
2041+
function ZeroBasedArray(a::AbstractArray)
2042+
Base.require_one_based_indexing(a)
2043+
new{eltype(a), ndims(a), typeof(a)}(a)
2044+
end
2045+
end
2046+
Base.parent(z::ZeroBasedArray) = z.a
2047+
Base.size(z::ZeroBasedArray) = size(parent(z))
2048+
Base.axes(z::ZeroBasedArray) = map(x -> Base.IdentityUnitRange(0:x - 1), size(parent(z)))
2049+
Base.getindex(z::ZeroBasedArray{<:Any, N}, i::Vararg{Int,N}) where {N} = parent(z)[map(x -> x + 1, i)...]
2050+
Base.setindex!(z::ZeroBasedArray{<:Any, N}, val, i::Vararg{Int,N}) where {N} = parent(z)[map(x -> x + 1, i)...] = val
2051+
2052+
z = ZeroBasedArray(collect(1:4))
2053+
r2 = reshape(z, :, 1)
2054+
@test r2[CartesianIndices(r2)] == r2[LinearIndices(r2)]
2055+
r2[firstindex(r2)] = 34
2056+
@test z[0] == 34
2057+
r2[eachindex(r2)] = r2 .* 2
2058+
for (i, j) in zip(eachindex(r2), eachindex(z))
2059+
@test r2[i] == z[j]
2060+
end
2061+
end

0 commit comments

Comments
 (0)