From 5be83f9285e7db6fc6498eda3698829ca0cbf2c0 Mon Sep 17 00:00:00 2001 From: matthias314 Date: Sat, 18 Feb 2023 15:45:39 -0500 Subject: [PATCH 1/4] added `iterate` method for `FastContiguousSubArray` --- base/subarray.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/base/subarray.jl b/base/subarray.jl index 214a2f98afe31..f4b2f011dbd8f 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -433,6 +433,12 @@ find_extended_inds(::ScalarIndex, I...) = (@inline; find_extended_inds(I...)) find_extended_inds(i1, I...) = (@inline; (i1, find_extended_inds(I...)...)) find_extended_inds() = () +function iterate(V::FastContiguousSubArray, + state = (V.offset1+firstindex(V), V.offset1+lastindex(V))) + i, l = state + @inbounds i-1 < l ? (V.parent[i], (i+1, l)) : nothing +end + function unsafe_convert(::Type{Ptr{T}}, V::SubArray{T,N,P,<:Tuple{Vararg{RangeIndex}}}) where {T,N,P} return unsafe_convert(Ptr{T}, V.parent) + _memory_offset(V.parent, map(first, V.indices)...) end From 70d1d95d79eebff458b52c3e2a551c035d30d2bd Mon Sep 17 00:00:00 2001 From: matthias314 Date: Tue, 21 Feb 2023 13:27:56 -0500 Subject: [PATCH 2/4] made `iterate` method safe --- base/subarray.jl | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/base/subarray.jl b/base/subarray.jl index f4b2f011dbd8f..1f97ebbc09b5f 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -433,10 +433,28 @@ find_extended_inds(::ScalarIndex, I...) = (@inline; find_extended_inds(I...)) find_extended_inds(i1, I...) = (@inline; (i1, find_extended_inds(I...)...)) find_extended_inds() = () -function iterate(V::FastContiguousSubArray, - state = (V.offset1+firstindex(V), V.offset1+lastindex(V))) +function isvalid_index(p, i, l) + if firstindex(p) == 1 + (i-1)%UInt < l%UInt <= lastindex(p)%UInt + else + firstindex(p) <= i <= l <= lastindex(p) + end +end + +function Base.iterate(v::Base.FastContiguousSubArray, + state = v.offset1 .+ (firstindex(v), lastindex(v))) + p = parent(v) + i, l = state + isvalid_index(p, i, l) ? (@inbounds p[i], (i+1, l)) : nothing +end + +stride1(v::SubArray{T,N,P}) where {T,N,P} = P <: StridedArray ? stride(v, 1) : v.stride1 + +function Base.iterate(v::Base.FastSubArray, + state = v.offset1 .+ stride1(v) .* (firstindex(v), lastindex(v))) + p = parent(v) i, l = state - @inbounds i-1 < l ? (V.parent[i], (i+1, l)) : nothing + isvalid_index(p, i, l) ? (@inbounds p[i], (i+stride1(v), l)) : nothing end function unsafe_convert(::Type{Ptr{T}}, V::SubArray{T,N,P,<:Tuple{Vararg{RangeIndex}}}) where {T,N,P} From 3b2d9b0da49add2e394724202207ec7db6e3b25c Mon Sep 17 00:00:00 2001 From: matthias314 Date: Tue, 21 Feb 2023 17:26:09 -0500 Subject: [PATCH 3/4] fixed problem with negative stride1 --- base/subarray.jl | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/base/subarray.jl b/base/subarray.jl index 1f97ebbc09b5f..88acc7068f6e2 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -433,28 +433,32 @@ find_extended_inds(::ScalarIndex, I...) = (@inline; find_extended_inds(I...)) find_extended_inds(i1, I...) = (@inline; (i1, find_extended_inds(I...)...)) find_extended_inds() = () -function isvalid_index(p, i, l) - if firstindex(p) == 1 - (i-1)%UInt < l%UInt <= lastindex(p)%UInt +function is_valid_ind(p, i, l, stride1) + fi = firstindex(p) + li = lastindex(p) + if stride1 < 0 + fi <= l <= i <= li + elseif fi != 1 + fi <= i <= l <= li else - firstindex(p) <= i <= l <= lastindex(p) + (i-1) % UInt < l % UInt <= li % UInt end end -function Base.iterate(v::Base.FastContiguousSubArray, +function iterate(v::FastContiguousSubArray, state = v.offset1 .+ (firstindex(v), lastindex(v))) p = parent(v) i, l = state - isvalid_index(p, i, l) ? (@inbounds p[i], (i+1, l)) : nothing + is_valid_ind(p, i, l, 1) ? (@inbounds p[i], (i+1, l)) : nothing end stride1(v::SubArray{T,N,P}) where {T,N,P} = P <: StridedArray ? stride(v, 1) : v.stride1 -function Base.iterate(v::Base.FastSubArray, +function iterate(v::FastSubArray, state = v.offset1 .+ stride1(v) .* (firstindex(v), lastindex(v))) p = parent(v) i, l = state - isvalid_index(p, i, l) ? (@inbounds p[i], (i+stride1(v), l)) : nothing + is_valid_ind(p, i, l, stride1(v)) ? (@inbounds p[i], (i+stride1(v), l)) : nothing end function unsafe_convert(::Type{Ptr{T}}, V::SubArray{T,N,P,<:Tuple{Vararg{RangeIndex}}}) where {T,N,P} From bb8417755c884a4e7535004b3c93013b3c7068b6 Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Wed, 22 Feb 2023 15:48:25 +0800 Subject: [PATCH 4/4] switch to `checkindex` optimization. the `checkindex` hack is based on the assumption that `last(ind) >= 0` remove `iterate` specialization. --- base/abstractarray.jl | 2 ++ base/subarray.jl | 28 ---------------------------- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index a1d910e38e169..f79872818de31 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -767,6 +767,8 @@ false checkindex(::Type{Bool}, inds::AbstractUnitRange, i) = throw(ArgumentError("unable to check bounds for indices of type $(typeof(i))")) checkindex(::Type{Bool}, inds::AbstractUnitRange, i::Real) = (first(inds) <= i) & (i <= last(inds)) +checkindex(::Type{Bool}, inds::IdentityUnitRange, i::Real) = checkindex(Bool, inds.indices, i) +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 function checkindex(::Type{Bool}, inds::AbstractUnitRange, r::AbstractRange) diff --git a/base/subarray.jl b/base/subarray.jl index 88acc7068f6e2..214a2f98afe31 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -433,34 +433,6 @@ find_extended_inds(::ScalarIndex, I...) = (@inline; find_extended_inds(I...)) find_extended_inds(i1, I...) = (@inline; (i1, find_extended_inds(I...)...)) find_extended_inds() = () -function is_valid_ind(p, i, l, stride1) - fi = firstindex(p) - li = lastindex(p) - if stride1 < 0 - fi <= l <= i <= li - elseif fi != 1 - fi <= i <= l <= li - else - (i-1) % UInt < l % UInt <= li % UInt - end -end - -function iterate(v::FastContiguousSubArray, - state = v.offset1 .+ (firstindex(v), lastindex(v))) - p = parent(v) - i, l = state - is_valid_ind(p, i, l, 1) ? (@inbounds p[i], (i+1, l)) : nothing -end - -stride1(v::SubArray{T,N,P}) where {T,N,P} = P <: StridedArray ? stride(v, 1) : v.stride1 - -function iterate(v::FastSubArray, - state = v.offset1 .+ stride1(v) .* (firstindex(v), lastindex(v))) - p = parent(v) - i, l = state - is_valid_ind(p, i, l, stride1(v)) ? (@inbounds p[i], (i+stride1(v), l)) : nothing -end - function unsafe_convert(::Type{Ptr{T}}, V::SubArray{T,N,P,<:Tuple{Vararg{RangeIndex}}}) where {T,N,P} return unsafe_convert(Ptr{T}, V.parent) + _memory_offset(V.parent, map(first, V.indices)...) end