Skip to content

Commit 6e3044d

Browse files
authored
Fix linear indexing for ReshapedArray if the parent has offset axes (JuliaLang#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 ```
1 parent 26b3b5f commit 6e3044d

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
@@ -2060,3 +2060,33 @@ end
20602060
test_unsetindex(MyMatrixUnsetIndexCartInds)
20612061
test_unsetindex(MyMatrixUnsetIndexLinInds)
20622062
end
2063+
2064+
@testset "reshape for offset arrays" begin
2065+
p = Base.IdentityUnitRange(3:4)
2066+
r = reshape(p, :, 1)
2067+
@test r[eachindex(r)] == UnitRange(p)
2068+
@test collect(r) == r
2069+
2070+
struct ZeroBasedArray{T,N,A<:AbstractArray{T,N}} <: AbstractArray{T,N}
2071+
a :: A
2072+
function ZeroBasedArray(a::AbstractArray)
2073+
Base.require_one_based_indexing(a)
2074+
new{eltype(a), ndims(a), typeof(a)}(a)
2075+
end
2076+
end
2077+
Base.parent(z::ZeroBasedArray) = z.a
2078+
Base.size(z::ZeroBasedArray) = size(parent(z))
2079+
Base.axes(z::ZeroBasedArray) = map(x -> Base.IdentityUnitRange(0:x - 1), size(parent(z)))
2080+
Base.getindex(z::ZeroBasedArray{<:Any, N}, i::Vararg{Int,N}) where {N} = parent(z)[map(x -> x + 1, i)...]
2081+
Base.setindex!(z::ZeroBasedArray{<:Any, N}, val, i::Vararg{Int,N}) where {N} = parent(z)[map(x -> x + 1, i)...] = val
2082+
2083+
z = ZeroBasedArray(collect(1:4))
2084+
r2 = reshape(z, :, 1)
2085+
@test r2[CartesianIndices(r2)] == r2[LinearIndices(r2)]
2086+
r2[firstindex(r2)] = 34
2087+
@test z[0] == 34
2088+
r2[eachindex(r2)] = r2 .* 2
2089+
for (i, j) in zip(eachindex(r2), eachindex(z))
2090+
@test r2[i] == z[j]
2091+
end
2092+
end

0 commit comments

Comments
 (0)