num_complex/
pow.rs

1use super::Complex;
2
3use core::ops::Neg;
4#[cfg(feature = "std")]
5use traits::Float;
6use 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);
79#[cfg(has_i128)]
80pow_impl!(u128, i128);
81
82// Note: we can't add `impl<T: Float> Pow<T> for Complex<T>` because new blanket impls are a
83// breaking change.  Someone could already have their own `F` and `impl Pow<F> for Complex<F>`
84// which would conflict.  We can't even do this in a new semantic version, because we have to
85// gate it on the "std" feature, and features can't add breaking changes either.
86
87macro_rules! powf_impl {
88    ($F:ty) => {
89        #[cfg(feature = "std")]
90        impl<'a, T: Float> Pow<$F> for &'a Complex<T>
91        where
92            $F: Into<T>,
93        {
94            type Output = Complex<T>;
95
96            #[inline]
97            fn pow(self, exp: $F) -> Self::Output {
98                self.powf(exp.into())
99            }
100        }
101
102        #[cfg(feature = "std")]
103        impl<'a, 'b, T: Float> Pow<&'b $F> for &'a Complex<T>
104        where
105            $F: Into<T>,
106        {
107            type Output = Complex<T>;
108
109            #[inline]
110            fn pow(self, &exp: &$F) -> Self::Output {
111                self.powf(exp.into())
112            }
113        }
114
115        #[cfg(feature = "std")]
116        impl<T: Float> Pow<$F> for Complex<T>
117        where
118            $F: Into<T>,
119        {
120            type Output = Complex<T>;
121
122            #[inline]
123            fn pow(self, exp: $F) -> Self::Output {
124                self.powf(exp.into())
125            }
126        }
127
128        #[cfg(feature = "std")]
129        impl<'b, T: Float> Pow<&'b $F> for Complex<T>
130        where
131            $F: Into<T>,
132        {
133            type Output = Complex<T>;
134
135            #[inline]
136            fn pow(self, &exp: &$F) -> Self::Output {
137                self.powf(exp.into())
138            }
139        }
140    };
141}
142
143powf_impl!(f32);
144powf_impl!(f64);
145
146// These blanket impls are OK, because both the target type and the trait parameter would be
147// foreign to anyone else trying to implement something that would overlap, raising E0117.
148
149#[cfg(feature = "std")]
150impl<'a, T: Float> Pow<Complex<T>> for &'a Complex<T> {
151    type Output = Complex<T>;
152
153    #[inline]
154    fn pow(self, exp: Complex<T>) -> Self::Output {
155        self.powc(exp)
156    }
157}
158
159#[cfg(feature = "std")]
160impl<'a, 'b, T: Float> Pow<&'b Complex<T>> for &'a Complex<T> {
161    type Output = Complex<T>;
162
163    #[inline]
164    fn pow(self, &exp: &'b Complex<T>) -> Self::Output {
165        self.powc(exp)
166    }
167}
168
169#[cfg(feature = "std")]
170impl<T: Float> Pow<Complex<T>> for Complex<T> {
171    type Output = Complex<T>;
172
173    #[inline]
174    fn pow(self, exp: Complex<T>) -> Self::Output {
175        self.powc(exp)
176    }
177}
178
179#[cfg(feature = "std")]
180impl<'b, T: Float> Pow<&'b Complex<T>> for Complex<T> {
181    type Output = Complex<T>;
182
183    #[inline]
184    fn pow(self, &exp: &'b Complex<T>) -> Self::Output {
185        self.powc(exp)
186    }
187}