21 constexpr double log2 (
double x) {
28 constexpr uint32_t log2_lsb(
const T&)
30 static_assert(always_false<T>::value,
"log2_lsb can only be used with types uint32_t or uint64_t");
35 constexpr uint32_t log2_lsb<uint32_t>(
const uint32_t &x)
41 constexpr uint32_t index32[32] = {
42 0, 1, 28, 2, 29, 14, 24, 3,
43 30, 22, 20, 15, 25, 17, 4, 8,
44 31, 27, 13, 23, 21, 19, 16, 7,
45 26, 12, 18, 6, 11, 5, 10, 9
48 constexpr uint32_t debruijn32 = 0x077CB531u;
50 return index32[((x & -x) * debruijn32) >> 27];
54 constexpr uint32_t log2_lsb<uint64_t>(
const uint64_t &x)
60 constexpr uint32_t index64[64] = {
61 63, 0, 58, 1, 59, 47, 53, 2,
62 60, 39, 48, 27, 54, 33, 42, 3,
63 61, 51, 37, 40, 49, 18, 28, 20,
64 55, 30, 34, 11, 43, 14, 22, 4,
65 62, 57, 46, 52, 38, 26, 32, 41,
66 50, 36, 17, 19, 29, 10, 13, 21,
67 56, 45, 25, 31, 35, 16, 9, 12,
68 44, 24, 15, 8, 23, 7, 6, 5
71 constexpr uint64_t debruijn64 = 0x07EDD5E59A4E28C2ull;
73 return index64[((x & -x) * debruijn64) >> 58];
77 constexpr uint64_t floor_log2(T x)
91 constexpr uint64_t floor_log2<double>(
double x)
93 return std::floor(log2(x));
97 constexpr uint64_t floor_log2<uint32_t>(uint32_t x)
108 constexpr uint64_t lut[] = {
109 0, 9, 1, 10, 13, 21, 2, 29,
110 11, 14, 16, 18, 22, 25, 3, 30,
111 8, 12, 20, 28, 15, 17, 24, 7,
112 19, 27, 23, 6, 26, 5, 4, 31};
119 return lut[(uint32_t)(x * 0x07C4ACDDul) >> 27];
123 constexpr uint64_t floor_log2<uint64_t>(uint64_t x)
134 constexpr uint64_t lut[] = {
135 63, 0, 58, 1, 59, 47, 53, 2,
136 60, 39, 48, 27, 54, 33, 42, 3,
137 61, 51, 37, 40, 49, 18, 28, 20,
138 55, 30, 34, 11, 43, 14, 22, 4,
139 62, 57, 46, 52, 38, 26, 32, 41,
140 50, 36, 17, 19, 29, 10, 13, 21,
141 56, 45, 25, 31, 35, 16, 9, 12,
142 44, 24, 15, 8, 23, 7, 6, 5};
150 return lut[((uint64_t)((x - (x >> 1)) * 0x07EDD5E59A4E28C2ull)) >> 58];
153 constexpr uint64_t ceil_log2 (uint64_t x)
157 uint64_t y = floor_log2(x);
158 if ((
static_cast<uint64_t
>(1) << y) != x) {
164 constexpr uint64_t pow2 (uint64_t x) {
165 const uint64_t y =
static_cast<uint64_t
>(1) << x;
169 constexpr bool is_power_of_2 (uint64_t x) {
170 const bool y = x && !(x & (x - 1));
174 constexpr uint64_t next_power_of_2(uint64_t v)
179 return 1ull << ((
sizeof(uint64_t) * 8) - __builtin_clzll(v - 1ull));
182 constexpr uint64_t ones (uint64_t x) {
183 const uint64_t y = (
static_cast<uint64_t
>(1) << x) - 1;
195 return (x < 0 ? -x : x);
199 constexpr uint8_t abs<uint8_t>(uint8_t x) {
200 uint8_t sign_mask = int8_t(x) >> 7;
201 return (x + sign_mask) ^ sign_mask;
205 constexpr uint16_t abs<uint16_t>(uint16_t x) {
206 uint16_t sign_mask = int16_t(x) >> 15;
207 return (x + sign_mask) ^ sign_mask;
211 constexpr uint32_t abs<uint32_t>(uint32_t x) {
212 uint32_t sign_mask = int32_t(x) >> 31;
213 return (x + sign_mask) ^ sign_mask;
217 constexpr uint64_t abs<uint64_t>(uint64_t x) {
218 uint64_t sign_mask = int64_t(x) >> 63;
219 return (x + sign_mask) ^ sign_mask;
223 constexpr T gcd(T u, T v)
227 static_assert(always_false<T>::value,
"gcd can only be used with types uint32_t or uint64_t");
232 constexpr uint32_t gcd<uint32_t>(uint32_t u, uint32_t v)
235 if (u == 0 || v == 0)
240 uint32_t shift = log2_lsb(u | v);
267 constexpr uint64_t gcd<uint64_t>(uint64_t u, uint64_t v)
270 if (u == 0 || v == 0)
275 uint32_t shift = log2_lsb(u | v);
301 constexpr T lcm(
const T&,
const T&)
303 static_assert(always_false<T>::value,
"lcm can only be used with types uint32_t or uint64_t");
307 constexpr uint32_t lcm<uint32_t>(
const uint32_t &u,
const uint32_t &v)
315 return u / gcd(u, v) * v;
320 constexpr uint64_t lcm<uint64_t>(
const uint64_t &u,
const uint64_t &v)
328 return u / gcd(u, v) * v;
336 static_assert(std::is_integral<T>::value,
"sparta::safe_power only supports integer data types");
342 for (T x = 1; x < e; x++)
344 T old_result = result;
346 if (old_result > result)
348 throw SpartaException(
"power() overflowed!");
357 template <
typename T>
359 typename std::enable_if<
360 std::is_floating_point<T>::value,
362 approximatelyEqual(
const T a,
const T b,
363 const T epsilon = std::numeric_limits<T>::epsilon())
365 const T fabs_a = std::fabs(a);
366 const T fabs_b = std::fabs(b);
367 const T fabs_diff = std::fabs(a - b);
369 return fabs_diff <= ((fabs_a < fabs_b ? fabs_b : fabs_a) * epsilon);
374 static std::mt19937 & get() {
375 static std::mt19937 rng(time(
nullptr));
381 template <
typename T>
383 typename std::enable_if<
384 std::is_integral<T>::value,
388 std::uniform_int_distribution<T> dist;
389 return dist(RandNumGen::get());
393 template <
typename T>
395 typename std::enable_if<
396 std::is_floating_point<T>::value,
400 std::normal_distribution<T> dist(0, 1000);
401 return dist(RandNumGen::get());
Exception class for all of Sparta.
Macros for handling exponential backoff.
Static/global random number generator.