1 use super::Complex; 2 3 use core::ops::Neg; 4 #[cfg(any(feature = "std", feature = "libm"))] 5 use num_traits::Float; 6 use num_traits::{Num, One, Pow}; 7 8 macro_rules! pow_impl { 9 ($U:ty, $S:ty) => { 10 impl<'a, T: Clone + Num> Pow<$U> for &'a Complex<T> { 11 type Output = Complex<T>; 12 13 #[inline] 14 fn pow(self, mut exp: $U) -> Self::Output { 15 if exp == 0 { 16 return Complex::one(); 17 } 18 let mut base = self.clone(); 19 20 while exp & 1 == 0 { 21 base = base.clone() * base; 22 exp >>= 1; 23 } 24 25 if exp == 1 { 26 return base; 27 } 28 29 let mut acc = base.clone(); 30 while exp > 1 { 31 exp >>= 1; 32 base = base.clone() * base; 33 if exp & 1 == 1 { 34 acc = acc * base.clone(); 35 } 36 } 37 acc 38 } 39 } 40 41 impl<'a, 'b, T: Clone + Num> Pow<&'b $U> for &'a Complex<T> { 42 type Output = Complex<T>; 43 44 #[inline] 45 fn pow(self, exp: &$U) -> Self::Output { 46 self.pow(*exp) 47 } 48 } 49 50 impl<'a, T: Clone + Num + Neg<Output = T>> Pow<$S> for &'a Complex<T> { 51 type Output = Complex<T>; 52 53 #[inline] 54 fn pow(self, exp: $S) -> Self::Output { 55 if exp < 0 { 56 Pow::pow(&self.inv(), exp.wrapping_neg() as $U) 57 } else { 58 Pow::pow(self, exp as $U) 59 } 60 } 61 } 62 63 impl<'a, 'b, T: Clone + Num + Neg<Output = T>> Pow<&'b $S> for &'a Complex<T> { 64 type Output = Complex<T>; 65 66 #[inline] 67 fn pow(self, exp: &$S) -> Self::Output { 68 self.pow(*exp) 69 } 70 } 71 }; 72 } 73 74 pow_impl!(u8, i8); 75 pow_impl!(u16, i16); 76 pow_impl!(u32, i32); 77 pow_impl!(u64, i64); 78 pow_impl!(usize, isize); 79 pow_impl!(u128, i128); 80 81 // Note: we can't add `impl<T: Float> Pow<T> for Complex<T>` because new blanket impls are a 82 // breaking change. Someone could already have their own `F` and `impl Pow<F> for Complex<F>` 83 // which would conflict. We can't even do this in a new semantic version, because we have to 84 // gate it on the "std" feature, and features can't add breaking changes either. 85 86 macro_rules! powf_impl { 87 ($F:ty) => { 88 #[cfg(any(feature = "std", feature = "libm"))] 89 impl<'a, T: Float> Pow<$F> for &'a Complex<T> 90 where 91 $F: Into<T>, 92 { 93 type Output = Complex<T>; 94 95 #[inline] 96 fn pow(self, exp: $F) -> Self::Output { 97 self.powf(exp.into()) 98 } 99 } 100 101 #[cfg(any(feature = "std", feature = "libm"))] 102 impl<'a, 'b, T: Float> Pow<&'b $F> for &'a Complex<T> 103 where 104 $F: Into<T>, 105 { 106 type Output = Complex<T>; 107 108 #[inline] 109 fn pow(self, &exp: &$F) -> Self::Output { 110 self.powf(exp.into()) 111 } 112 } 113 114 #[cfg(any(feature = "std", feature = "libm"))] 115 impl<T: Float> Pow<$F> for Complex<T> 116 where 117 $F: Into<T>, 118 { 119 type Output = Complex<T>; 120 121 #[inline] 122 fn pow(self, exp: $F) -> Self::Output { 123 self.powf(exp.into()) 124 } 125 } 126 127 #[cfg(any(feature = "std", feature = "libm"))] 128 impl<'b, T: Float> Pow<&'b $F> for Complex<T> 129 where 130 $F: Into<T>, 131 { 132 type Output = Complex<T>; 133 134 #[inline] 135 fn pow(self, &exp: &$F) -> Self::Output { 136 self.powf(exp.into()) 137 } 138 } 139 }; 140 } 141 142 powf_impl!(f32); 143 powf_impl!(f64); 144 145 // These blanket impls are OK, because both the target type and the trait parameter would be 146 // foreign to anyone else trying to implement something that would overlap, raising E0117. 147 148 #[cfg(any(feature = "std", feature = "libm"))] 149 impl<'a, T: Float> Pow<Complex<T>> for &'a Complex<T> { 150 type Output = Complex<T>; 151 152 #[inline] pow(self, exp: Complex<T>) -> Self::Output153 fn pow(self, exp: Complex<T>) -> Self::Output { 154 self.powc(exp) 155 } 156 } 157 158 #[cfg(any(feature = "std", feature = "libm"))] 159 impl<'a, 'b, T: Float> Pow<&'b Complex<T>> for &'a Complex<T> { 160 type Output = Complex<T>; 161 162 #[inline] pow(self, &exp: &'b Complex<T>) -> Self::Output163 fn pow(self, &exp: &'b Complex<T>) -> Self::Output { 164 self.powc(exp) 165 } 166 } 167 168 #[cfg(any(feature = "std", feature = "libm"))] 169 impl<T: Float> Pow<Complex<T>> for Complex<T> { 170 type Output = Complex<T>; 171 172 #[inline] pow(self, exp: Complex<T>) -> Self::Output173 fn pow(self, exp: Complex<T>) -> Self::Output { 174 self.powc(exp) 175 } 176 } 177 178 #[cfg(any(feature = "std", feature = "libm"))] 179 impl<'b, T: Float> Pow<&'b Complex<T>> for Complex<T> { 180 type Output = Complex<T>; 181 182 #[inline] pow(self, &exp: &'b Complex<T>) -> Self::Output183 fn pow(self, &exp: &'b Complex<T>) -> Self::Output { 184 self.powc(exp) 185 } 186 } 187