num_rational/
pow.rs

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}