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-
8988constexpr 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+
98136constexpr unsigned int ipow (unsigned int a, unsigned int b) {
99137 return b == 0 ? 1 : a * ipow (a, b - 1 );
100138}
0 commit comments