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