I am trying to use a transpose operator over a vector in order to perform am element-wise addition.
For example, I want to add a column vector a = [a1;a2;a3] to a row vector b = [b1,b2] I should get matrix
M = a+b = [a1+b1, a1+b2; a2+b1, a2+b2; a3+b1, a3+b2].
In MATLAB it is equivalent (if both vectors are row vectors) M = a.'+b
I am trying to get the same in Julia but here is the problem, there is no .’ operator in Julia starting from 1.0 version. There is the transpose operator which does not work in broadcasting mode. The adjoint operator is not Valid for me because I work with complex numbers.
a = Vector{ComplexF64}([1+3im,2])
b = Vector{ComplexF64}([0,0,0])
Z = zeros(ComplexF64,3,2)
G = zeros(ComplexF64,3,2)
@. Z = b + a' # Works but takes the complex conjugate
@. Z = b + transpose(a) # DOES NOT WORK!!!! The error is " DimensionMismatch("array could not be broadcast to match destination") "
Z = b .+ transpose(a) # Works but not efficient
@. Z = b + conj(a')
The third case Z = b .+ transpose(a) is not efficient because it makes 2 loops first one for addition b .+ transpose(a), than it runs the second loop one for the assignment of b .+ transpose(a) to Z. While the other 3 cases do it within one loop.
So which is the fastest way?
And why transpose doesn’t within Broadcasting?
To expand on @DNF s answer: The @. macro is broadcasting every function call, so the function transpose is not applied to the whole array, but is broadcasted and applied to every entry of a on its own and therefore does nothing. In your case, you don’t even need to preallocate Z at all. If you just do Z = b .+ transpose(a) without initializing Z first, it should be just as, if not a bit more efficient than initializing Z with zeros and modifying it in place.
Thank you for your comment.
Now I understand why @. Z = b + transpose(a).This is equivalent to transpose.(a) which does nothing because each element of the vector “a” is just a number, so there is nothing to transpose!|
I better understand now how the macro @. operator works.
This is also true, without prealocation it is just 5 times slower. But in my case it is very critical because I am running an optimization. Thus 5 times speedup means to me waiting 1 day instead of 5
Thank you. It is good to know that operator $ can prevent element-wise operation.
I checked it out. That works but a bit slower than what @DNF suggests.
' is a special case, because it isn’t actually a regular function call, but instead gets its own AST representation. It is then lowered to a function call at the lowering stage, but because @. works on expressions, not on lowered IR, it doesn’t see ' as a function call and therefore doesn’t add any dots. I actually proposed making ' just a regular function call in RFC: parse `a'` as call expression by simeonschaub · Pull Request #33683 · JuliaLang/julia · GitHub, but unfortunately, that’s a bit breaking.
Another example of such an operator would be <::