complex_number/
lib.rs

1//! `complex_number` A basic implementation of complex numbers in rust.
2
3use std::ops;
4
5pub mod consts {
6    use super::Complex;
7    #[allow(unused)] 
8    ///The imaginary unit i. Equivalent to `0+1i`.
9    pub const I: Complex = Complex {real: 0.0, imag: 1.0};
10}
11
12use consts::I;
13
14/// Complex Exponentiation Function
15#[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/// Complex Exponential Function
22#[allow(unused)] 
23pub fn exp(z: Complex) -> Complex {
24    z.real.exp()*Complex::from_polar(1.0, z.imag)
25}
26
27/// Complex Natural Logarithm Function
28#[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    /// Constructs a complex number from polar coordinates.
45    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    /// Computes the complex conjugate of a complex number.
53    pub fn conj(self) -> Self {
54        Complex {
55            real: self.real,
56            imag: - self.imag,
57        }
58    }
59
60    /// Computes the argument of a complex number.
61    pub fn arg(self) -> f32 {
62        self.imag.atan2(self.real)
63    }
64
65    /// Computes the modulus of a complex number.
66    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}