Skip to content

Commit

Permalink
fix #45825, BitArray methods assuming 1-indexing of AbstractArray
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Jun 27, 2022
1 parent 684a8b7 commit 636b9be
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 9 deletions.
23 changes: 14 additions & 9 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -506,20 +506,23 @@ function BitArray{N}(A::AbstractArray{T,N}) where N where T
Bc = B.chunks
l = length(B)
l == 0 && return B
ind = 1
Aind = eachindex(A)
nextA = iterate(Aind)
@inbounds begin
for i = 1:length(Bc)-1
c = UInt64(0)
for j = 0:63
ind, Ast = nextA
c |= (UInt64(convert(Bool, A[ind])::Bool) << j)
ind += 1
nextA = iterate(Aind, Ast)
end
Bc[i] = c
end
c = UInt64(0)
for j = 0:_mod64(l-1)
ind, Ast = nextA
c |= (UInt64(convert(Bool, A[ind])::Bool) << j)
ind += 1
nextA = iterate(Aind, Ast)
end
Bc[end] = c
end
Expand Down Expand Up @@ -721,24 +724,26 @@ function _unsafe_setindex!(B::BitArray, X::AbstractArray, I::BitArray)
lx = length(X)
last_chunk_len = _mod64(length(B)-1)+1

c = 1
Xind = eachindex(X)
nextX = iterate(Xind)
for i = 1:lc
@inbounds Imsk = Ic[i]
@inbounds C = Bc[i]
u = UInt64(1)
for j = 1:(i < lc ? 64 : last_chunk_len)
if Imsk & u != 0
lx < c && throw_setindex_mismatch(X, c)
@inbounds x = convert(Bool, X[c])
nextX === nothing && throw_setindex_mismatch(X, count(I))
Xi, Xst = nextX
@inbounds x = convert(Bool, X[Xi])
C = ifelse(x, C | u, C & ~u)
c += 1
nextX = iterate(Xind, Xst)
end
u <<= 1
end
@inbounds Bc[i] = C
end
if length(X) != c-1
throw_setindex_mismatch(X, c-1)
if nextX !== nothing
throw_setindex_mismatch(X, count(I))
end
return B
end
Expand Down
18 changes: 18 additions & 0 deletions test/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1787,3 +1787,21 @@ end
@test all(bitarray[rangein, rangeout] .== true)
end
end

# issue #45825

isdefined(Main, :OffsetArrays) || @eval Main include("testhelpers/OffsetArrays.jl")
using .Main.OffsetArrays

let all_false = OffsetArray(falses(2001), -1000:1000)
@test !any(==(true), all_false)
# should be run with --check-bounds=yes
@test !any(==(true), BitArray(all_false))
end
let a = falses(1000),
msk = BitArray(rand(Bool, 1000)),
n = count(msk),
b = OffsetArray(rand(Bool, n), (-n÷2):(n÷2)-iseven(n))
a[msk] = b
@test a[msk] == collect(b)
end

0 comments on commit 636b9be

Please sign in to comment.