const_num_traits/ops/pow2.rs
1//! Power-of-two operations on unsigned integers, mirroring
2//! `is_power_of_two` / `next_power_of_two` / `checked_next_power_of_two`
3//! (stable since Rust 1.0) and the still-unstable
4//! `wrapping_next_power_of_two`.
5//!
6//! Split: the predicate (`is_power_of_two`, a branchless
7//! `count_ones == 1` check) is separate from the constructors (the three
8//! `next_power_of_two` flavors, which share the `one_less` shift trick).
9//!
10//! **CT tiers**: [`IsPowerOfTwo`] is Tier B (popcount plus a boolean);
11//! [`NextPowerOfTwo`] is Tier C (data-dependent early-out and overflow
12//! panic).
13
14c0nst::c0nst! {
15/// Power-of-two predicate, for unsigned integers.
16pub c0nst trait IsPowerOfTwo: Sized {
17 /// Returns `true` if and only if `self == 2^k` for some integer `k`.
18 /// Zero is not a power of two.
19 ///
20 /// ```
21 /// use const_num_traits::IsPowerOfTwo;
22 ///
23 /// assert!(IsPowerOfTwo::is_power_of_two(16u8));
24 /// assert!(!IsPowerOfTwo::is_power_of_two(10u8));
25 /// assert!(!IsPowerOfTwo::is_power_of_two(0u8));
26 /// ```
27 fn is_power_of_two(self) -> bool;
28}
29}
30
31c0nst::c0nst! {
32/// Rounding up to a power of two, for unsigned integers.
33pub c0nst trait NextPowerOfTwo: Sized {
34 /// Returns the smallest power of two greater than or equal to `self`.
35 ///
36 /// # Panics
37 ///
38 /// With overflow checks enabled, panics if the next power of two doesn't
39 /// fit in the type; without them, the result is wrapped (and wrong),
40 /// matching the inherent method.
41 type Output;
42 fn next_power_of_two(self) -> Self::Output;
43
44 /// Returns the smallest power of two greater than or equal to `self`,
45 /// or `None` if it doesn't fit in the type.
46 ///
47 /// ```
48 /// use const_num_traits::NextPowerOfTwo;
49 ///
50 /// assert_eq!(NextPowerOfTwo::checked_next_power_of_two(200u8), None);
51 /// assert_eq!(NextPowerOfTwo::checked_next_power_of_two(3u8), Some(4));
52 /// ```
53 fn checked_next_power_of_two(self) -> Option<Self::Output>;
54
55 /// Returns the smallest power of two greater than or equal to `self`,
56 /// or 0 if it doesn't fit in the type (i.e. the result wraps to zero).
57 ///
58 /// This mirrors the still-unstable `wrapping_next_power_of_two` inherent
59 /// method.
60 fn wrapping_next_power_of_two(self) -> Self::Output;
61}
62}
63
64macro_rules! power_of_two_impl {
65 ($($t:ty)*) => {$(
66 c0nst::c0nst! {
67 c0nst impl IsPowerOfTwo for $t {
68 #[inline]
69 fn is_power_of_two(self) -> bool {
70 <$t>::is_power_of_two(self)
71 }
72 }
73 }
74
75 c0nst::c0nst! {
76 c0nst impl NextPowerOfTwo for $t {
77 type Output = $t;
78 #[inline]
79 fn next_power_of_two(self) -> Self {
80 <$t>::next_power_of_two(self)
81 }
82
83 #[inline]
84 fn checked_next_power_of_two(self) -> Option<Self> {
85 <$t>::checked_next_power_of_two(self)
86 }
87
88 // unstable in std; same one-less-than trick as core
89 #[inline]
90 fn wrapping_next_power_of_two(self) -> Self {
91 if self <= 1 {
92 return 1;
93 }
94 let one_less = <$t>::MAX >> <$t>::leading_zeros(self - 1);
95 one_less.wrapping_add(1)
96 }
97 }
98 }
99 )*};
100}
101
102power_of_two_impl!(usize u8 u16 u32 u64 u128);
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn power_of_two() {
110 assert!(IsPowerOfTwo::is_power_of_two(1u8));
111 assert!(IsPowerOfTwo::is_power_of_two(128u8));
112 assert!(!IsPowerOfTwo::is_power_of_two(0u8));
113 assert_eq!(NextPowerOfTwo::next_power_of_two(0u8), 1);
114 assert_eq!(NextPowerOfTwo::next_power_of_two(100u8), 128);
115 assert_eq!(NextPowerOfTwo::checked_next_power_of_two(128u8), Some(128));
116 assert_eq!(NextPowerOfTwo::checked_next_power_of_two(129u8), None);
117 assert_eq!(NextPowerOfTwo::wrapping_next_power_of_two(129u8), 0);
118 assert_eq!(NextPowerOfTwo::wrapping_next_power_of_two(0u8), 1);
119 assert_eq!(NextPowerOfTwo::wrapping_next_power_of_two(65u8), 128);
120 }
121}