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 ] |
153 | 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 ] |
163 | fn pow(self, &exp: Complex: &'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 ] |
173 | 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 ] |
183 | fn pow(self, &exp: Complex: &'b Complex<T>) -> Self::Output { |
184 | self.powc(exp) |
185 | } |
186 | } |
187 | |