Skip to main content

common_stdx/
complex_number.rs

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