Complex Array Operations (vDSP)

AppleAccelerate wraps vDSP's split-complex (vDSP_z*) functions for Vector{Complex{Float32}} and Vector{Complex{Float64}}. These extend existing function names (e.g., vneg, vabs, vmul) with methods that dispatch on complex element types — no naming conflicts with the real-valued versions on the Array Operations page.

Julia's interleaved complex storage is passed to the split-complex vDSP routines directly (using a stride-2 split-complex view of the same memory), so the mutating (!) variants are in-place and allocation-free.

These functions are not exported. Access them via the AppleAccelerate. prefix.

Complex unary operations

FunctionDescription
vneg(X) / vneg!(result, X)Negate: -X
vabs(X) / vabs!(result, X)Modulus: abs.(X)
vconjComplex conjugate
vcopyCopy via split-complex move

The complex-valued docstrings for vneg and vabs are rendered alongside the real-valued ones on the Array Operations page.

Complex → real operations

FunctionDescription
vphaseComplex phase (angle)
vmagsSquared magnitude (abs2)
vmagsaSquared magnitude + accumulate

Complex binary operations

FunctionDescription
vmul(X, Y) / vmul!(result, X, Y)Element-wise multiply: X .* Y
vdiv(X, Y) / vdiv!(result, X, Y)Element-wise divide: X ./ Y
vsmul(X, c) / vsmul!(result, X, c)Scalar multiply (complex scalar)
dot(X, Y)Conjugated dot product matching LinearAlgebra.dot: sum(conj(X) .* Y)
dotu(X, Y)Unconjugated (bilinear) dot product: sum(X .* Y)
zvaddComplex addition: A + B
zvsubComplex subtraction: A - B
zvcmulConjugate multiply: conj(A) * B

Complex-real operations

FunctionDescription
zrvmulComplex × real
zrvdivComplex / real
zrvaddComplex + real (adds to real part)
zrvsubComplex − real

Complex compound operations

FunctionDescription
zvcmaconj(A)*B + C
zvmaA*B + C
zvsmaA*b + C (b is complex scalar)

Complex dot products

FunctionDescription
zidotprConjugate dot: sum(conj(A) .* B)
zrdotprComplex-real dot: sum(A .* B)

Complex fill & convolution

FunctionDescription
zvfill!Fill complex vector with scalar
zconvComplex convolution
zmmulComplex matrix multiply: A * B
zmmaComplex matrix multiply-add: A * B + C
zmmsComplex matrix multiply-subtract: A * B - C
zmsmComplex matrix multiply and reverse-subtract: C - A*B
zvmmaaElementwise multiply-multiply-add-add: A*B + C*D + E
zrdesampComplex-real decimating resample/correlation

Coordinate conversion

FunctionDescription
polarCartesian to polar coordinates
rectPolar to Cartesian coordinates

Format conversion

FunctionDescription
ctozInterleaved complex → split (real, imag) vectors
ztocSplit (real, imag) vectors → interleaved complex
Z = AppleAccelerate.cis(randn(Float64, 100))  # complex array

# Complex operations
conj_Z = AppleAccelerate.vconj(Z)
phases = AppleAccelerate.vphase(Z)
mags = AppleAccelerate.vmags(Z)

# Coordinate conversion
r, θ = AppleAccelerate.polar(Z)
Z_back = AppleAccelerate.rect(r, θ)

# Complex matrix multiply-add: D = A*B + C
A = rand(ComplexF64, 4, 3); B = rand(ComplexF64, 3, 5); C = rand(ComplexF64, 4, 5)
D = AppleAccelerate.zmma(A, B, C)   # ≈ A*B + C
AppleAccelerate.vmagsFunction
vmags(X::Vector{Complex{T}}) -> Vector{T}
vmags!(result, X)

Squared magnitude: result[i] = abs2(X[i]) = real(X[i])^2 + imag(X[i])^2. Wraps vDSP_zvmags.

source
AppleAccelerate.vmagsaFunction
vmagsa(X::Vector{Complex{T}}, B::Vector{T}) -> Vector{T}
vmagsa!(result, X, B)

Squared magnitude and accumulate: result[i] = abs2(X[i]) + B[i]. Wraps vDSP_zvmgsa.

source
AppleAccelerate.dotuFunction
dotu(X::Vector{Complex{Float32}}, Y::Vector{Complex{Float32}})

