1 use crate::Ratio; 2 3 use core::cmp; 4 use num_integer::Integer; 5 use num_traits::{One, Pow}; 6 7 macro_rules! pow_unsigned_impl { 8 (@ $exp:ty) => { 9 type Output = Ratio<T>; 10 #[inline] 11 fn pow(self, expon: $exp) -> Ratio<T> { 12 Ratio::new_raw(self.numer.pow(expon), self.denom.pow(expon)) 13 } 14 }; 15 ($exp:ty) => { 16 impl<T: Clone + Integer + Pow<$exp, Output = T>> Pow<$exp> for Ratio<T> { 17 pow_unsigned_impl!(@ $exp); 18 } 19 impl<'a, T: Clone + Integer> Pow<$exp> for &'a Ratio<T> 20 where 21 &'a T: Pow<$exp, Output = T>, 22 { 23 pow_unsigned_impl!(@ $exp); 24 } 25 impl<'b, T: Clone + Integer + Pow<$exp, Output = T>> Pow<&'b $exp> for Ratio<T> { 26 type Output = Ratio<T>; 27 #[inline] 28 fn pow(self, expon: &'b $exp) -> Ratio<T> { 29 Pow::pow(self, *expon) 30 } 31 } 32 impl<'a, 'b, T: Clone + Integer> Pow<&'b $exp> for &'a Ratio<T> 33 where 34 &'a T: Pow<$exp, Output = T>, 35 { 36 type Output = Ratio<T>; 37 #[inline] 38 fn pow(self, expon: &'b $exp) -> Ratio<T> { 39 Pow::pow(self, *expon) 40 } 41 } 42 }; 43 } 44 pow_unsigned_impl!(u8); 45 pow_unsigned_impl!(u16); 46 pow_unsigned_impl!(u32); 47 pow_unsigned_impl!(u64); 48 pow_unsigned_impl!(u128); 49 pow_unsigned_impl!(usize); 50 51 macro_rules! pow_signed_impl { 52 (@ &'b BigInt, BigUint) => { 53 type Output = Ratio<T>; 54 #[inline] 55 fn pow(self, expon: &'b BigInt) -> Ratio<T> { 56 match expon.sign() { 57 Sign::NoSign => One::one(), 58 Sign::Minus => { 59 Pow::pow(self, expon.magnitude()).into_recip() 60 } 61 Sign::Plus => Pow::pow(self, expon.magnitude()), 62 } 63 } 64 }; 65 (@ $exp:ty, $unsigned:ty) => { 66 type Output = Ratio<T>; 67 #[inline] 68 fn pow(self, expon: $exp) -> Ratio<T> { 69 match expon.cmp(&0) { 70 cmp::Ordering::Equal => One::one(), 71 cmp::Ordering::Less => { 72 let expon = expon.wrapping_abs() as $unsigned; 73 Pow::pow(self, expon).into_recip() 74 } 75 cmp::Ordering::Greater => Pow::pow(self, expon as $unsigned), 76 } 77 } 78 }; 79 ($exp:ty, $unsigned:ty) => { 80 impl<T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<$exp> for Ratio<T> { 81 pow_signed_impl!(@ $exp, $unsigned); 82 } 83 impl<'a, T: Clone + Integer> Pow<$exp> for &'a Ratio<T> 84 where 85 &'a T: Pow<$unsigned, Output = T>, 86 { 87 pow_signed_impl!(@ $exp, $unsigned); 88 } 89 impl<'b, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<&'b $exp> for Ratio<T> { 90 type Output = Ratio<T>; 91 #[inline] 92 fn pow(self, expon: &'b $exp) -> Ratio<T> { 93 Pow::pow(self, *expon) 94 } 95 } 96 impl<'a, 'b, T: Clone + Integer> Pow<&'b $exp> for &'a Ratio<T> 97 where 98 &'a T: Pow<$unsigned, Output = T>, 99 { 100 type Output = Ratio<T>; 101 #[inline] 102 fn pow(self, expon: &'b $exp) -> Ratio<T> { 103 Pow::pow(self, *expon) 104 } 105 } 106 }; 107 } 108 pow_signed_impl!(i8, u8); 109 pow_signed_impl!(i16, u16); 110 pow_signed_impl!(i32, u32); 111 pow_signed_impl!(i64, u64); 112 pow_signed_impl!(i128, u128); 113 pow_signed_impl!(isize, usize); 114 115 #[cfg(feature = "num-bigint")] 116 mod bigint { 117 use super::*; 118 use num_bigint::{BigInt, BigUint, Sign}; 119 120 impl<T: Clone + Integer + for<'b> Pow<&'b BigUint, Output = T>> Pow<BigUint> for Ratio<T> { 121 type Output = Ratio<T>; 122 #[inline] pow(self, expon: BigUint) -> Ratio<T>123 fn pow(self, expon: BigUint) -> Ratio<T> { 124 Pow::pow(self, &expon) 125 } 126 } 127 impl<'a, T: Clone + Integer> Pow<BigUint> for &'a Ratio<T> 128 where 129 &'a T: for<'b> Pow<&'b BigUint, Output = T>, 130 { 131 type Output = Ratio<T>; 132 #[inline] pow(self, expon: BigUint) -> Ratio<T>133 fn pow(self, expon: BigUint) -> Ratio<T> { 134 Pow::pow(self, &expon) 135 } 136 } 137 impl<'b, T: Clone + Integer + Pow<&'b BigUint, Output = T>> Pow<&'b BigUint> for Ratio<T> { 138 pow_unsigned_impl!(@ &'b BigUint); 139 } 140 impl<'a, 'b, T: Clone + Integer> Pow<&'b BigUint> for &'a Ratio<T> 141 where 142 &'a T: Pow<&'b BigUint, Output = T>, 143 { 144 pow_unsigned_impl!(@ &'b BigUint); 145 } 146 147 impl<T: Clone + Integer + for<'b> Pow<&'b BigUint, Output = T>> Pow<BigInt> for Ratio<T> { 148 type Output = Ratio<T>; 149 #[inline] pow(self, expon: BigInt) -> Ratio<T>150 fn pow(self, expon: BigInt) -> Ratio<T> { 151 Pow::pow(self, &expon) 152 } 153 } 154 impl<'a, T: Clone + Integer> Pow<BigInt> for &'a Ratio<T> 155 where 156 &'a T: for<'b> Pow<&'b BigUint, Output = T>, 157 { 158 type Output = Ratio<T>; 159 #[inline] pow(self, expon: BigInt) -> Ratio<T>160 fn pow(self, expon: BigInt) -> Ratio<T> { 161 Pow::pow(self, &expon) 162 } 163 } 164 impl<'b, T: Clone + Integer + Pow<&'b BigUint, Output = T>> Pow<&'b BigInt> for Ratio<T> { 165 pow_signed_impl!(@ &'b BigInt, BigUint); 166 } 167 impl<'a, 'b, T: Clone + Integer> Pow<&'b BigInt> for &'a Ratio<T> 168 where 169 &'a T: Pow<&'b BigUint, Output = T>, 170 { 171 pow_signed_impl!(@ &'b BigInt, BigUint); 172 } 173 } 174