Skip to main content

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}