use crate::numeric_types::Float; use core::{fmt, ops}; #[derive(Copy, Clone)] pub struct Complex { pub real: T, pub imaginary: T, } impl fmt::Debug for Complex { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "Complex {{ real: {:?}, imaginary: {:?} }}", self.real, self.imaginary ) } } impl fmt::Display for Complex { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{} + {}i", self.real, self.imaginary) } } impl Complex { pub fn new(real: T, imaginary: T) -> Complex { Complex { real, imaginary } } pub fn get_conjugate(&self) -> Complex { Complex::new(self.real, -self.imaginary) } pub fn conjugate(&mut self) { self.imaginary = -self.imaginary; } pub fn phase(&self) -> T { T::atan2(self.imaginary, self.real) } pub fn norm(&self) -> T { self.real * self.real + self.imaginary * self.imaginary } pub fn abs(&self) -> T { T::sqrt(self.norm()) } } impl ops::Add for Complex { type Output = Complex; fn add(self, other: Complex) -> Complex { Complex { real: self.real + other.real, imaginary: self.imaginary + other.imaginary, } } } impl ops::Sub for Complex { type Output = Complex; fn sub(self, other: Complex) -> Complex { Complex { real: self.real - other.real, imaginary: self.imaginary - other.imaginary, } } } impl ops::Mul for Complex { type Output = Complex; fn mul(self, other: Complex) -> Complex { Complex { real: self.real * other.real - self.imaginary * other.imaginary, imaginary: self.real * other.imaginary + self.imaginary * other.real, } } } impl ops::Div for Complex { type Output = Complex; fn div(self, other: Complex) -> Complex { let denom = other.real * other.real + other.imaginary * other.imaginary; Complex { real: (self.real * other.real + self.imaginary * other.imaginary) / denom, imaginary: (self.imaginary * other.real - self.real * other.imaginary) / denom, } } } impl ops::Add for Complex { type Output = Complex; fn add(self, other: T) -> Complex { Complex { real: self.real + other, imaginary: self.imaginary, } } } impl ops::Sub for Complex { type Output = Complex; fn sub(self, other: T) -> Complex { Complex { real: self.real - other, imaginary: self.imaginary, } } } impl ops::Mul for Complex { type Output = Complex; fn mul(self, other: T) -> Complex { Complex { real: self.real * other, imaginary: self.imaginary * other, } } } impl ops::Div for Complex { type Output = Complex; fn div(self, other: T) -> Complex { Complex { real: self.real / other, imaginary: self.imaginary / other, } } } impl ops::AddAssign for Complex { fn add_assign(&mut self, other: Complex) { self.real += other.real; self.imaginary += other.imaginary; } } impl ops::SubAssign for Complex { fn sub_assign(&mut self, other: Complex) { self.real -= other.real; self.imaginary -= other.imaginary; } } impl ops::MulAssign for Complex { fn mul_assign(&mut self, other: Complex) { let new_real = self.real * other.real - self.imaginary * other.imaginary; let new_imaginary = self.real * other.imaginary + self.imaginary * other.real; self.real = new_real; self.imaginary = new_imaginary; } } impl ops::DivAssign for Complex { fn div_assign(&mut self, other: Complex) { let denom = other.real * other.real + other.imaginary * other.imaginary; let new_real = (self.real * other.real + self.imaginary * other.imaginary) / denom; let new_imaginary = (self.imaginary * other.real - self.real * other.imaginary) / denom; self.real = new_real; self.imaginary = new_imaginary; } } impl ops::AddAssign for Complex { fn add_assign(&mut self, other: T) { self.real += other; } } impl ops::SubAssign for Complex { fn sub_assign(&mut self, other: T) { self.real -= other; } } impl ops::MulAssign for Complex { fn mul_assign(&mut self, other: T) { self.real *= other; self.imaginary *= other; } } impl ops::DivAssign for Complex { fn div_assign(&mut self, other: T) { self.real /= other; self.imaginary /= other; } }