1use super::Complex;
2
3use core::ops::Neg;
4#[cfg(any(feature = "std", feature = "libm"))]
5use num_traits::Float;
6use num_traits::{Num, One, Pow};
7
8macro_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
74pow_impl!(u8, i8);
75pow_impl!(u16, i16);
76pow_impl!(u32, i32);
77pow_impl!(u64, i64);
78pow_impl!(usize, isize);
79pow_impl!(u128, i128);
80
81macro_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
142powf_impl!(f32);
143powf_impl!(f64);
144
145#[cfg(any(feature = "std", feature = "libm"))]
149impl<'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"))]
159impl<'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: &'b Complex<T>) -> Self::Output {
164 self.powc(exp)
165 }
166}
167
168#[cfg(any(feature = "std", feature = "libm"))]
169impl<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"))]
179impl<'b, T: Float> Pow<&'b Complex<T>> for Complex<T> {
180 type Output = Complex<T>;
181
182 #[inline]
183 fn pow(self, &exp: &'b Complex<T>) -> Self::Output {
184 self.powc(exp)
185 }
186}