rust_matrix/
complex_number.rs

1use crate::{pow::Pow, sqrt::Sqrt};
2use std::{
3    fmt::{self, Display},
4    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub},
5};
6
7/// These are the traits required for `ComplexNumber`
8/// to work with `Matrix`
9/// These are identical to `MatrixElementRequiredTraits`
10/// and should be combined at some point
11/// Note the trait `From<u8>` is required in order to
12/// create identity matrices
13pub trait ComplexNumberRequiredTraits<T>:
14    Add<Output = T>
15    + Sub<Output = T>
16    + Mul<Output = T>
17    + Div<Output = T>
18    + Add<Output = T>
19    + AddAssign
20    + MulAssign
21    + DivAssign
22    + Clone
23    + Copy
24    + Display
25    + PartialOrd<T>
26    + Neg<Output = T>
27    + Default
28    + Sqrt
29    + Pow
30    + From<u8>
31{
32}
33
34impl<
35        T: Add<Output = T>
36            + Sub<Output = T>
37            + Mul<Output = T>
38            + Div<Output = T>
39            + Add<Output = T>
40            + AddAssign
41            + MulAssign
42            + DivAssign
43            + Clone
44            + Copy
45            + Display
46            + PartialOrd<T>
47            + Neg<Output = T>
48            + Default
49            + Sqrt
50            + Pow
51            + From<u8>
52            + ?Sized,
53    > ComplexNumberRequiredTraits<T> for T
54{
55}
56
57#[derive(PartialEq, Debug, PartialOrd, Copy, Clone)]
58pub struct ComplexNumber<T: ComplexNumberRequiredTraits<T>> {
59    pub real: T,
60    pub complex: T,
61}
62
63impl<T: ComplexNumberRequiredTraits<T>> ComplexNumber<T> {
64    pub fn new(real: T, complex: T) -> ComplexNumber<T> {
65        ComplexNumber { real, complex }
66    }
67
68    /// Creates a new complex number that is the complex conjugate
69    /// of the original
70    /// ```
71    /// use matrix::complex_number::ComplexNumber;
72    /// use rand::prelude::*;
73    /// let mut rng = rand::thread_rng();
74    /// let real = rng.gen_range(1.0..=100.0);
75    /// let complex = rng.gen_range(1.0..=100.0);
76    /// let complex_number = ComplexNumber::new(real, complex);
77    ///
78    /// assert_eq!(
79    ///     complex_number.complex_conjugate(),
80    ///     ComplexNumber::new(real, -complex,)
81    /// );
82    /// ```
83    pub fn complex_conjugate(&self) -> Self {
84        ComplexNumber {
85            real: self.real,
86            complex: -self.complex,
87        }
88    }
89
90    /// Calculates the cartesian magnitude of a complex number
91    /// Requires T to implement the `sqrt` trait which
92    /// exposes the `square_root()` method
93    /// ```
94    /// use matrix::complex_number::ComplexNumber;
95    /// let test_complex_number = ComplexNumber::new(3.0, 4.0);
96    /// assert_eq!(test_complex_number.magnitude(), 5.0);
97    /// ```
98    pub fn magnitude(&self) -> T {
99        ((self.real * self.real) + (self.complex * self.complex)).square_root()
100    }
101
102    /// Creates a new complex number that is a normalised
103    /// copy of the first.
104    /// ```
105    ///
106    /// use matrix::complex_number::ComplexNumber;
107    /// let test_complex_number = ComplexNumber::new(3.0, 4.0);
108    /// let normalised = test_complex_number.normalized();
109    /// assert_eq!(normalised.real, 0.6);
110    /// assert_eq!(normalised.complex, 0.8);
111    /// ```
112    pub fn normalized(&self) -> Self {
113        let magnitude = self.magnitude();
114
115        ComplexNumber::new(self.real / magnitude, self.complex / magnitude)
116    }
117
118    /// Calculates the square root of a complex number
119    /// ```
120    /// use matrix::complex_number::ComplexNumber;
121    /// let complex = ComplexNumber::new(3.0, 4.0);
122    ///
123    /// assert_eq!(complex.square_root(), ComplexNumber::new(2.0, 1.0));
124    /// ```
125    pub fn square_root(&self) -> Self {
126        let magnitude = self.magnitude();
127        let real = ((magnitude + self.real) / 2.into()).square_root();
128        let complex = if self.complex < T::default() {
129            -((magnitude - self.real) / 2.into()).square_root()
130        } else {
131            ((magnitude - self.real) / 2.into()).square_root()
132        };
133        ComplexNumber::new(real, complex)
134    }
135
136    /// Implementation of the Pow trait for ComplexNumber
137    ///
138    pub fn powf(&self, n: T) -> Self {
139        if n == T::default() {
140            return ComplexNumber::new(T::from(1), T::default());
141        } else {
142            *self * self.powf(n - T::from(1))
143        }
144    }
145}
146
147impl<T: ComplexNumberRequiredTraits<T>> Neg for ComplexNumber<T> {
148    type Output = Self;
149
150    fn neg(self) -> Self::Output {
151        ComplexNumber {
152            real: -self.real,
153            complex: -self.complex,
154        }
155    }
156}
157
158impl<T: ComplexNumberRequiredTraits<T>> Default for ComplexNumber<T> {
159    fn default() -> Self {
160        Self {
161            real: Default::default(),
162            complex: Default::default(),
163        }
164    }
165}
166
167fn complex_number_add<T: ComplexNumberRequiredTraits<T>>(
168    lhs: &ComplexNumber<T>,
169    rhs: &ComplexNumber<T>,
170) -> ComplexNumber<T> {
171    ComplexNumber {
172        real: lhs.real + rhs.real,
173        complex: lhs.complex + rhs.complex,
174    }
175}
176
177impl<T: ComplexNumberRequiredTraits<T>> Add for ComplexNumber<T> {
178    type Output = Self;
179
180    fn add(self, other: Self) -> Self {
181        complex_number_add(&self, &other)
182    }
183}
184
185impl<T: ComplexNumberRequiredTraits<T>> From<u8> for ComplexNumber<T> {
186    fn from(value: u8) -> Self {
187        ComplexNumber {
188            real: T::from(value),
189            complex: T::from(0),
190        }
191    }
192}
193
194fn complex_number_sub<T: ComplexNumberRequiredTraits<T>>(
195    lhs: &ComplexNumber<T>,
196    rhs: &ComplexNumber<T>,
197) -> ComplexNumber<T> {
198    ComplexNumber {
199        real: lhs.real - rhs.real,
200        complex: lhs.complex - rhs.complex,
201    }
202}
203
204impl<T: ComplexNumberRequiredTraits<T>> Sub for ComplexNumber<T> {
205    type Output = Self;
206
207    fn sub(self, other: Self) -> Self {
208        complex_number_sub(&self, &other)
209    }
210}
211
212fn complex_number_multiply<T: ComplexNumberRequiredTraits<T>>(
213    lhs: &ComplexNumber<T>,
214    rhs: &ComplexNumber<T>,
215) -> ComplexNumber<T> {
216    ComplexNumber {
217        real: (lhs.real * rhs.real) - (lhs.complex * rhs.complex),
218        complex: (lhs.real * rhs.complex) + (rhs.real * lhs.complex),
219    }
220}
221
222impl<T: ComplexNumberRequiredTraits<T>> Mul for ComplexNumber<T> {
223    type Output = Self;
224
225    fn mul(self, rhs: Self) -> Self {
226        complex_number_multiply::<T>(&self, &rhs)
227    }
228}
229
230fn complex_number_divide<T: ComplexNumberRequiredTraits<T>>(
231    lhs: &ComplexNumber<T>,
232    rhs: &ComplexNumber<T>,
233) -> ComplexNumber<T> {
234    let rhs_complex_conjugate = rhs.complex_conjugate();
235    let numerator = *lhs * rhs_complex_conjugate;
236    let denominator = *rhs * rhs_complex_conjugate;
237
238    if denominator.complex != T::default() {
239        panic!(
240            "Something went wrong. Denominator has complex element: {}",
241            denominator
242        );
243    }
244
245    ComplexNumber {
246        real: numerator.real / denominator.real,
247        complex: numerator.complex / denominator.real,
248    }
249}
250
251impl<T: ComplexNumberRequiredTraits<T>> Div for ComplexNumber<T> {
252    type Output = Self;
253
254    fn div(self, rhs: Self) -> Self::Output {
255        complex_number_divide::<T>(&self, &rhs)
256    }
257}
258
259fn complex_number_add_assign<T: ComplexNumberRequiredTraits<T>>(
260    lhs: &ComplexNumber<T>,
261    rhs: &ComplexNumber<T>,
262) -> ComplexNumber<T> {
263    complex_number_add(lhs, rhs)
264}
265
266impl<T: ComplexNumberRequiredTraits<T>> AddAssign for ComplexNumber<T> {
267    fn add_assign(&mut self, rhs: Self) {
268        *self = complex_number_add_assign::<T>(self, &rhs);
269    }
270}
271
272fn complex_number_mul_assign<T: ComplexNumberRequiredTraits<T>>(
273    lhs: &ComplexNumber<T>,
274    rhs: &ComplexNumber<T>,
275) -> ComplexNumber<T> {
276    complex_number_multiply(lhs, rhs)
277}
278
279impl<T: ComplexNumberRequiredTraits<T>> MulAssign for ComplexNumber<T> {
280    fn mul_assign(&mut self, rhs: Self) {
281        *self = complex_number_mul_assign::<T>(self, &rhs)
282    }
283}
284
285fn complex_number_div_assign<T: ComplexNumberRequiredTraits<T>>(
286    lhs: &ComplexNumber<T>,
287    rhs: &ComplexNumber<T>,
288) -> ComplexNumber<T> {
289    complex_number_divide(lhs, rhs)
290}
291
292impl<T: ComplexNumberRequiredTraits<T>> DivAssign for ComplexNumber<T> {
293    fn div_assign(&mut self, rhs: Self) {
294        *self = complex_number_div_assign::<T>(self, &rhs)
295    }
296}
297
298fn format_complex_number_component<T: ComplexNumberRequiredTraits<T>>(
299    input: &T,
300    complex: bool,
301) -> String {
302    if *input == T::default() {
303        return "".to_owned();
304    } else if complex {
305        if *input > T::default() {
306            return "+".to_owned() + &input.to_string() + "i";
307        } else {
308            return input.to_string() + "i";
309        }
310    } else {
311        input.to_string()
312    }
313}
314
315impl<T: ComplexNumberRequiredTraits<T>> fmt::Display for ComplexNumber<T> {
316    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
317        let display_string = format_complex_number_component(&self.real, false)
318            + " "
319            + &format_complex_number_component(&self.complex, true);
320        let _ = fmt.write_str(&display_string);
321        Ok(())
322    }
323}
324
325impl<T: ComplexNumberRequiredTraits<T>> Sqrt for ComplexNumber<T> {
326    fn square_root(&self) -> Self {
327        self.square_root()
328    }
329}
330
331impl<T: ComplexNumberRequiredTraits<T>> Pow for ComplexNumber<T> {
332    fn pow(&self, n: ComplexNumber<T>) -> Self {
333        self.powf(n.real)
334    }
335}
336
337#[cfg(test)]
338mod tests {
339    use crate::complex_number::ComplexNumber;
340    use rand::prelude::*;
341
342    #[test]
343    fn test_complex_number_add() {
344        let mut rng = rand::thread_rng();
345        let real_one = rng.gen_range(1.0..=100.0);
346        let complex_one = rng.gen_range(1.0..=100.0);
347        let real_two = rng.gen_range(1.0..=100.0);
348        let complex_two = rng.gen_range(1.0..=100.0);
349
350        let lhs = ComplexNumber::new(real_one, complex_one);
351        let rhs = ComplexNumber::new(real_two, complex_two);
352
353        assert_eq!(
354            lhs + rhs,
355            ComplexNumber::new(real_one + real_two, complex_one + complex_two)
356        );
357    }
358
359    #[test]
360    fn test_complex_number_sub() {
361        let mut rng = rand::thread_rng();
362        let real_one = rng.gen_range(1.0..=100.0);
363        let complex_one = rng.gen_range(1.0..=100.0);
364        let real_two = rng.gen_range(1.0..=100.0);
365        let complex_two = rng.gen_range(1.0..=100.0);
366
367        let lhs = ComplexNumber::new(real_one, complex_one);
368        let rhs = ComplexNumber::new(real_two, complex_two);
369
370        assert_eq!(
371            lhs - rhs,
372            ComplexNumber::new(real_one - real_two, complex_one - complex_two)
373        );
374    }
375
376    #[test]
377    fn test_complex_number_multiply() {
378        let mut rng = rand::thread_rng();
379        let real_one = rng.gen_range(1.0..=100.0);
380        let complex_one = rng.gen_range(1.0..=100.0);
381        let real_two = rng.gen_range(1.0..=100.0);
382        let complex_two = rng.gen_range(1.0..=100.0);
383
384        let lhs = ComplexNumber::new(real_one, complex_one);
385        let rhs = ComplexNumber::new(real_two, complex_two);
386
387        assert_eq!(
388            lhs * rhs,
389            ComplexNumber::new(
390                (real_one * real_two) - (complex_one * complex_two),
391                (complex_one * real_two) + (complex_two * real_one)
392            )
393        );
394    }
395
396    #[test]
397    fn test_complex_conjugate() {
398        let mut rng = rand::thread_rng();
399        let real = rng.gen_range(1.0..=100.0);
400        let complex = rng.gen_range(1.0..=100.0);
401        let complex_number = ComplexNumber::new(real, complex);
402
403        assert_eq!(
404            complex_number.complex_conjugate(),
405            ComplexNumber::new(real, -complex,)
406        );
407    }
408
409    #[test]
410    fn test_complex_number_divide() {
411        let mut rng = rand::thread_rng();
412        let real_one = rng.gen_range(1.0..=100.0);
413        let complex_one = rng.gen_range(1.0..=100.0);
414        let real_two = rng.gen_range(1.0..=100.0);
415        let complex_two = rng.gen_range(1.0..=100.0);
416
417        let lhs = ComplexNumber::new(real_one, complex_one);
418        let rhs = ComplexNumber::new(real_two, complex_two);
419
420        assert_eq!(
421            lhs / rhs,
422            ComplexNumber::new(
423                ((real_one * real_two) + (complex_one * complex_two))
424                    / (real_two * real_two + complex_two * complex_two),
425                ((complex_one * real_two) - (complex_two * real_one))
426                    / (real_two * real_two + complex_two * complex_two),
427            )
428        );
429    }
430
431    #[test]
432    fn test_complex_number_sqrt() {
433        let complex = ComplexNumber::new(3.0, 4.0);
434
435        assert_eq!(complex.square_root(), ComplexNumber::new(2.0, 1.0));
436    }
437}