aboutsummaryrefslogtreecommitdiff
path: root/src/maths/complex.rs
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-08-24 14:48:36 +0200
committerhachem <im@hachem.wtf>2026-08-24 14:48:36 +0200
commit24d639224ca11112025289065d7538851606b56e (patch)
treee7e26c89cd20099f03ff32727ba0af2cf4762088 /src/maths/complex.rs
parent548dc42d9f454cb8c29fddb88ca41f8b1b595882 (diff)
[chore]: unwrap project
Diffstat (limited to 'src/maths/complex.rs')
-rw-r--r--src/maths/complex.rs180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/maths/complex.rs b/src/maths/complex.rs
new file mode 100644
index 0000000..31eae69
--- /dev/null
+++ b/src/maths/complex.rs
@@ -0,0 +1,180 @@
+use crate::Float;
+use core::{fmt, ops};
+
+#[macro_export]
+macro_rules! complex {
+ ($real:expr, $imaginary:expr) => {
+ $crate::Complex::new($real, $imaginary)
+ };
+}
+
+macro_rules! impl_ops {
+ ($trait:ident, $method:ident, $op:tt) => {
+ impl<T: Float> ops::$trait for Complex<T> {
+ type Output = Complex<T>;
+
+ fn $method(self, other: Complex<T>) -> Complex<T> {
+ Complex {
+ real: self.real $op other.real,
+ imaginary: self.imaginary $op other.imaginary,
+ }
+ }
+ }
+ };
+
+ ($trait:ident, $method:ident, $op:tt, real) => {
+ impl<T: Float> ops::$trait<T> for Complex<T> {
+ type Output = Complex<T>;
+
+ fn $method(self, other: T) -> Complex<T> {
+ Complex {
+ real: self.real $op other,
+ imaginary: self.imaginary,
+ }
+ }
+ }
+ };
+
+ ($trait_assign:ident, $method_assign:ident, $op:tt, assign) => {
+ impl<T: Float> ops::$trait_assign for Complex<T> {
+ fn $method_assign(&mut self, other: Complex<T>) {
+ self.real = self.real $op other.real;
+ self.imaginary = self.imaginary $op other.imaginary;
+ }
+ }
+ };
+
+ ($trait_assign:ident, $method_assign:ident, $op:tt, assign_real) => {
+ impl<T: Float> ops::$trait_assign<T> for Complex<T> {
+ fn $method_assign(&mut self, other: T) {
+ self.real = self.real $op other;
+ }
+ }
+ };
+}
+
+#[derive(Copy, Clone, PartialOrd, PartialEq)]
+pub struct Complex<T: Float> {
+ pub real: T,
+ pub imaginary: T,
+}
+
+impl<T: Float + fmt::Debug> fmt::Debug for Complex<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "Complex {{ real: {:?}, imaginary: {:?} }}",
+ self.real, self.imaginary
+ )
+ }
+}
+
+impl<T: Float + fmt::Display> fmt::Display for Complex<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{} + {}i", self.real, self.imaginary)
+ }
+}
+
+impl<T: Float> ops::Neg for Complex<T> {
+ type Output = Complex<T>;
+
+ fn neg(self) -> Complex<T> {
+ Complex {
+ real: -self.real,
+ imaginary: -self.imaginary,
+ }
+ }
+}
+
+impl<T: Float> From<T> for Complex<T> {
+ fn from(real: T) -> Complex<T> {
+ Complex {
+ real,
+ imaginary: T::zero(),
+ }
+ }
+}
+
+impl<T: Float> Complex<T> {
+ pub fn new(real: T, imaginary: T) -> Complex<T> {
+ Complex { real, imaginary }
+ }
+
+ pub fn get_conjugate(&self) -> Complex<T> {
+ Complex {
+ real: self.real,
+ imaginary: -self.imaginary,
+ }
+ }
+
+ pub fn conjugate(&mut self) {
+ self.imaginary = -self.imaginary;
+ }
+
+ pub fn phase(&self) -> T {
+ T::atan2(self.imaginary, self.real)
+ }
+
+ pub fn norm2(&self) -> T {
+ self.real * self.real + self.imaginary * self.imaginary
+ }
+
+ pub fn abs(&self) -> T {
+ T::sqrt(self.norm2())
+ }
+}
+
+impl_ops!(Add, add, +);
+impl_ops!(Sub, sub, -);
+
+impl<T: Float> ops::Mul for Complex<T> {
+ type Output = Complex<T>;
+
+ fn mul(self, other: Complex<T>) -> Complex<T> {
+ // (a + bi) * (c + di) = (ac - bd) + (ad + bc)i
+ Complex {
+ real: self.real * other.real - self.imaginary * other.imaginary,
+ imaginary: self.real * other.imaginary + self.imaginary * other.real,
+ }
+ }
+}
+
+impl<T: Float> ops::Div for Complex<T> {
+ type Output = Complex<T>;
+
+ fn div(self, other: Complex<T>) -> Complex<T> {
+ // (a + bi) / (c + di) = ((ac + bd) + (bc - ad)i) / (c² + d²)
+ 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!(AddAssign, add_assign, +, assign);
+impl_ops!(SubAssign, sub_assign, -, assign);
+
+impl<T: Float> ops::MulAssign for Complex<T> {
+ fn mul_assign(&mut self, other: Complex<T>) {
+ let new_real = self.real * other.real - self.imaginary * other.imaginary;
+ let new_imag = self.real * other.imaginary + self.imaginary * other.real;
+ self.real = new_real;
+ self.imaginary = new_imag;
+ }
+}
+
+impl<T: Float> ops::DivAssign for Complex<T> {
+ fn div_assign(&mut self, other: Complex<T>) {
+ let denom = other.real * other.real + other.imaginary * other.imaginary;
+ let new_real = (self.real * other.real + self.imaginary * other.imaginary) / denom;
+ let new_imag = (self.imaginary * other.real - self.real * other.imaginary) / denom;
+ self.real = new_real;
+ self.imaginary = new_imag;
+ }
+}
+
+impl_ops!(Add, add, +, real);
+impl_ops!(Sub, sub, -, real);
+impl_ops!(Mul, mul, *, real);
+impl_ops!(Div, div, /, real);