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 ] |
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 | |