Skip to content

Commit

Permalink
Fix linear indexing for ReshapedArray if the parent has offset axes (#…
Browse files Browse the repository at this point in the history
…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)
  • Loading branch information
jishnub authored and KristofferC committed Mar 27, 2024
1 parent 396f5d1 commit c2d480c
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
9 changes: 6 additions & 3 deletions base/reshapedarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ offset_if_vec(i::Integer, axs::Tuple) = i

@inline function isassigned(A::ReshapedArrayLF, index::Int)
@boundscheck checkbounds(Bool, A, index) || return false
@inbounds ret = isassigned(parent(A), index)
indexparent = index - firstindex(A) + firstindex(parent(A))
@inbounds ret = isassigned(parent(A), indexparent)
ret
end
@inline function isassigned(A::ReshapedArray{T,N}, indices::Vararg{Int, N}) where {T,N}
Expand All @@ -241,7 +242,8 @@ end

@inline function getindex(A::ReshapedArrayLF, index::Int)
@boundscheck checkbounds(A, index)
@inbounds ret = parent(A)[index]
indexparent = index - firstindex(A) + firstindex(parent(A))
@inbounds ret = parent(A)[indexparent]
ret
end
@inline function getindex(A::ReshapedArray{T,N}, indices::Vararg{Int,N}) where {T,N}
Expand All @@ -265,7 +267,8 @@ end

@inline function setindex!(A::ReshapedArrayLF, val, index::Int)
@boundscheck checkbounds(A, index)
@inbounds parent(A)[index] = val
indexparent = index - firstindex(A) + firstindex(parent(A))
@inbounds parent(A)[indexparent] = val
val
end
@inline function setindex!(A::ReshapedArray{T,N}, val, indices::Vararg{Int,N}) where {T,N}
Expand Down
30 changes: 30 additions & 0 deletions test/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1854,3 +1854,33 @@ f45952(x) = [x;;]
@test_throws "invalid index: true of type Bool" isassigned(A, 1, true)
@test_throws "invalid index: true of type Bool" isassigned(A, true)
end

@testset "reshape for offset arrays" begin
p = Base.IdentityUnitRange(3:4)
r = reshape(p, :, 1)
@test r[eachindex(r)] == UnitRange(p)
@test collect(r) == r

struct ZeroBasedArray{T,N,A<:AbstractArray{T,N}} <: AbstractArray{T,N}
a :: A
function ZeroBasedArray(a::AbstractArray)
Base.require_one_based_indexing(a)
new{eltype(a), ndims(a), typeof(a)}(a)
end
end
Base.parent(z::ZeroBasedArray) = z.a
Base.size(z::ZeroBasedArray) = size(parent(z))
Base.axes(z::ZeroBasedArray) = map(x -> Base.IdentityUnitRange(0:x - 1), size(parent(z)))
Base.getindex(z::ZeroBasedArray{<:Any, N}, i::Vararg{Int,N}) where {N} = parent(z)[map(x -> x + 1, i)...]
Base.setindex!(z::ZeroBasedArray{<:Any, N}, val, i::Vararg{Int,N}) where {N} = parent(z)[map(x -> x + 1, i)...] = val

z = ZeroBasedArray(collect(1:4))
r2 = reshape(z, :, 1)
@test r2[CartesianIndices(r2)] == r2[LinearIndices(r2)]
r2[firstindex(r2)] = 34
@test z[0] == 34
r2[eachindex(r2)] = r2 .* 2
for (i, j) in zip(eachindex(r2), eachindex(z))
@test r2[i] == z[j]
end
end

0 comments on commit c2d480c

Please sign in to comment.