Casting `Vector{Complex{T}}` to `Vector{T}` of twice the size

I have an Vector of complex numbers and want to interpret it as a vector of real numbers with twice the length. Currently I allocate a new vector and then manually fill it, but I wonder if there is a faster way without reallocations since I suspect, that the data is already stored in exactly the desired way.

My current implementation:

function realize(v::AbstractVector{Complex{T}}) where {T}
    v_real = Array{T}(undef, 2 *length(v))
    @inbounds for i in eachindex(v)
        v_real[2i-1], v_real[2i] = real(v[i]), imag(v[i])
    end
    return v_real
end

Is there a way to get the same v_real by simple typecasting?

julia> x = rand(Complex{Float64}, 2)
2-element Array{Complex{Float64},1}:
 0.8199153266362134 + 0.6218323711392901im
 0.9962922034287771 + 0.8647751860682487im

julia> reinterpret(Float64, x)
4-element reinterpret(Float64, ::Array{Complex{Float64},1}):
 0.8199153266362134
 0.6218323711392901
 0.9962922034287771
 0.8647751860682487
10 Likes

Well, that is surprisingly straight forward :smiley:

3 Likes

Starting with Julia 1.6, you’ll get considerably better performance on certain operations if you use reinterpret(reshape, Float64, x). That’s available to earlier versions via Compat.jl, but it doesn’t help performance, just API compatibility.

julia> x = rand(Complex{Float64}, 3)
3-element Vector{ComplexF64}:
 0.3844083358603547 + 0.33079943531346534im
 0.6951482675152381 + 0.01509661529380657im
  0.517480198308429 + 0.21516809906601297im

julia> reinterpret(reshape, Float64, x)
2×3 reinterpret(reshape, Float64, ::Vector{ComplexF64}) with eltype Float64:
 0.384408  0.695148   0.51748
 0.330799  0.0150966  0.215168
5 Likes