Skip to content

Commit

Permalink
Fast bounds-check for CartesianIndex ranges (#55596)
Browse files Browse the repository at this point in the history
`StepRangeLen{<:CartesianIndex}` indices have been supported since
v1.11, but bounds-checking for such indices currently falls back to
iterating over the entire range. This PR adds a quick `checkindex` for
such ranges.

The performance improvement as a consequence:
```julia
julia> D = Diagonal(1:10_000);

julia> @Btime checkbounds($D, diagind($D, IndexCartesian()));
  6.697 μs (0 allocations: 0 bytes) # nightly, O(n)
  4.044 ns (0 allocations: 0 bytes) # This PR, O(1)
```
  • Loading branch information
jishnub authored Aug 28, 2024
1 parent d882d62 commit 6440292
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 0 deletions.
2 changes: 2 additions & 0 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,8 @@ end
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)))

# Indexing into Array with mixtures of Integers and CartesianIndices is
# extremely performance-sensitive. While the abstract fallbacks support this,
Expand Down
5 changes: 5 additions & 0 deletions stdlib/LinearAlgebra/test/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1354,4 +1354,9 @@ end
end
end

@testset "bounds-check with CartesianIndex ranges" begin
D = Diagonal(1:typemax(Int))
@test checkbounds(Bool, D, diagind(D, IndexCartesian()))
end

end # module TestDiagonal

0 comments on commit 6440292

Please sign in to comment.