malachite_q/arithmetic/next_power_of_2.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 core::cmp::Ordering::*;
11use malachite_base::num::arithmetic::traits::{NextPowerOf2, NextPowerOf2Assign, PowerOf2};
12use malachite_base::num::conversion::traits::ExactFrom;
13use malachite_base::num::logic::traits::SignificantBits;
14
15impl NextPowerOf2 for Rational {
16 type Output = Rational;
17
18 /// Finds the smallest power of 2 greater than or equal to a [`Rational`]. The [`Rational`] is
19 /// taken by value.
20 ///
21 /// $f(x) = 2^{\lceil \log_2 x \rceil}$.
22 ///
23 /// # Worst-case complexity
24 /// $T(n) = O(n)$
25 ///
26 /// $M(n) = O(n)$
27 ///
28 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
29 ///
30 /// # Panics
31 /// Panics if `self` is less than or equal to zero.
32 ///
33 /// # Examples
34 /// ```
35 /// use malachite_base::num::arithmetic::traits::NextPowerOf2;
36 /// use malachite_q::Rational;
37 ///
38 /// assert_eq!(Rational::from(123).next_power_of_2(), 128);
39 /// assert_eq!(
40 /// Rational::from_signeds(1, 10).next_power_of_2().to_string(),
41 /// "1/8"
42 /// );
43 /// ```
44 #[inline]
45 fn next_power_of_2(self) -> Rational {
46 assert!(self > 0);
47 let mut exponent = i64::exact_from(self.numerator.significant_bits())
48 - i64::exact_from(self.denominator.significant_bits());
49 match self.numerator.cmp_normalized(&self.denominator) {
50 Equal => return self,
51 Greater => exponent += 1,
52 _ => {}
53 }
54 Rational::power_of_2(exponent)
55 }
56}
57
58impl NextPowerOf2 for &Rational {
59 type Output = Rational;
60
61 /// Finds the smallest power of 2 greater than or equal to a [`Rational`]. The [`Rational`] is
62 /// taken by reference.
63 ///
64 /// $f(x) = 2^{\lceil \log_2 x \rceil}$.
65 ///
66 /// # Worst-case complexity
67 /// $T(n) = O(n)$
68 ///
69 /// $M(n) = O(n)$
70 ///
71 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
72 ///
73 /// # Panics
74 /// Panics if `self` is less than or equal to zero.
75 ///
76 /// # Examples
77 /// ```
78 /// use malachite_base::num::arithmetic::traits::NextPowerOf2;
79 /// use malachite_q::Rational;
80 ///
81 /// assert_eq!((&Rational::from(123)).next_power_of_2(), 128);
82 /// assert_eq!(
83 /// (&Rational::from_signeds(1, 10))
84 /// .next_power_of_2()
85 /// .to_string(),
86 /// "1/8"
87 /// );
88 /// ```
89 fn next_power_of_2(self) -> Rational {
90 assert!(*self > 0);
91 let mut exponent = i64::exact_from(self.numerator.significant_bits())
92 - i64::exact_from(self.denominator.significant_bits());
93 if self.numerator.cmp_normalized(&self.denominator) == Greater {
94 exponent += 1;
95 }
96 Rational::power_of_2(exponent)
97 }
98}
99
100impl NextPowerOf2Assign for Rational {
101 /// Finds the smallest power of 2 greater than or equal to a [`Rational`]. The [`Rational`] is
102 /// taken by reference.
103 ///
104 /// $f(x) = 2^{\lceil \log_2 x \rceil}$.
105 ///
106 /// # Worst-case complexity
107 /// $T(n) = O(n)$
108 ///
109 /// $M(n) = O(n)$
110 ///
111 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
112 ///
113 /// # Panics
114 /// Panics if `self` is less than or equal to zero.
115 ///
116 /// # Examples
117 /// ```
118 /// use malachite_base::num::arithmetic::traits::NextPowerOf2Assign;
119 /// use malachite_q::Rational;
120 ///
121 /// let mut x = Rational::from(123);
122 /// x.next_power_of_2_assign();
123 /// assert_eq!(x, 128);
124 ///
125 /// let mut x = Rational::from_signeds(1, 10);
126 /// x.next_power_of_2_assign();
127 /// assert_eq!(x.to_string(), "1/8");
128 /// ```
129 #[inline]
130 fn next_power_of_2_assign(&mut self) {
131 *self = (&*self).next_power_of_2();
132 }
133}