Skip to content

Commit 7b41e72

Browse files
authored
Merge pull request #18198 from pabloferz/pz/mapbitarray
Fix #17970 (output of map over BitArrays)
2 parents 96f6ccc + a6fec5b commit 7b41e72

File tree

2 files changed

+30
-20
lines changed

2 files changed

+30
-20
lines changed

base/bitarray.jl

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,32 +1992,34 @@ maximum(B::BitArray) = isempty(B) ? throw(ArgumentError("argument must be non-em
19921992
# arrays since there can be a 64x speedup by working at the level of Int64
19931993
# instead of looping bit-by-bit.
19941994

1995-
map(f::Function, A::BitArray) = map!(f, similar(A), A)
1996-
map(f::Function, A::BitArray, B::BitArray) = map!(f, similar(A), A, B)
1995+
map(::Union{typeof(~), typeof(!)}, A::BitArray) = bit_map!(~, similar(A), A)
1996+
map(::typeof(zero), A::BitArray) = fill!(similar(A), false)
1997+
map(::typeof(one), A::BitArray) = fill!(similar(A), true)
1998+
map(::typeof(identity), A::BitArray) = copy(A)
19971999

19982000
map!(f, A::BitArray) = map!(f, A, A)
1999-
map!(f::typeof(!), dest::BitArray, A::BitArray) = map!(~, dest, A)
2000-
map!(f::typeof(zero), dest::BitArray, A::BitArray) = fill!(dest, false)
2001-
map!(f::typeof(one), dest::BitArray, A::BitArray) = fill!(dest, true)
2002-
2003-
immutable BitChunkFunctor{F<:Function}
2004-
f::F
2001+
map!(::typeof(identity), A::BitArray) = A
2002+
map!(::Union{typeof(~), typeof(!)}, dest::BitArray, A::BitArray) = bit_map!(~, dest, A)
2003+
map!(::typeof(zero), dest::BitArray, A::BitArray) = fill!(dest, false)
2004+
map!(::typeof(one), dest::BitArray, A::BitArray) = fill!(dest, true)
2005+
map!(::typeof(identity), dest::BitArray, A::BitArray) = copy!(dest, A)
2006+
2007+
for (T, f) in ((:(Union{typeof(&), typeof(*), typeof(min)}), :(&)),
2008+
(:(Union{typeof(|), typeof(max)}), :(|)),
2009+
(:(Union{typeof($), typeof(!=)}), :($)),
2010+
(:(Union{typeof(>=), typeof(^)}), :((p, q) -> p | ~q)),
2011+
(:(typeof(<=)), :((p, q) -> ~p | q)),
2012+
(:(typeof(==)), :((p, q) -> ~(p $ q))),
2013+
(:(typeof(<)), :((p, q) -> ~p & q)),
2014+
(:(typeof(>)), :((p, q) -> p & ~q)))
2015+
@eval map(::$T, A::BitArray, B::BitArray) = bit_map!($f, similar(A), A, B)
2016+
@eval map!(::$T, dest::BitArray, A::BitArray, B::BitArray) = bit_map!($f, dest, A, B)
20052017
end
2006-
(f::BitChunkFunctor)(x, y) = f.f(x,y)
2007-
2008-
map!(f::Union{typeof(*), typeof(min)}, dest::BitArray, A::BitArray, B::BitArray) = map!(&, dest, A, B)
2009-
map!(f::typeof(max), dest::BitArray, A::BitArray, B::BitArray) = map!(|, dest, A, B)
2010-
map!(f::typeof(!=), dest::BitArray, A::BitArray, B::BitArray) = map!($, dest, A, B)
2011-
map!(f::Union{typeof(>=), typeof(^)}, dest::BitArray, A::BitArray, B::BitArray) = map!(BitChunkFunctor((p, q) -> p | ~q), dest, A, B)
2012-
map!(f::typeof(<=), dest::BitArray, A::BitArray, B::BitArray) = map!(BitChunkFunctor((p, q) -> ~p | q), dest, A, B)
2013-
map!(f::typeof(==), dest::BitArray, A::BitArray, B::BitArray) = map!(BitChunkFunctor((p, q) -> ~(p $ q)), dest, A, B)
2014-
map!(f::typeof(<), dest::BitArray, A::BitArray, B::BitArray) = map!(BitChunkFunctor((p, q) -> ~p & q), dest, A, B)
2015-
map!(f::typeof(>), dest::BitArray, A::BitArray, B::BitArray) = map!(BitChunkFunctor((p, q) -> p & ~q), dest, A, B)
20162018

20172019
# If we were able to specialize the function to a known bitwise operation,
20182020
# map across the chunks. Otherwise, fall-back to the AbstractArray method that
20192021
# iterates bit-by-bit.
2020-
function map!(f::Union{typeof(identity), typeof(~)}, dest::BitArray, A::BitArray)
2022+
function bit_map!{F}(f::F, dest::BitArray, A::BitArray)
20212023
size(A) == size(dest) || throw(DimensionMismatch("sizes of dest and A must match"))
20222024
isempty(A) && return dest
20232025
destc = dest.chunks
@@ -2028,7 +2030,7 @@ function map!(f::Union{typeof(identity), typeof(~)}, dest::BitArray, A::BitArray
20282030
destc[end] = f(Ac[end]) & _msk_end(A)
20292031
dest
20302032
end
2031-
function map!(f::Union{BitChunkFunctor, typeof(&), typeof(|), typeof($)}, dest::BitArray, A::BitArray, B::BitArray)
2033+
function bit_map!{F}(f::F, dest::BitArray, A::BitArray, B::BitArray)
20322034
size(A) == size(B) == size(dest) || throw(DimensionMismatch("sizes of dest, A, and B must all match"))
20332035
isempty(A) && return dest
20342036
destc = dest.chunks

test/bitarray.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,14 @@ for l = [0, 1, 63, 64, 65, 127, 128, 129, 255, 256, 257, 6399, 6400, 6401]
13171317
@test map!(!=, b, b1, b2) == map!((x,y)->x!=y, b, b1, b2) == (b1 .!= b2) == b
13181318
end
13191319

1320+
# Issue #17970
1321+
let A17970 = [1,2,3] .== [3,2,1]
1322+
B17970 = map(x -> x ? 1 : 2, A17970)
1323+
@test B17970::Array{Int,1} == [2,1,2]
1324+
C17970 = map(x -> x ? false : true, A17970)
1325+
@test C17970::BitArray{1} == map(~, A17970)
1326+
end
1327+
13201328
## Filter ##
13211329

13221330
# TODO

0 commit comments

Comments
 (0)