Skip to main content

common_stdx/
complex_number.rs

1use num_traits::Num;
2use num_traits::NumCast;
3use std::ops::Div;
4
5pub struct ComplexNum<T: Num + Copy> {
6    real: T,
7    imaginary: T,
8}
9
10pub struct ComplexPolar<T: Num + Copy> {
11    radius: T,
12    angle: T,
13}
14
15impl<T> ComplexNum<T>
16where
17    T: Copy + Clone + NumCast + Num,
18{
19    pub fn new(real: T, imaginary: T) -> Self {
20        ComplexNum { real, imaginary }
21    }
22
23    pub fn conjugate(self) -> Self {
24        ComplexNum::new(self.real, T::zero() - self.imaginary)
25    }
26
27    pub fn as_tuple(self) -> (T, T) {
28        (self.real, self.imaginary)
29    }
30
31    pub fn from_polar(polar: ComplexPolar<T>) -> Option<Self> {
32        let radius = polar.radius.to_f64()?;
33        let angle = polar.angle.to_f64()?;
34
35        let real_f64 = radius * angle.cos();
36        let imaginary_f64 = radius * angle.sin();
37
38        Some(ComplexNum {
39            real: NumCast::from(real_f64)?,
40            imaginary: NumCast::from(imaginary_f64)?,
41        })
42    }
43    pub fn as_polar(&self) -> Option<ComplexPolar<T>> {
44        let a = self.real.to_f64()?;
45        let b = self.imaginary.to_f64()?;
46
47        let radius = (a * a + b * b).sqrt();
48        let angle = b.atan2(a);
49
50        Some(ComplexPolar {
51            radius: NumCast::from(radius)?,
52            angle: NumCast::from(angle)?,
53        })
54    }
55}
56
57impl<T> std::ops::Add for ComplexNum<T>
58where
59    T: Num + Copy + Clone + NumCast,
60{
61    type Output = ComplexNum<T>;
62
63    fn add(self, rhs: Self) -> Self::Output {
64        ComplexNum::new(self.real + rhs.real, self.imaginary + rhs.imaginary)
65    }
66}
67
68impl<T> std::ops::Sub for ComplexNum<T>
69where
70    T: Num + Copy + Clone + NumCast,
71{
72    type Output = ComplexNum<T>;
73
74    fn sub(self, rhs: Self) -> Self::Output {
75        ComplexNum::new(self.real - rhs.real, self.imaginary - rhs.imaginary)
76    }
77}
78
79impl<T> std::ops::Mul for ComplexNum<T>
80where
81    T: Num + Copy + Clone + NumCast,
82{
83    type Output = ComplexNum<T>;
84
85    fn mul(self, rhs: Self) -> Self::Output {
86        // (a + bi)(c + di) = (ac - bd) + (ad + bc)i
87        ComplexNum::new(
88            self.real * rhs.real - self.imaginary * rhs.imaginary,
89            self.real * rhs.imaginary + self.imaginary * rhs.real,
90        )
91    }
92}
93
94impl<T> std::ops::Div for ComplexNum<T>
95where
96    T: Num + Copy + Div<Output = T> + Clone + NumCast,
97{
98    type Output = ComplexNum<T>;
99
100    fn div(self, rhs: Self) -> Self::Output {
101        let denom = rhs.real * rhs.real + rhs.imaginary * rhs.imaginary;
102        let numer = self * rhs.conjugate();
103
104        ComplexNum::new(numer.real / denom, numer.imaginary / denom)
105    }
106}