1use crate::Ratio;
2
3use core::cmp;
4use num_integer::Integer;
5use num_traits::{One, Pow};
6
7macro_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}
44pow_unsigned_impl!(u8);
45pow_unsigned_impl!(u16);
46pow_unsigned_impl!(u32);
47pow_unsigned_impl!(u64);
48pow_unsigned_impl!(u128);
49pow_unsigned_impl!(usize);
50
51macro_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}
108pow_signed_impl!(i8, u8);
109pow_signed_impl!(i16, u16);
110pow_signed_impl!(i32, u32);
111pow_signed_impl!(i64, u64);
112pow_signed_impl!(i128, u128);
113pow_signed_impl!(isize, usize);
114
115#[cfg(feature = "num-bigint")]
116mod 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]
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]
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]
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]
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