Un-conjugated complex dot product sum(X .* Y) (the "bilinear" dot, without conjugating X). Wraps vDSP_zdotpr. For the conjugated product matching LinearAlgebra.dot use dot.

source
dotu(X::Vector{Complex{Float64}}, Y::Vector{Complex{Float64}})

Un-conjugated complex dot product sum(X .* Y) (the "bilinear" dot, without conjugating X). Wraps vDSP_zdotpr. For the conjugated product matching LinearAlgebra.dot use dot.

source
AppleAccelerate.rectFunction
rect(magnitudes::Vector{T}, angles::Vector{T}) -> Vector{Complex{T}}

Convert polar coordinates to complex Cartesian form. Wraps vDSP_rect.

source
AppleAccelerate.zmmaFunction

Complex matrix multiply-add: D = A * B + C. C and D are size(A,1)×size(B,2). The zmma!(D, A, B, C) form writes into D. Wraps vDSP_zmma.

source
AppleAccelerate.zmmsFunction

Complex matrix multiply-subtract: D = A * B - C. C and D are size(A,1)×size(B,2). The zmms!(D, A, B, C) form writes into D. Wraps vDSP_zmms.

source
AppleAccelerate.zmsmFunction
zmsm(A::Matrix{Complex{Float32}}, B::Matrix{Complex{Float32}}, C::Matrix{Complex{Float32}}) -> Matrix{Complex{Float32}}
zmsm!(D, A, B, C)

Complex matrix multiply and reverse-subtract: D = C - A*B. Wraps vDSP_zmsm (the vDSP.h header labels this "matrix multiply and reverse subtract"; confirmed empirically to compute C - A*B, not (A-B)*C).

source
zmsm(A::Matrix{Complex{Float64}}, B::Matrix{Complex{Float64}}, C::Matrix{Complex{Float64}}) -> Matrix{Complex{Float64}}
zmsm!(D, A, B, C)

Complex matrix multiply and reverse-subtract: D = C - A*B. Wraps vDSP_zmsm (the vDSP.h header labels this "matrix multiply and reverse subtract"; confirmed empirically to compute C - A*B, not (A-B)*C).

source
AppleAccelerate.zvmmaaFunction
zvmmaa(A::Vector{Complex{Float32}}, B::Vector{Complex{Float32}}, C::Vector{Complex{Float32}}, D::Vector{Complex{Float32}}, E::Vector{Complex{Float32}}) -> Vector{Complex{Float32}}
zvmmaa!(F, A, B, C, D, E)

Elementwise vector multiply-multiply-add-add: F[i] = A[i]*B[i] + C[i]*D[i] + E[i]. Wraps vDSP_zvmmaa.

source
zvmmaa(A::Vector{Complex{Float64}}, B::Vector{Complex{Float64}}, C::Vector{Complex{Float64}}, D::Vector{Complex{Float64}}, E::Vector{Complex{Float64}}) -> Vector{Complex{Float64}}
zvmmaa!(F, A, B, C, D, E)

Elementwise vector multiply-multiply-add-add: F[i] = A[i]*B[i] + C[i]*D[i] + E[i]. Wraps vDSP_zvmmaa.

source
AppleAccelerate.zrdesampFunction
zrdesamp(A::Vector{Complex{Float32}}, DF::Int, F::Vector{Float32}) -> Vector{Complex{Float32}}
zrdesamp!(C, A, DF, F)

Complex-real decimating resample/correlation using vDSP_zrdesamp. Filters complex input A with real FIR coefficients F (P taps) and decimation factor DF. C must have at least div(length(A) - P, DF) + 1 elements. Computes: C[n] = sum(A[n*DF+p] * F[p] for p in 0:P-1) (0-indexed). Wraps vDSP_zrdesamp.

source
zrdesamp(A::Vector{Complex{Float64}}, DF::Int, F::Vector{Float64}) -> Vector{Complex{Float64}}
zrdesamp!(C, A, DF, F)

Complex-real decimating resample/correlation using vDSP_zrdesamp. Filters complex input A with real FIR coefficients F (P taps) and decimation factor DF. C must have at least div(length(A) - P, DF) + 1 elements. Computes: C[n] = sum(A[n*DF+p] * F[p] for p in 0:P-1) (0-indexed). Wraps vDSP_zrdesamp.

source