Creating a complex matrix from a vector

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)
2 Likes

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)
1 Like
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.

3 Likes

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
3 Likes