kordes
kordes

Reputation: 21

complementing logical arrays in Julia

I want to convert a Matlab routine that does block composition of big logical arrays. The ONLY operations are copy, complementation, and array concatenation. Julia has Bool arrays, which I gather are the uint8 equivalent of a Matlab logical array. But it would be even better to use a Julia BitArray, since it is 8 times smaller than a Uint8 array. But I can't make complementation work.

Well, the Julia manual says that "The following bitwise operators are supported on all primitive integer types" and this includes the bitwise operator not (~). But if I create this array in the VS Terminal:

julia>A = zeros(Int8, 2, 3)
2×3 Matrix{Int8}:
0  0  0
0  0  0

and then use ~A, I get: ERROR: MethodError: no method matching ~(::Matrix{Int8})

So I tried 2 alternatives:

   julia> B = falses(2,3)
   2×3 BitMatrix:
   0  0  0
   0  0  0

   julia> ~B
   ERROR: MethodError: no method matching ~(::BitMatrix)


   julia> C = collect(B)
   2×3 Matrix{Bool}:
   0  0  0
   0  0  0

   julia> ~C
   ERROR: MethodError: no method matching ~(::Matrix{Bool})

Why is this? Bitwise complementation of a logical array is very fundamental action, even more so than for an integer array.

Upvotes: 2

Views: 87

Answers (2)

L.Grozinger
L.Grozinger

Reputation: 2398

You should use 'broadcasting'

The operator (method) ~ is defined for Integer (as well as some other types), which includes the Int8 type you are using.

julia> A = zeros(Int8, 2, 3)
2×3 Matrix{Int8}:
 0  0  0
 0  0  0

julia> ~(A[1, 1])
-1

julia> ~A[1, 1]
-1

But it is not defined for arrays of Integer, as you have found out. Basically what you want to do is make a new matrix B where B[i, j] = ~A[i, j]. You can type all that out if you want:

julia> B = Matrix{Int8}(undef, 2, 3)
2×3 Matrix{Int8}:
 0  0  0
 0  0  0

julia> for i in 1:2
           for j in 1:3
               B[i, j] = ~A[i, j]
           end
       end

julia> B
2×3 Matrix{Int8}:
 -1  -1  -1
 -1  -1  -1

Or you can broadcast the ~ operator over A, applying ~ elementwise.

julia> broadcast(~, A)
2×3 Matrix{Int8}:
 -1  -1  -1
 -1  -1  -1

Broadcasting has a handy syntax using the . (dot) operator, which does the same thing:

julia> .~A
2×3 Matrix{Int8}:
 -1  -1  -1
 -1  -1  -1

This will work on BitArray too.

julia> A = falses(2, 3)
2×3 BitMatrix:
 0  0  0
 0  0  0

julia> .~A
2×3 BitMatrix:
 1  1  1
 1  1  1

Broadcasting can be applied to more than one argument, to user-defined methods, and is very useful in general. You can (and should) read more about broadcasting here

Upvotes: 4

Sash Sinha
Sash Sinha

Reputation: 22370

Use .!:

julia> B = falses(2, 3)
2×3 BitMatrix:
 0  0  0
 0  0  0

julia> .!B
2×3 BitMatrix:
 1  1  1
 1  1  1

julia> C = collect(B) 
2×3 Matrix{Bool}:
 0  0  0
 0  0  0

julia> .!C
2×3 BitMatrix:
 1  1  1
 1  1  1

The ! operator is not defined for integer types in Julia, so you'll need to first convert your matrix to a BitArray or Bool array in that case:

julia> A = zeros(Int8, 2, 3)
2×3 Matrix{Int8}:
 0  0  0
 0  0  0

julia> D = BitArray(A .== 0)
2×3 BitMatrix:
 1  1  1
 1  1  1

Upvotes: 2

Related Questions