Skip to content

Commit f579d14

Browse files
mbaumanKristofferC
andauthored
More efficient indexing by CartesianIndices (#31214)
Treat CartesianIndices as its tuple of ranges when indexing. This allows views that use CartesianIndices as indices to be strided and changes the complexity of boundschecking from O(n^d) to O(d) Co-authored-by: Kristoffer Carlsson <kristoffer.carlsson@chalmers.se>
1 parent 6d86384 commit f579d14

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

base/multidimensional.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
module IteratorsMD
55
import .Base: eltype, length, size, first, last, in, getindex,
66
setindex!, IndexStyle, min, max, zero, oneunit, isless, eachindex,
7-
ndims, IteratorSize, convert, show, iterate, promote_rule
7+
ndims, IteratorSize, convert, show, iterate, promote_rule, to_indices
88

99
import .Base: +, -, *, (:)
1010
import .Base: simd_outer_range, simd_inner_length, simd_index
@@ -381,6 +381,10 @@ module IteratorsMD
381381
first(iter::CartesianIndices) = CartesianIndex(map(first, iter.indices))
382382
last(iter::CartesianIndices) = CartesianIndex(map(last, iter.indices))
383383

384+
# When used as indices themselves, CartesianIndices can simply become its tuple of ranges
385+
@inline to_indices(A, inds, I::Tuple{CartesianIndices, Vararg{Any}}) =
386+
to_indices(A, inds, (I[1].indices..., tail(I)...))
387+
384388
@inline function in(i::CartesianIndex{N}, r::CartesianIndices{N}) where {N}
385389
_in(true, i.I, first(r).I, last(r).I)
386390
end
@@ -573,6 +577,7 @@ function checkindex(::Type{Bool}, inds::Tuple, I::AbstractArray{<:CartesianIndex
573577
end
574578
b
575579
end
580+
checkindex(::Type{Bool}, inds::Tuple, I::CartesianIndices) = all(checkindex.(Bool, inds, I.indices))
576581

577582
# combined count of all indices, including CartesianIndex and
578583
# AbstractArray{CartesianIndex}

test/arrayops.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2648,6 +2648,21 @@ end
26482648
# Fix oneunit bug for unitful arrays
26492649
@test oneunit([Second(1) Second(2); Second(3) Second(4)]) == [Second(1) Second(0); Second(0) Second(1)]
26502650

2651+
@testset "indexing by CartesianIndices" begin
2652+
A = rand(10,10)
2653+
for (I,Rs) in ((keys(A), (1:10, 1:10)),
2654+
(CartesianIndex(2,2):CartesianIndex(9,9), (2:9, 2:9)),
2655+
(CartesianIndex(5,3):CartesianIndex(6,7), (5:6, 3:7)))
2656+
@test A[I] == A[Rs...] == @view(A[I]) == @view(A[Rs...])
2657+
@test @view(A[I]) isa StridedArray
2658+
@test !checkbounds(Bool, [], I)
2659+
@test !checkbounds(Bool, fill(2,1,1,1), :, I)
2660+
@test !checkbounds(Bool, fill(2,1,1,1), I, :)
2661+
end
2662+
@test !checkbounds(Bool, rand(3,3,3), :, CartesianIndex(0,0):CartesianIndex(1,1))
2663+
@test !checkbounds(Bool, rand(3,3,3), CartesianIndex(0,0):CartesianIndex(1,1), :)
2664+
end
2665+
26512666
# Throws ArgumentError for negative dimensions in Array
26522667
@test_throws ArgumentError fill('a', -10)
26532668

0 commit comments

Comments
 (0)