diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 7add7b9e74205..1cc1f53575a32 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -403,6 +403,12 @@ module IteratorsMD getindex(iter, C.indices...) end @inline Base.getindex(iter::CartesianIndices{0}, ::CartesianIndices{0}) = iter + @inline function Base.getindex(iter::CartesianIndices{N}, r::AbstractRange{CartesianIndex{N}}) where {N} + @boundscheck checkbounds(iter, r) + start = first(iter) + CartesianIndex((Tuple(first(r)) .- first.(axes(iter))) .* Tuple(step(iter))) + stepsz = CartesianIndex(Tuple(step(iter)) .* Tuple(step(r))) + StepRangeLen(start, stepsz, length(r)) + end # If dimensions permit, we may index into a CartesianIndices directly instead of constructing a SubArray wrapper @propagate_inbounds function Base.view(c::CartesianIndices{N}, r::Vararg{Union{OrdinalRange{<:Integer, <:Integer}, Colon},N}) where {N} @@ -743,7 +749,7 @@ end @inline checkindex(::Type{Bool}, inds::Tuple, I::CartesianIndex) = checkbounds_indices(Bool, inds, I.I) @inline checkindex(::Type{Bool}, inds::Tuple, i::AbstractRange{<:CartesianIndex}) = - isempty(i) | (checkindex(Bool, inds, first(i)) & checkindex(Bool, inds, last(i))) + isempty(i) || (checkindex(Bool, inds, first(i)) & checkindex(Bool, inds, last(i))) # Indexing into Array with mixtures of Integers and CartesianIndices is # extremely performance-sensitive. While the abstract fallbacks support this, diff --git a/test/abstractarray.jl b/test/abstractarray.jl index bbac7812174da..9d9fcd0716672 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -285,6 +285,34 @@ end end end +@testset "Indexing CartesianIndices as an nD range" begin + for (m, n) in [(4, 6), (4, 4), (6,4)] + C = CartesianIndices((m, n)) + for k in -7:7 + dlen = length = max(0, k <= 0 ? min(m+k, n) : min(m, n-k)) + dind = StepRangeLen(CartesianIndex(1+max(0,-k),1+max(0,k)), CartesianIndex(1,1), dlen) + @test C[dind] === dind + @test C[dind[1:2:end]] === dind[1:2:end] + end + end + for C in [CartesianIndices((20:4:100,)), + CartesianIndices((20:-4:-100,)), + CartesianIndices((20:100,)), + CartesianIndices((Base.IdentityUnitRange(20:100),))] + r = StepRangeLen(CartesianIndex(firstindex(C)+1), CartesianIndex(3), 4) + @test C[r] == C[collect(r)] + end + C = CartesianIndices((3:8, 3:8, 3:8)) + r = StepRangeLen(CartesianIndex(1,1,1), CartesianIndex(1,1,1), 6) + @test C[r] == StepRangeLen(CartesianIndex(3,3,3), CartesianIndex(1,1,1), 6) + r = StepRangeLen(CartesianIndex(1,1,1), CartesianIndex(1,0,0), 6) + @test C[r] == StepRangeLen(CartesianIndex(3,3,3), CartesianIndex(1,0,0), 6) + + C = CartesianIndices((3:8, 3:8, Base.IdentityUnitRange(3:8))) + r = StepRangeLen(CartesianIndex(1,1,3), CartesianIndex(1,1,1), 6) + @test C[r] == StepRangeLen(CartesianIndex(3,3,3), CartesianIndex(1,1,1), 6) +end + @testset "LinearIndices" begin @testset "constructors" begin for oinds in [