#![warn(missing_debug_implementations, missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Layout {
RowMajor,
ColMajor,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Trans {
No,
T,
C,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Uplo {
Upper,
Lower,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Diag {
NonUnit,
Unit,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Side {
Left,
Right,
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Complex32 {
pub re: f32,
pub im: f32,
}
impl Complex32 {
#[inline]
pub const fn new(re: f32, im: f32) -> Self {
Self { re, im }
}
pub const ZERO: Self = Self::new(0.0, 0.0);
pub const ONE: Self = Self::new(1.0, 0.0);
pub const I: Self = Self::new(0.0, 1.0);
#[inline]
pub fn norm_sqr(&self) -> f32 {
self.re * self.re + self.im * self.im
}
#[inline]
pub fn abs(&self) -> f32 {
self.norm_sqr().sqrt()
}
#[inline]
pub fn conj(&self) -> Self {
Self::new(self.re, -self.im)
}
}
impl From<(f32, f32)> for Complex32 {
#[inline]
fn from((re, im): (f32, f32)) -> Self {
Self::new(re, im)
}
}
impl From<[f32; 2]> for Complex32 {
#[inline]
fn from(a: [f32; 2]) -> Self {
Self::new(a[0], a[1])
}
}
impl From<Complex32> for [f32; 2] {
#[inline]
fn from(c: Complex32) -> Self {
[c.re, c.im]
}
}
impl From<f32> for Complex32 {
#[inline]
fn from(re: f32) -> Self {
Self::new(re, 0.0)
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Complex64 {
pub re: f64,
pub im: f64,
}
impl Complex64 {
#[inline]
pub const fn new(re: f64, im: f64) -> Self {
Self { re, im }
}
pub const ZERO: Self = Self::new(0.0, 0.0);
pub const ONE: Self = Self::new(1.0, 0.0);
pub const I: Self = Self::new(0.0, 1.0);
#[inline]
pub fn norm_sqr(&self) -> f64 {
self.re * self.re + self.im * self.im
}
#[inline]
pub fn abs(&self) -> f64 {
self.norm_sqr().sqrt()
}
#[inline]
pub fn conj(&self) -> Self {
Self::new(self.re, -self.im)
}
}
impl From<(f64, f64)> for Complex64 {
#[inline]
fn from((re, im): (f64, f64)) -> Self {
Self::new(re, im)
}
}
impl From<[f64; 2]> for Complex64 {
#[inline]
fn from(a: [f64; 2]) -> Self {
Self::new(a[0], a[1])
}
}
impl From<Complex64> for [f64; 2] {
#[inline]
fn from(c: Complex64) -> Self {
[c.re, c.im]
}
}
impl From<f64> for Complex64 {
#[inline]
fn from(re: f64) -> Self {
Self::new(re, 0.0)
}
}
pub mod sealed {
use super::{Complex32, Complex64};
pub trait Sealed {}
impl Sealed for f32 {}
impl Sealed for f64 {}
impl Sealed for Complex32 {}
impl Sealed for Complex64 {}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn complex32_layout_matches_array() {
assert_eq!(std::mem::size_of::<Complex32>(), 8);
assert_eq!(
std::mem::align_of::<Complex32>(),
std::mem::align_of::<f32>()
);
let c = Complex32::new(1.5, -2.0);
let arr: [f32; 2] = c.into();
assert_eq!(arr, [1.5, -2.0]);
}
#[test]
fn complex64_layout_matches_array() {
assert_eq!(std::mem::size_of::<Complex64>(), 16);
assert_eq!(
std::mem::align_of::<Complex64>(),
std::mem::align_of::<f64>()
);
let c = Complex64::new(3.0, 4.0);
assert_eq!(c.abs(), 5.0);
assert_eq!(c.norm_sqr(), 25.0);
assert_eq!(c.conj(), Complex64::new(3.0, -4.0));
}
#[test]
fn complex_constants() {
assert_eq!(Complex32::ZERO, Complex32::new(0.0, 0.0));
assert_eq!(Complex32::ONE, Complex32::new(1.0, 0.0));
assert_eq!(Complex32::I, Complex32::new(0.0, 1.0));
assert_eq!(Complex64::ZERO, Complex64::new(0.0, 0.0));
}
}