From 1407d7643c35129ae05461b0c531386d7c210311 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 27 Aug 2024 13:14:14 +0530 Subject: [PATCH 1/2] Fast bounds-check for CartesianIndex ranges --- base/abstractarray.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 754ab20660ab8..3972d64a77572 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -754,8 +754,11 @@ checkindex(::Type{Bool}, inds::IdentityUnitRange, i::Real) = checkindex(Bool, in checkindex(::Type{Bool}, inds::OneTo{T}, i::T) where {T<:BitInteger} = unsigned(i - one(i)) < unsigned(last(inds)) checkindex(::Type{Bool}, inds::AbstractUnitRange, ::Colon) = true checkindex(::Type{Bool}, inds::AbstractUnitRange, ::Slice) = true -checkindex(::Type{Bool}, inds::AbstractUnitRange, i::AbstractRange) = +_checkindex_range(::Type{Bool}, inds, i::AbstractRange) = isempty(i) | (checkindex(Bool, inds, first(i)) & checkindex(Bool, inds, last(i))) +checkindex(::Type{Bool}, inds::AbstractUnitRange, i::AbstractRange) = _checkindex_range(Bool, inds, i) +# generic fallback method for unusual range indices, e.g. CartesianIndex ranges +checkindex(::Type{Bool}, inds, i::AbstractRange) = _checkindex_range(Bool, inds, i) # range like indices with cheap `extrema` checkindex(::Type{Bool}, inds::AbstractUnitRange, i::LinearIndices) = isempty(i) | (checkindex(Bool, inds, first(i)) & checkindex(Bool, inds, last(i))) From 14c21b43b86b781bbcd26f8fffc8f7dca4bf38b9 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 27 Aug 2024 15:26:08 +0530 Subject: [PATCH 2/2] Make method narrower --- base/abstractarray.jl | 5 +---- base/multidimensional.jl | 2 ++ stdlib/LinearAlgebra/test/diagonal.jl | 5 +++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 3972d64a77572..754ab20660ab8 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -754,11 +754,8 @@ checkindex(::Type{Bool}, inds::IdentityUnitRange, i::Real) = checkindex(Bool, in checkindex(::Type{Bool}, inds::OneTo{T}, i::T) where {T<:BitInteger} = unsigned(i - one(i)) < unsigned(last(inds)) checkindex(::Type{Bool}, inds::AbstractUnitRange, ::Colon) = true checkindex(::Type{Bool}, inds::AbstractUnitRange, ::Slice) = true -_checkindex_range(::Type{Bool}, inds, i::AbstractRange) = +checkindex(::Type{Bool}, inds::AbstractUnitRange, i::AbstractRange) = isempty(i) | (checkindex(Bool, inds, first(i)) & checkindex(Bool, inds, last(i))) -checkindex(::Type{Bool}, inds::AbstractUnitRange, i::AbstractRange) = _checkindex_range(Bool, inds, i) -# generic fallback method for unusual range indices, e.g. CartesianIndex ranges -checkindex(::Type{Bool}, inds, i::AbstractRange) = _checkindex_range(Bool, inds, i) # range like indices with cheap `extrema` checkindex(::Type{Bool}, inds::AbstractUnitRange, i::LinearIndices) = isempty(i) | (checkindex(Bool, inds, first(i)) & checkindex(Bool, inds, last(i))) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 5e32a19c2cafb..99f41f2404e47 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -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, diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index afb49b696d968..866c11b9931cd 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -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