common_stdx/
complex_number.rs1use 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 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}