use std::{ f32::consts::PI, fmt::Display, ops::{Add, Div, Mul, Neg, Sub}, }; #[derive(Copy, Clone, Debug)] pub struct Complex { pub re: T, pub im: T, } impl Complex { pub fn new(re: T, im: T) -> Self { Complex { re, im } } } impl> Add> for Complex { type Output = Complex; #[inline] fn add(self, rhs: Self) -> Self::Output { Self::new(self.re + rhs.re, self.im + rhs.im) } } impl> Sub> for Complex { type Output = Complex; #[inline] fn sub(self, rhs: Self) -> Self::Output { Self::new(self.re - rhs.re, self.im - rhs.im) } } impl> Add for Complex { type Output = Complex; #[inline] fn add(self, rhs: T) -> Self::Output { Self::new(self.re + rhs, self.im) } } impl + Mul + Sub> Mul> for Complex { type Output = Complex; #[inline] fn mul(self, rhs: Complex) -> Self::Output { self::Complex::new( self.re.clone() * rhs.re.clone() - self.im.clone() * rhs.im.clone(), self.re * rhs.im + self.im * rhs.re, ) } } impl> Mul for Complex { type Output = Complex; #[inline] fn mul(self, rhs: T) -> Self::Output { self::Complex::new(self.re * rhs.clone(), self.im * rhs) } } impl> Neg for Complex { type Output = Complex; fn neg(self) -> Self::Output { Self::new(-self.re.clone(), -self.im.clone()) } } impl> Complex { pub fn conj(&self) -> Complex { Self::new(self.re.clone(), -self.im.clone()) } } impl Display for Complex { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{} + i{}", self.re, self.im) } } pub type Complex32 = Complex; impl Complex32 { pub fn zero() -> Self { Complex { re: 0.0, im: 0.0 } } pub fn cexp(angle: f32) -> Complex32 { Complex32 { re: angle.cos(), im: angle.sin(), } } pub fn mag(&self) -> f32 { (self.re * self.re + self.im * self.im).sqrt() } pub fn arg(&self) -> f32 { if self.im == 0. { if self.re >= 0. { 0. } else { PI } } else if self.re == 0. { if self.im >= 0. { PI / 2.0 } else { -PI / 2.0 } } else { (self.im / self.re).atan() } } }