dsalgo/
complex_number_f64.rs

1/// rectangular form (real, imaginary)
2#[derive(Debug, Clone, Copy, PartialEq)]
3
4pub struct Complex(pub f64, pub f64);
5
6impl From<f64> for Complex {
7    fn from(real: f64) -> Self {
8        Self(real, 0.0)
9    }
10}
11
12impl From<(f64, f64)> for Complex {
13    fn from(rect: (f64, f64)) -> Self {
14        Self(rect.0, rect.1)
15    }
16}
17
18impl Complex {
19    /// as f64 real integer
20
21    pub fn rint(&self) -> f64 {
22        self.0.round()
23    }
24
25    pub fn zero() -> Self {
26        Self(0.0, 0.0)
27    }
28
29    pub fn one() -> Self {
30        Self(1.0, 0.0)
31    }
32
33    pub fn i() -> Self {
34        Self(0.0, 1.0)
35    }
36
37    pub fn norm_square(&self) -> f64 {
38        self.0 * self.0 + self.1 * self.1
39    }
40
41    pub fn conjugate(&self) -> Self {
42        Self(self.0, -self.1)
43    }
44
45    pub fn mul_inv(&self) -> Self {
46        let ns = self.norm_square();
47
48        Self(self.0 / ns, -self.1 / ns)
49    }
50
51    pub fn argument(&self) -> f64 {
52        self.1.atan2(self.0)
53    }
54
55    pub fn norm(&self) -> f64 {
56        self.0.hypot(self.1)
57    }
58
59    pub fn polar(&self) -> (f64, f64) {
60        (self.norm(), self.argument())
61    }
62
63    pub fn from_polar(
64        r: f64,
65        theta: f64,
66    ) -> Self {
67        Self::rectangular(r, theta)
68    }
69
70    pub fn rectangular(
71        r: f64,
72        theta: f64,
73    ) -> Self {
74        Self(r * theta.cos(), r * theta.sin())
75    }
76
77    /// e^{a + bi} = e^a * e^{bi} = e^a * (cos(b) + i*sin(b))
78
79    pub fn exp(&self) -> Self {
80        Self(self.1.cos(), self.1.sin()) * self.0.exp()
81    }
82
83    /// t := arg(z)
84    /// z = |z|*exp(i*t) = exp(ln(|z|) + i*t)
85    /// ln(z) = ln(|z|) + i*t
86
87    pub fn ln(&self) -> Self {
88        Self(self.norm().ln(), self.argument())
89    }
90
91    pub fn sqrt(&self) -> Complex {
92        let (r, theta) = self.polar();
93
94        Self::rectangular(r, theta / 2.0)
95    }
96
97    /// sin(a + bi) = sin(a)cosh(b) + i*cos(a)sinh(b)
98
99    pub fn sin(&self) -> Complex {
100        Self(self.0.sin() * self.1.cosh(), self.0.cos() * self.1.sinh())
101    }
102
103    /// cos(a + bi) = cos(a)cosh(b) - i*sin(a)sinh(b)
104
105    pub fn cos(&self) -> Complex {
106        Self(self.0.cos() * self.1.cosh(), -self.0.sin() * self.1.sinh())
107    }
108
109    /// tan(a + bi) = (sin(2a) + i*sinh(2b)) / (cos(2a) + cosh(2b))
110
111    pub fn tan(&self) -> Complex {
112        let Self(a, b) = *self * 2.0;
113
114        Self(a.sin(), b.sinh()) / (a.cos() + b.cosh())
115    }
116}
117
118use std::ops::*;
119
120impl MulAssign<f64> for Complex {
121    fn mul_assign(
122        &mut self,
123        x: f64,
124    ) {
125        self.0 *= x;
126
127        self.1 *= x;
128    }
129}
130
131impl Mul<f64> for Complex {
132    type Output = Self;
133
134    fn mul(
135        mut self,
136        x: f64,
137    ) -> Self::Output {
138        self *= x;
139
140        self
141    }
142}
143
144impl DivAssign<f64> for Complex {
145    fn div_assign(
146        &mut self,
147        x: f64,
148    ) {
149        self.0 /= x;
150
151        self.1 /= x;
152    }
153}
154
155impl Div<f64> for Complex {
156    type Output = Self;
157
158    fn div(
159        mut self,
160        x: f64,
161    ) -> Self::Output {
162        self /= x;
163
164        self
165    }
166}
167
168impl AddAssign for Complex {
169    fn add_assign(
170        &mut self,
171        rhs: Self,
172    ) {
173        self.0 += rhs.0;
174
175        self.1 += rhs.1;
176    }
177}
178
179impl Add for Complex {
180    type Output = Self;
181
182    fn add(
183        mut self,
184        rhs: Self,
185    ) -> Self::Output {
186        self += rhs;
187
188        self
189    }
190}
191
192impl MulAssign for Complex {
193    fn mul_assign(
194        &mut self,
195        rhs: Self,
196    ) {
197        *self = *self * rhs;
198    }
199}
200
201impl Mul for Complex {
202    type Output = Self;
203
204    fn mul(
205        self,
206        rhs: Self,
207    ) -> Self::Output {
208        Self(self.0 * rhs.0 - self.1 * rhs.1, self.0 * rhs.1 + self.1 * rhs.0)
209    }
210}
211
212impl Neg for Complex {
213    type Output = Self;
214
215    fn neg(self) -> Self::Output {
216        Self(-self.0, -self.1)
217    }
218}
219
220impl SubAssign for Complex {
221    fn sub_assign(
222        &mut self,
223        rhs: Self,
224    ) {
225        *self += -rhs;
226    }
227}
228
229impl Sub for Complex {
230    type Output = Self;
231
232    fn sub(
233        mut self,
234        rhs: Self,
235    ) -> Self::Output {
236        self -= rhs;
237
238        self
239    }
240}
241
242impl DivAssign for Complex {
243    fn div_assign(
244        &mut self,
245        rhs: Self,
246    ) {
247        *self *= rhs.mul_inv();
248    }
249}
250
251impl Div for Complex {
252    type Output = Self;
253
254    fn div(
255        mut self,
256        rhs: Self,
257    ) -> Self::Output {
258        self /= rhs;
259
260        self
261    }
262}
263
264#[cfg(test)]
265
266mod tests {
267
268    #[test]
269
270    fn test() {}
271}