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 let (r, theta) = self.to_polar();
348 Self::from_polar(r.powf(exp), theta * exp)
349 }
350
351 #[inline]
353 pub fn log(self, base: T) -> Self {
354 let (r, theta) = self.to_polar();
358 Self::new(r.log(base), theta / base.ln())
359 }
360
361 #[inline]
363 pub fn powc(self, exp: Self) -> Self {
364 let (r, theta) = self.to_polar();
376 Self::from_polar(
377 r.powf(exp.re) * (-exp.im * theta).exp(),
378 exp.re * theta + exp.im * r.ln(),
379 )
380 }
381
382 #[inline]
384 pub fn expf(self, base: T) -> Self {
385 Self::from_polar(base.powf(self.re), self.im * base.ln())
388 }
389
390 #[inline]
392 pub fn sin(self) -> Self {
393 Self::new(
395 self.re.sin() * self.im.cosh(),
396 self.re.cos() * self.im.sinh(),
397 )
398 }
399
400 #[inline]
402 pub fn cos(self) -> Self {
403 Self::new(
405 self.re.cos() * self.im.cosh(),
406 -self.re.sin() * self.im.sinh(),
407 )
408 }
409
410 #[inline]
412 pub fn tan(self) -> Self {
413 let (two_re, two_im) = (self.re + self.re, self.im + self.im);
415 Self::new(two_re.sin(), two_im.sinh()).unscale(two_re.cos() + two_im.cosh())
416 }
417
418 #[inline]
427 pub fn asin(self) -> Self {
428 let i = Self::i();
430 -i * ((Self::one() - self * self).sqrt() + i * self).ln()
431 }
432
433 #[inline]
442 pub fn acos(self) -> Self {
443 let i = Self::i();
445 -i * (i * (Self::one() - self * self).sqrt() + self).ln()
446 }
447
448 #[inline]
457 pub fn atan(self) -> Self {
458 let i = Self::i();
460 let one = Self::one();
461 let two = one + one;
462 if self == i {
463 return Self::new(T::zero(), T::infinity());
464 } else if self == -i {
465 return Self::new(T::zero(), -T::infinity());
466 }
467 ((one + i * self).ln() - (one - i * self).ln()) / (two * i)
468 }
469
470 #[inline]
472 pub fn sinh(self) -> Self {
473 Self::new(
475 self.re.sinh() * self.im.cos(),
476 self.re.cosh() * self.im.sin(),
477 )
478 }
479
480 #[inline]
482 pub fn cosh(self) -> Self {
483 Self::new(
485 self.re.cosh() * self.im.cos(),
486 self.re.sinh() * self.im.sin(),
487 )
488 }
489
490 #[inline]
492 pub fn tanh(self) -> Self {
493 let (two_re, two_im) = (self.re + self.re, self.im + self.im);
495 Self::new(two_re.sinh(), two_im.sin()).unscale(two_re.cosh() + two_im.cos())
496 }
497
498 #[inline]
507 pub fn asinh(self) -> Self {
508 let one = Self::one();
510 (self + (one + self * self).sqrt()).ln()
511 }
512
513 #[inline]
521 pub fn acosh(self) -> Self {
522 let one = Self::one();
524 let two = one + one;
525 two * (((self + one) / two).sqrt() + ((self - one) / two).sqrt()).ln()
526 }
527
528 #[inline]
537 pub fn atanh(self) -> Self {
538 let one = Self::one();
540 let two = one + one;
541 if self == one {
542 return Self::new(T::infinity(), T::zero());
543 } else if self == -one {
544 return Self::new(-T::infinity(), T::zero());
545 }
546 ((one + self).ln() - (one - self).ln()) / two
547 }
548
549 #[inline]
572 pub fn finv(self) -> Complex<T> {
573 let norm = self.norm();
574 self.conj() / norm / norm
575 }
576
577 #[inline]
601 pub fn fdiv(self, other: Complex<T>) -> Complex<T> {
602 self * other.finv()
603 }
604}
605
606#[cfg(any(feature = "std", feature = "libm"))]
607impl<T: Float + FloatConst> Complex<T> {
608 #[inline]
610 pub fn exp2(self) -> Self {
611 Self::from_polar(self.re.exp2(), self.im * T::LN_2())
614 }
615
616 #[inline]
618 pub fn log2(self) -> Self {
619 Self::ln(self) / T::LN_2()
620 }
621
622 #[inline]
624 pub fn log10(self) -> Self {
625 Self::ln(self) / T::LN_10()
626 }
627}
628
629impl<T: FloatCore> Complex<T> {
630 #[inline]
632 pub fn is_nan(self) -> bool {
633 self.re.is_nan() || self.im.is_nan()
634 }
635
636 #[inline]
638 pub fn is_infinite(self) -> bool {
639 !self.is_nan() && (self.re.is_infinite() || self.im.is_infinite())
640 }
641
642 #[inline]
644 pub fn is_finite(self) -> bool {
645 self.re.is_finite() && self.im.is_finite()
646 }
647
648 #[inline]
650 pub fn is_normal(self) -> bool {
651 self.re.is_normal() && self.im.is_normal()
652 }
653}
654
655#[cfg(feature = "bytemuck")]
659unsafe impl<T: bytemuck::Zeroable> bytemuck::Zeroable for Complex<T> {}
660
661#[cfg(feature = "bytemuck")]
665unsafe impl<T: bytemuck::Pod> bytemuck::Pod for Complex<T> {}
666
667impl<T: Clone + Num> From<T> for Complex<T> {
668 #[inline]
669 fn from(re: T) -> Self {
670 Self::new(re, T::zero())
671 }
672}
673
674impl<'a, T: Clone + Num> From<&'a T> for Complex<T> {
675 #[inline]
676 fn from(re: &T) -> Self {
677 From::from(re.clone())
678 }
679}
680
681macro_rules! forward_ref_ref_binop {
682 (impl $imp:ident, $method:ident) => {
683 impl<'a, 'b, T: Clone + Num> $imp<&'b Complex<T>> for &'a Complex<T> {
684 type Output = Complex<T>;
685
686 #[inline]
687 fn $method(self, other: &Complex<T>) -> Self::Output {
688 self.clone().$method(other.clone())
689 }
690 }
691 };
692}
693
694macro_rules! forward_ref_val_binop {
695 (impl $imp:ident, $method:ident) => {
696 impl<'a, T: Clone + Num> $imp<Complex<T>> for &'a Complex<T> {
697 type Output = Complex<T>;
698
699 #[inline]
700 fn $method(self, other: Complex<T>) -> Self::Output {
701 self.clone().$method(other)
702 }
703 }
704 };
705}
706
707macro_rules! forward_val_ref_binop {
708 (impl $imp:ident, $method:ident) => {
709 impl<'a, T: Clone + Num> $imp<&'a Complex<T>> for Complex<T> {
710 type Output = Complex<T>;
711
712 #[inline]
713 fn $method(self, other: &Complex<T>) -> Self::Output {
714 self.$method(other.clone())
715 }
716 }
717 };
718}
719
720macro_rules! forward_all_binop {
721 (impl $imp:ident, $method:ident) => {
722 forward_ref_ref_binop!(impl $imp, $method);
723 forward_ref_val_binop!(impl $imp, $method);
724 forward_val_ref_binop!(impl $imp, $method);
725 };
726}
727
728forward_all_binop!(impl Add, add);
730
731impl<T: Clone + Num> Add<Complex<T>> for Complex<T> {
733 type Output = Self;
734
735 #[inline]
736 fn add(self, other: Self) -> Self::Output {
737 Self::Output::new(self.re + other.re, self.im + other.im)
738 }
739}
740
741forward_all_binop!(impl Sub, sub);
742
743impl<T: Clone + Num> Sub<Complex<T>> for Complex<T> {
745 type Output = Self;
746
747 #[inline]
748 fn sub(self, other: Self) -> Self::Output {
749 Self::Output::new(self.re - other.re, self.im - other.im)
750 }
751}
752
753forward_all_binop!(impl Mul, mul);
754
755impl<T: Clone + Num> Mul<Complex<T>> for Complex<T> {
757 type Output = Self;
758
759 #[inline]
760 fn mul(self, other: Self) -> Self::Output {
761 let re = self.re.clone() * other.re.clone() - self.im.clone() * other.im.clone();
762 let im = self.re * other.im + self.im * other.re;
763 Self::Output::new(re, im)
764 }
765}
766
767impl<T: Clone + Num + MulAdd<Output = T>> MulAdd<Complex<T>> for Complex<T> {
769 type Output = Complex<T>;
770
771 #[inline]
772 fn mul_add(self, other: Complex<T>, add: Complex<T>) -> Complex<T> {
773 let re = self.re.clone().mul_add(other.re.clone(), add.re)
774 - (self.im.clone() * other.im.clone()); let im = self.re.mul_add(other.im, self.im.mul_add(other.re, add.im));
776 Complex::new(re, im)
777 }
778}
779impl<'a, 'b, T: Clone + Num + MulAdd<Output = T>> MulAdd<&'b Complex<T>> for &'a Complex<T> {
780 type Output = Complex<T>;
781
782 #[inline]
783 fn mul_add(self, other: &Complex<T>, add: &Complex<T>) -> Complex<T> {
784 self.clone().mul_add(other.clone(), add.clone())
785 }
786}
787
788forward_all_binop!(impl Div, div);
789
790impl<T: Clone + Num> Div<Complex<T>> for Complex<T> {
793 type Output = Self;
794
795 #[inline]
796 fn div(self, other: Self) -> Self::Output {
797 let norm_sqr = other.norm_sqr();
798 let re = self.re.clone() * other.re.clone() + self.im.clone() * other.im.clone();
799 let im = self.im * other.re - self.re * other.im;
800 Self::Output::new(re / norm_sqr.clone(), im / norm_sqr)
801 }
802}
803
804forward_all_binop!(impl Rem, rem);
805
806impl<T: Clone + Num> Complex<T> {
807 fn div_trunc(&self, divisor: &Self) -> Self {
809 let Complex { re, im } = self / divisor;
810 Complex::new(re.clone() - re % T::one(), im.clone() - im % T::one())
811 }
812}
813
814impl<T: Clone + Num> Rem<Complex<T>> for Complex<T> {
815 type Output = Self;
816
817 #[inline]
818 fn rem(self, modulus: Self) -> Self::Output {
819 let gaussian = self.div_trunc(&modulus);
820 self - modulus * gaussian
821 }
822}
823
824mod opassign {
827 use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
828
829 use num_traits::{MulAddAssign, NumAssign};
830
831 use crate::Complex;
832
833 impl<T: Clone + NumAssign> AddAssign for Complex<T> {
834 fn add_assign(&mut self, other: Self) {
835 self.re += other.re;
836 self.im += other.im;
837 }
838 }
839
840 impl<T: Clone + NumAssign> SubAssign for Complex<T> {
841 fn sub_assign(&mut self, other: Self) {
842 self.re -= other.re;
843 self.im -= other.im;
844 }
845 }
846
847 impl<T: Clone + NumAssign> MulAssign for Complex<T> {
849 fn mul_assign(&mut self, other: Self) {
850 let a = self.re.clone();
851
852 self.re *= other.re.clone();
853 self.re -= self.im.clone() * other.im.clone();
854
855 self.im *= other.re;
856 self.im += a * other.im;
857 }
858 }
859
860 impl<T: Clone + NumAssign + MulAddAssign> MulAddAssign for Complex<T> {
862 fn mul_add_assign(&mut self, other: Complex<T>, add: Complex<T>) {
863 let a = self.re.clone();
864
865 self.re.mul_add_assign(other.re.clone(), add.re); self.re -= self.im.clone() * other.im.clone(); let mut adf = a;
869 adf.mul_add_assign(other.im, add.im); self.im.mul_add_assign(other.re, adf); }
872 }
873
874 impl<'a, 'b, T: Clone + NumAssign + MulAddAssign> MulAddAssign<&'a Complex<T>, &'b Complex<T>>
875 for Complex<T>
876 {
877 fn mul_add_assign(&mut self, other: &Complex<T>, add: &Complex<T>) {
878 self.mul_add_assign(other.clone(), add.clone());
879 }
880 }
881
882 impl<T: Clone + NumAssign> DivAssign for Complex<T> {
885 fn div_assign(&mut self, other: Self) {
886 let a = self.re.clone();
887 let norm_sqr = other.norm_sqr();
888
889 self.re *= other.re.clone();
890 self.re += self.im.clone() * other.im.clone();
891 self.re /= norm_sqr.clone();
892
893 self.im *= other.re;
894 self.im -= a * other.im;
895 self.im /= norm_sqr;
896 }
897 }
898
899 impl<T: Clone + NumAssign> RemAssign for Complex<T> {
900 fn rem_assign(&mut self, modulus: Self) {
901 let gaussian = self.div_trunc(&modulus);
902 *self -= modulus * gaussian;
903 }
904 }
905
906 impl<T: Clone + NumAssign> AddAssign<T> for Complex<T> {
907 fn add_assign(&mut self, other: T) {
908 self.re += other;
909 }
910 }
911
912 impl<T: Clone + NumAssign> SubAssign<T> for Complex<T> {
913 fn sub_assign(&mut self, other: T) {
914 self.re -= other;
915 }
916 }
917
918 impl<T: Clone + NumAssign> MulAssign<T> for Complex<T> {
919 fn mul_assign(&mut self, other: T) {
920 self.re *= other.clone();
921 self.im *= other;
922 }
923 }
924
925 impl<T: Clone + NumAssign> DivAssign<T> for Complex<T> {
926 fn div_assign(&mut self, other: T) {
927 self.re /= other.clone();
928 self.im /= other;
929 }
930 }
931
932 impl<T: Clone + NumAssign> RemAssign<T> for Complex<T> {
933 fn rem_assign(&mut self, other: T) {
934 self.re %= other.clone();
935 self.im %= other;
936 }
937 }
938
939 macro_rules! forward_op_assign {
940 (impl $imp:ident, $method:ident) => {
941 impl<'a, T: Clone + NumAssign> $imp<&'a Complex<T>> for Complex<T> {
942 #[inline]
943 fn $method(&mut self, other: &Self) {
944 self.$method(other.clone())
945 }
946 }
947 impl<'a, T: Clone + NumAssign> $imp<&'a T> for Complex<T> {
948 #[inline]
949 fn $method(&mut self, other: &T) {
950 self.$method(other.clone())
951 }
952 }
953 };
954 }
955
956 forward_op_assign!(impl AddAssign, add_assign);
957 forward_op_assign!(impl SubAssign, sub_assign);
958 forward_op_assign!(impl MulAssign, mul_assign);
959 forward_op_assign!(impl DivAssign, div_assign);
960 forward_op_assign!(impl RemAssign, rem_assign);
961}
962
963impl<T: Clone + Num + Neg<Output = T>> Neg for Complex<T> {
964 type Output = Self;
965
966 #[inline]
967 fn neg(self) -> Self::Output {
968 Self::Output::new(-self.re, -self.im)
969 }
970}
971
972impl<'a, T: Clone + Num + Neg<Output = T>> Neg for &'a Complex<T> {
973 type Output = Complex<T>;
974
975 #[inline]
976 fn neg(self) -> Self::Output {
977 -self.clone()
978 }
979}
980
981impl<T: Clone + Num + Neg<Output = T>> Inv for Complex<T> {
982 type Output = Self;
983
984 #[inline]
985 fn inv(self) -> Self::Output {
986 (&self).inv()
987 }
988}
989
990impl<'a, T: Clone + Num + Neg<Output = T>> Inv for &'a Complex<T> {
991 type Output = Complex<T>;
992
993 #[inline]
994 fn inv(self) -> Self::Output {
995 self.inv()
996 }
997}
998
999macro_rules! real_arithmetic {
1000 (@forward $imp:ident::$method:ident for $($real:ident),*) => (
1001 impl<'a, T: Clone + Num> $imp<&'a T> for Complex<T> {
1002 type Output = Complex<T>;
1003
1004 #[inline]
1005 fn $method(self, other: &T) -> Self::Output {
1006 self.$method(other.clone())
1007 }
1008 }
1009 impl<'a, T: Clone + Num> $imp<T> for &'a Complex<T> {
1010 type Output = Complex<T>;
1011
1012 #[inline]
1013 fn $method(self, other: T) -> Self::Output {
1014 self.clone().$method(other)
1015 }
1016 }
1017 impl<'a, 'b, T: Clone + Num> $imp<&'a T> for &'b Complex<T> {
1018 type Output = Complex<T>;
1019
1020 #[inline]
1021 fn $method(self, other: &T) -> Self::Output {
1022 self.clone().$method(other.clone())
1023 }
1024 }
1025 $(
1026 impl<'a> $imp<&'a Complex<$real>> for $real {
1027 type Output = Complex<$real>;
1028
1029 #[inline]
1030 fn $method(self, other: &Complex<$real>) -> Complex<$real> {
1031 self.$method(other.clone())
1032 }
1033 }
1034 impl<'a> $imp<Complex<$real>> for &'a $real {
1035 type Output = Complex<$real>;
1036
1037 #[inline]
1038 fn $method(self, other: Complex<$real>) -> Complex<$real> {
1039 self.clone().$method(other)
1040 }
1041 }
1042 impl<'a, 'b> $imp<&'a Complex<$real>> for &'b $real {
1043 type Output = Complex<$real>;
1044
1045 #[inline]
1046 fn $method(self, other: &Complex<$real>) -> Complex<$real> {
1047 self.clone().$method(other.clone())
1048 }
1049 }
1050 )*
1051 );
1052 ($($real:ident),*) => (
1053 real_arithmetic!(@forward Add::add for $($real),*);
1054 real_arithmetic!(@forward Sub::sub for $($real),*);
1055 real_arithmetic!(@forward Mul::mul for $($real),*);
1056 real_arithmetic!(@forward Div::div for $($real),*);
1057 real_arithmetic!(@forward Rem::rem for $($real),*);
1058
1059 $(
1060 impl Add<Complex<$real>> for $real {
1061 type Output = Complex<$real>;
1062
1063 #[inline]
1064 fn add(self, other: Complex<$real>) -> Self::Output {
1065 Self::Output::new(self + other.re, other.im)
1066 }
1067 }
1068
1069 impl Sub<Complex<$real>> for $real {
1070 type Output = Complex<$real>;
1071
1072 #[inline]
1073 fn sub(self, other: Complex<$real>) -> Self::Output {
1074 Self::Output::new(self - other.re, $real::zero() - other.im)
1075 }
1076 }
1077
1078 impl Mul<Complex<$real>> for $real {
1079 type Output = Complex<$real>;
1080
1081 #[inline]
1082 fn mul(self, other: Complex<$real>) -> Self::Output {
1083 Self::Output::new(self * other.re, self * other.im)
1084 }
1085 }
1086
1087 impl Div<Complex<$real>> for $real {
1088 type Output = Complex<$real>;
1089
1090 #[inline]
1091 fn div(self, other: Complex<$real>) -> Self::Output {
1092 let norm_sqr = other.norm_sqr();
1094 Self::Output::new(self * other.re / norm_sqr.clone(),
1095 $real::zero() - self * other.im / norm_sqr)
1096 }
1097 }
1098
1099 impl Rem<Complex<$real>> for $real {
1100 type Output = Complex<$real>;
1101
1102 #[inline]
1103 fn rem(self, other: Complex<$real>) -> Self::Output {
1104 Self::Output::new(self, Self::zero()) % other
1105 }
1106 }
1107 )*
1108 );
1109}
1110
1111impl<T: Clone + Num> Add<T> for Complex<T> {
1112 type Output = Complex<T>;
1113
1114 #[inline]
1115 fn add(self, other: T) -> Self::Output {
1116 Self::Output::new(self.re + other, self.im)
1117 }
1118}
1119
1120impl<T: Clone + Num> Sub<T> for Complex<T> {
1121 type Output = Complex<T>;
1122
1123 #[inline]
1124 fn sub(self, other: T) -> Self::Output {
1125 Self::Output::new(self.re - other, self.im)
1126 }
1127}
1128
1129impl<T: Clone + Num> Mul<T> for Complex<T> {
1130 type Output = Complex<T>;
1131
1132 #[inline]
1133 fn mul(self, other: T) -> Self::Output {
1134 Self::Output::new(self.re * other.clone(), self.im * other)
1135 }
1136}
1137
1138impl<T: Clone + Num> Div<T> for Complex<T> {
1139 type Output = Self;
1140
1141 #[inline]
1142 fn div(self, other: T) -> Self::Output {
1143 Self::Output::new(self.re / other.clone(), self.im / other)
1144 }
1145}
1146
1147impl<T: Clone + Num> Rem<T> for Complex<T> {
1148 type Output = Complex<T>;
1149
1150 #[inline]
1151 fn rem(self, other: T) -> Self::Output {
1152 Self::Output::new(self.re % other.clone(), self.im % other)
1153 }
1154}
1155
1156real_arithmetic!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64);
1157
1158impl<T: Clone + Num> Zero for Complex<T> {
1160 #[inline]
1161 fn zero() -> Self {
1162 Self::new(Zero::zero(), Zero::zero())
1163 }
1164
1165 #[inline]
1166 fn is_zero(&self) -> bool {
1167 self.re.is_zero() && self.im.is_zero()
1168 }
1169
1170 #[inline]
1171 fn set_zero(&mut self) {
1172 self.re.set_zero();
1173 self.im.set_zero();
1174 }
1175}
1176
1177impl<T: Clone + Num> One for Complex<T> {
1178 #[inline]
1179 fn one() -> Self {
1180 Self::new(One::one(), Zero::zero())
1181 }
1182
1183 #[inline]
1184 fn is_one(&self) -> bool {
1185 self.re.is_one() && self.im.is_zero()
1186 }
1187
1188 #[inline]
1189 fn set_one(&mut self) {
1190 self.re.set_one();
1191 self.im.set_zero();
1192 }
1193}
1194
1195macro_rules! write_complex {
1196 ($f:ident, $t:expr, $prefix:expr, $re:expr, $im:expr, $T:ident) => {{
1197 let abs_re = if $re < Zero::zero() {
1198 $T::zero() - $re.clone()
1199 } else {
1200 $re.clone()
1201 };
1202 let abs_im = if $im < Zero::zero() {
1203 $T::zero() - $im.clone()
1204 } else {
1205 $im.clone()
1206 };
1207
1208 return if let Some(prec) = $f.precision() {
1209 fmt_re_im(
1210 $f,
1211 $re < $T::zero(),
1212 $im < $T::zero(),
1213 format_args!(concat!("{:.1$", $t, "}"), abs_re, prec),
1214 format_args!(concat!("{:.1$", $t, "}"), abs_im, prec),
1215 )
1216 } else {
1217 fmt_re_im(
1218 $f,
1219 $re < $T::zero(),
1220 $im < $T::zero(),
1221 format_args!(concat!("{:", $t, "}"), abs_re),
1222 format_args!(concat!("{:", $t, "}"), abs_im),
1223 )
1224 };
1225
1226 fn fmt_re_im(
1227 f: &mut fmt::Formatter<'_>,
1228 re_neg: bool,
1229 im_neg: bool,
1230 real: fmt::Arguments<'_>,
1231 imag: fmt::Arguments<'_>,
1232 ) -> fmt::Result {
1233 let prefix = if f.alternate() { $prefix } else { "" };
1234 let sign = if re_neg {
1235 "-"
1236 } else if f.sign_plus() {
1237 "+"
1238 } else {
1239 ""
1240 };
1241
1242 if im_neg {
1243 fmt_complex(
1244 f,
1245 format_args!(
1246 "{}{pre}{re}-{pre}{im}i",
1247 sign,
1248 re = real,
1249 im = imag,
1250 pre = prefix
1251 ),
1252 )
1253 } else {
1254 fmt_complex(
1255 f,
1256 format_args!(
1257 "{}{pre}{re}+{pre}{im}i",
1258 sign,
1259 re = real,
1260 im = imag,
1261 pre = prefix
1262 ),
1263 )
1264 }
1265 }
1266
1267 #[cfg(feature = "std")]
1268 fn fmt_complex(f: &mut fmt::Formatter<'_>, complex: fmt::Arguments<'_>) -> fmt::Result {
1270 use std::string::ToString;
1271 if let Some(width) = f.width() {
1272 write!(f, "{0: >1$}", complex.to_string(), width)
1273 } else {
1274 write!(f, "{}", complex)
1275 }
1276 }
1277
1278 #[cfg(not(feature = "std"))]
1279 fn fmt_complex(f: &mut fmt::Formatter<'_>, complex: fmt::Arguments<'_>) -> fmt::Result {
1280 write!(f, "{}", complex)
1281 }
1282 }};
1283}
1284
1285impl<T> fmt::Display for Complex<T>
1287where
1288 T: fmt::Display + Num + PartialOrd + Clone,
1289{
1290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1291 write_complex!(f, "", "", self.re, self.im, T)
1292 }
1293}
1294
1295impl<T> fmt::LowerExp for Complex<T>
1296where
1297 T: fmt::LowerExp + Num + PartialOrd + Clone,
1298{
1299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1300 write_complex!(f, "e", "", self.re, self.im, T)
1301 }
1302}
1303
1304impl<T> fmt::UpperExp for Complex<T>
1305where
1306 T: fmt::UpperExp + Num + PartialOrd + Clone,
1307{
1308 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1309 write_complex!(f, "E", "", self.re, self.im, T)
1310 }
1311}
1312
1313impl<T> fmt::LowerHex for Complex<T>
1314where
1315 T: fmt::LowerHex + Num + PartialOrd + Clone,
1316{
1317 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1318 write_complex!(f, "x", "0x", self.re, self.im, T)
1319 }
1320}
1321
1322impl<T> fmt::UpperHex for Complex<T>
1323where
1324 T: fmt::UpperHex + Num + PartialOrd + Clone,
1325{
1326 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1327 write_complex!(f, "X", "0x", self.re, self.im, T)
1328 }
1329}
1330
1331impl<T> fmt::Octal for Complex<T>
1332where
1333 T: fmt::Octal + Num + PartialOrd + Clone,
1334{
1335 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1336 write_complex!(f, "o", "0o", self.re, self.im, T)
1337 }
1338}
1339
1340impl<T> fmt::Binary for Complex<T>
1341where
1342 T: fmt::Binary + Num + PartialOrd + Clone,
1343{
1344 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1345 write_complex!(f, "b", "0b", self.re, self.im, T)
1346 }
1347}
1348
1349#[allow(deprecated)] fn from_str_generic<T, E, F>(s: &str, from: F) -> Result<Complex<T>, ParseComplexError<E>>
1351where
1352 F: Fn(&str) -> Result<T, E>,
1353 T: Clone + Num,
1354{
1355 let imag = match s.rfind('j') {
1356 None => 'i',
1357 _ => 'j',
1358 };
1359
1360 let mut neg_b = false;
1361 let mut a = s;
1362 let mut b = "";
1363
1364 for (i, w) in s.as_bytes().windows(2).enumerate() {
1365 let p = w[0];
1366 let c = w[1];
1367
1368 if (c == b'+' || c == b'-') && !(p == b'e' || p == b'E') {
1370 a = &s[..=i].trim_right_matches(char::is_whitespace);
1372 b = &s[i + 2..].trim_left_matches(char::is_whitespace);
1373 neg_b = c == b'-';
1374
1375 if b.is_empty() || (neg_b && b.starts_with('-')) {
1376 return Err(ParseComplexError::expr_error());
1377 }
1378 break;
1379 }
1380 }
1381
1382 if b.is_empty() {
1384 b = if a.ends_with(imag) { "0" } else { "0i" };
1386 }
1387
1388 let re;
1389 let neg_re;
1390 let im;
1391 let neg_im;
1392 if a.ends_with(imag) {
1393 im = a;
1394 neg_im = false;
1395 re = b;
1396 neg_re = neg_b;
1397 } else if b.ends_with(imag) {
1398 re = a;
1399 neg_re = false;
1400 im = b;
1401 neg_im = neg_b;
1402 } else {
1403 return Err(ParseComplexError::expr_error());
1404 }
1405
1406 let re = from(re).map_err(ParseComplexError::from_error)?;
1408 let re = if neg_re { T::zero() - re } else { re };
1409
1410 let mut im = &im[..im.len() - 1];
1412 if im.is_empty() || im == "+" {
1414 im = "1";
1415 } else if im == "-" {
1416 im = "-1";
1417 }
1418
1419 let im = from(im).map_err(ParseComplexError::from_error)?;
1421 let im = if neg_im { T::zero() - im } else { im };
1422
1423 Ok(Complex::new(re, im))
1424}
1425
1426impl<T> FromStr for Complex<T>
1427where
1428 T: FromStr + Num + Clone,
1429{
1430 type Err = ParseComplexError<T::Err>;
1431
1432 fn from_str(s: &str) -> Result<Self, Self::Err> {
1434 from_str_generic(s, T::from_str)
1435 }
1436}
1437
1438impl<T: Num + Clone> Num for Complex<T> {
1439 type FromStrRadixErr = ParseComplexError<T::FromStrRadixErr>;
1440
1441 fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
1451 assert!(
1452 radix <= 36,
1453 "from_str_radix: radix is too high (maximum 36)"
1454 );
1455
1456 if radix > 18 {
1458 return Err(ParseComplexError::unsupported_radix());
1459 }
1460
1461 from_str_generic(s, |x| -> Result<T, T::FromStrRadixErr> {
1462 T::from_str_radix(x, radix)
1463 })
1464 }
1465}
1466
1467impl<T: Num + Clone> Sum for Complex<T> {
1468 fn sum<I>(iter: I) -> Self
1469 where
1470 I: Iterator<Item = Self>,
1471 {
1472 iter.fold(Self::zero(), |acc, c| acc + c)
1473 }
1474}
1475
1476impl<'a, T: 'a + Num + Clone> Sum<&'a Complex<T>> for Complex<T> {
1477 fn sum<I>(iter: I) -> Self
1478 where
1479 I: Iterator<Item = &'a Complex<T>>,
1480 {
1481 iter.fold(Self::zero(), |acc, c| acc + c)
1482 }
1483}
1484
1485impl<T: Num + Clone> Product for Complex<T> {
1486 fn product<I>(iter: I) -> Self
1487 where
1488 I: Iterator<Item = Self>,
1489 {
1490 iter.fold(Self::one(), |acc, c| acc * c)
1491 }
1492}
1493
1494impl<'a, T: 'a + Num + Clone> Product<&'a Complex<T>> for Complex<T> {
1495 fn product<I>(iter: I) -> Self
1496 where
1497 I: Iterator<Item = &'a Complex<T>>,
1498 {
1499 iter.fold(Self::one(), |acc, c| acc * c)
1500 }
1501}
1502
1503#[cfg(feature = "serde")]
1504impl<T> serde::Serialize for Complex<T>
1505where
1506 T: serde::Serialize,
1507{
1508 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1509 where
1510 S: serde::Serializer,
1511 {
1512 (&self.re, &self.im).serialize(serializer)
1513 }
1514}
1515
1516#[cfg(feature = "serde")]
1517impl<'de, T> serde::Deserialize<'de> for Complex<T>
1518where
1519 T: serde::Deserialize<'de> + Num + Clone,
1520{
1521 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1522 where
1523 D: serde::Deserializer<'de>,
1524 {
1525 let (re, im) = serde::Deserialize::deserialize(deserializer)?;
1526 Ok(Self::new(re, im))
1527 }
1528}
1529
1530#[derive(Debug, PartialEq)]
1531pub struct ParseComplexError<E> {
1532 kind: ComplexErrorKind<E>,
1533}
1534
1535#[derive(Debug, PartialEq)]
1536enum ComplexErrorKind<E> {
1537 ParseError(E),
1538 ExprError,
1539 UnsupportedRadix,
1540}
1541
1542impl<E> ParseComplexError<E> {
1543 fn expr_error() -> Self {
1544 ParseComplexError {
1545 kind: ComplexErrorKind::ExprError,
1546 }
1547 }
1548
1549 fn unsupported_radix() -> Self {
1550 ParseComplexError {
1551 kind: ComplexErrorKind::UnsupportedRadix,
1552 }
1553 }
1554
1555 fn from_error(error: E) -> Self {
1556 ParseComplexError {
1557 kind: ComplexErrorKind::ParseError(error),
1558 }
1559 }
1560}
1561
1562#[cfg(feature = "std")]
1563impl<E: Error> Error for ParseComplexError<E> {
1564 #[allow(deprecated)]
1565 fn description(&self) -> &str {
1566 match self.kind {
1567 ComplexErrorKind::ParseError(ref e) => e.description(),
1568 ComplexErrorKind::ExprError => "invalid or unsupported complex expression",
1569 ComplexErrorKind::UnsupportedRadix => "unsupported radix for conversion",
1570 }
1571 }
1572}
1573
1574impl<E: fmt::Display> fmt::Display for ParseComplexError<E> {
1575 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1576 match self.kind {
1577 ComplexErrorKind::ParseError(ref e) => e.fmt(f),
1578 ComplexErrorKind::ExprError => "invalid or unsupported complex expression".fmt(f),
1579 ComplexErrorKind::UnsupportedRadix => "unsupported radix for conversion".fmt(f),
1580 }
1581 }
1582}
1583
1584#[cfg(test)]
1585fn hash<T: hash::Hash>(x: &T) -> u64 {
1586 use std::collections::hash_map::RandomState;
1587 use std::hash::{BuildHasher, Hasher};
1588 let mut hasher = <RandomState as BuildHasher>::Hasher::new();
1589 x.hash(&mut hasher);
1590 hasher.finish()
1591}
1592
1593#[cfg(test)]
1594pub(crate) mod test {
1595 #![allow(non_upper_case_globals)]
1596
1597 use super::{Complex, Complex64};
1598 use super::{ComplexErrorKind, ParseComplexError};
1599 use core::f64;
1600 use core::str::FromStr;
1601
1602 use std::string::{String, ToString};
1603
1604 use num_traits::{Num, One, Zero};
1605
1606 pub const _0_0i: Complex64 = Complex::new(0.0, 0.0);
1607 pub const _1_0i: Complex64 = Complex::new(1.0, 0.0);
1608 pub const _1_1i: Complex64 = Complex::new(1.0, 1.0);
1609 pub const _0_1i: Complex64 = Complex::new(0.0, 1.0);
1610 pub const _neg1_1i: Complex64 = Complex::new(-1.0, 1.0);
1611 pub const _05_05i: Complex64 = Complex::new(0.5, 0.5);
1612 pub const all_consts: [Complex64; 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i];
1613 pub const _4_2i: Complex64 = Complex::new(4.0, 2.0);
1614 pub const _1_infi: Complex64 = Complex::new(1.0, f64::INFINITY);
1615 pub const _neg1_infi: Complex64 = Complex::new(-1.0, f64::INFINITY);
1616 pub const _1_nani: Complex64 = Complex::new(1.0, f64::NAN);
1617 pub const _neg1_nani: Complex64 = Complex::new(-1.0, f64::NAN);
1618 pub const _inf_0i: Complex64 = Complex::new(f64::INFINITY, 0.0);
1619 pub const _neginf_1i: Complex64 = Complex::new(f64::NEG_INFINITY, 1.0);
1620 pub const _neginf_neg1i: Complex64 = Complex::new(f64::NEG_INFINITY, -1.0);
1621 pub const _inf_1i: Complex64 = Complex::new(f64::INFINITY, 1.0);
1622 pub const _inf_neg1i: Complex64 = Complex::new(f64::INFINITY, -1.0);
1623 pub const _neginf_infi: Complex64 = Complex::new(f64::NEG_INFINITY, f64::INFINITY);
1624 pub const _inf_infi: Complex64 = Complex::new(f64::INFINITY, f64::INFINITY);
1625 pub const _neginf_nani: Complex64 = Complex::new(f64::NEG_INFINITY, f64::NAN);
1626 pub const _inf_nani: Complex64 = Complex::new(f64::INFINITY, f64::NAN);
1627 pub const _nan_0i: Complex64 = Complex::new(f64::NAN, 0.0);
1628 pub const _nan_1i: Complex64 = Complex::new(f64::NAN, 1.0);
1629 pub const _nan_neg1i: Complex64 = Complex::new(f64::NAN, -1.0);
1630 pub const _nan_nani: Complex64 = Complex::new(f64::NAN, f64::NAN);
1631
1632 #[test]
1633 fn test_consts() {
1634 fn test(c: Complex64, r: f64, i: f64) {
1636 assert_eq!(c, Complex::new(r, i));
1637 }
1638 test(_0_0i, 0.0, 0.0);
1639 test(_1_0i, 1.0, 0.0);
1640 test(_1_1i, 1.0, 1.0);
1641 test(_neg1_1i, -1.0, 1.0);
1642 test(_05_05i, 0.5, 0.5);
1643
1644 assert_eq!(_0_0i, Zero::zero());
1645 assert_eq!(_1_0i, One::one());
1646 }
1647
1648 #[test]
1649 fn test_scale_unscale() {
1650 assert_eq!(_05_05i.scale(2.0), _1_1i);
1651 assert_eq!(_1_1i.unscale(2.0), _05_05i);
1652 for &c in all_consts.iter() {
1653 assert_eq!(c.scale(2.0).unscale(2.0), c);
1654 }
1655 }
1656
1657 #[test]
1658 fn test_conj() {
1659 for &c in all_consts.iter() {
1660 assert_eq!(c.conj(), Complex::new(c.re, -c.im));
1661 assert_eq!(c.conj().conj(), c);
1662 }
1663 }
1664
1665 #[test]
1666 fn test_inv() {
1667 assert_eq!(_1_1i.inv(), _05_05i.conj());
1668 assert_eq!(_1_0i.inv(), _1_0i.inv());
1669 }
1670
1671 #[test]
1672 #[should_panic]
1673 fn test_divide_by_zero_natural() {
1674 let n = Complex::new(2, 3);
1675 let d = Complex::new(0, 0);
1676 let _x = n / d;
1677 }
1678
1679 #[test]
1680 fn test_inv_zero() {
1681 assert!(_0_0i.inv().is_nan());
1683 }
1684
1685 #[test]
1686 #[allow(clippy::float_cmp)]
1687 fn test_l1_norm() {
1688 assert_eq!(_0_0i.l1_norm(), 0.0);
1689 assert_eq!(_1_0i.l1_norm(), 1.0);
1690 assert_eq!(_1_1i.l1_norm(), 2.0);
1691 assert_eq!(_0_1i.l1_norm(), 1.0);
1692 assert_eq!(_neg1_1i.l1_norm(), 2.0);
1693 assert_eq!(_05_05i.l1_norm(), 1.0);
1694 assert_eq!(_4_2i.l1_norm(), 6.0);
1695 }
1696
1697 #[test]
1698 fn test_pow() {
1699 for c in all_consts.iter() {
1700 assert_eq!(c.powi(0), _1_0i);
1701 let mut pos = _1_0i;
1702 let mut neg = _1_0i;
1703 for i in 1i32..20 {
1704 pos *= c;
1705 assert_eq!(pos, c.powi(i));
1706 if c.is_zero() {
1707 assert!(c.powi(-i).is_nan());
1708 } else {
1709 neg /= c;
1710 assert_eq!(neg, c.powi(-i));
1711 }
1712 }
1713 }
1714 }
1715
1716 #[cfg(any(feature = "std", feature = "libm"))]
1717 pub(crate) mod float {
1718 use super::*;
1719 use num_traits::{Float, Pow};
1720
1721 #[test]
1722 fn test_cis() {
1723 assert!(close(Complex::cis(0.0 * f64::consts::PI), _1_0i));
1724 assert!(close(Complex::cis(0.5 * f64::consts::PI), _0_1i));
1725 assert!(close(Complex::cis(1.0 * f64::consts::PI), -_1_0i));
1726 assert!(close(Complex::cis(1.5 * f64::consts::PI), -_0_1i));
1727 assert!(close(Complex::cis(2.0 * f64::consts::PI), _1_0i));
1728 }
1729
1730 #[test]
1731 #[cfg_attr(target_arch = "x86", ignore)]
1732 #[allow(clippy::float_cmp)]
1734 fn test_norm() {
1735 fn test(c: Complex64, ns: f64) {
1736 assert_eq!(c.norm_sqr(), ns);
1737 assert_eq!(c.norm(), ns.sqrt())
1738 }
1739 test(_0_0i, 0.0);
1740 test(_1_0i, 1.0);
1741 test(_1_1i, 2.0);
1742 test(_neg1_1i, 2.0);
1743 test(_05_05i, 0.5);
1744 }
1745
1746 #[test]
1747 fn test_arg() {
1748 fn test(c: Complex64, arg: f64) {
1749 assert!((c.arg() - arg).abs() < 1.0e-6)
1750 }
1751 test(_1_0i, 0.0);
1752 test(_1_1i, 0.25 * f64::consts::PI);
1753 test(_neg1_1i, 0.75 * f64::consts::PI);
1754 test(_05_05i, 0.25 * f64::consts::PI);
1755 }
1756
1757 #[test]
1758 fn test_polar_conv() {
1759 fn test(c: Complex64) {
1760 let (r, theta) = c.to_polar();
1761 assert!((c - Complex::from_polar(r, theta)).norm() < 1e-6);
1762 }
1763 for &c in all_consts.iter() {
1764 test(c);
1765 }
1766 }
1767
1768 pub(crate) fn close(a: Complex64, b: Complex64) -> bool {
1769 close_to_tol(a, b, 1e-10)
1770 }
1771
1772 fn close_to_tol(a: Complex64, b: Complex64, tol: f64) -> bool {
1773 let close = (a == b) || (a - b).norm() < tol;
1775 if !close {
1776 println!("{:?} != {:?}", a, b);
1777 }
1778 close
1779 }
1780
1781 fn close_naninf(a: Complex64, b: Complex64) -> bool {
1783 close_naninf_to_tol(a, b, 1.0e-10)
1784 }
1785
1786 fn close_naninf_to_tol(a: Complex64, b: Complex64, tol: f64) -> bool {
1787 let mut close = true;
1788
1789 if a.re.is_finite() {
1791 if b.re.is_finite() {
1792 close = (a.re == b.re) || (a.re - b.re).abs() < tol;
1793 } else {
1794 close = false;
1795 }
1796 } else if (a.re.is_nan() && !b.re.is_nan())
1797 || (a.re.is_infinite()
1798 && a.re.is_sign_positive()
1799 && !(b.re.is_infinite() && b.re.is_sign_positive()))
1800 || (a.re.is_infinite()
1801 && a.re.is_sign_negative()
1802 && !(b.re.is_infinite() && b.re.is_sign_negative()))
1803 {
1804 close = false;
1805 }
1806
1807 if a.im.is_finite() {
1809 if b.im.is_finite() {
1810 close &= (a.im == b.im) || (a.im - b.im).abs() < tol;
1811 } else {
1812 close = false;
1813 }
1814 } else if (a.im.is_nan() && !b.im.is_nan())
1815 || (a.im.is_infinite()
1816 && a.im.is_sign_positive()
1817 && !(b.im.is_infinite() && b.im.is_sign_positive()))
1818 || (a.im.is_infinite()
1819 && a.im.is_sign_negative()
1820 && !(b.im.is_infinite() && b.im.is_sign_negative()))
1821 {
1822 close = false;
1823 }
1824
1825 if close == false {
1826 println!("{:?} != {:?}", a, b);
1827 }
1828 close
1829 }
1830
1831 #[test]
1832 fn test_exp2() {
1833 assert!(close(_0_0i.exp2(), _1_0i));
1834 }
1835
1836 #[test]
1837 fn test_exp() {
1838 assert!(close(_1_0i.exp(), _1_0i.scale(f64::consts::E)));
1839 assert!(close(_0_0i.exp(), _1_0i));
1840 assert!(close(_0_1i.exp(), Complex::new(1.0.cos(), 1.0.sin())));
1841 assert!(close(_05_05i.exp() * _05_05i.exp(), _1_1i.exp()));
1842 assert!(close(
1843 _0_1i.scale(-f64::consts::PI).exp(),
1844 _1_0i.scale(-1.0)
1845 ));
1846 for &c in all_consts.iter() {
1847 assert!(close(c.conj().exp(), c.exp().conj()));
1849 assert!(close(
1851 c.exp(),
1852 (c + _0_1i.scale(f64::consts::PI * 2.0)).exp()
1853 ));
1854 }
1855
1856 assert!(close_naninf(_1_infi.exp(), _nan_nani));
1858 assert!(close_naninf(_neg1_infi.exp(), _nan_nani));
1859 assert!(close_naninf(_1_nani.exp(), _nan_nani));
1860 assert!(close_naninf(_neg1_nani.exp(), _nan_nani));
1861 assert!(close_naninf(_inf_0i.exp(), _inf_0i));
1862 assert!(close_naninf(_neginf_1i.exp(), 0.0 * Complex::cis(1.0)));
1863 assert!(close_naninf(_neginf_neg1i.exp(), 0.0 * Complex::cis(-1.0)));
1864 assert!(close_naninf(
1865 _inf_1i.exp(),
1866 f64::INFINITY * Complex::cis(1.0)
1867 ));
1868 assert!(close_naninf(
1869 _inf_neg1i.exp(),
1870 f64::INFINITY * Complex::cis(-1.0)
1871 ));
1872 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));
1877 assert!(close_naninf(_nan_1i.exp(), _nan_nani));
1878 assert!(close_naninf(_nan_neg1i.exp(), _nan_nani));
1879 assert!(close_naninf(_nan_nani.exp(), _nan_nani));
1880 }
1881
1882 #[test]
1883 fn test_ln() {
1884 assert!(close(_1_0i.ln(), _0_0i));
1885 assert!(close(_0_1i.ln(), _0_1i.scale(f64::consts::PI / 2.0)));
1886 assert!(close(_0_0i.ln(), Complex::new(f64::neg_infinity(), 0.0)));
1887 assert!(close(
1888 (_neg1_1i * _05_05i).ln(),
1889 _neg1_1i.ln() + _05_05i.ln()
1890 ));
1891 for &c in all_consts.iter() {
1892 assert!(close(c.conj().ln(), c.ln().conj()));
1894 assert!(-f64::consts::PI <= c.ln().arg() && c.ln().arg() <= f64::consts::PI);
1896 }
1897 }
1898
1899 #[test]
1900 fn test_powc() {
1901 let a = Complex::new(2.0, -3.0);
1902 let b = Complex::new(3.0, 0.0);
1903 assert!(close(a.powc(b), a.powf(b.re)));
1904 assert!(close(b.powc(a), a.expf(b.re)));
1905 let c = Complex::new(1.0 / 3.0, 0.1);
1906 assert!(close_to_tol(
1907 a.powc(c),
1908 Complex::new(1.65826, -0.33502),
1909 1e-5
1910 ));
1911 }
1912
1913 #[test]
1914 fn test_powf() {
1915 let c = Complex64::new(2.0, -1.0);
1916 let expected = Complex64::new(-0.8684746, -16.695934);
1917 assert!(close_to_tol(c.powf(3.5), expected, 1e-5));
1918 assert!(close_to_tol(Pow::pow(c, 3.5_f64), expected, 1e-5));
1919 assert!(close_to_tol(Pow::pow(c, 3.5_f32), expected, 1e-5));
1920 }
1921
1922 #[test]
1923 fn test_log() {
1924 let c = Complex::new(2.0, -1.0);
1925 let r = c.log(10.0);
1926 assert!(close_to_tol(r, Complex::new(0.349485, -0.20135958), 1e-5));
1927 }
1928
1929 #[test]
1930 fn test_log2() {
1931 assert!(close(_1_0i.log2(), _0_0i));
1932 }
1933
1934 #[test]
1935 fn test_log10() {
1936 assert!(close(_1_0i.log10(), _0_0i));
1937 }
1938
1939 #[test]
1940 fn test_some_expf_cases() {
1941 let c = Complex::new(2.0, -1.0);
1942 let r = c.expf(10.0);
1943 assert!(close_to_tol(r, Complex::new(-66.82015, -74.39803), 1e-5));
1944
1945 let c = Complex::new(5.0, -2.0);
1946 let r = c.expf(3.4);
1947 assert!(close_to_tol(r, Complex::new(-349.25, -290.63), 1e-2));
1948
1949 let c = Complex::new(-1.5, 2.0 / 3.0);
1950 let r = c.expf(1.0 / 3.0);
1951 assert!(close_to_tol(r, Complex::new(3.8637, -3.4745), 1e-2));
1952 }
1953
1954 #[test]
1955 fn test_sqrt() {
1956 assert!(close(_0_0i.sqrt(), _0_0i));
1957 assert!(close(_1_0i.sqrt(), _1_0i));
1958 assert!(close(Complex::new(-1.0, 0.0).sqrt(), _0_1i));
1959 assert!(close(Complex::new(-1.0, -0.0).sqrt(), _0_1i.scale(-1.0)));
1960 assert!(close(_0_1i.sqrt(), _05_05i.scale(2.0.sqrt())));
1961 for &c in all_consts.iter() {
1962 assert!(close(c.conj().sqrt(), c.sqrt().conj()));
1964 assert!(
1966 -f64::consts::FRAC_PI_2 <= c.sqrt().arg()
1967 && c.sqrt().arg() <= f64::consts::FRAC_PI_2
1968 );
1969 assert!(close(c.sqrt() * c.sqrt(), c));
1971 }
1972 }
1973
1974 #[test]
1975 fn test_sqrt_real() {
1976 for n in (0..100).map(f64::from) {
1977 let n2 = n * n;
1979 assert_eq!(Complex64::new(n2, 0.0).sqrt(), Complex64::new(n, 0.0));
1980 assert_eq!(Complex64::new(-n2, 0.0).sqrt(), Complex64::new(0.0, n));
1982 assert_eq!(Complex64::new(-n2, -0.0).sqrt(), Complex64::new(0.0, -n));
1984 }
1985 }
1986
1987 #[test]
1988 fn test_sqrt_imag() {
1989 for n in (0..100).map(f64::from) {
1990 let n2 = n * n;
1992 assert!(close(
1993 Complex64::new(0.0, n2).sqrt(),
1994 Complex64::from_polar(n, f64::consts::FRAC_PI_4)
1995 ));
1996 assert!(close(
1998 Complex64::new(0.0, -n2).sqrt(),
1999 Complex64::from_polar(n, -f64::consts::FRAC_PI_4)
2000 ));
2001 }
2002 }
2003
2004 #[test]
2005 fn test_cbrt() {
2006 assert!(close(_0_0i.cbrt(), _0_0i));
2007 assert!(close(_1_0i.cbrt(), _1_0i));
2008 assert!(close(
2009 Complex::new(-1.0, 0.0).cbrt(),
2010 Complex::new(0.5, 0.75.sqrt())
2011 ));
2012 assert!(close(
2013 Complex::new(-1.0, -0.0).cbrt(),
2014 Complex::new(0.5, -(0.75.sqrt()))
2015 ));
2016 assert!(close(_0_1i.cbrt(), Complex::new(0.75.sqrt(), 0.5)));
2017 assert!(close(_0_1i.conj().cbrt(), Complex::new(0.75.sqrt(), -0.5)));
2018 for &c in all_consts.iter() {
2019 assert!(close(c.conj().cbrt(), c.cbrt().conj()));
2021 assert!(
2023 -f64::consts::FRAC_PI_3 <= c.cbrt().arg()
2024 && c.cbrt().arg() <= f64::consts::FRAC_PI_3
2025 );
2026 assert!(close(c.cbrt() * c.cbrt() * c.cbrt(), c));
2028 }
2029 }
2030
2031 #[test]
2032 fn test_cbrt_real() {
2033 for n in (0..100).map(f64::from) {
2034 let n3 = n * n * n;
2036 assert!(close(
2037 Complex64::new(n3, 0.0).cbrt(),
2038 Complex64::new(n, 0.0)
2039 ));
2040 assert!(close(
2042 Complex64::new(-n3, 0.0).cbrt(),
2043 Complex64::from_polar(n, f64::consts::FRAC_PI_3)
2044 ));
2045 assert!(close(
2047 Complex64::new(-n3, -0.0).cbrt(),
2048 Complex64::from_polar(n, -f64::consts::FRAC_PI_3)
2049 ));
2050 }
2051 }
2052
2053 #[test]
2054 fn test_cbrt_imag() {
2055 for n in (0..100).map(f64::from) {
2056 let n3 = n * n * n;
2058 assert!(close(
2059 Complex64::new(0.0, n3).cbrt(),
2060 Complex64::from_polar(n, f64::consts::FRAC_PI_6)
2061 ));
2062 assert!(close(
2064 Complex64::new(0.0, -n3).cbrt(),
2065 Complex64::from_polar(n, -f64::consts::FRAC_PI_6)
2066 ));
2067 }
2068 }
2069
2070 #[test]
2071 fn test_sin() {
2072 assert!(close(_0_0i.sin(), _0_0i));
2073 assert!(close(_1_0i.scale(f64::consts::PI * 2.0).sin(), _0_0i));
2074 assert!(close(_0_1i.sin(), _0_1i.scale(1.0.sinh())));
2075 for &c in all_consts.iter() {
2076 assert!(close(c.conj().sin(), c.sin().conj()));
2078 assert!(close(c.scale(-1.0).sin(), c.sin().scale(-1.0)));
2080 }
2081 }
2082
2083 #[test]
2084 fn test_cos() {
2085 assert!(close(_0_0i.cos(), _1_0i));
2086 assert!(close(_1_0i.scale(f64::consts::PI * 2.0).cos(), _1_0i));
2087 assert!(close(_0_1i.cos(), _1_0i.scale(1.0.cosh())));
2088 for &c in all_consts.iter() {
2089 assert!(close(c.conj().cos(), c.cos().conj()));
2091 assert!(close(c.scale(-1.0).cos(), c.cos()));
2093 }
2094 }
2095
2096 #[test]
2097 fn test_tan() {
2098 assert!(close(_0_0i.tan(), _0_0i));
2099 assert!(close(_1_0i.scale(f64::consts::PI / 4.0).tan(), _1_0i));
2100 assert!(close(_1_0i.scale(f64::consts::PI).tan(), _0_0i));
2101 for &c in all_consts.iter() {
2102 assert!(close(c.conj().tan(), c.tan().conj()));
2104 assert!(close(c.scale(-1.0).tan(), c.tan().scale(-1.0)));
2106 }
2107 }
2108
2109 #[test]
2110 fn test_asin() {
2111 assert!(close(_0_0i.asin(), _0_0i));
2112 assert!(close(_1_0i.asin(), _1_0i.scale(f64::consts::PI / 2.0)));
2113 assert!(close(
2114 _1_0i.scale(-1.0).asin(),
2115 _1_0i.scale(-f64::consts::PI / 2.0)
2116 ));
2117 assert!(close(_0_1i.asin(), _0_1i.scale((1.0 + 2.0.sqrt()).ln())));
2118 for &c in all_consts.iter() {
2119 assert!(close(c.conj().asin(), c.asin().conj()));
2121 assert!(close(c.scale(-1.0).asin(), c.asin().scale(-1.0)));
2123 assert!(
2125 -f64::consts::PI / 2.0 <= c.asin().re && c.asin().re <= f64::consts::PI / 2.0
2126 );
2127 }
2128 }
2129
2130 #[test]
2131 fn test_acos() {
2132 assert!(close(_0_0i.acos(), _1_0i.scale(f64::consts::PI / 2.0)));
2133 assert!(close(_1_0i.acos(), _0_0i));
2134 assert!(close(
2135 _1_0i.scale(-1.0).acos(),
2136 _1_0i.scale(f64::consts::PI)
2137 ));
2138 assert!(close(
2139 _0_1i.acos(),
2140 Complex::new(f64::consts::PI / 2.0, (2.0.sqrt() - 1.0).ln())
2141 ));
2142 for &c in all_consts.iter() {
2143 assert!(close(c.conj().acos(), c.acos().conj()));
2145 assert!(0.0 <= c.acos().re && c.acos().re <= f64::consts::PI);
2147 }
2148 }
2149
2150 #[test]
2151 fn test_atan() {
2152 assert!(close(_0_0i.atan(), _0_0i));
2153 assert!(close(_1_0i.atan(), _1_0i.scale(f64::consts::PI / 4.0)));
2154 assert!(close(
2155 _1_0i.scale(-1.0).atan(),
2156 _1_0i.scale(-f64::consts::PI / 4.0)
2157 ));
2158 assert!(close(_0_1i.atan(), Complex::new(0.0, f64::infinity())));
2159 for &c in all_consts.iter() {
2160 assert!(close(c.conj().atan(), c.atan().conj()));
2162 assert!(close(c.scale(-1.0).atan(), c.atan().scale(-1.0)));
2164 assert!(
2166 -f64::consts::PI / 2.0 <= c.atan().re && c.atan().re <= f64::consts::PI / 2.0
2167 );
2168 }
2169 }
2170
2171 #[test]
2172 fn test_sinh() {
2173 assert!(close(_0_0i.sinh(), _0_0i));
2174 assert!(close(
2175 _1_0i.sinh(),
2176 _1_0i.scale((f64::consts::E - 1.0 / f64::consts::E) / 2.0)
2177 ));
2178 assert!(close(_0_1i.sinh(), _0_1i.scale(1.0.sin())));
2179 for &c in all_consts.iter() {
2180 assert!(close(c.conj().sinh(), c.sinh().conj()));
2182 assert!(close(c.scale(-1.0).sinh(), c.sinh().scale(-1.0)));
2184 }
2185 }
2186
2187 #[test]
2188 fn test_cosh() {
2189 assert!(close(_0_0i.cosh(), _1_0i));
2190 assert!(close(
2191 _1_0i.cosh(),
2192 _1_0i.scale((f64::consts::E + 1.0 / f64::consts::E) / 2.0)
2193 ));
2194 assert!(close(_0_1i.cosh(), _1_0i.scale(1.0.cos())));
2195 for &c in all_consts.iter() {
2196 assert!(close(c.conj().cosh(), c.cosh().conj()));
2198 assert!(close(c.scale(-1.0).cosh(), c.cosh()));
2200 }
2201 }
2202
2203 #[test]
2204 fn test_tanh() {
2205 assert!(close(_0_0i.tanh(), _0_0i));
2206 assert!(close(
2207 _1_0i.tanh(),
2208 _1_0i.scale((f64::consts::E.powi(2) - 1.0) / (f64::consts::E.powi(2) + 1.0))
2209 ));
2210 assert!(close(_0_1i.tanh(), _0_1i.scale(1.0.tan())));
2211 for &c in all_consts.iter() {
2212 assert!(close(c.conj().tanh(), c.conj().tanh()));
2214 assert!(close(c.scale(-1.0).tanh(), c.tanh().scale(-1.0)));
2216 }
2217 }
2218
2219 #[test]
2220 fn test_asinh() {
2221 assert!(close(_0_0i.asinh(), _0_0i));
2222 assert!(close(_1_0i.asinh(), _1_0i.scale(1.0 + 2.0.sqrt()).ln()));
2223 assert!(close(_0_1i.asinh(), _0_1i.scale(f64::consts::PI / 2.0)));
2224 assert!(close(
2225 _0_1i.asinh().scale(-1.0),
2226 _0_1i.scale(-f64::consts::PI / 2.0)
2227 ));
2228 for &c in all_consts.iter() {
2229 assert!(close(c.conj().asinh(), c.conj().asinh()));
2231 assert!(close(c.scale(-1.0).asinh(), c.asinh().scale(-1.0)));
2233 assert!(
2235 -f64::consts::PI / 2.0 <= c.asinh().im && c.asinh().im <= f64::consts::PI / 2.0
2236 );
2237 }
2238 }
2239
2240 #[test]
2241 fn test_acosh() {
2242 assert!(close(_0_0i.acosh(), _0_1i.scale(f64::consts::PI / 2.0)));
2243 assert!(close(_1_0i.acosh(), _0_0i));
2244 assert!(close(
2245 _1_0i.scale(-1.0).acosh(),
2246 _0_1i.scale(f64::consts::PI)
2247 ));
2248 for &c in all_consts.iter() {
2249 assert!(close(c.conj().acosh(), c.conj().acosh()));
2251 assert!(
2253 -f64::consts::PI <= c.acosh().im
2254 && c.acosh().im <= f64::consts::PI
2255 && 0.0 <= c.cosh().re
2256 );
2257 }
2258 }
2259
2260 #[test]
2261 fn test_atanh() {
2262 assert!(close(_0_0i.atanh(), _0_0i));
2263 assert!(close(_0_1i.atanh(), _0_1i.scale(f64::consts::PI / 4.0)));
2264 assert!(close(_1_0i.atanh(), Complex::new(f64::infinity(), 0.0)));
2265 for &c in all_consts.iter() {
2266 assert!(close(c.conj().atanh(), c.conj().atanh()));
2268 assert!(close(c.scale(-1.0).atanh(), c.atanh().scale(-1.0)));
2270 assert!(
2272 -f64::consts::PI / 2.0 <= c.atanh().im && c.atanh().im <= f64::consts::PI / 2.0
2273 );
2274 }
2275 }
2276
2277 #[test]
2278 fn test_exp_ln() {
2279 for &c in all_consts.iter() {
2280 assert!(close(c.ln().exp(), c));
2282 }
2283 }
2284
2285 #[test]
2286 fn test_exp2_log() {
2287 for &c in all_consts.iter() {
2288 assert!(close(c.log2().exp2(), c));
2290 }
2291 }
2292
2293 #[test]
2294 fn test_trig_to_hyperbolic() {
2295 for &c in all_consts.iter() {
2296 assert!(close((_0_1i * c).sin(), _0_1i * c.sinh()));
2298 assert!(close((_0_1i * c).cos(), c.cosh()));
2300 assert!(close((_0_1i * c).tan(), _0_1i * c.tanh()));
2302 }
2303 }
2304
2305 #[test]
2306 fn test_trig_identities() {
2307 for &c in all_consts.iter() {
2308 assert!(close(c.tan(), c.sin() / c.cos()));
2310 assert!(close(c.sin() * c.sin() + c.cos() * c.cos(), _1_0i));
2312
2313 assert!(close(c.asin().sin(), c));
2315 assert!(close(c.acos().cos(), c));
2317 if c != _0_1i && c != _0_1i.scale(-1.0) {
2320 assert!(close(c.atan().tan(), c));
2321 }
2322
2323 assert!(close(
2325 ((_0_1i * c).exp() - (_0_1i * c).exp().inv()) / _0_1i.scale(2.0),
2326 c.sin()
2327 ));
2328 assert!(close(
2330 ((_0_1i * c).exp() + (_0_1i * c).exp().inv()).unscale(2.0),
2331 c.cos()
2332 ));
2333 assert!(close(
2335 _0_1i * (_1_0i - (_0_1i * c).scale(2.0).exp())
2336 / (_1_0i + (_0_1i * c).scale(2.0).exp()),
2337 c.tan()
2338 ));
2339 }
2340 }
2341
2342 #[test]
2343 fn test_hyperbolic_identites() {
2344 for &c in all_consts.iter() {
2345 assert!(close(c.tanh(), c.sinh() / c.cosh()));
2347 assert!(close(c.cosh() * c.cosh() - c.sinh() * c.sinh(), _1_0i));
2349
2350 assert!(close(c.asinh().sinh(), c));
2352 assert!(close(c.acosh().cosh(), c));
2354 if c != _1_0i && c != _1_0i.scale(-1.0) {
2357 assert!(close(c.atanh().tanh(), c));
2358 }
2359
2360 assert!(close((c.exp() - c.exp().inv()).unscale(2.0), c.sinh()));
2362 assert!(close((c.exp() + c.exp().inv()).unscale(2.0), c.cosh()));
2364 assert!(close(
2366 (c.scale(2.0).exp() - _1_0i) / (c.scale(2.0).exp() + _1_0i),
2367 c.tanh()
2368 ));
2369 }
2370 }
2371 }
2372
2373 macro_rules! test_a_op_b {
2375 ($a:ident + $b:expr, $answer:expr) => {
2376 assert_eq!($a + $b, $answer);
2377 assert_eq!(
2378 {
2379 let mut x = $a;
2380 x += $b;
2381 x
2382 },
2383 $answer
2384 );
2385 };
2386 ($a:ident - $b:expr, $answer:expr) => {
2387 assert_eq!($a - $b, $answer);
2388 assert_eq!(
2389 {
2390 let mut x = $a;
2391 x -= $b;
2392 x
2393 },
2394 $answer
2395 );
2396 };
2397 ($a:ident * $b:expr, $answer:expr) => {
2398 assert_eq!($a * $b, $answer);
2399 assert_eq!(
2400 {
2401 let mut x = $a;
2402 x *= $b;
2403 x
2404 },
2405 $answer
2406 );
2407 };
2408 ($a:ident / $b:expr, $answer:expr) => {
2409 assert_eq!($a / $b, $answer);
2410 assert_eq!(
2411 {
2412 let mut x = $a;
2413 x /= $b;
2414 x
2415 },
2416 $answer
2417 );
2418 };
2419 ($a:ident % $b:expr, $answer:expr) => {
2420 assert_eq!($a % $b, $answer);
2421 assert_eq!(
2422 {
2423 let mut x = $a;
2424 x %= $b;
2425 x
2426 },
2427 $answer
2428 );
2429 };
2430 }
2431
2432 macro_rules! test_op {
2434 ($a:ident $op:tt $b:expr, $answer:expr) => {
2435 test_a_op_b!($a $op $b, $answer);
2436 test_a_op_b!($a $op &$b, $answer);
2437 };
2438 }
2439
2440 mod complex_arithmetic {
2441 use super::{_05_05i, _0_0i, _0_1i, _1_0i, _1_1i, _4_2i, _neg1_1i, all_consts};
2442 use num_traits::{MulAdd, MulAddAssign, Zero};
2443
2444 #[test]
2445 fn test_add() {
2446 test_op!(_05_05i + _05_05i, _1_1i);
2447 test_op!(_0_1i + _1_0i, _1_1i);
2448 test_op!(_1_0i + _neg1_1i, _0_1i);
2449
2450 for &c in all_consts.iter() {
2451 test_op!(_0_0i + c, c);
2452 test_op!(c + _0_0i, c);
2453 }
2454 }
2455
2456 #[test]
2457 fn test_sub() {
2458 test_op!(_05_05i - _05_05i, _0_0i);
2459 test_op!(_0_1i - _1_0i, _neg1_1i);
2460 test_op!(_0_1i - _neg1_1i, _1_0i);
2461
2462 for &c in all_consts.iter() {
2463 test_op!(c - _0_0i, c);
2464 test_op!(c - c, _0_0i);
2465 }
2466 }
2467
2468 #[test]
2469 fn test_mul() {
2470 test_op!(_05_05i * _05_05i, _0_1i.unscale(2.0));
2471 test_op!(_1_1i * _0_1i, _neg1_1i);
2472
2473 test_op!(_0_1i * _0_1i, -_1_0i);
2475 assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i);
2476
2477 for &c in all_consts.iter() {
2478 test_op!(c * _1_0i, c);
2479 test_op!(_1_0i * c, c);
2480 }
2481 }
2482
2483 #[test]
2484 #[cfg(any(feature = "std", feature = "libm"))]
2485 fn test_mul_add_float() {
2486 assert_eq!(_05_05i.mul_add(_05_05i, _0_0i), _05_05i * _05_05i + _0_0i);
2487 assert_eq!(_05_05i * _05_05i + _0_0i, _05_05i.mul_add(_05_05i, _0_0i));
2488 assert_eq!(_0_1i.mul_add(_0_1i, _0_1i), _neg1_1i);
2489 assert_eq!(_1_0i.mul_add(_1_0i, _1_0i), _1_0i * _1_0i + _1_0i);
2490 assert_eq!(_1_0i * _1_0i + _1_0i, _1_0i.mul_add(_1_0i, _1_0i));
2491
2492 let mut x = _1_0i;
2493 x.mul_add_assign(_1_0i, _1_0i);
2494 assert_eq!(x, _1_0i * _1_0i + _1_0i);
2495
2496 for &a in &all_consts {
2497 for &b in &all_consts {
2498 for &c in &all_consts {
2499 let abc = a * b + c;
2500 assert_eq!(a.mul_add(b, c), abc);
2501 let mut x = a;
2502 x.mul_add_assign(b, c);
2503 assert_eq!(x, abc);
2504 }
2505 }
2506 }
2507 }
2508
2509 #[test]
2510 fn test_mul_add() {
2511 use super::Complex;
2512 const _0_0i: Complex<i32> = Complex { re: 0, im: 0 };
2513 const _1_0i: Complex<i32> = Complex { re: 1, im: 0 };
2514 const _1_1i: Complex<i32> = Complex { re: 1, im: 1 };
2515 const _0_1i: Complex<i32> = Complex { re: 0, im: 1 };
2516 const _neg1_1i: Complex<i32> = Complex { re: -1, im: 1 };
2517 const all_consts: [Complex<i32>; 5] = [_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i];
2518
2519 assert_eq!(_1_0i.mul_add(_1_0i, _0_0i), _1_0i * _1_0i + _0_0i);
2520 assert_eq!(_1_0i * _1_0i + _0_0i, _1_0i.mul_add(_1_0i, _0_0i));
2521 assert_eq!(_0_1i.mul_add(_0_1i, _0_1i), _neg1_1i);
2522 assert_eq!(_1_0i.mul_add(_1_0i, _1_0i), _1_0i * _1_0i + _1_0i);
2523 assert_eq!(_1_0i * _1_0i + _1_0i, _1_0i.mul_add(_1_0i, _1_0i));
2524
2525 let mut x = _1_0i;
2526 x.mul_add_assign(_1_0i, _1_0i);
2527 assert_eq!(x, _1_0i * _1_0i + _1_0i);
2528
2529 for &a in &all_consts {
2530 for &b in &all_consts {
2531 for &c in &all_consts {
2532 let abc = a * b + c;
2533 assert_eq!(a.mul_add(b, c), abc);
2534 let mut x = a;
2535 x.mul_add_assign(b, c);
2536 assert_eq!(x, abc);
2537 }
2538 }
2539 }
2540 }
2541
2542 #[test]
2543 fn test_div() {
2544 test_op!(_neg1_1i / _0_1i, _1_1i);
2545 for &c in all_consts.iter() {
2546 if c != Zero::zero() {
2547 test_op!(c / c, _1_0i);
2548 }
2549 }
2550 }
2551
2552 #[test]
2553 fn test_rem() {
2554 test_op!(_neg1_1i % _0_1i, _0_0i);
2555 test_op!(_4_2i % _0_1i, _0_0i);
2556 test_op!(_05_05i % _0_1i, _05_05i);
2557 test_op!(_05_05i % _1_1i, _05_05i);
2558 assert_eq!((_4_2i + _05_05i) % _0_1i, _05_05i);
2559 assert_eq!((_4_2i + _05_05i) % _1_1i, _05_05i);
2560 }
2561
2562 #[test]
2563 fn test_neg() {
2564 assert_eq!(-_1_0i + _0_1i, _neg1_1i);
2565 assert_eq!((-_0_1i) * _0_1i, _1_0i);
2566 for &c in all_consts.iter() {
2567 assert_eq!(-(-c), c);
2568 }
2569 }
2570 }
2571
2572 mod real_arithmetic {
2573 use super::super::Complex;
2574 use super::{_4_2i, _neg1_1i};
2575
2576 #[test]
2577 fn test_add() {
2578 test_op!(_4_2i + 0.5, Complex::new(4.5, 2.0));
2579 assert_eq!(0.5 + _4_2i, Complex::new(4.5, 2.0));
2580 }
2581
2582 #[test]
2583 fn test_sub() {
2584 test_op!(_4_2i - 0.5, Complex::new(3.5, 2.0));
2585 assert_eq!(0.5 - _4_2i, Complex::new(-3.5, -2.0));
2586 }
2587
2588 #[test]
2589 fn test_mul() {
2590 assert_eq!(_4_2i * 0.5, Complex::new(2.0, 1.0));
2591 assert_eq!(0.5 * _4_2i, Complex::new(2.0, 1.0));
2592 }
2593
2594 #[test]
2595 fn test_div() {
2596 assert_eq!(_4_2i / 0.5, Complex::new(8.0, 4.0));
2597 assert_eq!(0.5 / _4_2i, Complex::new(0.1, -0.05));
2598 }
2599
2600 #[test]
2601 fn test_rem() {
2602 assert_eq!(_4_2i % 2.0, Complex::new(0.0, 0.0));
2603 assert_eq!(_4_2i % 3.0, Complex::new(1.0, 2.0));
2604 assert_eq!(3.0 % _4_2i, Complex::new(3.0, 0.0));
2605 assert_eq!(_neg1_1i % 2.0, _neg1_1i);
2606 assert_eq!(-_4_2i % 3.0, Complex::new(-1.0, -2.0));
2607 }
2608
2609 #[test]
2610 fn test_div_rem_gaussian() {
2611 let max = Complex::new(255u8, 255u8);
2613 assert_eq!(max / 200, Complex::new(1, 1));
2614 assert_eq!(max % 200, Complex::new(55, 55));
2615 }
2616 }
2617
2618 #[test]
2619 fn test_to_string() {
2620 fn test(c: Complex64, s: String) {
2621 assert_eq!(c.to_string(), s);
2622 }
2623 test(_0_0i, "0+0i".to_string());
2624 test(_1_0i, "1+0i".to_string());
2625 test(_0_1i, "0+1i".to_string());
2626 test(_1_1i, "1+1i".to_string());
2627 test(_neg1_1i, "-1+1i".to_string());
2628 test(-_neg1_1i, "1-1i".to_string());
2629 test(_05_05i, "0.5+0.5i".to_string());
2630 }
2631
2632 #[test]
2633 fn test_string_formatting() {
2634 let a = Complex::new(1.23456, 123.456);
2635 assert_eq!(format!("{}", a), "1.23456+123.456i");
2636 assert_eq!(format!("{:.2}", a), "1.23+123.46i");
2637 assert_eq!(format!("{:.2e}", a), "1.23e0+1.23e2i");
2638 assert_eq!(format!("{:+.2E}", a), "+1.23E0+1.23E2i");
2639 #[cfg(feature = "std")]
2640 assert_eq!(format!("{:+20.2E}", a), " +1.23E0+1.23E2i");
2641
2642 let b = Complex::new(0x80, 0xff);
2643 assert_eq!(format!("{:X}", b), "80+FFi");
2644 assert_eq!(format!("{:#x}", b), "0x80+0xffi");
2645 assert_eq!(format!("{:+#b}", b), "+0b10000000+0b11111111i");
2646 assert_eq!(format!("{:+#o}", b), "+0o200+0o377i");
2647 #[cfg(feature = "std")]
2648 assert_eq!(format!("{:+#16o}", b), " +0o200+0o377i");
2649
2650 let c = Complex::new(-10, -10000);
2651 assert_eq!(format!("{}", c), "-10-10000i");
2652 #[cfg(feature = "std")]
2653 assert_eq!(format!("{:16}", c), " -10-10000i");
2654 }
2655
2656 #[test]
2657 fn test_hash() {
2658 let a = Complex::new(0i32, 0i32);
2659 let b = Complex::new(1i32, 0i32);
2660 let c = Complex::new(0i32, 1i32);
2661 assert!(crate::hash(&a) != crate::hash(&b));
2662 assert!(crate::hash(&b) != crate::hash(&c));
2663 assert!(crate::hash(&c) != crate::hash(&a));
2664 }
2665
2666 #[test]
2667 fn test_hashset() {
2668 use std::collections::HashSet;
2669 let a = Complex::new(0i32, 0i32);
2670 let b = Complex::new(1i32, 0i32);
2671 let c = Complex::new(0i32, 1i32);
2672
2673 let set: HashSet<_> = [a, b, c].iter().cloned().collect();
2674 assert!(set.contains(&a));
2675 assert!(set.contains(&b));
2676 assert!(set.contains(&c));
2677 assert!(!set.contains(&(a + b + c)));
2678 }
2679
2680 #[test]
2681 fn test_is_nan() {
2682 assert!(!_1_1i.is_nan());
2683 let a = Complex::new(f64::NAN, f64::NAN);
2684 assert!(a.is_nan());
2685 }
2686
2687 #[test]
2688 fn test_is_nan_special_cases() {
2689 let a = Complex::new(0f64, f64::NAN);
2690 let b = Complex::new(f64::NAN, 0f64);
2691 assert!(a.is_nan());
2692 assert!(b.is_nan());
2693 }
2694
2695 #[test]
2696 fn test_is_infinite() {
2697 let a = Complex::new(2f64, f64::INFINITY);
2698 assert!(a.is_infinite());
2699 }
2700
2701 #[test]
2702 fn test_is_finite() {
2703 assert!(_1_1i.is_finite())
2704 }
2705
2706 #[test]
2707 fn test_is_normal() {
2708 let a = Complex::new(0f64, f64::NAN);
2709 let b = Complex::new(2f64, f64::INFINITY);
2710 assert!(!a.is_normal());
2711 assert!(!b.is_normal());
2712 assert!(_1_1i.is_normal());
2713 }
2714
2715 #[test]
2716 fn test_from_str() {
2717 fn test(z: Complex64, s: &str) {
2718 assert_eq!(FromStr::from_str(s), Ok(z));
2719 }
2720 test(_0_0i, "0 + 0i");
2721 test(_0_0i, "0+0j");
2722 test(_0_0i, "0 - 0j");
2723 test(_0_0i, "0-0i");
2724 test(_0_0i, "0i + 0");
2725 test(_0_0i, "0");
2726 test(_0_0i, "-0");
2727 test(_0_0i, "0i");
2728 test(_0_0i, "0j");
2729 test(_0_0i, "+0j");
2730 test(_0_0i, "-0i");
2731
2732 test(_1_0i, "1 + 0i");
2733 test(_1_0i, "1+0j");
2734 test(_1_0i, "1 - 0j");
2735 test(_1_0i, "+1-0i");
2736 test(_1_0i, "-0j+1");
2737 test(_1_0i, "1");
2738
2739 test(_1_1i, "1 + i");
2740 test(_1_1i, "1+j");
2741 test(_1_1i, "1 + 1j");
2742 test(_1_1i, "1+1i");
2743 test(_1_1i, "i + 1");
2744 test(_1_1i, "1i+1");
2745 test(_1_1i, "+j+1");
2746
2747 test(_0_1i, "0 + i");
2748 test(_0_1i, "0+j");
2749 test(_0_1i, "-0 + j");
2750 test(_0_1i, "-0+i");
2751 test(_0_1i, "0 + 1i");
2752 test(_0_1i, "0+1j");
2753 test(_0_1i, "-0 + 1j");
2754 test(_0_1i, "-0+1i");
2755 test(_0_1i, "j + 0");
2756 test(_0_1i, "i");
2757 test(_0_1i, "j");
2758 test(_0_1i, "1j");
2759
2760 test(_neg1_1i, "-1 + i");
2761 test(_neg1_1i, "-1+j");
2762 test(_neg1_1i, "-1 + 1j");
2763 test(_neg1_1i, "-1+1i");
2764 test(_neg1_1i, "1i-1");
2765 test(_neg1_1i, "j + -1");
2766
2767 test(_05_05i, "0.5 + 0.5i");
2768 test(_05_05i, "0.5+0.5j");
2769 test(_05_05i, "5e-1+0.5j");
2770 test(_05_05i, "5E-1 + 0.5j");
2771 test(_05_05i, "5E-1i + 0.5");
2772 test(_05_05i, "0.05e+1j + 50E-2");
2773 }
2774
2775 #[test]
2776 fn test_from_str_radix() {
2777 fn test(z: Complex64, s: &str, radix: u32) {
2778 let res: Result<Complex64, <Complex64 as Num>::FromStrRadixErr> =
2779 Num::from_str_radix(s, radix);
2780 assert_eq!(res.unwrap(), z)
2781 }
2782 test(_4_2i, "4+2i", 10);
2783 test(Complex::new(15.0, 32.0), "F+20i", 16);
2784 test(Complex::new(15.0, 32.0), "1111+100000i", 2);
2785 test(Complex::new(-15.0, -32.0), "-F-20i", 16);
2786 test(Complex::new(-15.0, -32.0), "-1111-100000i", 2);
2787
2788 fn test_error(s: &str, radix: u32) -> ParseComplexError<<f64 as Num>::FromStrRadixErr> {
2789 let res = Complex64::from_str_radix(s, radix);
2790
2791 res.expect_err(&format!("Expected failure on input {:?}", s))
2792 }
2793
2794 let err = test_error("1ii", 19);
2795 if let ComplexErrorKind::UnsupportedRadix = err.kind {
2796 } else {
2798 panic!("Expected failure on invalid radix, got {:?}", err);
2799 }
2800
2801 let err = test_error("1 + 0", 16);
2802 if let ComplexErrorKind::ExprError = err.kind {
2803 } else {
2805 panic!("Expected failure on expr error, got {:?}", err);
2806 }
2807 }
2808
2809 #[test]
2810 #[should_panic(expected = "radix is too high")]
2811 fn test_from_str_radix_fail() {
2812 let _complex = Complex64::from_str_radix("1", 37);
2814 }
2815
2816 #[test]
2817 fn test_from_str_fail() {
2818 fn test(s: &str) {
2819 let complex: Result<Complex64, _> = FromStr::from_str(s);
2820 assert!(
2821 complex.is_err(),
2822 "complex {:?} -> {:?} should be an error",
2823 s,
2824 complex
2825 );
2826 }
2827 test("foo");
2828 test("6E");
2829 test("0 + 2.718");
2830 test("1 - -2i");
2831 test("314e-2ij");
2832 test("4.3j - i");
2833 test("1i - 2i");
2834 test("+ 1 - 3.0i");
2835 }
2836
2837 #[test]
2838 fn test_sum() {
2839 let v = vec![_0_1i, _1_0i];
2840 assert_eq!(v.iter().sum::<Complex64>(), _1_1i);
2841 assert_eq!(v.into_iter().sum::<Complex64>(), _1_1i);
2842 }
2843
2844 #[test]
2845 fn test_prod() {
2846 let v = vec![_0_1i, _1_0i];
2847 assert_eq!(v.iter().product::<Complex64>(), _0_1i);
2848 assert_eq!(v.into_iter().product::<Complex64>(), _0_1i);
2849 }
2850
2851 #[test]
2852 fn test_zero() {
2853 let zero = Complex64::zero();
2854 assert!(zero.is_zero());
2855
2856 let mut c = Complex::new(1.23, 4.56);
2857 assert!(!c.is_zero());
2858 assert_eq!(c + zero, c);
2859
2860 c.set_zero();
2861 assert!(c.is_zero());
2862 }
2863
2864 #[test]
2865 fn test_one() {
2866 let one = Complex64::one();
2867 assert!(one.is_one());
2868
2869 let mut c = Complex::new(1.23, 4.56);
2870 assert!(!c.is_one());
2871 assert_eq!(c * one, c);
2872
2873 c.set_one();
2874 assert!(c.is_one());
2875 }
2876
2877 #[test]
2878 #[allow(clippy::float_cmp)]
2879 fn test_const() {
2880 const R: f64 = 12.3;
2881 const I: f64 = -4.5;
2882 const C: Complex64 = Complex::new(R, I);
2883
2884 assert_eq!(C.re, 12.3);
2885 assert_eq!(C.im, -4.5);
2886 }
2887}