Skip to content

Commit b1e4c15

Browse files
committed
math: next_power_of_2
1 parent 1fa9eae commit b1e4c15

File tree

1 file changed

+40
-2
lines changed

1 file changed

+40
-2
lines changed

util/math.hh

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "util/math_tables.hh"
33
#include <algorithm>
44
#include <array>
5+
#include <climits>
56
#include <cstdint>
67
#include <cstdlib>
78
#include <numeric>
@@ -84,8 +85,6 @@ constexpr bool is_power_of_2(unsigned int v) {
8485
return v && ((v & (v - 1)) == 0);
8586
}
8687

87-
// Todo: log2_ceiling()
88-
8988
constexpr unsigned int log2_floor(const unsigned int x) {
9089
int i = 32;
9190
while (i--) {
@@ -95,6 +94,45 @@ constexpr unsigned int log2_floor(const unsigned int x) {
9594
return 0;
9695
}
9796

97+
// Returns 0 if next power of 2 cannot be represented in the type T
98+
template<typename T>
99+
constexpr T next_power_of_2(T value) noexcept {
100+
static_assert(std::is_integral<T>::value && !std::is_signed<T>::value,
101+
"next_power_of_2 only accepts unsigned integral types");
102+
103+
if (value == 0 || value == 1)
104+
return 1;
105+
106+
if (is_power_of_2(value))
107+
return value;
108+
109+
value |= value >> 1;
110+
value |= value >> 2;
111+
value |= value >> 4;
112+
if constexpr (sizeof(T) > 1) {
113+
value |= value >> 8;
114+
}
115+
if constexpr (sizeof(T) > 2) {
116+
value |= value >> 16;
117+
}
118+
if constexpr (sizeof(T) > 4) {
119+
value |= value >> 32;
120+
}
121+
122+
return value + 1;
123+
}
124+
125+
static_assert(next_power_of_2(0u) == 1); //2^0
126+
static_assert(next_power_of_2(1u) == 1); //2^0
127+
static_assert(next_power_of_2(2u) == 2); //2^1
128+
static_assert(next_power_of_2(3u) == 4); //2^2
129+
static_assert(next_power_of_2(123u) == 128);
130+
static_assert(next_power_of_2(511u) == 512);
131+
static_assert(next_power_of_2(512u) == 512);
132+
static_assert(next_power_of_2(513u) == 1024);
133+
static_assert(next_power_of_2(0x7FFFFFFFu) == 0x80000000u);
134+
static_assert(next_power_of_2(0x80000001u) == 0u); //overflow!
135+
98136
constexpr unsigned int ipow(unsigned int a, unsigned int b) {
99137
return b == 0 ? 1 : a * ipow(a, b - 1);
100138
}

0 commit comments

Comments
 (0)