Discrepancy between .~ and .==false for BitArrays


#1

Hi,

I’m having trouble understanding why the following don’t yield equivalent objects:

srand(1234)
x = rand(50,1); y=rand(50,1).>0.5; z=rand(50,1).>0.5;
size(x[.~y .& .~z])
size(x[y.==false .& z.==false])

size(x[.~y])
size(x[y.==false])

which at the REPL yields

julia> srand(1234)
MersenneTwister(UInt32[0x000004d2], Base.dSFMT.DSFMT_state(Int32[-1393240018, 1073611148, 45497681, 1072875908, 436273599, 1073674613, -2043716458, 1073445557, -254908435, 1072827086  …  -599655111, 1073144102, 367655457, 1072985259, -1278750689, 1018350124, -597141475, 249849711, 382, 0]), [1.19499, 1.28289, 1.02616, 1.15641, 1.0607, 1.92415, 1.88804, 1.81203, 1.56299, 1.17436  …  1.68022, 1.61886, 1.25895, 1.32248, 1.8879, 1.97766, 1.21481, 1.08087, 1.96411, 1.23217], 382)

julia> x = rand(50,1); y=rand(50,1).>0.5; z=rand(50,1).>0.5;

julia> size(x[.~y .& .~z])
(15,)

julia> size(x[y.==false .& z.==false])
(27,)

julia> size(x[.~y])
(27,)

julia> size(x[y.==false])
(27,)

Does anyone know the difference between .~ and .==false?

Here is my version info:

julia> versioninfo()
Julia Version 0.6.0
Commit 903644385b* (2017-06-19 13:05 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: AMD A9-9420 RADEON R5, 5 COMPUTE CORES 2C+3G
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Prescott)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, amdfam15)

#2

OK, it seems to be an order-of-operations issue:

size(x[(y.==false) .& (z.==false)])

gives

julia> size(x[(y.==false) .& (z.==false)])
(15,)

Can anyone elaborate on what’s going on?


#3

Yes, it is exactly a precedence issue. & and | have precedences geared for bitwise arithmetic — like accessing flags out of a bitmask. There you’re often wanting to compare the result to something (e.g., if bits & 0x07 == 0x03). Here, you’re wanting to use it as an elementwise logical operator like &&, which is commonly used to chain comparisons like you’re doing. This is a longstanding conflict that dates back to previous languages.

I’m hoping we’ll resolve this by allowing the parsing of .&& and .|| with the expected precedences and behaviors.