Skip to content

Commit

Permalink
Make LinearIndices consistent with linearindices for vectors (#26682)
Browse files Browse the repository at this point in the history
Change LinearIndices(x::AbstractVector) to use the same indices as axes(x, 1).
This is consistent with linearindices(x) and allows indexing into x.
Change CartesianIndices to use custom axes so that it works with indices returned by
LinearIndices for vectors.

Use IndexLinear indexing for LinearIndices

Add bounds check to getindex for LinearIndices and CartesianIndices.
  • Loading branch information
nalimilan committed Apr 4, 2018
1 parent a55c280 commit b64a8e0
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 17 deletions.
16 changes: 9 additions & 7 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,12 @@ module IteratorsMD
convert(Tuple{Vararg{UnitRange{Int}}}, R)

# AbstractArray implementation
Base.axes(iter::CartesianIndices{N,R}) where {N,R} = iter.indices
Base.IndexStyle(::Type{CartesianIndices{N,R}}) where {N,R} = IndexCartesian()
@inline Base.getindex(iter::CartesianIndices{N,R}, I::Vararg{Int, N}) where {N,R} = CartesianIndex(first.(iter.indices) .- 1 .+ I)
@inline function Base.getindex(iter::CartesianIndices{N,R}, I::Vararg{Int, N}) where {N,R}
@boundscheck checkbounds(iter, I...)
CartesianIndex(I)
end

ndims(R::CartesianIndices) = ndims(typeof(R))
ndims(::Type{CartesianIndices{N}}) where {N} = N
Expand Down Expand Up @@ -409,14 +413,12 @@ module IteratorsMD
LinearIndices(A::AbstractArray) = LinearIndices(CartesianIndices(A))

# AbstractArray implementation
Base.IndexStyle(::Type{LinearIndices{N,R}}) where {N,R} = IndexCartesian()
Base.IndexStyle(::Type{LinearIndices{N,R}}) where {N,R} = IndexLinear()
Base.axes(iter::LinearIndices{N,R}) where {N,R} = iter.indices
Base.size(iter::LinearIndices{N,R}) where {N,R} = length.(iter.indices)
@inline function Base.getindex(iter::LinearIndices{N,R}, I::Vararg{Int, N}) where {N,R}
dims = length.(iter.indices)
#without the inbounds, this is slower than Base._sub2ind(iter.indices, I...)
@inbounds result = reshape(1:prod(dims), dims)[(I .- first.(iter.indices) .+ 1)...]
return result
function Base.getindex(iter::LinearIndices{N,R}, i::Int) where {N,R}
@boundscheck checkbounds(iter, i)
i
end
end # IteratorsMD

Expand Down
17 changes: 10 additions & 7 deletions test/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,15 @@ end
@test LinearIndices((1:4,1:3,1:2))[l] == l
@test CartesianIndices((1:4,1:3,1:2))[i,j,k] == CartesianIndex(i,j,k)
@test CartesianIndices((1:4,1:3,1:2))[l] == CartesianIndex(i,j,k)
@test LinearIndices((0:3,3:5,-101:-100))[i-1,j+2,k-102] == l
end

l = 0
for k = -101:-100, j = 3:5, i = 0:3
l += 1
@test LinearIndices((0:3,3:5,-101:-100))[i,j,k] == l
@test LinearIndices((0:3,3:5,-101:-100))[l] == l
@test CartesianIndices((0:3,3:5,-101:-100))[i,j,k] == CartesianIndex(i-1, j+2, k-102)
@test CartesianIndices((0:3,3:5,-101:-100))[l] == CartesianIndex(i-1, j+2, k-102)
@test CartesianIndices((0:3,3:5,-101:-100))[i,j,k] == CartesianIndex(i,j,k)
@test CartesianIndices((0:3,3:5,-101:-100))[l] == CartesianIndex(i,j,k)
end

local A = reshape(Vector(1:9), (3,3))
Expand Down Expand Up @@ -862,10 +867,8 @@ end
yrng = 1:5
CR = CartesianIndices((xrng,yrng))

for (i,i_idx) in enumerate(xrng)
for (j,j_idx) in enumerate(yrng)
@test CR[i,j] == CartesianIndex(i_idx,j_idx)
end
for i in xrng, j in yrng
@test CR[i,j] == CartesianIndex(i,j)
end

for i_lin in linearindices(CR)
Expand Down
6 changes: 3 additions & 3 deletions test/arrayops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1681,7 +1681,7 @@ end
@test eltype(R) <: CartesianIndex{2}
@test eltype(typeof(R)) <: CartesianIndex{2}
@test eltype(CartesianIndices{2}) <: CartesianIndex{2}
indices = Array(R)
indices = collect(R)
@test indices[1] == CartesianIndex{2}(2,3)
@test indices[2] == CartesianIndex{2}(3,3)
@test indices[4] == CartesianIndex{2}(5,3)
Expand All @@ -1702,8 +1702,8 @@ end
@test @inferred(convert(NTuple{2,UnitRange}, R)) === (2:5, 3:5)
@test @inferred(convert(Tuple{Vararg{UnitRange}}, R)) === (2:5, 3:5)

@test CartesianIndices((3:5,-7:7)) == CartesianIndex.(3:5, reshape(-7:7, 1, :))
@test CartesianIndices((3,-7:7)) == CartesianIndex.(3, reshape(-7:7, 1, :))
@test collect(CartesianIndices((3:5,-7:7))) == CartesianIndex.(3:5, reshape(-7:7, 1, :))
@test collect(CartesianIndices((3,-7:7))) == CartesianIndex.(3, reshape(-7:7, 1, :))
end

# All we really care about is that we have an optimized
Expand Down

0 comments on commit b64a8e0

Please sign in to comment.