malachite_nz/natural/arithmetic/next_power_of_2.rs
1// Copyright © 2026 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::natural::InnerNatural::{Large, Small};
10use crate::natural::Natural;
11use crate::platform::Limb;
12use alloc::vec::Vec;
13use malachite_base::num::arithmetic::traits::{
14 ArithmeticCheckedShl, NextPowerOf2, NextPowerOf2Assign,
15};
16use malachite_base::slices::{slice_set_zero, slice_test_zero};
17
18// Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the
19// limbs of the smallest integer power of 2 greater than or equal to the `Natural`.
20//
21// This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero.
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 `xs.len()`.
29//
30// # Panics
31// Panics if `xs` is empty.
32pub_test! {limbs_next_power_of_2(xs: &[Limb]) -> Vec<Limb> {
33 let (xs_last, xs_init) = xs.split_last().unwrap();
34 let mut out;
35 if let Some(x) = xs_last.checked_next_power_of_two() {
36 out = vec![0; xs_init.len()];
37 if x == *xs_last && !slice_test_zero(xs_init) {
38 if let Some(x) = x.arithmetic_checked_shl(1) {
39 out.push(x);
40 } else {
41 out.push(0);
42 out.push(1);
43 }
44 } else {
45 out.push(x);
46 }
47 } else {
48 out = vec![0; xs.len()];
49 out.push(1);
50 }
51 out
52}}
53
54// Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the
55// limbs of the smallest integer power of 2 greater than or equal to the `Natural` to the input
56// slice. If the input slice is too small to hold the result, the limbs are all set to zero and the
57// carry bit, `true`, is returned. Otherwise, `false` is returned.
58//
59// This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero.
60//
61// # Worst-case complexity
62// $T(n) = O(n)$
63//
64// $M(n) = O(1)$
65//
66// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
67//
68// # Panics
69// Panics if `xs` is empty.
70pub_test! {limbs_slice_next_power_of_2_in_place(xs: &mut [Limb]) -> bool {
71 let (xs_last, xs_init) = xs.split_last_mut().unwrap();
72 if let Some(x) = xs_last.checked_next_power_of_two() {
73 if x == *xs_last && !slice_test_zero(xs_init) {
74 slice_set_zero(xs_init);
75 if let Some(x) = x.arithmetic_checked_shl(1) {
76 *xs_last = x;
77 false
78 } else {
79 *xs_last = 0;
80 true
81 }
82 } else {
83 slice_set_zero(xs_init);
84 *xs_last = x;
85 false
86 }
87 } else {
88 slice_set_zero(xs_init);
89 *xs_last = 0;
90 true
91 }
92}}
93
94// Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the
95// limbs of the smallest integer power of 2 greater than or equal to the `Natural` to the input
96// `Vec`.
97//
98// This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero.
99//
100// # Worst-case complexity
101// $T(n) = O(n)$
102//
103// $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate)
104//
105// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
106//
107// # Panics
108// Panics if `xs` is empty.
109pub_test! {limbs_vec_next_power_of_2_in_place(xs: &mut Vec<Limb>) {
110 if limbs_slice_next_power_of_2_in_place(xs) {
111 xs.push(1);
112 }
113}}
114
115impl NextPowerOf2 for Natural {
116 type Output = Self;
117
118 /// Finds the smallest power of 2 greater than or equal to a [`Natural`]. The [`Natural`] is
119 /// taken by value.
120 ///
121 /// $f(x) = 2^{\lceil \log_2 x \rceil}$.
122 ///
123 /// # Worst-case complexity
124 /// $T(n) = O(n)$
125 ///
126 /// $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate)
127 ///
128 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
129 ///
130 /// # Examples
131 /// ```
132 /// use malachite_base::num::arithmetic::traits::{NextPowerOf2, Pow};
133 /// use malachite_base::num::basic::traits::Zero;
134 /// use malachite_nz::natural::Natural;
135 ///
136 /// assert_eq!(Natural::ZERO.next_power_of_2(), 1);
137 /// assert_eq!(Natural::from(123u32).next_power_of_2(), 128);
138 /// assert_eq!(
139 /// Natural::from(10u32).pow(12).next_power_of_2(),
140 /// 1099511627776u64
141 /// );
142 /// ```
143 #[inline]
144 fn next_power_of_2(mut self) -> Self {
145 self.next_power_of_2_assign();
146 self
147 }
148}
149
150impl NextPowerOf2 for &Natural {
151 type Output = Natural;
152
153 /// Finds the smallest power of 2 greater than or equal to a [`Natural`]. The [`Natural`] is
154 /// taken by reference.
155 ///
156 /// $f(x) = 2^{\lceil \log_2 x \rceil}$.
157 ///
158 /// # Worst-case complexity
159 /// $T(n) = O(n)$
160 ///
161 /// $M(n) = O(n)$
162 ///
163 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
164 ///
165 /// # Examples
166 /// ```
167 /// use malachite_base::num::arithmetic::traits::{NextPowerOf2, Pow};
168 /// use malachite_base::num::basic::traits::Zero;
169 /// use malachite_nz::natural::Natural;
170 ///
171 /// assert_eq!((&Natural::ZERO).next_power_of_2(), 1);
172 /// assert_eq!((&Natural::from(123u32)).next_power_of_2(), 128);
173 /// assert_eq!(
174 /// (&Natural::from(10u32).pow(12)).next_power_of_2(),
175 /// 1099511627776u64
176 /// );
177 /// ```
178 fn next_power_of_2(self) -> Natural {
179 Natural(match self {
180 Natural(Small(small)) => {
181 if let Some(result) = small.checked_next_power_of_two() {
182 Small(result)
183 } else {
184 Large(vec![0, 1])
185 }
186 }
187 Natural(Large(limbs)) => Large(limbs_next_power_of_2(limbs)),
188 })
189 }
190}
191
192impl NextPowerOf2Assign for Natural {
193 /// Replaces a [`Natural`] with the smallest power of 2 greater than or equal to it.
194 ///
195 /// $x \gets 2^{\lceil \log_2 x \rceil}$.
196 ///
197 /// # Worst-case complexity
198 /// $T(n) = O(n)$
199 ///
200 /// $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate)
201 ///
202 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
203 ///
204 /// # Examples
205 /// ```
206 /// use malachite_base::num::arithmetic::traits::{NextPowerOf2Assign, Pow};
207 /// use malachite_base::num::basic::traits::Zero;
208 /// use malachite_nz::natural::Natural;
209 ///
210 /// let mut x = Natural::ZERO;
211 /// x.next_power_of_2_assign();
212 /// assert_eq!(x, 1);
213 ///
214 /// let mut x = Natural::from(123u32);
215 /// x.next_power_of_2_assign();
216 /// assert_eq!(x, 128);
217 ///
218 /// let mut x = Natural::from(10u32).pow(12);
219 /// x.next_power_of_2_assign();
220 /// assert_eq!(x, 1099511627776u64);
221 /// ```
222 fn next_power_of_2_assign(&mut self) {
223 match self {
224 Self(Small(small)) => {
225 if let Some(pow) = small.checked_next_power_of_two() {
226 *small = pow;
227 } else {
228 *self = Self(Large(vec![0, 1]));
229 }
230 }
231 Self(Large(limbs)) => {
232 limbs_vec_next_power_of_2_in_place(limbs);
233 }
234 }
235 }
236}