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);