Skip to content

Commit

Permalink
fix #2360 (BitArray ref/assign performance)
Browse files Browse the repository at this point in the history
  • Loading branch information
carlobaldassi committed Feb 20, 2013
1 parent 6952b1f commit 0c6b975
Showing 1 changed file with 61 additions and 26 deletions.
87 changes: 61 additions & 26 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ size(B::BitArray) = tuple(B.dims...)

## Aux functions ##

get_chunks_id(i::Integer) = @_div64(int(i-1))+1, @_mod64(int(i-1))
get_chunks_id(i::Integer) = @_div64(int(i)-1)+1, @_mod64(int(i)-1)

function glue_src_bitchunks(src::Vector{Uint64}, k::Int, ks1::Int, msk_s0::Uint64, ls0::Int)
chunk = ((src[k] & msk_s0) >>> ls0)
Expand Down Expand Up @@ -248,16 +248,22 @@ end

## Indexing: ref ##

function ref(B::BitArray, i::Integer)
function ref_unchecked(Bc::Vector{Uint64}, i::Integer)
i1, i2 = get_chunks_id(i)
u = uint64(1)
return (Bc[i1] >>> i2) & u == u
end

function ref(B::BitArray, i::Real)
i = to_index(i)
if i < 1 || i > length(B)
throw(BoundsError())
end
i1, i2 = get_chunks_id(i)
return (B.chunks[i1] >>> i2) & one(Uint64) == one(Uint64)
ref_unchecked(B.chunks, i)
end

# 0d bitarray
ref(B::BitArray{0}) = B[1]
ref(B::BitArray{0}) = ref_unchecked(B.chunks, 1)

ref(B::BitArray, i0::Real, i1::Real) = B[to_index(i0) + size(B,1)*(to_index(i1)-1)]
ref(B::BitArray, i0::Real, i1::Real, i2::Real) =
Expand Down Expand Up @@ -348,9 +354,17 @@ end
# (which is fine)
function ref{T<:Real}(B::BitArray, I::AbstractVector{T})
X = BitArray(length(I))
lB = length(B)
Xc = X.chunks
Bc = B.chunks
ind = 1
for i in I
X[ind] = B[i]
# faster X[ind] = B[i]
i = to_index(i)
if i < 1 || i > lB
throw(BoundsError())
end
assign_unchecked(Xc, ref_unchecked(Bc, i), ind)
ind += 1
end
return X
Expand All @@ -361,14 +375,16 @@ let ref_cache = nothing
function ref(B::BitArray, I::Union(Real,AbstractArray)...)
I = indices(I)
X = BitArray(ref_shape(I...))
Xc = X.chunks

if is(ref_cache,nothing)
ref_cache = Dict()
end
gen_cartesian_map(ref_cache, ivars -> quote
X[storeind] = B[$(ivars...)]
storeind += 1
end, I, (:B, :X, :storeind), B, X, 1)
#faster X[storeind] = B[$(ivars...)]
assign_unchecked(Xc, B[$(ivars...)], ind)
ind += 1
end, I, (:B, :Xc, :ind), B, Xc, 1)
return X
end
end
Expand All @@ -377,15 +393,22 @@ end

function ref_bool_1d(B::BitArray, I::AbstractArray{Bool})
n = sum(I)
out = BitArray(n)
c = 1
X = BitArray(n)
lI = length(I)
if lI != length(B)
throw(BoundsError())
end
Xc = X.chunks
Bc = B.chunks
ind = 1
for i = 1:length(I)
if I[i]
out[c] = B[i]
c += 1
# faster X[ind] = B[i]
assign_unchecked(Xc, ref_unchecked(Bc, i), ind)
ind += 1
end
end
out
return X
end

ref(B::BitVector, I::AbstractVector{Bool}) = ref_bool_1d(B, I)
Expand All @@ -402,19 +425,23 @@ ref{T<:Real}(B::BitMatrix, I::AbstractVector{Bool}, J::AbstractVector{T}) = B[fi

## Indexing: assign ##

function assign_unchecked(Bc::Array{Uint64}, x, i::Integer)
x = convert(Bool, x)
i1, i2 = get_chunks_id(i)
u = uint64(1) << i2
if x
Bc[i1] |= u
else
Bc[i1] &= ~u
end
end

function assign(B::BitArray, x, i::Real)
i = to_index(i)
if i < 1 || i > length(B)
throw(BoundsError())
end
i1, i2 = get_chunks_id(i)
u = uint64(1)
y = convert(Bool, x)
if !y
B.chunks[i1] &= ~(u << i2)
else
B.chunks[i1] |= (u << i2)
end
assign_unchecked(B.chunks, x, i)
return B
end

Expand Down Expand Up @@ -598,21 +625,29 @@ end
# logical indexing

function assign_bool_scalar_1d(A::BitArray, x, I::AbstractArray{Bool})
n = sum(I)
if length(I) > length(A)
throw(BoundsError())
end
Ac = A.chunks
for i = 1:length(I)
if I[i]
A[i] = x
# faster A[i] = x
assign_unchecked(Ac, x, i)
end
end
A
end

function assign_bool_vector_1d(A::BitArray, X::AbstractArray, I::AbstractArray{Bool})
n = sum(I)
if length(I) > length(A)
throw(BoundsError())
end
Ac = A.chunks
c = 1
for i = 1:length(I)
if I[i]
A[i] = X[c]
# faster A[i] = X[c]
assign_unchecked(Ac, X[c], i)
c += 1
end
end
Expand Down

2 comments on commit 0c6b975

@pao
Copy link
Member

@pao pao commented on 0c6b975 Feb 20, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the most likely candiate to have caused the current Travis errors: https://travis-ci.org/JuliaLang/julia/jobs/4918907

@pao
Copy link
Member

@pao pao commented on 0c6b975 Feb 20, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind, you appear to have fixed this already, just not before it trashed my builds :D

Please sign in to comment.