malachite_base/num/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::num::arithmetic::traits::{NextPowerOf2, NextPowerOf2Assign, PowerOf2, Sign};
10use crate::num::basic::floats::PrimitiveFloat;
11use crate::num::conversion::traits::SciMantissaAndExponent;
12use core::cmp::Ordering::*;
13
14macro_rules! impl_next_power_of_2_unsigned {
15    ($t:ident) => {
16        impl NextPowerOf2 for $t {
17            type Output = $t;
18
19            /// This is a wrapper over the `next_power_of_two` functions in the standard library,
20            /// for example [this one](u32::next_power_of_two).
21            #[inline]
22            fn next_power_of_2(self) -> $t {
23                $t::next_power_of_two(self)
24            }
25        }
26
27        impl NextPowerOf2Assign for $t {
28            /// Replaces a number with the smallest power of 2 greater than or equal to it.
29            ///
30            /// $x \gets 2^{\lceil \log_2 x \rceil}$.
31            ///
32            /// # Worst-case complexity
33            /// Constant time and additional memory.
34            ///
35            /// # Panics
36            /// Panics if the next power of 2 is greater than the type's maximum value.
37            ///
38            /// # Examples
39            /// See [here](super::next_power_of_2#next_power_of_2_assign).
40            #[inline]
41            fn next_power_of_2_assign(&mut self) {
42                *self = $t::next_power_of_2(*self);
43            }
44        }
45    };
46}
47apply_to_unsigneds!(impl_next_power_of_2_unsigned);
48
49macro_rules! impl_next_power_of_2_primitive_float {
50    ($t:ident) => {
51        impl NextPowerOf2 for $t {
52            type Output = $t;
53
54            /// Finds the smallest power of 2 greater than or equal to a number.
55            ///
56            /// $x \gets 2^{\lceil \log_2 x \rceil}$.
57            ///
58            /// # Worst-case complexity
59            /// Constant time and additional memory.
60            ///
61            /// # Panics
62            /// Panics if `self` has a negative sign (positive zero is allowed, but negative zero is
63            /// not), or if the next power of 2 is greater than the type's maximum value.
64            ///
65            /// # Examples
66            /// See [here](super::next_power_of_2#next_power_of_2).
67            #[inline]
68            fn next_power_of_2(self) -> $t {
69                assert_eq!(self.sign(), Greater);
70                assert!(self.is_finite());
71                if self == 0.0 {
72                    return $t::MIN_POSITIVE_SUBNORMAL;
73                }
74                let (mantissa, exponent) = self.sci_mantissa_and_exponent();
75                if mantissa == 1.0 {
76                    self
77                } else if exponent == $t::MAX_EXPONENT {
78                    panic!("Next power of 2 is too large to represent");
79                } else {
80                    $t::power_of_2(exponent + 1)
81                }
82            }
83        }
84
85        impl NextPowerOf2Assign for $t {
86            /// Replaces a number with the smallest power of 2 greater than or equal to it.
87            ///
88            /// $x \gets 2^{\lceil \log_2 x \rceil}$.
89            ///
90            /// # Worst-case complexity
91            /// Constant time and additional memory.
92            ///
93            /// # Panics
94            /// Panics if the next power of 2 is greater than the type's maximum value.
95            ///
96            /// # Examples
97            /// See [here](super::next_power_of_2#next_power_of_2_assign).
98            #[inline]
99            fn next_power_of_2_assign(&mut self) {
100                *self = $t::next_power_of_2(*self);
101            }
102        }
103    };
104}
105apply_to_primitive_floats!(impl_next_power_of_2_primitive_float);