complex_stuff/lib.rs
1//! `complex-stuff` is a collection of utilities to make calculations with complex numbers easy.
2//!
3//! # Examples
4//!
5//! ```
6//! use complex_stuff::{Complex, ComplexCartesian, ComplexPolar};
7//! use std::f64::consts::PI;
8//!
9//! // Some of the most important operations:
10//! fn main() {
11//! // Declare complex numbers with their cartesian or polar form.
12//! let c1 = Complex::new_cartesian(5.0, 3.0);
13//! let c2 = Complex::new_polar(7.0, PI / 4.0);
14//!
15//! // Basic arethmetic operations should work as expected.
16//! let sum = c1 + c2;
17//! let diff = c1 - c2;
18//!
19//! let prod = c1 * c2;
20//!
21//! // All operations which can result in undefined or infinite values
22//! // return a `Option` and need to be handled.
23//!
24//! let quot = (c1 / c2)?;
25//!
26//! let sqr = c1.pow(Complex::new_real(2.0))?;
27//! let sqrt = c1.root(Complex::new_real(2.0))?;
28//!
29//! let log10 = c1.log(Complex::new_real(10.0))?;
30//!
31//! let sin = c1.sin()?;
32//! let cos = c1.cos()?;
33//! }
34//! ```
35
36use std::{
37 f64::consts::E,
38 ops::{Add, Div, Mul, Neg, Sub},
39};
40
41#[derive(Debug, Clone, Copy)]
42/// Descibes a complex number in cartesion form _`re` + `im`i_.
43pub struct ComplexCartesian {
44 pub re: f64,
45 pub im: f64,
46}
47
48impl std::fmt::Display for ComplexCartesian {
49 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
50 write!(f, "{} + {}i", self.re, self.im)
51 }
52}
53
54impl ComplexCartesian {
55 /// Converts a complex number from polar to cartesion form.
56 ///
57 /// # Examples
58 ///
59 /// ```
60 /// use std::f64::consts::PI;
61 /// use complex_stuff::{ComplexCartesian, ComplexPolar};
62 ///
63 /// let polar = ComplexPolar { mag: 5.0, ang: PI / 2.0 };
64 /// let cartesian = ComplexCartesian::from_polar(&polar);
65 /// ```
66 pub fn from_polar(polar: &ComplexPolar) -> Self {
67 let re = polar.mag * polar.ang.cos();
68 let im = polar.mag * polar.ang.sin();
69 return Self { re, im };
70 }
71}
72
73#[derive(Debug, Clone, Copy)]
74/// Describes a complex number in polar form _`mag`e^(`ang`i)_
75pub struct ComplexPolar {
76 pub mag: f64,
77 pub ang: f64,
78}
79
80impl std::fmt::Display for ComplexPolar {
81 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
82 write!(f, "{}e^({}i)", self.mag, self.ang)
83 }
84}
85
86impl ComplexPolar {
87 /// Converts a complex number from cartesian to polar form.
88 ///
89 /// # Examples
90 ///
91 /// ```
92 /// use complex_stuff::{ComplexCartesian, ComplexPolar};
93 ///
94 /// let cartesian = ComplexCartesian { re: 5.0, im: 3.0 };
95 /// let polar = ComplexPolar::from_cartesian(&cartesian);
96 /// ```
97 pub fn from_cartesian(cartesian: &ComplexCartesian) -> Self {
98 let mag = (cartesian.re * cartesian.re + cartesian.im * cartesian.im).sqrt();
99 let ang = (cartesian.re / mag).acos();
100 return Self { mag, ang };
101 }
102}
103
104#[derive(Debug, Clone, Copy)]
105/// Describes a complex number in both cartesian and polar form.
106pub struct Complex {
107 cartesian: ComplexCartesian,
108 polar: ComplexPolar,
109}
110
111impl std::fmt::Display for Complex {
112 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
113 write!(f, "Cartesian: {}\nPolar: {}", self.cartesian, self.polar)
114 }
115}
116
117impl Complex {
118 /// Creates a complex number from its cartesian parts.
119 ///
120 /// # Examples
121 ///
122 /// ```
123 /// use complex_stuff::Complex;
124 ///
125 /// let complex = Complex::new_cartesian(5.0, 3.0);
126 /// ```
127 pub fn new_cartesian(re: f64, im: f64) -> Self {
128 let cartesian = ComplexCartesian { re, im };
129 let polar = ComplexPolar::from_cartesian(&cartesian);
130
131 Self { cartesian, polar }
132 }
133
134 /// Creates a complex number from its polar parts.
135 ///
136 /// # Examples
137 ///
138 /// ```
139 /// use std::f64::consts::PI;
140 /// use complex_stuff::Complex;
141 ///
142 /// let complex = Complex::new_polar(5.0, PI / 2.0);
143 /// ```
144 pub fn new_polar(mag: f64, ang: f64) -> Self {
145 let polar = ComplexPolar { mag, ang };
146 let cartesian = ComplexCartesian::from_polar(&polar);
147
148 Self { cartesian, polar }
149 }
150
151 /// Creates a complex number just from its real cartesian part leaving the imaginary part 0.
152 ///
153 /// # Examples
154 ///
155 /// ```
156 /// use complex_stuff::Complex;
157 ///
158 /// let complex = Complex::new_real(5.0);
159 ///
160 /// assert_eq!(5.0, complex.re());
161 /// assert_eq!(0.0, complex.im());
162 /// ```
163 pub fn new_real(re: f64) -> Self {
164 Self::new_cartesian(re, 0.0)
165 }
166
167 /// Creates a complex number just from its imaginary cartesian part leaving the real part 0.
168 ///
169 /// # Examples
170 ///
171 /// ```
172 /// use complex_stuff::Complex;
173 ///
174 /// let complex = Complex::new_imaginary(3.0);
175 ///
176 /// assert_eq!(0.0, complex.re());
177 /// assert_eq!(3.0, complex.im());
178 /// ```
179 pub fn new_imaginary(im: f64) -> Self {
180 Self::new_cartesian(0.0, im)
181 }
182
183 /// Creates a complex number representing the value 0.
184 ///
185 /// # Examples
186 ///
187 /// ```
188 /// use complex_stuff::Complex;
189 ///
190 /// let complex = Complex::zero();
191 ///
192 /// assert_eq!(0.0, complex.re());
193 /// assert_eq!(0.0, complex.im());
194 /// ```
195 pub fn zero() -> Self {
196 Self::new_cartesian(0.0, 0.0)
197 }
198
199 /// Creates a complex number representing the value 1.
200 ///
201 /// # Examples
202 ///
203 /// ```
204 /// use complex_stuff::Complex;
205 ///
206 /// let complex = Complex::one();
207 ///
208 /// assert_eq!(1.0, complex.re());
209 /// assert_eq!(0.0, complex.im());
210 /// ```
211 pub fn one() -> Self {
212 Self::new_cartesian(1.0, 0.0)
213 }
214
215 /// Creates a complex number representing the value i.
216 ///
217 /// # Examples
218 ///
219 /// ```
220 /// use complex_stuff::Complex;
221 ///
222 /// let complex = Complex::i();
223 ///
224 /// assert_eq!(0.0, complex.re());
225 /// assert_eq!(1.0, complex.im());
226 /// ```
227 pub fn i() -> Self {
228 Self::new_cartesian(0.0, 1.0)
229 }
230
231 /// Creates a complex number representing the value e.
232 ///
233 /// # Examples
234 ///
235 /// ```
236 /// use std::f64::consts::E;
237 /// use complex_stuff::Complex;
238 ///
239 /// let complex = Complex::e();
240 ///
241 /// assert_eq!(E, complex.re());
242 /// assert_eq!(0.0, complex.im());
243 /// ```
244 pub fn e() -> Self {
245 Self::new_real(E)
246 }
247}
248
249impl Complex {
250 /// Returns the complex number in cartesian form.
251 ///
252 /// # Examples
253 ///
254 /// ```
255 /// use complex_stuff::Complex;
256 ///
257 /// let complex = Complex::new_cartesian(5.0, 3.0);
258 ///
259 /// let cartesian = complex.cartesian();
260 ///
261 /// assert_eq!(5.0, cartesian.re);
262 /// assert_eq!(3.0, cartesian.im);
263 /// ```
264 pub fn cartesian(&self) -> ComplexCartesian {
265 self.cartesian
266 }
267
268 /// Returns the complex number in polar form.
269 ///
270 /// # Examples
271 ///
272 /// ```
273 /// use std::f64::consts::PI;
274 /// use complex_stuff::Complex;
275 ///
276 /// let complex = Complex::new_polar(5.0, PI / 2.0);
277 ///
278 /// let polar = complex.polar();
279 ///
280 /// assert_eq!(5.0, polar.mag);
281 /// assert_eq!(PI / 2.0, polar.ang);
282 /// ```
283 pub fn polar(&self) -> ComplexPolar {
284 self.polar
285 }
286
287 /// Returns just the real part of the complex numbers cartesian form.
288 ///
289 /// # Examples
290 ///
291 /// ```
292 /// use complex_stuff::Complex;
293 ///
294 /// let complex = Complex::new_cartesian(5.0, 3.0);
295 ///
296 /// let real = complex.re();
297 ///
298 /// assert_eq!(5.0, real);
299 /// ```
300 pub fn re(&self) -> f64 {
301 self.cartesian.re
302 }
303
304 /// # Examples
305 ///
306 /// ```
307 /// use complex_stuff::Complex;
308 ///
309 /// let complex = Complex::new_cartesian(5.0, 3.0);
310 ///
311 /// let imaginary = complex.im();
312 ///
313 /// assert_eq!(3.0, imaginary);
314 /// ```
315 /// Returns just the imaginary part of the complex numbers cartesian form.
316 pub fn im(&self) -> f64 {
317 self.cartesian.im
318 }
319
320 /// Returns just the magnitude of the complex numbers polar form.
321 ///
322 /// # Examples
323 ///
324 /// ```
325 /// use std::f64::consts::PI;
326 /// use complex_stuff::Complex;
327 ///
328 /// let complex = Complex::new_polar(5.0, PI / 2.0);
329 ///
330 /// let magnitude = complex.mag();
331 ///
332 /// assert_eq!(5.0, magnitude);
333 /// ```
334 pub fn mag(&self) -> f64 {
335 self.polar.mag
336 }
337
338 /// Returns just the angle of the complex numbers polar form.
339 ///
340 /// # Examples
341 ///
342 /// ```
343 /// use std::f64::consts::PI;
344 /// use complex_stuff::Complex;
345 ///
346 /// let complex = Complex::new_polar(5.0, PI / 2.0);
347 ///
348 /// let angle = complex.ang();
349 ///
350 /// assert_eq!(PI / 2.0, angle);
351 /// ```
352 pub fn ang(&self) -> f64 {
353 self.polar.ang
354 }
355}
356
357impl Complex {
358 /// Returns the negation of the complex number.
359 /// Same as using the unary negation operator `-`.
360 ///
361 /// # Examples
362 ///
363 /// ```
364 /// use complex_stuff::Complex;
365 ///
366 /// let complex = Complex::new_cartesian(5.0, 3.0);
367 ///
368 /// let opposite = complex.opposite();
369 ///
370 /// assert_eq!(-5.0, opposite.re());
371 /// assert_eq!(-3.0, opposite.im());
372 /// ```
373 pub fn opposite(self) -> Self {
374 let re = -self.cartesian.re;
375 let im = -self.cartesian.im;
376 Self::new_cartesian(re, im)
377 }
378
379 /// Returns the reciprocal of the complex number.
380 /// # Examples
381 ///
382 /// ```
383 /// use complex_stuff::Complex;
384 ///
385 /// let complex = Complex::new_cartesian(5.0, 0.0);
386 ///
387 /// let reciprocal = complex.reciprocal();
388 /// ```
389 pub fn reciprocal(self) -> Option<Self> {
390 Self::one() / self
391 }
392}
393
394impl Neg for Complex {
395 type Output = Self;
396
397 fn neg(self) -> Self {
398 self.opposite()
399 }
400}
401
402impl Add for Complex {
403 type Output = Self;
404
405 /// Performs the `+` operation.
406 ///
407 /// # Examples
408 ///
409 /// ```
410 /// use complex_stuff::Complex;
411 ///
412 /// let c1 = Complex::new_cartesian(5.0, 3.0);
413 /// let c2 = Complex::new_cartesian(1.0, 2.0);
414 ///
415 /// let sum = c1 + c2;
416 ///
417 /// assert_eq!(6.0, sum.re());
418 /// assert_eq!(5.0, sum.im());
419 /// ```
420 fn add(self, other: Self) -> Self {
421 let re = self.cartesian.re + other.cartesian.re;
422 let im = self.cartesian.im + other.cartesian.im;
423
424 Self::new_cartesian(re, im)
425 }
426}
427
428impl Sub for Complex {
429 type Output = Self;
430
431 /// Performs the `-` operation.
432 ///
433 /// # Examples
434 ///
435 /// ```
436 /// use complex_stuff::Complex;
437 ///
438 /// let c1 = Complex::new_cartesian(5.0, 3.0);
439 /// let c2 = Complex::new_cartesian(1.0, 2.0);
440 ///
441 /// let diff = c1 - c2;
442 ///
443 /// assert_eq!(4.0, diff.re());
444 /// assert_eq!(1.0, diff.im());
445 /// ```
446 fn sub(self, other: Self) -> Self {
447 let re = self.cartesian.re - other.cartesian.re;
448 let im = self.cartesian.im - other.cartesian.im;
449
450 Self::new_cartesian(re, im)
451 }
452}
453
454impl Mul for Complex {
455 type Output = Self;
456
457 /// Performs the `*` operation.
458 ///
459 /// # Examples
460 ///
461 /// ```
462 /// use complex_stuff::Complex;
463 ///
464 /// let c1 = Complex::new_polar(5.0, 2.0);
465 /// let c2 = Complex::new_polar(2.0, 1.0);
466 ///
467 /// let product = c1 * c2;
468 ///
469 /// assert_eq!(10.0, product.mag());
470 /// assert_eq!(3.0, product.ang());
471 /// ```
472 fn mul(self, other: Self) -> Self {
473 let mag = self.polar.mag * other.polar.mag;
474 let ang = self.polar.ang + other.polar.ang;
475
476 Self::new_polar(mag, ang)
477 }
478}
479
480impl Div for Complex {
481 type Output = Option<Self>;
482
483 /// Performs the `/` operation.
484 ///
485 /// Returns `None` when the result is undefined or infinite.
486 ///
487 /// # Examples
488 ///
489 /// ```ignore
490 /// use complex_stuff::Complex;
491 ///
492 /// let c1 = Complex::new_polar(5.0, 2.0);
493 /// let c2 = Complex::new_polar(2.0, 1.0);
494 ///
495 /// let quotient = (c1 / c2)?;
496 ///
497 /// assert_eq!(2.5, product.mag());
498 /// assert_eq!(1.0, product.ang());
499 /// ```
500 fn div(self, other: Self) -> Option<Self> {
501 if other.polar.mag == 0.0 {
502 return None;
503 }
504
505 let mag = self.polar.mag / other.polar.mag;
506 let ang = self.polar.ang - other.polar.ang;
507
508 Some(Self::new_polar(mag, ang))
509 }
510}
511
512impl Complex {
513 /// Returns the natural logarithm of the complex number.
514 ///
515 /// Returns `None` when the result is undefined or infinite.
516 ///
517 /// # Examples
518 ///
519 /// ```ignore
520 /// use complex_stuff::Complex;
521 ///
522 /// let complex = Complex::new_cartesian(5.0, 3.0);
523 ///
524 /// let result = complex.ln()?;
525 /// ```
526 pub fn ln(self) -> Option<Self> {
527 if self.polar.mag == 0.0 {
528 return None;
529 }
530
531 let re = self.polar.mag.ln();
532 let im = self.polar.ang;
533
534 Some(Self::new_cartesian(re, im))
535 }
536
537 /// Returns the logarithm to any other base of the complex number.
538 ///
539 /// Returns `None` when the result is undefined or infinite.
540 ///
541 /// # Examples
542 ///
543 /// ```ignore
544 /// use complex_stuff::Complex;
545 ///
546 /// let complex = Complex::new_cartesian(5.0, 3.0);
547 /// let base = Complex::new_cartesian(7.0, 10.0);
548 ///
549 /// let result = complex.log(base)?;
550 /// ```
551 pub fn log(self, other: Self) -> Option<Self> {
552 if other.polar.mag == 1.0 || self.polar.mag == 0.0 {
553 return None;
554 }
555
556 if other.polar.mag == 0.0 {
557 return Some(Self::zero());
558 }
559
560 let mag_s = self.polar.mag;
561 let ang_s = self.polar.ang;
562
563 let mag_o = other.polar.mag;
564 let ang_o = other.polar.ang;
565
566 let divisor = mag_o.ln().powi(2) + ang_o.powi(2);
567
568 let re = (mag_s.ln() * mag_o.ln() + ang_s * ang_o) / divisor;
569 let im = (ang_s * mag_o.ln() - ang_o * mag_s.ln()) / divisor;
570
571 Some(Self::new_cartesian(re, im))
572 }
573}
574
575impl Complex {
576 /// Raises the complex number to any other complex number and returns the result.
577 ///
578 /// Returns `None` when the result is undefined or infinite.
579 ///
580 /// # Examples
581 ///
582 /// ```ignore
583 /// use complex_stuff::Complex;
584 ///
585 /// let complex = Complex::new_cartesian(5.0, 3.0);
586 /// let exponent = Complex::new_cartesian(2.0, 1.0);
587 ///
588 /// let result = complex.pow(exponent)?;
589 /// ```
590 pub fn pow(self, other: Self) -> Option<Self> {
591 if self.polar.mag == 0.0 && other.polar.mag == 0.0 {
592 return None;
593 }
594
595 if other.polar.mag == 0.0 {
596 return Some(Self::one());
597 }
598
599 if self.polar.mag == 0.0 {
600 return Some(Self::zero());
601 }
602
603 let b_mag = self.polar.mag;
604 let b_ang = self.polar.ang;
605
606 let e_re = other.cartesian.re;
607 let e_im = other.cartesian.im;
608
609 let mag = (e_re * b_mag.ln() - e_im * b_ang).exp();
610 let ang = e_re * b_ang + e_im * b_mag.ln();
611
612 Some(Self::new_polar(mag, ang))
613 }
614
615 /// Retuns the nth root of the complex number with n being any other complex number.
616 ///
617 /// Returns `None` when the result is undefined or infinite.
618 ///
619 /// # Examples
620 ///
621 /// ```ignore
622 /// use complex_stuff::Complex;
623 ///
624 /// let complex = Complex::new_cartesian(5.0, 3.0);
625 /// let n = Complex::new_cartesian(2.0, 1.0);
626 ///
627 /// let result = complex.root(n)?;
628 /// ```
629 pub fn root(self, other: Self) -> Option<Self> {
630 self.pow(other.reciprocal()?)
631 }
632}
633
634impl Complex {
635 /// Returns the sine of the complex number.
636 ///
637 /// Returns `None` when the result is undefined or infinite.
638 ///
639 /// # Examples
640 ///
641 /// ```ignore
642 /// use complex_stuff::Complex;
643 ///
644 /// let complex = Complex::new_cartesian(5.0, 3.0);
645 ///
646 /// let result = complex.sin()?;
647 /// ```
648 pub fn sin(self) -> Option<Self> {
649 let re = self.cartesian.re.sin() * self.cartesian.im.cosh();
650 let im = self.cartesian.re.cos() * self.cartesian.im.sinh();
651
652 Some(Self::new_cartesian(re, im))
653 }
654
655 /// Returns the cosine of the complex number.
656 ///
657 /// Returns `None` when the result is undefined or infinite.
658 ///
659 /// # Examples
660 ///
661 /// ```ignore
662 /// use complex_stuff::Complex;
663 ///
664 /// let complex = Complex::new_cartesian(5.0, 3.0);
665 ///
666 /// let result = complex.cos()?;
667 /// ```
668 pub fn cos(self) -> Option<Self> {
669 let re = self.cartesian.re.cos() * self.cartesian.im.cosh();
670 let im = -(self.cartesian.re.sin() * self.cartesian.im.sinh());
671
672 Some(Self::new_cartesian(re, im))
673 }
674}