1use std::ops;
4
5pub mod consts {
6 use super::Complex;
7 #[allow(unused)]
8 pub const I: Complex = Complex {real: 0.0, imag: 1.0};
10}
11
12use consts::I;
13
14#[allow(unused)]
16pub fn pow(a: Complex, b: Complex) -> Complex {
17 let amod2 = a.real*a.real + a.imag*a.imag;
18 amod2.powf(b.real/2.0) * (-b.imag*a.arg()).exp() * Complex::from_polar(1.0, b.real*a.arg() + 0.5*b.imag*(amod2.ln()))
19}
20
21#[allow(unused)]
23pub fn exp(z: Complex) -> Complex {
24 z.real.exp()*Complex::from_polar(1.0, z.imag)
25}
26
27#[allow(unused)]
29pub fn ln(z: Complex) -> Complex {
30 z.modulus().ln() + z.arg()*I
31}
32
33
34#[allow(unused)]
35#[derive(Debug, Copy, Clone, PartialEq)]
36pub struct Complex {
37 pub real: f32,
38 pub imag: f32,
39}
40
41
42impl Complex {
43
44 pub fn from_polar(r: f32, th: f32) -> Self {
46 Complex {
47 real: r * f32::cos(th),
48 imag: r * f32::sin(th),
49 }
50 }
51
52 pub fn conj(self) -> Self {
54 Complex {
55 real: self.real,
56 imag: - self.imag,
57 }
58 }
59
60 pub fn arg(self) -> f32 {
62 self.imag.atan2(self.real)
63 }
64
65 pub fn modulus(self) -> f32 {
67 (self.conj() * self).real.sqrt()
68 }
69
70
71}
72
73impl ops::Add for Complex {
74 type Output = Self;
75
76 fn add(self, rhs: Self) -> Self::Output {
77 Complex {
78 real: self.real + rhs.real,
79 imag: self.imag + rhs.imag,
80 }
81 }
82}
83
84impl ops::Sub for Complex {
85 type Output = Self;
86 fn sub(self, rhs: Self) -> Self::Output {
87 Complex {
88 real: self.real - rhs.real,
89 imag: self.imag - rhs.imag,
90 }
91 }
92}
93
94impl ops::Mul for Complex {
95 type Output = Self;
96
97 fn mul(self, rhs: Self) -> Self::Output {
98 Complex {
99 real: (self.real * rhs.real) - (self.imag * rhs.imag),
100 imag: (self.real * rhs.imag) + (self.imag * rhs.real),
101 }
102 }
103}
104
105impl ops::Div for Complex {
106 type Output = Self;
107
108 fn div(self, rhs: Self) -> Self::Output {
109 if rhs.real == 0_f32 && rhs.imag == 0_f32 {
110 panic!("Cannot divide by 0!");
111 }
112 let s = rhs.real*rhs.real + rhs.imag*rhs.imag;
113 Complex {
114 real: (self.real*rhs.real + self.imag*rhs.imag)/s,
115 imag: (self.imag*rhs.real - self.real*rhs.imag)/s,
116 }
117 }
118}
119
120impl ops::Add<f32> for Complex {
121 type Output = Complex;
122
123 fn add(self, rhs: f32) -> Self::Output {
124 Complex {
125 real: self.real + rhs,
126 imag: self.imag,
127 }
128 }
129}
130
131impl ops::Sub<f32> for Complex {
132 type Output = Complex;
133
134 fn sub(self, rhs: f32) -> Self::Output {
135 Complex {
136 real: self.real - rhs,
137 imag: self.imag,
138 }
139 }
140}
141
142impl ops::Mul<f32> for Complex {
143 type Output = Complex;
144
145 fn mul(self, rhs: f32) -> Self::Output {
146 Complex {
147 real: self.real * rhs,
148 imag: self.imag * rhs,
149 }
150 }
151}
152
153impl ops::Div<f32> for Complex {
154 type Output = Complex;
155
156 fn div(self, rhs: f32) -> Self::Output {
157 assert_eq!(rhs, 0_f32, "Cannot divide by 0!");
158 Complex {
159 real: self.real / rhs,
160 imag: self.imag / rhs,
161 }
162 }
163}
164
165impl ops::Add<Complex> for f32 {
166 type Output = Complex;
167 fn add(self, rhs: Complex) -> Self::Output {
168 rhs + self
169 }
170}
171
172impl ops::Sub<Complex> for f32 {
173 type Output = Complex;
174 fn sub(self, rhs: Complex) -> Self::Output {
175 rhs + self
176 }
177}
178
179impl ops::Mul<Complex> for f32 {
180 type Output = Complex;
181 fn mul(self, rhs: Complex) -> Self::Output {
182 rhs * self
183 }
184}
185
186impl ops::Div<Complex> for f32 {
187 type Output = Complex;
188 fn div(self, rhs: Complex) -> Self::Output {
189 rhs / self
190 }
191}
192
193impl std::fmt::Display for Complex {
194 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
195 let sign = if self.imag < 0.0 { "-" } else { "+" };
196 write!(f, "{}{}{}i", self.real, sign, self.imag*self.imag.signum())
197 }
198}
199
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204
205 #[test]
206 fn test_addition() {
207 let a = Complex { real: 1.0, imag: 2.0 };
208 let b = Complex { real: 3.0, imag: 4.0 };
209 let result = a + b;
210 assert_eq!(result, Complex { real: 4.0, imag: 6.0 });
211 }
212
213 #[test]
214 fn test_subtraction() {
215 let a = Complex { real: 5.0, imag: 6.0 };
216 let b = Complex { real: 3.0, imag: 4.0 };
217 let result = a - b;
218 assert_eq!(result, Complex { real: 2.0, imag: 2.0 });
219 }
220
221 #[test]
222 fn test_multiplication() {
223 let a = Complex { real: 1.0, imag: 2.0 };
224 let b = Complex { real: 3.0, imag: 4.0 };
225 let result = a * b;
226 assert_eq!(result, Complex { real: -5.0, imag: 10.0 });
227 }
228
229 #[test]
230 fn test_division() {
231 let a = Complex { real: 1.0, imag: 2.0 };
232 let b = Complex { real: 3.0, imag: 4.0 };
233 let result = a / b;
234 assert_eq!(result, Complex { real: 0.44, imag: 0.08 });
235 }
236
237 #[test]
238 #[should_panic(expected = "Cannot divide by 0!")]
239 fn test_division_by_zero() {
240 let a = Complex { real: 1.0, imag: 2.0 };
241 let b = Complex { real: 0.0, imag: 0.0 };
242 let _ = a / b;
243 }
244
245 #[test]
246 fn test_conjugate() {
247 let a = Complex { real: 1.0, imag: 2.0 };
248 let result = a.conj();
249 assert_eq!(result, Complex { real: 1.0, imag: -2.0 });
250 }
251
252 #[test]
253 fn test_modulus() {
254 let a = Complex { real: 3.0, imag: 4.0 };
255 let result = a.modulus();
256 assert_eq!(result, 5.0);
257 }
258
259 #[test]
260 fn test_argument() {
261 let a = Complex { real: 1.0, imag: 1.0 };
262 let result = a.arg();
263 assert!((result - std::f32::consts::FRAC_PI_4).abs() < 1e-6);
264 }
265
266 #[test]
267 fn test_from_polar() {
268 let r = 2.0;
269 let theta = std::f32::consts::PI / 4.0;
270 let result = Complex::from_polar(r, theta);
271 assert!((result.real - 1.4142).abs() < 1e-4);
272 assert!((result.imag - 1.4142).abs() < 1e-4);
273 }
274
275 #[test]
276 fn test_display_format() {
277 let a = Complex { real: 1.0, imag: -2.0 };
278 assert_eq!(a.to_string(), "1-2i");
279
280 let b = Complex { real: 3.5, imag: 4.0 };
281 assert_eq!(b.to_string(), "3.5+4i");
282 }
283}