1#![doc(html_root_url = "https://docs.rs/num-complex/0.4")]
18#![no_std]
19
20#[cfg(any(test, feature = "std"))]
21#[cfg_attr(test, macro_use)]
22extern crate std;
23
24use core::fmt;
25#[cfg(test)]
26use core::hash;
27use core::iter::{Product, Sum};
28use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
29use core::str::FromStr;
30#[cfg(feature = "std")]
31use std::error::Error;
32
33use num_traits::{Inv, MulAdd, Num, One, Pow, Signed, Zero};
34
35use num_traits::float::FloatCore;
36#[cfg(any(feature = "std", feature = "libm"))]
37use num_traits::float::{Float, FloatConst};
38
39mod cast;
40mod pow;
41
42#[cfg(any(feature = "std", feature = "libm"))]
43mod complex_float;
44#[cfg(any(feature = "std", feature = "libm"))]
45pub use crate::complex_float::ComplexFloat;
46
47#[cfg(feature = "rand")]
48mod crand;
49#[cfg(feature = "rand")]
50pub use crate::crand::ComplexDistribution;
51
52#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Default)]
81#[repr(C)]
82#[cfg_attr(
83 feature = "rkyv",
84 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
85)]
86#[cfg_attr(feature = "rkyv", archive(as = "Complex<T::Archived>"))]
87#[cfg_attr(feature = "bytecheck", derive(bytecheck::CheckBytes))]
88pub struct Complex<T> {
89 pub re: T,
91 pub im: T,
93}
94
95pub type Complex32 = Complex<f32>;
96pub type Complex64 = Complex<f64>;
97
98impl<T> Complex<T> {
99 #[inline]
101 pub const fn new(re: T, im: T) -> Self {
102 Complex { re, im }
103 }
104}
105
106impl<T: Clone + Num> Complex<T> {
107 #[inline]
109 pub fn i() -> Self {
110 Self::new(T::zero(), T::one())
111 }
112
113 #[inline]
116 pub fn norm_sqr(&self) -> T {
117 self.re.clone() * self.re.clone() + self.im.clone() * self.im.clone()
118 }
119
120 #[inline]
122 pub fn scale(&self, t: T) -> Self {
123 Self::new(self.re.clone() * t.clone(), self.im.clone() * t)
124 }
125
126 #[inline]
128 pub fn unscale(&self, t: T) -> Self {
129 Self::new(self.re.clone() / t.clone(), self.im.clone() / t)
130 }
131
132 #[inline]
134 pub fn powu(&self, exp: u32) -> Self {
135 Pow::pow(self, exp)
136 }
137}
138
139impl<T: Clone + Num + Neg<Output = T>> Complex<T> {
140 #[inline]
142 pub fn conj(&self) -> Self {
143 Self::new(self.re.clone(), -self.im.clone())
144 }
145
146 #[inline]
148 pub fn inv(&self) -> Self {
149 let norm_sqr = self.norm_sqr();
150 Self::new(
151 self.re.clone() / norm_sqr.clone(),
152 -self.im.clone() / norm_sqr,
153 )
154 }
155
156 #[inline]
158 pub fn powi(&self, exp: i32) -> Self {
159 Pow::pow(self, exp)
160 }
161}
162
163impl<T: Clone + Signed> Complex<T> {
164 #[inline]
168 pub fn l1_norm(&self) -> T {
169 self.re.abs() + self.im.abs()
170 }
171}
172
173#[cfg(any(feature = "std", feature = "libm"))]
174impl<T: Float> Complex<T> {
175 #[inline]
178 pub fn cis(phase: T) -> Self {
179 Self::new(phase.cos(), phase.sin())
180 }
181
182 #[inline]
184 pub fn norm(self) -> T {
185 self.re.hypot(self.im)
186 }
187 #[inline]
189 pub fn arg(self) -> T {
190 self.im.atan2(self.re)
191 }
192 #[inline]
195 pub fn to_polar(self) -> (T, T) {
196 (self.norm(), self.arg())
197 }
198 #[inline]
200 pub fn from_polar(r: T, theta: T) -> Self {
201 Self::new(r * theta.cos(), r * theta.sin())
202 }
203
204 #[inline]
206 pub fn exp(self) -> Self {
207 let Complex { re, mut im } = self;
210 if re.is_infinite() {
212 if re < T::zero() {
213 if !im.is_finite() {
214 return Self::new(T::zero(), T::zero());
215 }
216 } else {
217 if im == T::zero() || !im.is_finite() {
218 if im.is_infinite() {
219 im = T::nan();
220 }
221 return Self::new(re, im);
222 }
223 }
224 } else if re.is_nan() && im == T::zero() {
225 return self;
226 }
227
228 Self::from_polar(re.exp(), im)
229 }
230
231 #[inline]
239 pub fn ln(self) -> Self {
240 let (r, theta) = self.to_polar();
242 Self::new(r.ln(), theta)
243 }
244
245 #[inline]
253 pub fn sqrt(self) -> Self {
254 if self.im.is_zero() {
255 if self.re.is_sign_positive() {
256 Self::new(self.re.sqrt(), self.im)
258 } else {
259 let re = T::zero();
262 let im = (-self.re).sqrt();
263 if self.im.is_sign_positive() {
264 Self::new(re, im)
265 } else {
266 Self::new(re, -im)
267 }
268 }
269 } else if self.re.is_zero() {
270 let one = T::one();
273 let two = one + one;
274 let x = (self.im.abs() / two).sqrt();
275 if self.im.is_sign_positive() {
276 Self::new(x, x)
277 } else {
278 Self::new(x, -x)
279 }
280 } else {
281 let one = T::one();
283 let two = one + one;
284 let (r, theta) = self.to_polar();
285 Self::from_polar(r.sqrt(), theta / two)
286 }
287 }
288
289 #[inline]
301 pub fn cbrt(self) -> Self {
302 if self.im.is_zero() {
303 if self.re.is_sign_positive() {
304 Self::new(self.re.cbrt(), self.im)
306 } else {
307 let one = T::one();
310 let two = one + one;
311 let three = two + one;
312 let re = (-self.re).cbrt() / two;
313 let im = three.sqrt() * re;
314 if self.im.is_sign_positive() {
315 Self::new(re, im)
316 } else {
317 Self::new(re, -im)
318 }
319 }
320 } else if self.re.is_zero() {
321 let one = T::one();
324 let two = one + one;
325 let three = two + one;
326 let im = self.im.abs().cbrt() / two;
327 let re = three.sqrt() * im;
328 if self.im.is_sign_positive() {
329 Self::new(re, im)
330 } else {
331 Self::new(re, -im)
332 }
333 } else {
334 let one = T::one();
336 let three = one + one + one;
337 let (r, theta) = self.to_polar();
338 Self::from_polar(r.cbrt(), theta / three)
339 }
340 }
341
342 #[inline]
344 pub fn powf(self, exp: T) -> Self {
345 if exp.is_zero() {
346 return Self::one();
347 }
348 let (r, theta) = self.to_polar();
351 Self::from_polar(r.powf(exp), theta * exp)
352 }
353
354 #[inline]
356 pub fn log(self, base: T) -> Self {
357 let (r, theta) = self.to_polar();
361 Self::new(r.log(base), theta / base.ln())
362 }
363
364 #[inline]
366 pub fn powc(self, exp: Self) -> Self {
367 if exp.is_zero() {
368 return Self::one();
369 }
370 (exp * self.ln()).exp()
372 }
373
374 #[inline]
376 pub fn expf(self, base: T) -> Self {
377 Self::from_polar(base.powf(self.re), self.im * base.ln())
380 }
381
382 #[inline]
384 pub fn sin(self) -> Self {
385 Self::new(
387 self.re.sin() * self.im.cosh(),
388 self.re.cos() * self.im.sinh(),
389 )
390 }
391
392 #[inline]
394 pub fn cos(self) -> Self {
395 Self::new(
397 self.re.cos() * self.im.cosh(),
398 -self.re.sin() * self.im.sinh(),
399 )
400 }
401
402 #[inline]
404 pub fn tan(self) -> Self {
405 let (two_re, two_im) = (self.re + self.re, self.im + self.im);
407 Self::new(two_re.sin(), two_im.sinh()).unscale(two_re.cos() + two_im.cosh())
408 }
409
410 #[inline]
419 pub fn asin(self) -> Self {
420 let i = Self::i();
422 -i * ((Self::one() - self * self).sqrt() + i * self).ln()
423 }
424
425 #[inline]
434 pub fn acos(self) -> Self {
435 let i = Self::i();
437 -i * (i * (Self::one() - self * self).sqrt() + self).ln()
438 }
439
440 #[inline]
449 pub fn atan(self) -> Self {
450 let i = Self::i();
452 let one = Self::one();
453 let two = one + one;
454 if self == i {
455 return Self::new(T::zero(), T::infinity());
456 } else if self == -i {
457 return Self::new(T::zero(), -T::infinity());
458 }
459 ((one + i * self).ln() - (one - i * self).ln()) / (two * i)
460 }
461
462 #[inline]
464 pub fn sinh(self) -> Self {
465 Self::new(
467 self.re.sinh() * self.im.cos(),
468 self.re.cosh() * self.im.sin(),
469 )
470 }
471
472 #[inline]
474 pub fn cosh(self) -> Self {
475 Self::new(
477 self.re.cosh() * self.im.cos(),
478 self.re.sinh() * self.im.sin(),
479 )
480 }
481
482 #[inline]
484 pub fn tanh(self) -> Self {
485 let (two_re, two_im) = (self.re + self.re, self.im + self.im);
487 Self::new(two_re.sinh(), two_im.sin()).unscale(two_re.cosh() + two_im.cos())
488 }
489
490 #[inline]
499 pub fn asinh(self) -> Self {
500 let one = Self::one();
502 (self + (one + self * self).sqrt()).ln()
503 }
504
505 #[inline]
513 pub fn acosh(self) -> Self {
514 let one = Self::one();
516 let two = one + one;
517 two * (((self + one) / two).sqrt() + ((self - one) / two).sqrt()).ln()
518 }
519
520 #[inline]
529 pub fn atanh(self) -> Self {
530 let one = Self::one();
532 let two = one + one;
533 if self == one {
534 return Self::new(T::infinity(), T::zero());
535 } else if self == -one {
536 return Self::new(-T::infinity(), T::zero());
537 }
538 ((one + self).ln() - (one - self).ln()) / two
539 }
540
541 #[inline]
564 pub fn finv(self) -> Complex<T> {
565 let norm = self.norm();
566 self.conj() / norm / norm
567 }
568
569 #[inline]
593 pub fn fdiv(self, other: Complex<T>) -> Complex<T> {
594 self * other.finv()
595 }
596}
597
598#[cfg(any(feature = "std", feature = "libm"))]
599impl<T: Float + FloatConst> Complex<T> {
600 #[inline]
602 pub fn exp2(self) -> Self {
603 Self::from_polar(self.re.exp2(), self.im * T::LN_2())
606 }
607
608 #[inline]
610 pub fn log2(self) -> Self {
611 Self::ln(self) / T::LN_2()
612 }
613
614 #[inline]
616 pub fn log10(self) -> Self {
617 Self::ln(self) / T::LN_10()
618 }
619}
620
621impl<T: FloatCore> Complex<T> {
622 #[inline]
624 pub fn is_nan(self) -> bool {
625 self.re.is_nan() || self.im.is_nan()
626 }
627
628 #[inline]
630 pub fn is_infinite(self) -> bool {
631 !self.is_nan() && (self.re.is_infinite() || self.im.is_infinite())
632 }
633
634 #[inline]
636 pub fn is_finite(self) -> bool {
637 self.re.is_finite() && self.im.is_finite()
638 }
639
640 #[inline]
642 pub fn is_normal(self) -> bool {
643 self.re.is_normal() && self.im.is_normal()
644 }
645}
646
647#[cfg(feature = "bytemuck")]
651unsafe impl<T: bytemuck::Zeroable> bytemuck::Zeroable for Complex<T> {}
652
653#[cfg(feature = "bytemuck")]
657unsafe impl<T: bytemuck::Pod> bytemuck::Pod for Complex<T> {}
658
659impl<T: Clone + Num> From<T> for Complex<T> {
660 #[inline]
661 fn from(re: T) -> Self {
662 Self::new(re, T::zero())
663 }
664}
665
666impl<'a, T: Clone + Num> From<&'a T> for Complex<T> {
667 #[inline]
668 fn from(re: &T) -> Self {
669 From::from(re.clone())
670 }
671}
672
673macro_rules! forward_ref_ref_binop {
674 (impl $imp:ident, $method:ident) => {
675 impl<'a, 'b, T: Clone + Num> $imp<&'b Complex<T>> for &'a Complex<T> {
676 type Output = Complex<T>;
677
678 #[inline]
679 fn $method(self, other: &Complex<T>) -> Self::Output {
680 self.clone().$method(other.clone())
681 }
682 }
683 };
684}
685
686macro_rules! forward_ref_val_binop {
687 (impl $imp:ident, $method:ident) => {
688 impl<'a, T: Clone + Num> $imp<Complex<T>> for &'a Complex<T> {
689 type Output = Complex<T>;
690
691 #[inline]
692 fn $method(self, other: Complex<T>) -> Self::Output {
693 self.clone().$method(other)
694 }
695 }
696 };
697}
698
699macro_rules! forward_val_ref_binop {
700 (impl $imp:ident, $method:ident) => {
701 impl<'a, T: Clone + Num> $imp<&'a Complex<T>> for Complex<T> {
702 type Output = Complex<T>;
703
704 #[inline]
705 fn $method(self, other: &Complex<T>) -> Self::Output {
706 self.$method(other.clone())
707 }
708 }
709 };
710}
711
712macro_rules! forward_all_binop {
713 (impl $imp:ident, $method:ident) => {
714 forward_ref_ref_binop!(impl $imp, $method);
715 forward_ref_val_binop!(impl $imp, $method);
716 forward_val_ref_binop!(impl $imp, $method);
717 };
718}
719
720forward_all_binop!(impl Add, add);
722
723impl<T: Clone + Num> Add<Complex<T>> for Complex<T> {
725 type Output = Self;
726
727 #[inline]
728 fn add(self, other: Self) -> Self::Output {
729 Self::Output::new(self.re + other.re, self.im + other.im)
730 }
731}
732
733forward_all_binop!(impl Sub, sub);
734
735impl<T: Clone + Num> Sub<Complex<T>> for Complex<T> {
737 type Output = Self;
738
739 #[inline]
740 fn sub(self, other: Self) -> Self::Output {
741 Self::Output::new(self.re - other.re, self.im - other.im)
742 }
743}
744
745forward_all_binop!(impl Mul, mul);
746
747impl<T: Clone + Num> Mul<Complex<T>> for Complex<T> {
749 type Output = Self;
750
751 #[inline]
752 fn mul(self, other: Self) -> Self::Output {
753 let re = self.re.clone() * other.re.clone() - self.im.clone() * other.im.clone();
754 let im = self.re * other.im + self.im * other.re;
755 Self::Output::new(re, im)
756 }
757}
758
759impl<T: Clone + Num + MulAdd<Output = T>> MulAdd<Complex<T>> for Complex<T> {
761 type Output = Complex<T>;
762
763 #[inline]
764 fn mul_add(self, other: Complex<T>, add: Complex<T>) -> Complex<T> {
765 let re = self.re.clone().mul_add(other.re.clone(), add.re)
766 - (self.im.clone() * other.im.clone()); let im = self.re.mul_add(other.im, self.im.mul_add(other.re, add.im));
768 Complex::new(re, im)
769 }
770}
771impl<'a, 'b, T: Clone + Num + MulAdd<Output = T>> MulAdd<&'b Complex<T>> for &'a Complex<T> {
772 type Output = Complex<T>;
773
774 #[inline]
775 fn mul_add(self, other: &Complex<T>, add: &Complex<T>) -> Complex<T> {
776 self.clone().mul_add(other.clone(), add.clone())
777 }
778}
779
780forward_all_binop!(impl Div, div);
781
782impl<T: Clone + Num> Div<Complex<T>> for Complex<T> {
785 type Output = Self;
786
787 #[inline]
788 fn div(self, other: Self) -> Self::Output {
789 let norm_sqr = other.norm_sqr();
790 let re = self.re.clone() * other.re.clone() + self.im.clone() * other.im.clone();
791 let im = self.im * other.re - self.re * other.im;
792 Self::Output::new(re / norm_sqr.clone(), im / norm_sqr)
793 }
794}
795
796forward_all_binop!(impl Rem, rem);
797
798impl<T: Clone + Num> Complex<T> {
799 fn div_trunc(&self, divisor: &Self) -> Self {
801 let Complex { re, im } = self / divisor;
802 Complex::new(re.clone() - re % T::one(), im.clone() - im % T::one())
803 }
804}
805
806impl<T: Clone + Num> Rem<Complex<T>> for Complex<T> {
807 type Output = Self;
808
809 #[inline]
810 fn rem(self, modulus: Self) -> Self::Output {
811 let gaussian = self.div_trunc(&modulus);
812 self - modulus * gaussian
813 }
814}
815
816mod opassign {
819 use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
820
821 use num_traits::{MulAddAssign, NumAssign};
822
823 use crate::Complex;
824
825 impl<T: Clone + NumAssign> AddAssign for Complex<T> {
826 fn add_assign(&mut self, other: Self) {
827 self.re += other.re;
828 self.im += other.im;
829 }
830 }
831
832 impl<T: Clone + NumAssign> SubAssign for Complex<T> {
833 fn sub_assign(&mut self, other: Self) {
834 self.re -= other.re;
835 self.im -= other.im;
836 }
837 }
838
839 impl<T: Clone + NumAssign> MulAssign for Complex<T> {
841 fn mul_assign(&mut self, other: Self) {
842 let a = self.re.clone();
843
844 self.re *= other.re.clone();
845 self.re -= self.im.clone() * other.im.clone();
846
847 self.im *= other.re;
848 self.im += a * other.im;
849 }
850 }
851
852 impl<T: Clone + NumAssign + MulAddAssign> MulAddAssign for Complex<T> {
854 fn mul_add_assign(&mut self, other: Complex<T>, add: Complex<T>) {
855 let a = self.re.clone();
856
857 self.re.mul_add_assign(other.re.clone(), add.re); self.re -= self.im.clone() * other.im.clone(); let mut adf = a;
861 adf.mul_add_assign(other.im, add.im); self.im.mul_add_assign(other.re, adf); }
864 }
865
866 impl<'a, 'b, T: Clone + NumAssign + MulAddAssign> MulAddAssign<&'a Complex<T>, &'b Complex<T>>
867 for Complex<T>
868 {
869 fn mul_add_assign(&mut self, other: &Complex<T>, add: &Complex<T>) {
870 self.mul_add_assign(other.clone(), add.clone());
871 }
872 }
873
874 impl<T: Clone + NumAssign> DivAssign for Complex<T> {
877 fn div_assign(&mut self, other: Self) {
878 let a = self.re.clone();
879 let norm_sqr = other.norm_sqr();
880
881 self.re *= other.re.clone();
882 self.re += self.im.clone() * other.im.clone();
883 self.re /= norm_sqr.clone();
884
885 self.im *= other.re;
886 self.im -= a * other.im;
887 self.im /= norm_sqr;
888 }
889 }
890
891 impl<T: Clone + NumAssign> RemAssign for Complex<T> {
892 fn rem_assign(&mut self, modulus: Self) {
893 let gaussian = self.div_trunc(&modulus);
894 *self -= modulus * gaussian;
895 }
896 }
897
898 impl<T: Clone + NumAssign> AddAssign<T> for Complex<T> {
899 fn add_assign(&mut self, other: T) {
900 self.re += other;
901 }
902 }
903
904 impl<T: Clone + NumAssign> SubAssign<T> for Complex<T> {
905 fn sub_assign(&mut self, other: T) {
906 self.re -= other;
907 }
908 }
909
910 impl<T: Clone + NumAssign> MulAssign<T> for Complex<T> {
911 fn mul_assign(&mut self, other: T) {
912 self.re *= other.clone();
913 self.im *= other;
914 }
915 }
916
917 impl<T: Clone + NumAssign> DivAssign<T> for Complex<T> {
918 fn div_assign(&mut self, other: T) {
919 self.re /= other.clone();
920 self.im /= other;
921 }
922 }
923
924 impl<T: Clone + NumAssign> RemAssign<T> for Complex<T> {
925 fn rem_assign(&mut self, other: T) {
926 self.re %= other.clone();
927 self.im %= other;
928 }
929 }
930
931 macro_rules! forward_op_assign {
932 (impl $imp:ident, $method:ident) => {
933 impl<'a, T: Clone + NumAssign> $imp<&'a Complex<T>> for Complex<T> {
934 #[inline]
935 fn $method(&mut self, other: &Self) {
936 self.$method(other.clone())
937 }
938 }
939 impl<'a, T: Clone + NumAssign> $imp<&'a T> for Complex<T> {
940 #[inline]
941 fn $method(&mut self, other: &T) {
942 self.$method(other.clone())
943 }
944 }
945 };
946 }
947
948 forward_op_assign!(impl AddAssign, add_assign);
949 forward_op_assign!(impl SubAssign, sub_assign);
950 forward_op_assign!(impl MulAssign, mul_assign);
951 forward_op_assign!(impl DivAssign, div_assign);
952 forward_op_assign!(impl RemAssign, rem_assign);
953}
954
955impl<T: Clone + Num + Neg<Output = T>> Neg for Complex<T> {
956 type Output = Self;
957
958 #[inline]
959 fn neg(self) -> Self::Output {
960 Self::Output::new(-self.re, -self.im)
961 }
962}
963
964impl<'a, T: Clone + Num + Neg<Output = T>> Neg for &'a Complex<T> {
965 type Output = Complex<T>;
966
967 #[inline]
968 fn neg(self) -> Self::Output {
969 -self.clone()
970 }
971}
972
973impl<T: Clone + Num + Neg<Output = T>> Inv for Complex<T> {
974 type Output = Self;
975
976 #[inline]
977 fn inv(self) -> Self::Output {
978 (&self).inv()
979 }
980}
981
982impl<'a, T: Clone + Num + Neg<Output = T>> Inv for &'a Complex<T> {
983 type Output = Complex<T>;
984
985 #[inline]
986 fn inv(self) -> Self::Output {
987 self.inv()
988 }
989}
990
991macro_rules! real_arithmetic {
992 (@forward $imp:ident::$method:ident for $($real:ident),*) => (
993 impl<'a, T: Clone + Num> $imp<&'a T> for Complex<T> {
994 type Output = Complex<T>;
995
996 #[inline]
997 fn $method(self, other: &T) -> Self::Output {
998 self.$method(other.clone())
999 }
1000 }
1001 impl<'a, T: Clone + Num> $imp<T> for &'a Complex<T> {
1002 type Output = Complex<T>;
1003
1004 #[inline]
1005 fn $method(self, other: T) -> Self::Output {
1006 self.clone().$method(other)
1007 }
1008 }
1009 impl<'a, 'b, T: Clone + Num> $imp<&'a T> for &'b Complex<T> {
1010 type Output = Complex<T>;
1011
1012 #[inline]
1013 fn $method(self, other: &T) -> Self::Output {
1014 self.clone().$method(other.clone())
1015 }
1016 }
1017 $(
1018 impl<'a> $imp<&'a Complex<$real>> for $real {
1019 type Output = Complex<$real>;
1020
1021 #[inline]
1022 fn $method(self, other: &Complex<$real>) -> Complex<$real> {
1023 self.$method(other.clone())
1024 }
1025 }
1026 impl<'a> $imp<Complex<$real>> for &'a $real {
1027 type Output = Complex<$real>;
1028
1029 #[inline]
1030 fn $method(self, other: Complex<$real>) -> Complex<$real> {
1031 self.clone().$method(other)
1032 }
1033 }
1034 impl<'a, 'b> $imp<&'a Complex<$real>> for &'b $real {
1035 type Output = Complex<$real>;
1036
1037 #[inline]
1038 fn $method(self, other: &Complex<$real>) -> Complex<$real> {
1039 self.clone().$method(other.clone())
1040 }
1041 }
1042 )*
1043 );
1044 ($($real:ident),*) => (
1045 real_arithmetic!(@forward Add::add for $($real),*);
1046 real_arithmetic!(@forward Sub::sub for $($real),*);
1047 real_arithmetic!(@forward Mul::mul for $($real),*);
1048 real_arithmetic!(@forward Div::div for $($real),*);
1049 real_arithmetic!(@forward Rem::rem for $($real),*);
1050
1051 $(
1052 impl Add<Complex<$real>> for $real {
1053 type Output = Complex<$real>;
1054
1055 #[inline]
1056 fn add(self, other: Complex<$real>) -> Self::Output {
1057 Self::Output::new(self + other.re, other.im)
1058 }
1059 }
1060
1061 impl Sub<Complex<$real>> for $real {
1062 type Output = Complex<$real>;
1063
1064 #[inline]
1065 fn sub(self, other: Complex<$real>) -> Self::Output {
1066 Self::Output::new(self - other.re, $real::zero() - other.im)
1067 }
1068 }
1069
1070 impl Mul<Complex<$real>> for $real {
1071 type Output = Complex<$real>;
1072
1073 #[inline]
1074 fn mul(self, other: Complex<$real>) -> Self::Output {
1075 Self::Output::new(self * other.re, self * other.im)
1076 }
1077 }
1078
1079 impl Div<Complex<$real>> for $real {
1080 type Output = Complex<$real>;
1081
1082 #[inline]
1083 fn div(self, other: Complex<$real>) -> Self::Output {
1084 let norm_sqr = other.norm_sqr();
1086 Self::Output::new(self * other.re / norm_sqr.clone(),
1087 $real::zero() - self * other.im / norm_sqr)
1088 }
1089 }
1090
1091 impl Rem<Complex<$real>> for $real {
1092 type Output = Complex<$real>;
1093
1094 #[inline]
1095 fn rem(self, other: Complex<$real>) -> Self::Output {
1096 Self::Output::new(self, Self::zero()) % other
1097 }
1098 }
1099 )*
1100 );
1101}
1102
1103impl<T: Clone + Num> Add<T> for Complex<T> {
1104 type Output = Complex<T>;
1105
1106 #[inline]
1107 fn add(self, other: T) -> Self::Output {
1108 Self::Output::new(self.re + other, self.im)
1109 }
1110}
1111
1112impl<T: Clone + Num> Sub<T> for Complex<T> {
1113 type Output = Complex<T>;
1114
1115 #[inline]
1116 fn sub(self, other: T) -> Self::Output {
1117 Self::Output::new(self.re - other, self.im)
1118 }
1119}
1120
1121impl<T: Clone + Num> Mul<T> for Complex<T> {
1122 type Output = Complex<T>;
1123
1124 #[inline]
1125 fn mul(self, other: T) -> Self::Output {
1126 Self::Output::new(self.re * other.clone(), self.im * other)
1127 }
1128}
1129
1130impl<T: Clone + Num> Div<T> for Complex<T> {
1131 type Output = Self;
1132
1133 #[inline]
1134 fn div(self, other: T) -> Self::Output {
1135 Self::Output::new(self.re / other.clone(), self.im / other)
1136 }
1137}
1138
1139impl<T: Clone + Num> Rem<T> for Complex<T> {
1140 type Output = Complex<T>;
1141
1142 #[inline]
1143 fn rem(self, other: T) -> Self::Output {
1144 Self::Output::new(self.re % other.clone(), self.im % other)
1145 }
1146}
1147
1148real_arithmetic!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64);
1149
1150impl<T: Clone + Num> Zero for Complex<T> {
1152 #[inline]
1153 fn zero() -> Self {
1154 Self::new(Zero::zero(), Zero::zero())
1155 }
1156
1157 #[inline]
1158 fn is_zero(&self) -> bool {
1159 self.re.is_zero() && self.im.is_zero()
1160 }
1161
1162 #[inline]
1163 fn set_zero(&mut self) {
1164 self.re.set_zero();
1165 self.im.set_zero();
1166 }
1167}
1168
1169impl<T: Clone + Num> One for Complex<T> {
1170 #[inline]
1171 fn one() -> Self {
1172 Self::new(One::one(), Zero::zero())
1173 }
1174
1175 #[inline]
1176 fn is_one(&self) -> bool {
1177 self.re.is_one() && self.im.is_zero()
1178 }
1179
1180 #[inline]
1181 fn set_one(&mut self) {
1182 self.re.set_one();
1183 self.im.set_zero();
1184 }
1185}
1186
1187macro_rules! write_complex {
1188 ($f:ident, $t:expr, $prefix:expr, $re:expr, $im:expr, $T:ident) => {{
1189 let abs_re = if $re < Zero::zero() {
1190 $T::zero() - $re.clone()
1191 } else {
1192 $re.clone()
1193 };
1194 let abs_im = if $im < Zero::zero() {
1195 $T::zero() - $im.clone()
1196 } else {
1197 $im.clone()
1198 };
1199
1200 return if let Some(prec) = $f.precision() {
1201 fmt_re_im(
1202 $f,
1203 $re < $T::zero(),
1204 $im < $T::zero(),
1205 format_args!(concat!("{:.1$", $t, "}"), abs_re, prec),
1206 format_args!(concat!("{:.1$", $t, "}"), abs_im, prec),
1207 )
1208 } else {
1209 fmt_re_im(
1210 $f,
1211 $re < $T::zero(),
1212 $im < $T::zero(),
1213 format_args!(concat!("{:", $t, "}"), abs_re),
1214 format_args!(concat!("{:", $t, "}"), abs_im),
1215 )
1216 };
1217
1218 fn fmt_re_im(
1219 f: &mut fmt::Formatter<'_>,
1220 re_neg: bool,
1221 im_neg: bool,
1222 real: fmt::Arguments<'_>,
1223 imag: fmt::Arguments<'_>,
1224 ) -> fmt::Result {
1225 let prefix = if f.alternate() { $prefix } else { "" };
1226 let sign = if re_neg {
1227 "-"
1228 } else if f.sign_plus() {
1229 "+"
1230 } else {
1231 ""
1232 };
1233
1234 if im_neg {
1235 fmt_complex(
1236 f,
1237 format_args!(
1238 "{}{pre}{re}-{pre}{im}i",
1239 sign,
1240 re = real,
1241 im = imag,
1242 pre = prefix
1243 ),
1244 )
1245 } else {
1246 fmt_complex(
1247 f,
1248 format_args!(
1249 "{}{pre}{re}+{pre}{im}i",
1250 sign,
1251 re = real,
1252 im = imag,
1253 pre = prefix
1254 ),
1255 )
1256 }
1257 }
1258
1259 #[cfg(feature = "std")]
1260 fn fmt_complex(f: &mut fmt::Formatter<'_>, complex: fmt::Arguments<'_>) -> fmt::Result {
1262 use std::string::ToString;
1263 if let Some(width) = f.width() {
1264 write!(f, "{0: >1$}", complex.to_string(), width)
1265 } else {
1266 write!(f, "{}", complex)
1267 }
1268 }
1269
1270 #[cfg(not(feature = "std"))]
1271 fn fmt_complex(f: &mut fmt::Formatter<'_>, complex: fmt::Arguments<'_>) -> fmt::Result {
1272 write!(f, "{}", complex)
1273 }
1274 }};
1275}
1276
1277impl<T> fmt::Display for Complex<T>
1279where
1280 T: fmt::Display + Num + PartialOrd + Clone,
1281{
1282 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1283 write_complex!(f, "", "", self.re, self.im, T)
1284 }
1285}
1286
1287impl<T> fmt::LowerExp for Complex<T>
1288where
1289 T: fmt::LowerExp + Num + PartialOrd + Clone,
1290{
1291 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1292 write_complex!(f, "e", "", self.re, self.im, T)
1293 }
1294}
1295
1296impl<T> fmt::UpperExp for Complex<T>
1297where
1298 T: fmt::UpperExp + Num + PartialOrd + Clone,
1299{
1300 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1301 write_complex!(f, "E", "", self.re, self.im, T)
1302 }
1303}
1304
1305impl<T> fmt::LowerHex for Complex<T>
1306where
1307 T: fmt::LowerHex + Num + PartialOrd + Clone,
1308{
1309 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1310 write_complex!(f, "x", "0x", self.re, self.im, T)
1311 }
1312}
1313
1314impl<T> fmt::UpperHex for Complex<T>
1315where
1316 T: fmt::UpperHex + Num + PartialOrd + Clone,
1317{
1318 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1319 write_complex!(f, "X", "0x", self.re, self.im, T)
1320 }
1321}
1322
1323impl<T> fmt::Octal for Complex<T>
1324where
1325 T: fmt::Octal + Num + PartialOrd + Clone,
1326{
1327 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1328 write_complex!(f, "o", "0o", self.re, self.im, T)
1329 }
1330}
1331
1332impl<T> fmt::Binary for Complex<T>
1333where
1334 T: fmt::Binary + Num + PartialOrd + Clone,
1335{
1336 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1337 write_complex!(f, "b", "0b", self.re, self.im, T)
1338 }
1339}
1340
1341#[allow(deprecated)] fn from_str_generic<T, E, F>(s: &str, from: F) -> Result<Complex<T>, ParseComplexError<E>>
1343where
1344 F: Fn(&str) -> Result<T, E>,
1345 T: Clone + Num,
1346{
1347 let imag = match s.rfind('j') {
1348 None => 'i',
1349 _ => 'j',
1350 };
1351
1352 let mut neg_b = false;
1353 let mut a = s;
1354 let mut b = "";
1355
1356 for (i, w) in s.as_bytes().windows(2).enumerate() {
1357 let p = w[0];
1358 let c = w[1];
1359
1360 if (c == b'+' || c == b'-') && !(p == b'e' || p == b'E') {
1362 a = &s[..=i].trim_right_matches(char::is_whitespace);
1364 b = &s[i + 2..].trim_left_matches(char::is_whitespace);
1365 neg_b = c == b'-';
1366
1367 if b.is_empty() || (neg_b && b.starts_with('-')) {
1368 return Err(ParseComplexError::expr_error());
1369 }
1370 break;
1371 }
1372 }
1373
1374 if b.is_empty() {
1376 b = if a.ends_with(imag) { "0" } else { "0i" };
1378 }
1379
1380 let re;
1381 let neg_re;
1382 let im;
1383 let neg_im;
1384 if a.ends_with(imag) {
1385 im = a;
1386 neg_im = false;
1387 re = b;
1388 neg_re = neg_b;
1389 } else if b.ends_with(imag) {
1390 re = a;
1391 neg_re = false;
1392 im = b;
1393 neg_im = neg_b;
1394 } else {
1395 return Err(ParseComplexError::expr_error());
1396 }
1397
1398 let re = from(re).map_err(ParseComplexError::from_error)?;
1400 let re = if neg_re { T::zero() - re } else { re };
1401
1402 let mut im = &im[..im.len() - 1];
1404 if im.is_empty() || im == "+" {
1406 im = "1";
1407 } else if im == "-" {
1408 im = "-1";
1409 }
1410
1411 let im = from(im).map_err(ParseComplexError::from_error)?;
1413 let im = if neg_im { T::zero() - im } else { im };
1414
1415 Ok(Complex::new(re, im))
1416}
1417
1418impl<T> FromStr for Complex<T>
1419where
1420 T: FromStr + Num + Clone,
1421{
1422 type Err = ParseComplexError<T::Err>;
1423
1424 fn from_str(s: &str) -> Result<Self, Self::Err> {
1426 from_str_generic(s, T::from_str)
1427 }
1428}
1429
1430impl<T: Num + Clone> Num for Complex<T> {
1431 type FromStrRadixErr = ParseComplexError<T::FromStrRadixErr>;
1432
1433 fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
1443 assert!(
1444 radix <= 36,
1445 "from_str_radix: radix is too high (maximum 36)"
1446 );
1447
1448 if radix > 18 {
1450 return Err(ParseComplexError::unsupported_radix());
1451 }
1452
1453 from_str_generic(s, |x| -> Result<T, T::FromStrRadixErr> {
1454 T::from_str_radix(x, radix)
1455 })
1456 }
1457}
1458
1459impl<T: Num + Clone> Sum for Complex<T> {
1460 fn sum<I>(iter: I) -> Self
1461 where
1462 I: Iterator<Item = Self>,
1463 {
1464 iter.fold(Self::zero(), |acc, c| acc + c)
1465 }
1466}
1467
1468impl<'a, T: 'a + Num + Clone> Sum<&'a Complex<T>> for Complex<T> {
1469 fn sum<I>(iter: I) -> Self
1470 where
1471 I: Iterator<Item = &'a Complex<T>>,
1472 {
1473 iter.fold(Self::zero(), |acc, c| acc + c)
1474 }
1475}
1476
1477impl<T: Num + Clone> Product for Complex<T> {
1478 fn product<I>(iter: I) -> Self
1479 where
1480 I: Iterator<Item = Self>,
1481 {
1482 iter.fold(Self::one(), |acc, c| acc * c)
1483 }
1484}
1485
1486impl<'a, T: 'a + Num + Clone> Product<&'a Complex<T>> for Complex<T> {
1487 fn product<I>(iter: I) -> Self
1488 where
1489 I: Iterator<Item = &'a Complex<T>>,
1490 {
1491 iter.fold(Self::one(), |acc, c| acc * c)
1492 }
1493}
1494
1495#[cfg(feature = "serde")]
1496impl<T> serde::Serialize for Complex<T>
1497where
1498 T: serde::Serialize,
1499{
1500 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1501 where
1502 S: serde::Serializer,
1503 {
1504 (&self.re, &self.im).serialize(serializer)
1505 }
1506}
1507
1508#[cfg(feature = "serde")]
1509impl<'de, T> serde::Deserialize<'de> for Complex<T>
1510where
1511 T: serde::Deserialize<'de>,
1512{
1513 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1514 where
1515 D: serde::Deserializer<'de>,
1516 {
1517 let (re, im) = serde::Deserialize::deserialize(deserializer)?;
1518 Ok(Self::new(re, im))
1519 }
1520}
1521
1522#[derive(Debug, PartialEq)]
1523pub struct ParseComplexError<E> {
1524 kind: ComplexErrorKind<E>,
1525}
1526
1527#[derive(Debug, PartialEq)]
1528enum ComplexErrorKind<E> {
1529 ParseError(E),
1530 ExprError,
1531 UnsupportedRadix,
1532}
1533
1534impl<E> ParseComplexError<E> {
1535 fn expr_error() -> Self {
1536 ParseComplexError {
1537 kind: ComplexErrorKind::ExprError,
1538 }
1539 }
1540
1541 fn unsupported_radix() -> Self {
1542 ParseComplexError {
1543 kind: ComplexErrorKind::UnsupportedRadix,
1544 }
1545 }
1546
1547 fn from_error(error: E) -> Self {
1548 ParseComplexError {
1549 kind: ComplexErrorKind::ParseError(error),
1550 }
1551 }
1552}
1553
1554#[cfg(feature = "std")]
1555impl<E: Error> Error for ParseComplexError<E> {
1556 #[allow(deprecated)]
1557 fn description(&self) -> &str {
1558 match self.kind {
1559 ComplexErrorKind::ParseError(ref e) => e.description(),
1560 ComplexErrorKind::ExprError => "invalid or unsupported complex expression",
1561 ComplexErrorKind::UnsupportedRadix => "unsupported radix for conversion",
1562 }
1563 }
1564}
1565
1566impl<E: fmt::Display> fmt::Display for ParseComplexError<E> {
1567 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1568 match self.kind {
1569 ComplexErrorKind::ParseError(ref e) => e.fmt(f),
1570 ComplexErrorKind::ExprError => "invalid or unsupported complex expression".fmt(f),
1571 ComplexErrorKind::UnsupportedRadix => "unsupported radix for conversion".fmt(f),
1572 }
1573 }
1574}
1575
1576#[cfg(test)]
1577fn hash<T: hash::Hash>(x: &T) -> u64 {
1578 use std::collections::hash_map::RandomState;
1579 use std::hash::{BuildHasher, Hasher};
1580 let mut hasher = <RandomState as BuildHasher>::Hasher::new();
1581 x.hash(&mut hasher);
1582 hasher.finish()
1583}
1584
1585#[cfg(test)]
1586pub(crate) mod test {
1587 #![allow(non_upper_case_globals)]
1588
1589 use super::{Complex, Complex64};
1590 use super::{ComplexErrorKind, ParseComplexError};
1591 use core::f64;
1592 use core::str::FromStr;
1593
1594 use std::string::{String, ToString};
1595
1596 use num_traits::{Num, One, Zero};
1597
1598 pub const _0_0i: Complex64 = Complex::new(0.0, 0.0);
1599 pub const _1_0i: Complex64 = Complex::new(1.0, 0.0);
1600 pub const _1_1i: Complex64 = Complex::new(1.0, 1.0);
1601 pub const _0_1i: Complex64 = Complex::new(0.0, 1.0);
1602 pub const _neg1_1i: Complex64 = Complex::new(-1.0, 1.0);
1603 pub const _05_05i: Complex64 = Complex::new(0.5, 0.5);
1604 pub const all_consts: [Complex64; 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i];
1605 pub const _4_2i: Complex64 = Complex::new(4.0, 2.0);
1606 pub const _1_infi: Complex64 = Complex::new(1.0, f64::INFINITY);
1607 pub const _neg1_infi: Complex64 = Complex::new(-1.0, f64::INFINITY);
1608 pub const _1_nani: Complex64 = Complex::new(1.0, f64::NAN);
1609 pub const _neg1_nani: Complex64 = Complex::new(-1.0, f64::NAN);
1610 pub const _inf_0i: Complex64 = Complex::new(f64::INFINITY, 0.0);
1611 pub const _neginf_1i: Complex64 = Complex::new(f64::NEG_INFINITY, 1.0);
1612 pub const _neginf_neg1i: Complex64 = Complex::new(f64::NEG_INFINITY, -1.0);
1613 pub const _inf_1i: Complex64 = Complex::new(f64::INFINITY, 1.0);
1614 pub const _inf_neg1i: Complex64 = Complex::new(f64::INFINITY, -1.0);
1615 pub const _neginf_infi: Complex64 = Complex::new(f64::NEG_INFINITY, f64::INFINITY);
1616 pub const _inf_infi: Complex64 = Complex::new(f64::INFINITY, f64::INFINITY);
1617 pub const _neginf_nani: Complex64 = Complex::new(f64::NEG_INFINITY, f64::NAN);
1618 pub const _inf_nani: Complex64 = Complex::new(f64::INFINITY, f64::NAN);
1619 pub const _nan_0i: Complex64 = Complex::new(f64::NAN, 0.0);
1620 pub const _nan_1i: Complex64 = Complex::new(f64::NAN, 1.0);
1621 pub const _nan_neg1i: Complex64 = Complex::new(f64::NAN, -1.0);
1622 pub const _nan_nani: Complex64 = Complex::new(f64::NAN, f64::NAN);
1623
1624 #[test]
1625 fn test_consts() {
1626 fn test(c: Complex64, r: f64, i: f64) {
1628 assert_eq!(c, Complex::new(r, i));
1629 }
1630 test(_0_0i, 0.0, 0.0);
1631 test(_1_0i, 1.0, 0.0);
1632 test(_1_1i, 1.0, 1.0);
1633 test(_neg1_1i, -1.0, 1.0);
1634 test(_05_05i, 0.5, 0.5);
1635
1636 assert_eq!(_0_0i, Zero::zero());
1637 assert_eq!(_1_0i, One::one());
1638 }
1639
1640 #[test]
1641 fn test_scale_unscale() {
1642 assert_eq!(_05_05i.scale(2.0), _1_1i);
1643 assert_eq!(_1_1i.unscale(2.0), _05_05i);
1644 for &c in all_consts.iter() {
1645 assert_eq!(c.scale(2.0).unscale(2.0), c);
1646 }
1647 }
1648
1649 #[test]
1650 fn test_conj() {
1651 for &c in all_consts.iter() {
1652 assert_eq!(c.conj(), Complex::new(c.re, -c.im));
1653 assert_eq!(c.conj().conj(), c);
1654 }
1655 }
1656
1657 #[test]
1658 fn test_inv() {
1659 assert_eq!(_1_1i.inv(), _05_05i.conj());
1660 assert_eq!(_1_0i.inv(), _1_0i.inv());
1661 }
1662
1663 #[test]
1664 #[should_panic]
1665 fn test_divide_by_zero_natural() {
1666 let n = Complex::new(2, 3);
1667 let d = Complex::new(0, 0);
1668 let _x = n / d;
1669 }
1670
1671 #[test]
1672 fn test_inv_zero() {
1673 assert!(_0_0i.inv().is_nan());
1675 }
1676
1677 #[test]
1678 #[allow(clippy::float_cmp)]
1679 fn test_l1_norm() {
1680 assert_eq!(_0_0i.l1_norm(), 0.0);
1681 assert_eq!(_1_0i.l1_norm(), 1.0);
1682 assert_eq!(_1_1i.l1_norm(), 2.0);
1683 assert_eq!(_0_1i.l1_norm(), 1.0);
1684 assert_eq!(_neg1_1i.l1_norm(), 2.0);
1685 assert_eq!(_05_05i.l1_norm(), 1.0);
1686 assert_eq!(_4_2i.l1_norm(), 6.0);
1687 }
1688
1689 #[test]
1690 fn test_pow() {
1691 for c in all_consts.iter() {
1692 assert_eq!(c.powi(0), _1_0i);
1693 let mut pos = _1_0i;
1694 let mut neg = _1_0i;
1695 for i in 1i32..20 {
1696 pos *= c;
1697 assert_eq!(pos, c.powi(i));
1698 if c.is_zero() {
1699 assert!(c.powi(-i).is_nan());
1700 } else {
1701 neg /= c;
1702 assert_eq!(neg, c.powi(-i));
1703 }
1704 }
1705 }
1706 }
1707
1708 #[cfg(any(feature = "std", feature = "libm"))]
1709 pub(crate) mod float {
1710
1711 use core::f64::INFINITY;
1712
1713 use super::*;
1714 use num_traits::{Float, Pow};
1715
1716 #[test]
1717 fn test_cis() {
1718 assert!(close(Complex::cis(0.0 * f64::consts::PI), _1_0i));
1719 assert!(close(Complex::cis(0.5 * f64::consts::PI), _0_1i));
1720 assert!(close(Complex::cis(1.0 * f64::consts::PI), -_1_0i));
1721 assert!(close(Complex::cis(1.5 * f64::consts::PI), -_0_1i));
1722 assert!(close(Complex::cis(2.0 * f64::consts::PI), _1_0i));
1723 }
1724
1725 #[test]
1726 #[cfg_attr(target_arch = "x86", ignore)]
1727 #[allow(clippy::float_cmp)]
1729 fn test_norm() {
1730 fn test(c: Complex64, ns: f64) {
1731 assert_eq!(c.norm_sqr(), ns);
1732 assert_eq!(c.norm(), ns.sqrt())
1733 }
1734 test(_0_0i, 0.0);
1735 test(_1_0i, 1.0);
1736 test(_1_1i, 2.0);
1737 test(_neg1_1i, 2.0);
1738 test(_05_05i, 0.5);
1739 }
1740
1741 #[test]
1742 fn test_arg() {
1743 fn test(c: Complex64, arg: f64) {
1744 assert!((c.arg() - arg).abs() < 1.0e-6)
1745 }
1746 test(_1_0i, 0.0);
1747 test(_1_1i, 0.25 * f64::consts::PI);
1748 test(_neg1_1i, 0.75 * f64::consts::PI);
1749 test(_05_05i, 0.25 * f64::consts::PI);
1750 }
1751
1752 #[test]
1753 fn test_polar_conv() {
1754 fn test(c: Complex64) {
1755 let (r, theta) = c.to_polar();
1756 assert!((c - Complex::from_polar(r, theta)).norm() < 1e-6);
1757 }
1758 for &c in all_consts.iter() {
1759 test(c);
1760 }
1761 }
1762
1763 pub(crate) fn close(a: Complex64, b: Complex64) -> bool {
1764 close_to_tol(a, b, 1e-10)
1765 }
1766
1767 fn close_to_tol(a: Complex64, b: Complex64, tol: f64) -> bool {
1768 let close = (a == b) || (a - b).norm() < tol;
1770 if !close {
1771 println!("{:?} != {:?}", a, b);
1772 }
1773 close
1774 }
1775
1776 fn close_naninf(a: Complex64, b: Complex64) -> bool {
1778 close_naninf_to_tol(a, b, 1.0e-10)
1779 }
1780
1781 fn close_naninf_to_tol(a: Complex64, b: Complex64, tol: f64) -> bool {
1782 let mut close = true;
1783
1784 if a.re.is_finite() {
1786 if b.re.is_finite() {
1787 close = (a.re == b.re) || (a.re - b.re).abs() < tol;
1788 } else {
1789 close = false;
1790 }
1791 } else if (a.re.is_nan() && !b.re.is_nan())
1792 || (a.re.is_infinite()
1793 && a.re.is_sign_positive()
1794 && !(b.re.is_infinite() && b.re.is_sign_positive()))
1795 || (a.re.is_infinite()
1796 && a.re.is_sign_negative()
1797 && !(b.re.is_infinite() && b.re.is_sign_negative()))
1798 {
1799 close = false;
1800 }
1801
1802 if a.im.is_finite() {
1804 if b.im.is_finite() {
1805 close &= (a.im == b.im) || (a.im - b.im).abs() < tol;
1806 } else {
1807 close = false;
1808 }
1809 } else if (a.im.is_nan() && !b.im.is_nan())
1810 || (a.im.is_infinite()
1811 && a.im.is_sign_positive()
1812 && !(b.im.is_infinite() && b.im.is_sign_positive()))
1813 || (a.im.is_infinite()
1814 && a.im.is_sign_negative()
1815 && !(b.im.is_infinite() && b.im.is_sign_negative()))
1816 {
1817 close = false;
1818 }
1819
1820 if close == false {
1821 println!("{:?} != {:?}", a, b);
1822 }
1823 close
1824 }
1825
1826 #[test]
1827 fn test_exp2() {
1828 assert!(close(_0_0i.exp2(), _1_0i));
1829 }
1830
1831 #[test]
1832 fn test_exp() {
1833 assert!(close(_1_0i.exp(), _1_0i.scale(f64::consts::E)));
1834 assert!(close(_0_0i.exp(), _1_0i));
1835 assert!(close(_0_1i.exp(), Complex::new(1.0.cos(), 1.0.sin())));
1836 assert!(close(_05_05i.exp() * _05_05i.exp(), _1_1i.exp()));
1837 assert!(close(
1838 _0_1i.scale(-f64::consts::PI).exp(),
1839 _1_0i.scale(-1.0)
1840 ));
1841 for &c in all_consts.iter() {
1842 assert!(close(c.conj().exp(), c.exp().conj()));
1844 assert!(close(
1846 c.exp(),
1847 (c + _0_1i.scale(f64::consts::PI * 2.0)).exp()
1848 ));
1849 }
1850
1851 assert!(close_naninf(_1_infi.exp(), _nan_nani));
1853 assert!(close_naninf(_neg1_infi.exp(), _nan_nani));
1854 assert!(close_naninf(_1_nani.exp(), _nan_nani));
1855 assert!(close_naninf(_neg1_nani.exp(), _nan_nani));
1856 assert!(close_naninf(_inf_0i.exp(), _inf_0i));
1857 assert!(close_naninf(_neginf_1i.exp(), 0.0 * Complex::cis(1.0)));
1858 assert!(close_naninf(_neginf_neg1i.exp(), 0.0 * Complex::cis(-1.0)));
1859 assert!(close_naninf(
1860 _inf_1i.exp(),
1861 f64::INFINITY * Complex::cis(1.0)
1862 ));
1863 assert!(close_naninf(
1864 _inf_neg1i.exp(),
1865 f64::INFINITY * Complex::cis(-1.0)
1866 ));
1867 assert!(close_naninf(_neginf_infi.exp(), _0_0i)); assert!(close_naninf(_inf_infi.exp(), _inf_nani)); assert!(close_naninf(_neginf_nani.exp(), _0_0i)); assert!(close_naninf(_inf_nani.exp(), _inf_nani)); assert!(close_naninf(_nan_0i.exp(), _nan_0i));
1872 assert!(close_naninf(_nan_1i.exp(), _nan_nani));
1873 assert!(close_naninf(_nan_neg1i.exp(), _nan_nani));
1874 assert!(close_naninf(_nan_nani.exp(), _nan_nani));
1875 }
1876
1877 #[test]
1878 fn test_ln() {
1879 assert!(close(_1_0i.ln(), _0_0i));
1880 assert!(close(_0_1i.ln(), _0_1i.scale(f64::consts::PI / 2.0)));
1881 assert!(close(_0_0i.ln(), Complex::new(f64::neg_infinity(), 0.0)));
1882 assert!(close(
1883 (_neg1_1i * _05_05i).ln(),
1884 _neg1_1i.ln() + _05_05i.ln()
1885 ));
1886 for &c in all_consts.iter() {
1887 assert!(close(c.conj().ln(), c.ln().conj()));
1889 assert!(-f64::consts::PI <= c.ln().arg() && c.ln().arg() <= f64::consts::PI);
1891 }
1892 }
1893
1894 #[test]
1895 fn test_powc() {
1896 let a = Complex::new(2.0, -3.0);
1897 let b = Complex::new(3.0, 0.0);
1898 assert!(close(a.powc(b), a.powf(b.re)));
1899 assert!(close(b.powc(a), a.expf(b.re)));
1900 let c = Complex::new(1.0 / 3.0, 0.1);
1901 assert!(close_to_tol(
1902 a.powc(c),
1903 Complex::new(1.65826, -0.33502),
1904 1e-5
1905 ));
1906 let z = Complex::new(0.0, 0.0);
1907 assert!(close(z.powc(b), z));
1908 assert!(z.powc(Complex64::new(0., INFINITY)).is_nan());
1909 assert!(z.powc(Complex64::new(10., INFINITY)).is_nan());
1910 assert!(z.powc(Complex64::new(INFINITY, INFINITY)).is_nan());
1911 assert!(close(z.powc(Complex64::new(INFINITY, 0.)), z));
1912 assert!(z.powc(Complex64::new(-1., 0.)).re.is_infinite());
1913 assert!(z.powc(Complex64::new(-1., 0.)).im.is_nan());
1914
1915 for c in all_consts.iter() {
1916 assert_eq!(c.powc(_0_0i), _1_0i);
1917 }
1918 assert_eq!(_nan_nani.powc(_0_0i), _1_0i);
1919 }
1920
1921 #[test]
1922 fn test_powf() {
1923 let c = Complex64::new(2.0, -1.0);
1924 let expected = Complex64::new(-0.8684746, -16.695934);
1925 assert!(close_to_tol(c.powf(3.5), expected, 1e-5));
1926 assert!(close_to_tol(Pow::pow(c, 3.5_f64), expected, 1e-5));
1927 assert!(close_to_tol(Pow::pow(c, 3.5_f32), expected, 1e-5));
1928
1929 for c in all_consts.iter() {
1930 assert_eq!(c.powf(0.0), _1_0i);
1931 }
1932 assert_eq!(_nan_nani.powf(0.0), _1_0i);
1933 }
1934
1935 #[test]
1936 fn test_log() {
1937 let c = Complex::new(2.0, -1.0);
1938 let r = c.log(10.0);
1939 assert!(close_to_tol(r, Complex::new(0.349485, -0.20135958), 1e-5));
1940 }
1941
1942 #[test]
1943 fn test_log2() {
1944 assert!(close(_1_0i.log2(), _0_0i));
1945 }
1946
1947 #[test]
1948 fn test_log10() {
1949 assert!(close(_1_0i.log10(), _0_0i));
1950 }
1951
1952 #[test]
1953 fn test_some_expf_cases() {
1954 let c = Complex::new(2.0, -1.0);
1955 let r = c.expf(10.0);
1956 assert!(close_to_tol(r, Complex::new(-66.82015, -74.39803), 1e-5));
1957
1958 let c = Complex::new(5.0, -2.0);
1959 let r = c.expf(3.4);
1960 assert!(close_to_tol(r, Complex::new(-349.25, -290.63), 1e-2));
1961
1962 let c = Complex::new(-1.5, 2.0 / 3.0);
1963 let r = c.expf(1.0 / 3.0);
1964 assert!(close_to_tol(r, Complex::new(3.8637, -3.4745), 1e-2));
1965 }
1966
1967 #[test]
1968 fn test_sqrt() {
1969 assert!(close(_0_0i.sqrt(), _0_0i));
1970 assert!(close(_1_0i.sqrt(), _1_0i));
1971 assert!(close(Complex::new(-1.0, 0.0).sqrt(), _0_1i));
1972 assert!(close(Complex::new(-1.0, -0.0).sqrt(), _0_1i.scale(-1.0)));
1973 assert!(close(_0_1i.sqrt(), _05_05i.scale(2.0.sqrt())));
1974 for &c in all_consts.iter() {
1975 assert!(close(c.conj().sqrt(), c.sqrt().conj()));
1977 assert!(
1979 -f64::consts::FRAC_PI_2 <= c.sqrt().arg()
1980 && c.sqrt().arg() <= f64::consts::FRAC_PI_2
1981 );
1982 assert!(close(c.sqrt() * c.sqrt(), c));
1984 }
1985 }
1986
1987 #[test]
1988 fn test_sqrt_real() {
1989 for n in (0..100).map(f64::from) {
1990 let n2 = n * n;
1992 assert_eq!(Complex64::new(n2, 0.0).sqrt(), Complex64::new(n, 0.0));
1993 assert_eq!(Complex64::new(-n2, 0.0).sqrt(), Complex64::new(0.0, n));
1995 assert_eq!(Complex64::new(-n2, -0.0).sqrt(), Complex64::new(0.0, -n));
1997 }
1998 }
1999
2000 #[test]
2001 fn test_sqrt_imag() {
2002 for n in (0..100).map(f64::from) {
2003 let n2 = n * n;
2005 assert!(close(
2006 Complex64::new(0.0, n2).sqrt(),
2007 Complex64::from_polar(n, f64::consts::FRAC_PI_4)
2008 ));
2009 assert!(close(
2011 Complex64::new(0.0, -n2).sqrt(),
2012 Complex64::from_polar(n, -f64::consts::FRAC_PI_4)
2013 ));
2014 }
2015 }
2016
2017 #[test]
2018 fn test_cbrt() {
2019 assert!(close(_0_0i.cbrt(), _0_0i));
2020 assert!(close(_1_0i.cbrt(), _1_0i));
2021 assert!(close(
2022 Complex::new(-1.0, 0.0).cbrt(),
2023 Complex::new(0.5, 0.75.sqrt())
2024 ));
2025 assert!(close(
2026 Complex::new(-1.0, -0.0).cbrt(),
2027 Complex::new(0.5, -(0.75.sqrt()))
2028 ));
2029 assert!(close(_0_1i.cbrt(), Complex::new(0.75.sqrt(), 0.5)));
2030 assert!(close(_0_1i.conj().cbrt(), Complex::new(0.75.sqrt(), -0.5)));
2031 for &c in all_consts.iter() {
2032 assert!(close(c.conj().cbrt(), c.cbrt().conj()));
2034 assert!(
2036 -f64::consts::FRAC_PI_3 <= c.cbrt().arg()
2037 && c.cbrt().arg() <= f64::consts::FRAC_PI_3
2038 );
2039 assert!(close(c.cbrt() * c.cbrt() * c.cbrt(), c));
2041 }
2042 }
2043
2044 #[test]
2045 fn test_cbrt_real() {
2046 for n in (0..100).map(f64::from) {
2047 let n3 = n * n * n;
2049 assert!(close(
2050 Complex64::new(n3, 0.0).cbrt(),
2051 Complex64::new(n, 0.0)
2052 ));
2053 assert!(close(
2055 Complex64::new(-n3, 0.0).cbrt(),
2056 Complex64::from_polar(n, f64::consts::FRAC_PI_3)
2057 ));
2058 assert!(close(
2060 Complex64::new(-n3, -0.0).cbrt(),
2061 Complex64::from_polar(n, -f64::consts::FRAC_PI_3)
2062 ));
2063 }
2064 }
2065
2066 #[test]
2067 fn test_cbrt_imag() {
2068 for n in (0..100).map(f64::from) {
2069 let n3 = n * n * n;
2071 assert!(close(
2072 Complex64::new(0.0, n3).cbrt(),
2073 Complex64::from_polar(n, f64::consts::FRAC_PI_6)
2074 ));
2075 assert!(close(
2077 Complex64::new(0.0, -n3).cbrt(),
2078 Complex64::from_polar(n, -f64::consts::FRAC_PI_6)
2079 ));
2080 }
2081 }
2082
2083 #[test]
2084 fn test_sin() {
2085 assert!(close(_0_0i.sin(), _0_0i));
2086 assert!(close(_1_0i.scale(f64::consts::PI * 2.0).sin(), _0_0i));
2087 assert!(close(_0_1i.sin(), _0_1i.scale(1.0.sinh())));
2088 for &c in all_consts.iter() {
2089 assert!(close(c.conj().sin(), c.sin().conj()));
2091 assert!(close(c.scale(-1.0).sin(), c.sin().scale(-1.0)));
2093 }
2094 }
2095
2096 #[test]
2097 fn test_cos() {
2098 assert!(close(_0_0i.cos(), _1_0i));
2099 assert!(close(_1_0i.scale(f64::consts::PI * 2.0).cos(), _1_0i));
2100 assert!(close(_0_1i.cos(), _1_0i.scale(1.0.cosh())));
2101 for &c in all_consts.iter() {
2102 assert!(close(c.conj().cos(), c.cos().conj()));
2104 assert!(close(c.scale(-1.0).cos(), c.cos()));
2106 }
2107 }
2108
2109 #[test]
2110 fn test_tan() {
2111 assert!(close(_0_0i.tan(), _0_0i));
2112 assert!(close(_1_0i.scale(f64::consts::PI / 4.0).tan(), _1_0i));
2113 assert!(close(_1_0i.scale(f64::consts::PI).tan(), _0_0i));
2114 for &c in all_consts.iter() {
2115 assert!(close(c.conj().tan(), c.tan().conj()));
2117 assert!(close(c.scale(-1.0).tan(), c.tan().scale(-1.0)));
2119 }
2120 }
2121
2122 #[test]
2123 fn test_asin() {
2124 assert!(close(_0_0i.asin(), _0_0i));
2125 assert!(close(_1_0i.asin(), _1_0i.scale(f64::consts::PI / 2.0)));
2126 assert!(close(
2127 _1_0i.scale(-1.0).asin(),
2128 _1_0i.scale(-f64::consts::PI / 2.0)
2129 ));
2130 assert!(close(_0_1i.asin(), _0_1i.scale((1.0 + 2.0.sqrt()).ln())));
2131 for &c in all_consts.iter() {
2132 assert!(close(c.conj().asin(), c.asin().conj()));
2134 assert!(close(c.scale(-1.0).asin(), c.asin().scale(-1.0)));
2136 assert!(
2138 -f64::consts::PI / 2.0 <= c.asin().re && c.asin().re <= f64::consts::PI / 2.0
2139 );
2140 }
2141 }
2142
2143 #[test]
2144 fn test_acos() {
2145 assert!(close(_0_0i.acos(), _1_0i.scale(f64::consts::PI / 2.0)));
2146 assert!(close(_1_0i.acos(), _0_0i));
2147 assert!(close(
2148 _1_0i.scale(-1.0).acos(),
2149 _1_0i.scale(f64::consts::PI)
2150 ));
2151 assert!(close(
2152 _0_1i.acos(),
2153 Complex::new(f64::consts::PI / 2.0, (2.0.sqrt() - 1.0).ln())
2154 ));
2155 for &c in all_consts.iter() {
2156 assert!(close(c.conj().acos(), c.acos().conj()));
2158 assert!(0.0 <= c.acos().re && c.acos().re <= f64::consts::PI);
2160 }
2161 }
2162
2163 #[test]
2164 fn test_atan() {
2165 assert!(close(_0_0i.atan(), _0_0i));
2166 assert!(close(_1_0i.atan(), _1_0i.scale(f64::consts::PI / 4.0)));
2167 assert!(close(
2168 _1_0i.scale(-1.0).atan(),
2169 _1_0i.scale(-f64::consts::PI / 4.0)
2170 ));
2171 assert!(close(_0_1i.atan(), Complex::new(0.0, f64::infinity())));
2172 for &c in all_consts.iter() {
2173 assert!(close(c.conj().atan(), c.atan().conj()));
2175 assert!(close(c.scale(-1.0).atan(), c.atan().scale(-1.0)));
2177 assert!(
2179 -f64::consts::PI / 2.0 <= c.atan().re && c.atan().re <= f64::consts::PI / 2.0
2180 );
2181 }
2182 }
2183
2184 #[test]
2185 fn test_sinh() {
2186 assert!(close(_0_0i.sinh(), _0_0i));
2187 assert!(close(
2188 _1_0i.sinh(),
2189 _1_0i.scale((f64::consts::E - 1.0 / f64::consts::E) / 2.0)
2190 ));
2191 assert!(close(_0_1i.sinh(), _0_1i.scale(1.0.sin())));
2192 for &c in all_consts.iter() {
2193 assert!(close(c.conj().sinh(), c.sinh().conj()));
2195 assert!(close(c.scale(-1.0).sinh(), c.sinh().scale(-1.0)));
2197 }
2198 }
2199
2200 #[test]
2201 fn test_cosh() {
2202 assert!(close(_0_0i.cosh(), _1_0i));
2203 assert!(close(
2204 _1_0i.cosh(),
2205 _1_0i.scale((f64::consts::E + 1.0 / f64::consts::E) / 2.0)
2206 ));
2207 assert!(close(_0_1i.cosh(), _1_0i.scale(1.0.cos())));
2208 for &c in all_consts.iter() {
2209 assert!(close(c.conj().cosh(), c.cosh().conj()));
2211 assert!(close(c.scale(-1.0).cosh(), c.cosh()));
2213 }
2214 }
2215
2216 #[test]
2217 fn test_tanh() {
2218 assert!(close(_0_0i.tanh(), _0_0i));
2219 assert!(close(
2220 _1_0i.tanh(),
2221 _1_0i.scale((f64::consts::E.powi(2) - 1.0) / (f64::consts::E.powi(2) + 1.0))
2222 ));
2223 assert!(close(_0_1i.tanh(), _0_1i.scale(1.0.tan())));
2224 for &c in all_consts.iter() {
2225 assert!(close(c.conj().tanh(), c.conj().tanh()));
2227 assert!(close(c.scale(-1.0).tanh(), c.tanh().scale(-1.0)));
2229 }
2230 }
2231
2232 #[test]
2233 fn test_asinh() {
2234 assert!(close(_0_0i.asinh(), _0_0i));
2235 assert!(close(_1_0i.asinh(), _1_0i.scale(1.0 + 2.0.sqrt()).ln()));
2236 assert!(close(_0_1i.asinh(), _0_1i.scale(f64::consts::PI / 2.0)));
2237 assert!(close(
2238 _0_1i.asinh().scale(-1.0),
2239 _0_1i.scale(-f64::consts::PI / 2.0)
2240 ));
2241 for &c in all_consts.iter() {
2242 assert!(close(c.conj().asinh(), c.conj().asinh()));
2244 assert!(close(c.scale(-1.0).asinh(), c.asinh().scale(-1.0)));
2246 assert!(
2248 -f64::consts::PI / 2.0 <= c.asinh().im && c.asinh().im <= f64::consts::PI / 2.0
2249 );
2250 }
2251 }
2252
2253 #[test]
2254 fn test_acosh() {
2255 assert!(close(_0_0i.acosh(), _0_1i.scale(f64::consts::PI / 2.0)));
2256 assert!(close(_1_0i.acosh(), _0_0i));
2257 assert!(close(
2258 _1_0i.scale(-1.0).acosh(),
2259 _0_1i.scale(f64::consts::PI)
2260 ));
2261 for &c in all_consts.iter() {
2262 assert!(close(c.conj().acosh(), c.conj().acosh()));
2264 assert!(
2266 -f64::consts::PI <= c.acosh().im
2267 && c.acosh().im <= f64::consts::PI
2268 && 0.0 <= c.cosh().re
2269 );
2270 }
2271 }
2272
2273 #[test]
2274 fn test_atanh() {
2275 assert!(close(_0_0i.atanh(), _0_0i));
2276 assert!(close(_0_1i.atanh(), _0_1i.scale(f64::consts::PI / 4.0)));
2277 assert!(close(_1_0i.atanh(), Complex::new(f64::infinity(), 0.0)));
2278 for &c in all_consts.iter() {
2279 assert!(close(c.conj().atanh(), c.conj().atanh()));
2281 assert!(close(c.scale(-1.0).atanh(), c.atanh().scale(-1.0)));
2283 assert!(
2285 -f64::consts::PI / 2.0 <= c.atanh().im && c.atanh().im <= f64::consts::PI / 2.0
2286 );
2287 }
2288 }
2289
2290 #[test]
2291 fn test_exp_ln() {
2292 for &c in all_consts.iter() {
2293 assert!(close(c.ln().exp(), c));
2295 }
2296 }
2297
2298 #[test]
2299 fn test_exp2_log() {
2300 for &c in all_consts.iter() {
2301 assert!(close(c.log2().exp2(), c));
2303 }
2304 }
2305
2306 #[test]
2307 fn test_trig_to_hyperbolic() {
2308 for &c in all_consts.iter() {
2309 assert!(close((_0_1i * c).sin(), _0_1i * c.sinh()));
2311 assert!(close((_0_1i * c).cos(), c.cosh()));
2313 assert!(close((_0_1i * c).tan(), _0_1i * c.tanh()));
2315 }
2316 }
2317
2318 #[test]
2319 fn test_trig_identities() {
2320 for &c in all_consts.iter() {
2321 assert!(close(c.tan(), c.sin() / c.cos()));
2323 assert!(close(c.sin() * c.sin() + c.cos() * c.cos(), _1_0i));
2325
2326 assert!(close(c.asin().sin(), c));
2328 assert!(close(c.acos().cos(), c));
2330 if c != _0_1i && c != _0_1i.scale(-1.0) {
2333 assert!(close(c.atan().tan(), c));
2334 }
2335
2336 assert!(close(
2338 ((_0_1i * c).exp() - (_0_1i * c).exp().inv()) / _0_1i.scale(2.0),
2339 c.sin()
2340 ));
2341 assert!(close(
2343 ((_0_1i * c).exp() + (_0_1i * c).exp().inv()).unscale(2.0),
2344 c.cos()
2345 ));
2346 assert!(close(
2348 _0_1i * (_1_0i - (_0_1i * c).scale(2.0).exp())
2349 / (_1_0i + (_0_1i * c).scale(2.0).exp()),
2350 c.tan()
2351 ));
2352 }
2353 }
2354
2355 #[test]
2356 fn test_hyperbolic_identites() {
2357 for &c in all_consts.iter() {
2358 assert!(close(c.tanh(), c.sinh() / c.cosh()));
2360 assert!(close(c.cosh() * c.cosh() - c.sinh() * c.sinh(), _1_0i));
2362
2363 assert!(close(c.asinh().sinh(), c));
2365 assert!(close(c.acosh().cosh(), c));
2367 if c != _1_0i && c != _1_0i.scale(-1.0) {
2370 assert!(close(c.atanh().tanh(), c));
2371 }
2372
2373 assert!(close((c.exp() - c.exp().inv()).unscale(2.0), c.sinh()));
2375 assert!(close((c.exp() + c.exp().inv()).unscale(2.0), c.cosh()));
2377 assert!(close(
2379 (c.scale(2.0).exp() - _1_0i) / (c.scale(2.0).exp() + _1_0i),
2380 c.tanh()
2381 ));
2382 }
2383 }
2384 }
2385
2386 macro_rules! test_a_op_b {
2388 ($a:ident + $b:expr, $answer:expr) => {
2389 assert_eq!($a + $b, $answer);
2390 assert_eq!(
2391 {
2392 let mut x = $a;
2393 x += $b;
2394 x
2395 },
2396 $answer
2397 );
2398 };
2399 ($a:ident - $b:expr, $answer:expr) => {
2400 assert_eq!($a - $b, $answer);
2401 assert_eq!(
2402 {
2403 let mut x = $a;
2404 x -= $b;
2405 x
2406 },
2407 $answer
2408 );
2409 };
2410 ($a:ident * $b:expr, $answer:expr) => {
2411 assert_eq!($a * $b, $answer);
2412 assert_eq!(
2413 {
2414 let mut x = $a;
2415 x *= $b;
2416 x
2417 },
2418 $answer
2419 );
2420 };
2421 ($a:ident / $b:expr, $answer:expr) => {
2422 assert_eq!($a / $b, $answer);
2423 assert_eq!(
2424 {
2425 let mut x = $a;
2426 x /= $b;
2427 x
2428 },
2429 $answer
2430 );
2431 };
2432 ($a:ident % $b:expr, $answer:expr) => {
2433 assert_eq!($a % $b, $answer);
2434 assert_eq!(
2435 {
2436 let mut x = $a;
2437 x %= $b;
2438 x
2439 },
2440 $answer
2441 );
2442 };
2443 }
2444
2445 macro_rules! test_op {
2447 ($a:ident $op:tt $b:expr, $answer:expr) => {
2448 test_a_op_b!($a $op $b, $answer);
2449 test_a_op_b!($a $op &$b, $answer);
2450 };
2451 }
2452
2453 mod complex_arithmetic {
2454 use super::{_05_05i, _0_0i, _0_1i, _1_0i, _1_1i, _4_2i, _neg1_1i, all_consts};
2455 use num_traits::{MulAdd, MulAddAssign, Zero};
2456
2457 #[test]
2458 fn test_add() {
2459 test_op!(_05_05i + _05_05i, _1_1i);
2460 test_op!(_0_1i + _1_0i, _1_1i);
2461 test_op!(_1_0i + _neg1_1i, _0_1i);
2462
2463 for &c in all_consts.iter() {
2464 test_op!(_0_0i + c, c);
2465 test_op!(c + _0_0i, c);
2466 }
2467 }
2468
2469 #[test]
2470 fn test_sub() {
2471 test_op!(_05_05i - _05_05i, _0_0i);
2472 test_op!(_0_1i - _1_0i, _neg1_1i);
2473 test_op!(_0_1i - _neg1_1i, _1_0i);
2474
2475 for &c in all_consts.iter() {
2476 test_op!(c - _0_0i, c);
2477 test_op!(c - c, _0_0i);
2478 }
2479 }
2480
2481 #[test]
2482 fn test_mul() {
2483 test_op!(_05_05i * _05_05i, _0_1i.unscale(2.0));
2484 test_op!(_1_1i * _0_1i, _neg1_1i);
2485
2486 test_op!(_0_1i * _0_1i, -_1_0i);
2488 assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i);
2489
2490 for &c in all_consts.iter() {
2491 test_op!(c * _1_0i, c);
2492 test_op!(_1_0i * c, c);
2493 }
2494 }
2495
2496 #[test]
2497 #[cfg(any(feature = "std", feature = "libm"))]
2498 fn test_mul_add_float() {
2499 assert_eq!(_05_05i.mul_add(_05_05i, _0_0i), _05_05i * _05_05i + _0_0i);
2500 assert_eq!(_05_05i * _05_05i + _0_0i, _05_05i.mul_add(_05_05i, _0_0i));
2501 assert_eq!(_0_1i.mul_add(_0_1i, _0_1i), _neg1_1i);
2502 assert_eq!(_1_0i.mul_add(_1_0i, _1_0i), _1_0i * _1_0i + _1_0i);
2503 assert_eq!(_1_0i * _1_0i + _1_0i, _1_0i.mul_add(_1_0i, _1_0i));
2504
2505 let mut x = _1_0i;
2506 x.mul_add_assign(_1_0i, _1_0i);
2507 assert_eq!(x, _1_0i * _1_0i + _1_0i);
2508
2509 for &a in &all_consts {
2510 for &b in &all_consts {
2511 for &c in &all_consts {
2512 let abc = a * b + c;
2513 assert_eq!(a.mul_add(b, c), abc);
2514 let mut x = a;
2515 x.mul_add_assign(b, c);
2516 assert_eq!(x, abc);
2517 }
2518 }
2519 }
2520 }
2521
2522 #[test]
2523 fn test_mul_add() {
2524 use super::Complex;
2525 const _0_0i: Complex<i32> = Complex { re: 0, im: 0 };
2526 const _1_0i: Complex<i32> = Complex { re: 1, im: 0 };
2527 const _1_1i: Complex<i32> = Complex { re: 1, im: 1 };
2528 const _0_1i: Complex<i32> = Complex { re: 0, im: 1 };
2529 const _neg1_1i: Complex<i32> = Complex { re: -1, im: 1 };
2530 const all_consts: [Complex<i32>; 5] = [_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i];
2531
2532 assert_eq!(_1_0i.mul_add(_1_0i, _0_0i), _1_0i * _1_0i + _0_0i);
2533 assert_eq!(_1_0i * _1_0i + _0_0i, _1_0i.mul_add(_1_0i, _0_0i));
2534 assert_eq!(_0_1i.mul_add(_0_1i, _0_1i), _neg1_1i);
2535 assert_eq!(_1_0i.mul_add(_1_0i, _1_0i), _1_0i * _1_0i + _1_0i);
2536 assert_eq!(_1_0i * _1_0i + _1_0i, _1_0i.mul_add(_1_0i, _1_0i));
2537
2538 let mut x = _1_0i;
2539 x.mul_add_assign(_1_0i, _1_0i);
2540 assert_eq!(x, _1_0i * _1_0i + _1_0i);
2541
2542 for &a in &all_consts {
2543 for &b in &all_consts {
2544 for &c in &all_consts {
2545 let abc = a * b + c;
2546 assert_eq!(a.mul_add(b, c), abc);
2547 let mut x = a;
2548 x.mul_add_assign(b, c);
2549 assert_eq!(x, abc);
2550 }
2551 }
2552 }
2553 }
2554
2555 #[test]
2556 fn test_div() {
2557 test_op!(_neg1_1i / _0_1i, _1_1i);
2558 for &c in all_consts.iter() {
2559 if c != Zero::zero() {
2560 test_op!(c / c, _1_0i);
2561 }
2562 }
2563 }
2564
2565 #[test]
2566 fn test_rem() {
2567 test_op!(_neg1_1i % _0_1i, _0_0i);
2568 test_op!(_4_2i % _0_1i, _0_0i);
2569 test_op!(_05_05i % _0_1i, _05_05i);
2570 test_op!(_05_05i % _1_1i, _05_05i);
2571 assert_eq!((_4_2i + _05_05i) % _0_1i, _05_05i);
2572 assert_eq!((_4_2i + _05_05i) % _1_1i, _05_05i);
2573 }
2574
2575 #[test]
2576 fn test_neg() {
2577 assert_eq!(-_1_0i + _0_1i, _neg1_1i);
2578 assert_eq!((-_0_1i) * _0_1i, _1_0i);
2579 for &c in all_consts.iter() {
2580 assert_eq!(-(-c), c);
2581 }
2582 }
2583 }
2584
2585 mod real_arithmetic {
2586 use super::super::Complex;
2587 use super::{_4_2i, _neg1_1i};
2588
2589 #[test]
2590 fn test_add() {
2591 test_op!(_4_2i + 0.5, Complex::new(4.5, 2.0));
2592 assert_eq!(0.5 + _4_2i, Complex::new(4.5, 2.0));
2593 }
2594
2595 #[test]
2596 fn test_sub() {
2597 test_op!(_4_2i - 0.5, Complex::new(3.5, 2.0));
2598 assert_eq!(0.5 - _4_2i, Complex::new(-3.5, -2.0));
2599 }
2600
2601 #[test]
2602 fn test_mul() {
2603 assert_eq!(_4_2i * 0.5, Complex::new(2.0, 1.0));
2604 assert_eq!(0.5 * _4_2i, Complex::new(2.0, 1.0));
2605 }
2606
2607 #[test]
2608 fn test_div() {
2609 assert_eq!(_4_2i / 0.5, Complex::new(8.0, 4.0));
2610 assert_eq!(0.5 / _4_2i, Complex::new(0.1, -0.05));
2611 }
2612
2613 #[test]
2614 fn test_rem() {
2615 assert_eq!(_4_2i % 2.0, Complex::new(0.0, 0.0));
2616 assert_eq!(_4_2i % 3.0, Complex::new(1.0, 2.0));
2617 assert_eq!(3.0 % _4_2i, Complex::new(3.0, 0.0));
2618 assert_eq!(_neg1_1i % 2.0, _neg1_1i);
2619 assert_eq!(-_4_2i % 3.0, Complex::new(-1.0, -2.0));
2620 }
2621
2622 #[test]
2623 fn test_div_rem_gaussian() {
2624 let max = Complex::new(255u8, 255u8);
2626 assert_eq!(max / 200, Complex::new(1, 1));
2627 assert_eq!(max % 200, Complex::new(55, 55));
2628 }
2629 }
2630
2631 #[test]
2632 fn test_to_string() {
2633 fn test(c: Complex64, s: String) {
2634 assert_eq!(c.to_string(), s);
2635 }
2636 test(_0_0i, "0+0i".to_string());
2637 test(_1_0i, "1+0i".to_string());
2638 test(_0_1i, "0+1i".to_string());
2639 test(_1_1i, "1+1i".to_string());
2640 test(_neg1_1i, "-1+1i".to_string());
2641 test(-_neg1_1i, "1-1i".to_string());
2642 test(_05_05i, "0.5+0.5i".to_string());
2643 }
2644
2645 #[test]
2646 fn test_string_formatting() {
2647 let a = Complex::new(1.23456, 123.456);
2648 assert_eq!(format!("{}", a), "1.23456+123.456i");
2649 assert_eq!(format!("{:.2}", a), "1.23+123.46i");
2650 assert_eq!(format!("{:.2e}", a), "1.23e0+1.23e2i");
2651 assert_eq!(format!("{:+.2E}", a), "+1.23E0+1.23E2i");
2652 #[cfg(feature = "std")]
2653 assert_eq!(format!("{:+20.2E}", a), " +1.23E0+1.23E2i");
2654
2655 let b = Complex::new(0x80, 0xff);
2656 assert_eq!(format!("{:X}", b), "80+FFi");
2657 assert_eq!(format!("{:#x}", b), "0x80+0xffi");
2658 assert_eq!(format!("{:+#b}", b), "+0b10000000+0b11111111i");
2659 assert_eq!(format!("{:+#o}", b), "+0o200+0o377i");
2660 #[cfg(feature = "std")]
2661 assert_eq!(format!("{:+#16o}", b), " +0o200+0o377i");
2662
2663 let c = Complex::new(-10, -10000);
2664 assert_eq!(format!("{}", c), "-10-10000i");
2665 #[cfg(feature = "std")]
2666 assert_eq!(format!("{:16}", c), " -10-10000i");
2667 }
2668
2669 #[test]
2670 fn test_hash() {
2671 let a = Complex::new(0i32, 0i32);
2672 let b = Complex::new(1i32, 0i32);
2673 let c = Complex::new(0i32, 1i32);
2674 assert!(crate::hash(&a) != crate::hash(&b));
2675 assert!(crate::hash(&b) != crate::hash(&c));
2676 assert!(crate::hash(&c) != crate::hash(&a));
2677 }
2678
2679 #[test]
2680 fn test_hashset() {
2681 use std::collections::HashSet;
2682 let a = Complex::new(0i32, 0i32);
2683 let b = Complex::new(1i32, 0i32);
2684 let c = Complex::new(0i32, 1i32);
2685
2686 let set: HashSet<_> = [a, b, c].iter().cloned().collect();
2687 assert!(set.contains(&a));
2688 assert!(set.contains(&b));
2689 assert!(set.contains(&c));
2690 assert!(!set.contains(&(a + b + c)));
2691 }
2692
2693 #[test]
2694 fn test_is_nan() {
2695 assert!(!_1_1i.is_nan());
2696 let a = Complex::new(f64::NAN, f64::NAN);
2697 assert!(a.is_nan());
2698 }
2699
2700 #[test]
2701 fn test_is_nan_special_cases() {
2702 let a = Complex::new(0f64, f64::NAN);
2703 let b = Complex::new(f64::NAN, 0f64);
2704 assert!(a.is_nan());
2705 assert!(b.is_nan());
2706 }
2707
2708 #[test]
2709 fn test_is_infinite() {
2710 let a = Complex::new(2f64, f64::INFINITY);
2711 assert!(a.is_infinite());
2712 }
2713
2714 #[test]
2715 fn test_is_finite() {
2716 assert!(_1_1i.is_finite())
2717 }
2718
2719 #[test]
2720 fn test_is_normal() {
2721 let a = Complex::new(0f64, f64::NAN);
2722 let b = Complex::new(2f64, f64::INFINITY);
2723 assert!(!a.is_normal());
2724 assert!(!b.is_normal());
2725 assert!(_1_1i.is_normal());
2726 }
2727
2728 #[test]
2729 fn test_from_str() {
2730 fn test(z: Complex64, s: &str) {
2731 assert_eq!(FromStr::from_str(s), Ok(z));
2732 }
2733 test(_0_0i, "0 + 0i");
2734 test(_0_0i, "0+0j");
2735 test(_0_0i, "0 - 0j");
2736 test(_0_0i, "0-0i");
2737 test(_0_0i, "0i + 0");
2738 test(_0_0i, "0");
2739 test(_0_0i, "-0");
2740 test(_0_0i, "0i");
2741 test(_0_0i, "0j");
2742 test(_0_0i, "+0j");
2743 test(_0_0i, "-0i");
2744
2745 test(_1_0i, "1 + 0i");
2746 test(_1_0i, "1+0j");
2747 test(_1_0i, "1 - 0j");
2748 test(_1_0i, "+1-0i");
2749 test(_1_0i, "-0j+1");
2750 test(_1_0i, "1");
2751
2752 test(_1_1i, "1 + i");
2753 test(_1_1i, "1+j");
2754 test(_1_1i, "1 + 1j");
2755 test(_1_1i, "1+1i");
2756 test(_1_1i, "i + 1");
2757 test(_1_1i, "1i+1");
2758 test(_1_1i, "+j+1");
2759
2760 test(_0_1i, "0 + i");
2761 test(_0_1i, "0+j");
2762 test(_0_1i, "-0 + j");
2763 test(_0_1i, "-0+i");
2764 test(_0_1i, "0 + 1i");
2765 test(_0_1i, "0+1j");
2766 test(_0_1i, "-0 + 1j");
2767 test(_0_1i, "-0+1i");
2768 test(_0_1i, "j + 0");
2769 test(_0_1i, "i");
2770 test(_0_1i, "j");
2771 test(_0_1i, "1j");
2772
2773 test(_neg1_1i, "-1 + i");
2774 test(_neg1_1i, "-1+j");
2775 test(_neg1_1i, "-1 + 1j");
2776 test(_neg1_1i, "-1+1i");
2777 test(_neg1_1i, "1i-1");
2778 test(_neg1_1i, "j + -1");
2779
2780 test(_05_05i, "0.5 + 0.5i");
2781 test(_05_05i, "0.5+0.5j");
2782 test(_05_05i, "5e-1+0.5j");
2783 test(_05_05i, "5E-1 + 0.5j");
2784 test(_05_05i, "5E-1i + 0.5");
2785 test(_05_05i, "0.05e+1j + 50E-2");
2786 }
2787
2788 #[test]
2789 fn test_from_str_radix() {
2790 fn test(z: Complex64, s: &str, radix: u32) {
2791 let res: Result<Complex64, <Complex64 as Num>::FromStrRadixErr> =
2792 Num::from_str_radix(s, radix);
2793 assert_eq!(res.unwrap(), z)
2794 }
2795 test(_4_2i, "4+2i", 10);
2796 test(Complex::new(15.0, 32.0), "F+20i", 16);
2797 test(Complex::new(15.0, 32.0), "1111+100000i", 2);
2798 test(Complex::new(-15.0, -32.0), "-F-20i", 16);
2799 test(Complex::new(-15.0, -32.0), "-1111-100000i", 2);
2800
2801 fn test_error(s: &str, radix: u32) -> ParseComplexError<<f64 as Num>::FromStrRadixErr> {
2802 let res = Complex64::from_str_radix(s, radix);
2803
2804 res.expect_err(&format!("Expected failure on input {:?}", s))
2805 }
2806
2807 let err = test_error("1ii", 19);
2808 if let ComplexErrorKind::UnsupportedRadix = err.kind {
2809 } else {
2811 panic!("Expected failure on invalid radix, got {:?}", err);
2812 }
2813
2814 let err = test_error("1 + 0", 16);
2815 if let ComplexErrorKind::ExprError = err.kind {
2816 } else {
2818 panic!("Expected failure on expr error, got {:?}", err);
2819 }
2820 }
2821
2822 #[test]
2823 #[should_panic(expected = "radix is too high")]
2824 fn test_from_str_radix_fail() {
2825 let _complex = Complex64::from_str_radix("1", 37);
2827 }
2828
2829 #[test]
2830 fn test_from_str_fail() {
2831 fn test(s: &str) {
2832 let complex: Result<Complex64, _> = FromStr::from_str(s);
2833 assert!(
2834 complex.is_err(),
2835 "complex {:?} -> {:?} should be an error",
2836 s,
2837 complex
2838 );
2839 }
2840 test("foo");
2841 test("6E");
2842 test("0 + 2.718");
2843 test("1 - -2i");
2844 test("314e-2ij");
2845 test("4.3j - i");
2846 test("1i - 2i");
2847 test("+ 1 - 3.0i");
2848 }
2849
2850 #[test]
2851 fn test_sum() {
2852 let v = vec![_0_1i, _1_0i];
2853 assert_eq!(v.iter().sum::<Complex64>(), _1_1i);
2854 assert_eq!(v.into_iter().sum::<Complex64>(), _1_1i);
2855 }
2856
2857 #[test]
2858 fn test_prod() {
2859 let v = vec![_0_1i, _1_0i];
2860 assert_eq!(v.iter().product::<Complex64>(), _0_1i);
2861 assert_eq!(v.into_iter().product::<Complex64>(), _0_1i);
2862 }
2863
2864 #[test]
2865 fn test_zero() {
2866 let zero = Complex64::zero();
2867 assert!(zero.is_zero());
2868
2869 let mut c = Complex::new(1.23, 4.56);
2870 assert!(!c.is_zero());
2871 assert_eq!(c + zero, c);
2872
2873 c.set_zero();
2874 assert!(c.is_zero());
2875 }
2876
2877 #[test]
2878 fn test_one() {
2879 let one = Complex64::one();
2880 assert!(one.is_one());
2881
2882 let mut c = Complex::new(1.23, 4.56);
2883 assert!(!c.is_one());
2884 assert_eq!(c * one, c);
2885
2886 c.set_one();
2887 assert!(c.is_one());
2888 }
2889
2890 #[test]
2891 #[allow(clippy::float_cmp)]
2892 fn test_const() {
2893 const R: f64 = 12.3;
2894 const I: f64 = -4.5;
2895 const C: Complex64 = Complex::new(R, I);
2896
2897 assert_eq!(C.re, 12.3);
2898 assert_eq!(C.im, -4.5);
2899 }
2900}