Reputation: 21
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
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
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