I am sure this is simple but I cannot find the solution. I have a problem where I would like to create a complex matrix out of a real vector. For example, say I have a vector:
test = randn(8)
And I want to populate a complex matrix with the elements of this vector using:
ComplexMatrix = Complex.(#,#)
I want to do something of the sort:
reshape(test,2,2)
But instead of a 2x2 real array. I of course want a 2x2 complex array. Can someone point me in the right direction here? I know how to create a complex matrix in general- the trick is to create one out of an already created vector.
This?
reshape(Complex.(test),2,4)
A nice way to do this without any extra allocations would be:
reshape(reinterpret(ComplexF64, test), 2, 2)
When I do this, I just get:
test = [1,2,3,4,5,6,7,8]
reshape(Complex.(test),2,4)
2×4 Array{Complex{Int64},2}:
1+0im 3+0im 5+0im 7+0im
2+0im 4+0im 6+0im 8+0im
But I am trying to achieve:
test = [1,2,3,4,5,6,7,8]
reshape(Complex.(test),2,2)
2×2 Array{Complex{Int64},2}:
1+2im 3+4im
5+6im 7+8im
I tried that but I am getting a strange result:
test = [1,2,3,4,5,6,7,8]
reshape(reinterpret(ComplexF64, test), 2, 2)
2×2 reshape(reinterpret(Complex{Float64}, ::Array{Int64,1}), 2, 2) with eltype Complex{Float64}:
4.94066e-324+9.88131e-324im 2.47033e-323+2.96439e-323im
1.4822e-323+1.97626e-323im 3.45846e-323+3.95253e-323im
If extra allocations is not a problem
reshape([Complex(z...) for z in Iterators.partition(test, 2)], 2, 2)
In this approach, you should convert Int to Float64
test = [1,2,3,4,5,6,7,8]
reshape(reinterpret(ComplexF64, Float64.(test)), 2, 2)
julia> reshape(reinterpret(Complex{Int}, test), 2, 2)
2×2 reshape(reinterpret(Complex{Int64}, ::Array{Int64,1}), 2, 2) with eltype Complex{Int64}:
1+2im 5+6im
3+4im 7+8im
Edit: Keep in mind that in this case you are reusing the underlying data, so if you mutate the output of the above operation, you also mutate the test
vector.
The reason, this produces a weird result is that reinterpret
just reinterprets the underlying memory to be of a different type, so if you’re reinterpreting an integer as a float, it will produce a completely different number due to the different underlying memory layout of IEEE floating points. You can see this also in the following example:
julia> bitstring(1)
"0000000000000000000000000000000000000000000000000000000000000001"
julia> reinterpret(Float64, 1)
5.0e-324
julia> bitstring(ans)
"0000000000000000000000000000000000000000000000000000000000000001"
You could write a function, which works for all (immutable) real number types like this:
julia> function complex_reshape(a::Array{T}, dims...) where {T<:Real}
return reshape(reinterpret(Complex{T}, a), dims...)
end
complex_reshape (generic function with 1 method)
julia> complex_reshape([1,2,3,4,5,6,7,8], 2, 2)
2×2 reshape(reinterpret(Complex{Int64}, ::Array{Int64,1}), 2, 2) with eltype Complex{Int64}:
1+2im 5+6im
3+4im 7+8im