pub trait ComplexOps<R: Runtime> {
// Provided methods
fn conj(&self, a: &Tensor<R>) -> Result<Tensor<R>> { ... }
fn real(&self, a: &Tensor<R>) -> Result<Tensor<R>> { ... }
fn imag(&self, a: &Tensor<R>) -> Result<Tensor<R>> { ... }
fn angle(&self, a: &Tensor<R>) -> Result<Tensor<R>> { ... }
fn make_complex(
&self,
real: &Tensor<R>,
imag: &Tensor<R>,
) -> Result<Tensor<R>> { ... }
fn complex_mul_real(
&self,
complex: &Tensor<R>,
real: &Tensor<R>,
) -> Result<Tensor<R>> { ... }
fn complex_div_real(
&self,
complex: &Tensor<R>,
real: &Tensor<R>,
) -> Result<Tensor<R>> { ... }
fn real_mul_complex(
&self,
real: &Tensor<R>,
complex: &Tensor<R>,
) -> Result<Tensor<R>> { ... }
}Expand description
Complex number operations
Provided Methods§
Sourcefn conj(&self, a: &Tensor<R>) -> Result<Tensor<R>>
fn conj(&self, a: &Tensor<R>) -> Result<Tensor<R>>
Complex conjugate: conj(a + bi) = a - bi
Returns the complex conjugate of the input tensor. For real tensors, returns the input unchanged.
§Arguments
a- Input tensor (Complex64, Complex128, or real types)
§Returns
- Complex types: Tensor with same shape and dtype, imaginary part negated
- Real types: Returns input tensor unchanged (real numbers equal their conjugate)
§Supported Types
- Complex64: All backends (CPU, CUDA, WebGPU)
- Complex128: CPU and CUDA only (WebGPU does not support F64)
- Real types: All backends (identity operation)
§Examples
use numr::ops::ComplexOps;
use numr::dtype::Complex64;
let z = Tensor::<CpuRuntime>::from_slice(
&[Complex64::new(1.0, 2.0), Complex64::new(3.0, -4.0)],
&[2],
&device
);
let conj_z = client.conj(&z)?;
// Result: [1.0 - 2.0i, 3.0 + 4.0i]Sourcefn real(&self, a: &Tensor<R>) -> Result<Tensor<R>>
fn real(&self, a: &Tensor<R>) -> Result<Tensor<R>>
Extract real part of complex tensor: real(a + bi) = a
Extracts the real component from a complex tensor. For real tensors, returns a copy of the input.
§Arguments
a- Input tensor
§Returns
- Complex64 input → F32 tensor with same shape
- Complex128 input → F64 tensor with same shape
- Real input → Copy of input tensor
§Supported Types
- Complex64: All backends (CPU, CUDA, WebGPU)
- Complex128: CPU and CUDA only (WebGPU does not support F64)
- Real types: All backends
§Examples
use numr::ops::ComplexOps;
use numr::dtype::Complex64;
let z = Tensor::<CpuRuntime>::from_slice(
&[Complex64::new(1.0, 2.0), Complex64::new(3.0, 4.0)],
&[2],
&device
);
let re = client.real(&z)?; // F32 tensor: [1.0, 3.0]Sourcefn imag(&self, a: &Tensor<R>) -> Result<Tensor<R>>
fn imag(&self, a: &Tensor<R>) -> Result<Tensor<R>>
Extract imaginary part of complex tensor: imag(a + bi) = b
Extracts the imaginary component from a complex tensor. For real tensors, returns a zero tensor with the same shape.
§Arguments
a- Input tensor
§Returns
- Complex64 input → F32 tensor with same shape
- Complex128 input → F64 tensor with same shape
- Real input → Zero tensor with same shape and dtype
§Supported Types
- Complex64: All backends (CPU, CUDA, WebGPU)
- Complex128: CPU and CUDA only (WebGPU does not support F64)
- Real types: All backends
§Examples
use numr::ops::ComplexOps;
use numr::dtype::Complex64;
let z = Tensor::<CpuRuntime>::from_slice(
&[Complex64::new(1.0, 2.0), Complex64::new(3.0, 4.0)],
&[2],
&device
);
let im = client.imag(&z)?; // F32 tensor: [2.0, 4.0]Sourcefn angle(&self, a: &Tensor<R>) -> Result<Tensor<R>>
fn angle(&self, a: &Tensor<R>) -> Result<Tensor<R>>
Compute phase angle of complex tensor: angle(a + bi) = atan2(b, a)
Returns the phase angle (argument) of complex numbers in radians. The result is in the range [-π, π].
§Arguments
a- Input tensor
§Returns
- Complex64 input → F32 tensor with angles in radians
- Complex128 input → F64 tensor with angles in radians
- Real input → Zero tensor (real numbers have phase angle 0 for positive, π for negative)
§Supported Types
- Complex64: All backends (CPU, CUDA, WebGPU)
- Complex128: CPU and CUDA only (WebGPU does not support F64)
- Real types: All backends
§Examples
use numr::ops::ComplexOps;
use numr::dtype::Complex64;
let z = Tensor::<CpuRuntime>::from_slice(
&[Complex64::new(1.0, 1.0), Complex64::new(-1.0, 0.0)],
&[2],
&device
);
let angles = client.angle(&z)?; // F32 tensor: [π/4, π]§Mathematical Notes
For complex z = a + bi, returns atan2(b, a) in radians [-π, π]. For real x, returns 0 if x ≥ 0, π if x < 0. To compute magnitude, use abs(z) = sqrt(re² + im²) separately.
Sourcefn make_complex(&self, real: &Tensor<R>, imag: &Tensor<R>) -> Result<Tensor<R>>
fn make_complex(&self, real: &Tensor<R>, imag: &Tensor<R>) -> Result<Tensor<R>>
Construct complex tensor from separate real and imaginary part tensors.
Creates a complex tensor where each element is real[i] + imag[i]*i.
§Arguments
real- Tensor containing real parts (F32 or F64)imag- Tensor containing imaginary parts (must matchrealdtype and shape)
§Returns
- F32 inputs → Complex64 tensor with same shape
- F64 inputs → Complex128 tensor with same shape
§Errors
ShapeMismatch- ifrealandimaghave different shapesDTypeMismatch- ifrealandimaghave different dtypesUnsupportedDType- if input dtype is not F32 or F64
§Supported Types
- F32 → Complex64: All backends (CPU, CUDA, WebGPU)
- F64 → Complex128: CPU and CUDA only (WebGPU does not support F64)
§Examples
use numr::ops::ComplexOps;
let real = Tensor::<CpuRuntime>::from_slice(&[1.0f32, 2.0, 3.0], &[3], &device);
let imag = Tensor::<CpuRuntime>::from_slice(&[4.0f32, 5.0, 6.0], &[3], &device);
let complex = client.make_complex(&real, &imag)?;
// Result: [1.0+4.0i, 2.0+5.0i, 3.0+6.0i]Sourcefn complex_mul_real(
&self,
complex: &Tensor<R>,
real: &Tensor<R>,
) -> Result<Tensor<R>>
fn complex_mul_real( &self, complex: &Tensor<R>, real: &Tensor<R>, ) -> Result<Tensor<R>>
Multiply complex tensor by real tensor element-wise.
Computes (a + bi) * r = ar + br*i for each element.
§Arguments
complex- Complex tensor (Complex64 or Complex128)real- Real tensor (F32 for Complex64, F64 for Complex128)
§Returns
Complex tensor with same dtype and shape as input complex tensor.
§Errors
ShapeMismatch- if shapes don’t match (no broadcasting)DTypeMismatch- if real dtype doesn’t match complex component dtypeUnsupportedDType- if complex is not Complex64/Complex128
§Supported Types
- Complex64 × F32: All backends (CPU, CUDA, WebGPU)
- Complex128 × F64: CPU and CUDA only (WebGPU does not support F64)
§Examples
use numr::ops::ComplexOps;
use numr::dtype::Complex64;
let complex = Tensor::<CpuRuntime>::from_slice(
&[Complex64::new(1.0, 2.0), Complex64::new(3.0, 4.0)],
&[2],
&device
);
let scale = Tensor::<CpuRuntime>::from_slice(&[2.0f32, 0.5], &[2], &device);
let result = client.complex_mul_real(&complex, &scale)?;
// Result: [2.0+4.0i, 1.5+2.0i]Sourcefn complex_div_real(
&self,
complex: &Tensor<R>,
real: &Tensor<R>,
) -> Result<Tensor<R>>
fn complex_div_real( &self, complex: &Tensor<R>, real: &Tensor<R>, ) -> Result<Tensor<R>>
Divide complex tensor by real tensor element-wise.
Computes (a + bi) / r = (a/r) + (b/r)*i for each element.
§Arguments
complex- Complex tensor (Complex64 or Complex128)real- Real tensor (F32 for Complex64, F64 for Complex128)
§Returns
Complex tensor with same dtype and shape as input complex tensor.
§Errors
ShapeMismatch- if shapes don’t match (no broadcasting)DTypeMismatch- if real dtype doesn’t match complex component dtypeUnsupportedDType- if complex is not Complex64/Complex128
§Supported Types
- Complex64 / F32: All backends (CPU, CUDA, WebGPU)
- Complex128 / F64: CPU and CUDA only (WebGPU does not support F64)
§Note
Division by zero will result in NaN/Inf values, following IEEE 754 semantics.
§Examples
use numr::ops::ComplexOps;
use numr::dtype::Complex64;
let complex = Tensor::<CpuRuntime>::from_slice(
&[Complex64::new(4.0, 6.0), Complex64::new(2.0, 4.0)],
&[2],
&device
);
let divisor = Tensor::<CpuRuntime>::from_slice(&[2.0f32, 2.0], &[2], &device);
let result = client.complex_div_real(&complex, &divisor)?;
// Result: [2.0+3.0i, 1.0+2.0i]Sourcefn real_mul_complex(
&self,
real: &Tensor<R>,
complex: &Tensor<R>,
) -> Result<Tensor<R>>
fn real_mul_complex( &self, real: &Tensor<R>, complex: &Tensor<R>, ) -> Result<Tensor<R>>
Multiply real tensor by complex tensor element-wise.
Computes r * (a + bi) = ra + rb*i for each element.
This is equivalent to complex_mul_real (multiplication is commutative).
§Arguments
real- Real tensor (F32 for Complex64, F64 for Complex128)complex- Complex tensor (Complex64 or Complex128)
§Returns
Complex tensor with same dtype and shape as input complex tensor.
§Examples
use numr::ops::ComplexOps;
use numr::dtype::Complex64;
let scale = Tensor::<CpuRuntime>::from_slice(&[2.0f32, 0.5], &[2], &device);
let complex = Tensor::<CpuRuntime>::from_slice(
&[Complex64::new(1.0, 2.0), Complex64::new(3.0, 4.0)],
&[2],
&device
);
let result = client.real_mul_complex(&scale, &complex)?;
// Result: [2.0+4.0i, 1.5+2.0i]Implementors§
impl ComplexOps<CpuRuntime> for CpuClient
ComplexOps implementation for CPU runtime.