malachite_q/arithmetic/
pow.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::Rational;
10use malachite_base::num::arithmetic::traits::{
11    Parity, Pow, PowAssign, Reciprocal, ReciprocalAssign,
12};
13
14impl Pow<u64> for Rational {
15    type Output = Self;
16
17    /// Raises a [`Rational`] to a power, taking the [`Rational`] by value.
18    ///
19    /// $f(x, n) = x^n$.
20    ///
21    /// # Worst-case complexity
22    /// $T(n, m) = O(nm \log (nm) \log\log (nm))$
23    ///
24    /// $M(n, m) = O(nm \log (nm))$
25    ///
26    /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
27    /// `exp`.
28    ///
29    /// # Examples
30    /// ```
31    /// use malachite_base::num::arithmetic::traits::Pow;
32    /// use malachite_q::Rational;
33    ///
34    /// assert_eq!(
35    ///     Rational::from_signeds(22, 7).pow(3u64).to_string(),
36    ///     "10648/343"
37    /// );
38    /// assert_eq!(
39    ///     Rational::from_signeds(-22, 7).pow(3u64).to_string(),
40    ///     "-10648/343"
41    /// );
42    /// assert_eq!(
43    ///     Rational::from_signeds(-22, 7).pow(4u64).to_string(),
44    ///     "234256/2401"
45    /// );
46    /// ```
47    #[inline]
48    fn pow(mut self, exp: u64) -> Self {
49        self.pow_assign(exp);
50        self
51    }
52}
53
54impl Pow<u64> for &Rational {
55    type Output = Rational;
56
57    /// Raises a [`Rational`] to a power, taking the [`Rational`] by reference.
58    ///
59    /// $f(x, n) = x^n$.
60    ///
61    /// # Worst-case complexity
62    /// $T(n, m) = O(nm \log (nm) \log\log (nm))$
63    ///
64    /// $M(n, m) = O(nm \log (nm))$
65    ///
66    /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
67    /// `exp`.
68    ///
69    /// # Examples
70    /// ```
71    /// use malachite_base::num::arithmetic::traits::Pow;
72    /// use malachite_q::Rational;
73    ///
74    /// assert_eq!(
75    ///     (&Rational::from_signeds(22, 7)).pow(3u64).to_string(),
76    ///     "10648/343"
77    /// );
78    /// assert_eq!(
79    ///     (&Rational::from_signeds(-22, 7)).pow(3u64).to_string(),
80    ///     "-10648/343"
81    /// );
82    /// assert_eq!(
83    ///     (&Rational::from_signeds(-22, 7)).pow(4u64).to_string(),
84    ///     "234256/2401"
85    /// );
86    /// ```
87    #[inline]
88    fn pow(self, exp: u64) -> Rational {
89        Rational {
90            sign: self.sign || exp.even(),
91            numerator: (&self.numerator).pow(exp),
92            denominator: (&self.denominator).pow(exp),
93        }
94    }
95}
96
97impl PowAssign<u64> for Rational {
98    /// Raises a [`Rational`] to a power in place.
99    ///
100    /// $x \gets x^n$.
101    ///
102    /// # Worst-case complexity
103    /// $T(n, m) = O(nm \log (nm) \log\log (nm))$
104    ///
105    /// $M(n, m) = O(nm \log (nm))$
106    ///
107    /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
108    /// `exp`.
109    ///
110    /// # Examples
111    /// ```
112    /// use malachite_base::num::arithmetic::traits::PowAssign;
113    /// use malachite_q::Rational;
114    ///
115    /// let mut x = Rational::from_signeds(22, 7);
116    /// x.pow_assign(3u64);
117    /// assert_eq!(x.to_string(), "10648/343");
118    ///
119    /// let mut x = Rational::from_signeds(-22, 7);
120    /// x.pow_assign(3u64);
121    /// assert_eq!(x.to_string(), "-10648/343");
122    ///
123    /// let mut x = Rational::from_signeds(22, 7);
124    /// x.pow_assign(4u64);
125    /// assert_eq!(x.to_string(), "234256/2401");
126    /// ```
127    fn pow_assign(&mut self, exp: u64) {
128        self.sign |= exp.even();
129        self.numerator.pow_assign(exp);
130        self.denominator.pow_assign(exp);
131    }
132}
133
134impl Pow<i64> for Rational {
135    type Output = Self;
136
137    /// Raises a [`Rational`] to a power, taking the [`Rational`] by value.
138    ///
139    /// $f(x, n) = x^n$.
140    ///
141    /// # Worst-case complexity
142    /// $T(n, m) = O(nm \log (nm) \log\log (nm))$
143    ///
144    /// $M(n, m) = O(nm \log (nm))$
145    ///
146    /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
147    /// `exp.abs()`.
148    ///
149    /// # Panics
150    /// Panics if `self` is zero and `exp` is negative.
151    ///
152    /// # Examples
153    /// ```
154    /// use malachite_base::num::arithmetic::traits::Pow;
155    /// use malachite_q::Rational;
156    ///
157    /// assert_eq!(
158    ///     Rational::from_signeds(22, 7).pow(3i64).to_string(),
159    ///     "10648/343"
160    /// );
161    /// assert_eq!(
162    ///     Rational::from_signeds(-22, 7).pow(3i64).to_string(),
163    ///     "-10648/343"
164    /// );
165    /// assert_eq!(
166    ///     Rational::from_signeds(-22, 7).pow(4i64).to_string(),
167    ///     "234256/2401"
168    /// );
169    /// assert_eq!(
170    ///     Rational::from_signeds(22, 7).pow(-3i64).to_string(),
171    ///     "343/10648"
172    /// );
173    /// assert_eq!(
174    ///     Rational::from_signeds(-22, 7).pow(-3i64).to_string(),
175    ///     "-343/10648"
176    /// );
177    /// assert_eq!(
178    ///     Rational::from_signeds(-22, 7).pow(-4i64).to_string(),
179    ///     "2401/234256"
180    /// );
181    /// ```
182    #[inline]
183    fn pow(mut self, exp: i64) -> Self {
184        self.pow_assign(exp);
185        self
186    }
187}
188
189impl Pow<i64> for &Rational {
190    type Output = Rational;
191
192    /// Raises a [`Rational`] to a power, taking the [`Rational`] by reference.
193    ///
194    /// $f(x, n) = x^n$.
195    ///
196    /// # Worst-case complexity
197    /// $T(n, m) = O(nm \log (nm) \log\log (nm))$
198    ///
199    /// $M(n, m) = O(nm \log (nm))$
200    ///
201    /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
202    /// `exp.abs()`.
203    ///
204    /// # Panics
205    /// Panics if `self` is zero and `exp` is negative.
206    ///
207    /// # Examples
208    /// ```
209    /// use malachite_base::num::arithmetic::traits::Pow;
210    /// use malachite_q::Rational;
211    ///
212    /// assert_eq!(
213    ///     (&Rational::from_signeds(22, 7)).pow(3i64).to_string(),
214    ///     "10648/343"
215    /// );
216    /// assert_eq!(
217    ///     (&Rational::from_signeds(-22, 7)).pow(3i64).to_string(),
218    ///     "-10648/343"
219    /// );
220    /// assert_eq!(
221    ///     (&Rational::from_signeds(-22, 7)).pow(4i64).to_string(),
222    ///     "234256/2401"
223    /// );
224    /// assert_eq!(
225    ///     (&Rational::from_signeds(22, 7)).pow(-3i64).to_string(),
226    ///     "343/10648"
227    /// );
228    /// assert_eq!(
229    ///     (&Rational::from_signeds(-22, 7)).pow(-3i64).to_string(),
230    ///     "-343/10648"
231    /// );
232    /// assert_eq!(
233    ///     (&Rational::from_signeds(-22, 7)).pow(-4i64).to_string(),
234    ///     "2401/234256"
235    /// );
236    /// ```
237    #[inline]
238    fn pow(self, exp: i64) -> Rational {
239        let abs_exp = exp.unsigned_abs();
240        if exp >= 0 {
241            self.pow(abs_exp)
242        } else {
243            self.pow(abs_exp).reciprocal()
244        }
245    }
246}
247
248impl PowAssign<i64> for Rational {
249    /// Raises a [`Rational`] to a power in place.
250    ///
251    /// $x \gets x^n$.
252    ///
253    /// # Worst-case complexity
254    /// $T(n, m) = O(nm \log (nm) \log\log (nm))$
255    ///
256    /// $M(n, m) = O(nm \log (nm))$
257    ///
258    /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
259    /// `exp.abs()`.
260    ///
261    /// # Panics
262    /// Panics if `self` is zero and `exp` is negative.
263    ///
264    /// # Examples
265    /// ```
266    /// use malachite_base::num::arithmetic::traits::PowAssign;
267    /// use malachite_q::Rational;
268    ///
269    /// let mut x = Rational::from_signeds(22, 7);
270    /// x.pow_assign(3i64);
271    /// assert_eq!(x.to_string(), "10648/343");
272    ///
273    /// let mut x = Rational::from_signeds(-22, 7);
274    /// x.pow_assign(3i64);
275    /// assert_eq!(x.to_string(), "-10648/343");
276    ///
277    /// let mut x = Rational::from_signeds(22, 7);
278    /// x.pow_assign(4i64);
279    /// assert_eq!(x.to_string(), "234256/2401");
280    ///
281    /// let mut x = Rational::from_signeds(22, 7);
282    /// x.pow_assign(-3i64);
283    /// assert_eq!(x.to_string(), "343/10648");
284    ///
285    /// let mut x = Rational::from_signeds(-22, 7);
286    /// x.pow_assign(-3i64);
287    /// assert_eq!(x.to_string(), "-343/10648");
288    ///
289    /// let mut x = Rational::from_signeds(22, 7);
290    /// x.pow_assign(-4i64);
291    /// assert_eq!(x.to_string(), "2401/234256");
292    /// ```
293    fn pow_assign(&mut self, exp: i64) {
294        let abs_exp = exp.unsigned_abs();
295        if exp >= 0 {
296            self.pow_assign(abs_exp);
297        } else {
298            self.pow_assign(abs_exp);
299            self.reciprocal_assign();
300        }
301    }
302}