Skip to content

Commit 6d3120c

Browse files
chethegaKristofferC
authored andcommitted
speed up logical indexing by bitarray (#29746)
* speed up logical indexing by bitarray * changed inbounds / OOB behavior to match array iterators switched spelling of _blsr * Update base/multidimensional.jl Co-Authored-By: chethega <[email protected]> (cherry picked from commit 44f2563)
1 parent 9e103a2 commit 6d3120c

File tree

2 files changed

+16
-11
lines changed

2 files changed

+16
-11
lines changed

base/bitarray.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ IndexStyle(::Type{<:BitArray}) = IndexLinear()
8484
const _msk64 = ~UInt64(0)
8585
@inline _div64(l) = l >> 6
8686
@inline _mod64(l) = l & 63
87+
@inline _blsr(x)= x & (x-1) #zeros the last set bit. Has native instruction on many archs. needed in multidimensional.jl
8788
@inline _msk_end(l::Integer) = _msk64 >>> _mod64(-l)
8889
@inline _msk_end(B::BitArray) = _msk_end(length(B))
8990
num_bit_chunks(n::Int) = _div64(n+63)

base/multidimensional.jl

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -520,19 +520,23 @@ end
520520
L.mask[idx] && return (idx, s)
521521
end
522522
end
523-
# When wrapping a BitArray, lean heavily upon its internals -- this is a common
524-
# case. Just use the Int index and count as its state.
525-
@inline function iterate(L::LogicalIndex{Int,<:BitArray}, s=(0,1))
526-
s[2] > length(L) && return nothing
527-
i, n = s
523+
# When wrapping a BitArray, lean heavily upon its internals.
524+
@inline function iterate(L::Base.LogicalIndex{Int,<:BitArray})
525+
L.sum == 0 && return nothing
528526
Bc = L.mask.chunks
529-
while true
530-
if Bc[_div64(i)+1] & (UInt64(1)<<_mod64(i)) != 0
531-
i += 1
532-
return (i, (i, n+1))
533-
end
534-
i += 1
527+
return iterate(L, (1, @inbounds Bc[1]))
528+
end
529+
@inline function iterate(L::Base.LogicalIndex{Int,<:BitArray}, s)
530+
Bc = L.mask.chunks
531+
i1, c = s
532+
while c==0
533+
i1 % UInt >= length(Bc) % UInt && return nothing
534+
i1 += 1
535+
@inbounds c = Bc[i1]
535536
end
537+
tz = trailing_zeros(c) + 1
538+
c = _blsr(c)
539+
return ((i1-1)<<6 + tz, (i1, c))
536540
end
537541

538542
@inline checkbounds(::Type{Bool}, A::AbstractArray, I::LogicalIndex{<:Any,<:AbstractArray{Bool,1}}) =

0 commit comments

Comments
 (0)