19 inline double log2 (
double x) {
26 inline uint32_t log2_lsb(
const T& x)
30 throw SpartaException(
"Unsupported type for log2_lsb: ") <<
typeid(T).name();
34 inline uint32_t log2_lsb<uint32_t>(
const uint32_t &x)
40 static const uint32_t index32[32] = {
41 0, 1, 28, 2, 29, 14, 24, 3,
42 30, 22, 20, 15, 25, 17, 4, 8,
43 31, 27, 13, 23, 21, 19, 16, 7,
44 26, 12, 18, 6, 11, 5, 10, 9
47 static const uint32_t debruijn32 = 0x077CB531u;
49 return index32[((x & -x) * debruijn32) >> 27];
53 inline uint32_t log2_lsb<uint64_t>(
const uint64_t &x)
59 static const uint32_t index64[64] = {
60 63, 0, 58, 1, 59, 47, 53, 2,
61 60, 39, 48, 27, 54, 33, 42, 3,
62 61, 51, 37, 40, 49, 18, 28, 20,
63 55, 30, 34, 11, 43, 14, 22, 4,
64 62, 57, 46, 52, 38, 26, 32, 41,
65 50, 36, 17, 19, 29, 10, 13, 21,
66 56, 45, 25, 31, 35, 16, 9, 12,
67 44, 24, 15, 8, 23, 7, 6, 5
70 static const uint64_t debruijn64 = 0x07EDD5E59A4E28C2ull;
72 return index64[((x & -x) * debruijn64) >> 58];
76 inline uint64_t floor_log2(T x)
90 inline uint64_t floor_log2<double>(
double x)
92 return std::floor(log2(x));
96 inline uint64_t floor_log2<uint32_t>(uint32_t x)
107 static const uint64_t lut[] = {
108 0, 9, 1, 10, 13, 21, 2, 29,
109 11, 14, 16, 18, 22, 25, 3, 30,
110 8, 12, 20, 28, 15, 17, 24, 7,
111 19, 27, 23, 6, 26, 5, 4, 31};
118 return lut[(uint32_t)(x * 0x07C4ACDDul) >> 27];
122 inline uint64_t floor_log2<uint64_t>(uint64_t x)
133 static const uint64_t lut[] = {
134 63, 0, 58, 1, 59, 47, 53, 2,
135 60, 39, 48, 27, 54, 33, 42, 3,
136 61, 51, 37, 40, 49, 18, 28, 20,
137 55, 30, 34, 11, 43, 14, 22, 4,
138 62, 57, 46, 52, 38, 26, 32, 41,
139 50, 36, 17, 19, 29, 10, 13, 21,
140 56, 45, 25, 31, 35, 16, 9, 12,
141 44, 24, 15, 8, 23, 7, 6, 5};
149 return lut[((uint64_t)((x - (x >> 1)) * 0x07EDD5E59A4E28C2ull)) >> 58];
152 inline uint64_t ceil_log2 (uint64_t x)
156 uint64_t y = floor_log2(x);
157 if ((
static_cast<uint64_t
>(1) << y) != x) {
163 inline uint64_t pow2 (uint64_t x) {
164 uint64_t y =
static_cast<uint64_t
>(1) << x;
168 inline bool is_power_of_2 (uint64_t x) {
169 bool y = x && !(x & (x - 1));
173 inline uint64_t next_power_of_2(uint64_t v)
178 return 1ull << ((
sizeof(uint64_t) * 8) - __builtin_clzll(v - 1ull));
181 inline uint64_t ones (uint64_t x) {
182 uint64_t y = (
static_cast<uint64_t
>(1) << x) - 1;
194 return (x < 0 ? -x : x);
198 inline uint8_t abs<uint8_t>(uint8_t x) {
199 uint8_t sign_mask = int8_t(x) >> 7;
200 return (x + sign_mask) ^ sign_mask;
204 inline uint16_t abs<uint16_t>(uint16_t x) {
205 uint16_t sign_mask = int16_t(x) >> 15;
206 return (x + sign_mask) ^ sign_mask;
210 inline uint32_t abs<uint32_t>(uint32_t x) {
211 uint32_t sign_mask = int32_t(x) >> 31;
212 return (x + sign_mask) ^ sign_mask;
216 inline uint64_t abs<uint64_t>(uint64_t x) {
217 uint64_t sign_mask = int64_t(x) >> 63;
218 return (x + sign_mask) ^ sign_mask;
222 inline T gcd(T u, T v)
226 static_assert(
"This is an unsupported type");
231 inline uint32_t gcd<uint32_t>(uint32_t u, uint32_t v)
234 if (u == 0 || v == 0)
239 uint32_t shift = log2_lsb(u | v);
266 inline uint64_t gcd<uint64_t>(uint64_t u, uint64_t v)
269 if (u == 0 || v == 0)
274 uint32_t shift = log2_lsb(u | v);
300 inline T lcm(
const T& u,
const T& v)
305 throw SpartaException(
"Unsupported type for lcm: ") <<
typeid(T).name();
309 inline uint32_t lcm<uint32_t>(
const uint32_t &u,
const uint32_t &v)
317 return u / gcd(u, v) * v;
322 inline uint64_t lcm<uint64_t>(
const uint64_t &u,
const uint64_t &v)
330 return u / gcd(u, v) * v;
338 static_assert(std::is_integral<T>::value,
"sparta::safe_power only supports integer data types");
344 for (T x = 1; x < e; x++)
346 T old_result = result;
348 if (old_result > result)
350 throw SpartaException(
"power() overflowed!");
359 template <
typename T>
361 typename std::enable_if<
362 std::is_floating_point<T>::value,
364 approximatelyEqual(
const T a,
const T b,
365 const T epsilon = std::numeric_limits<T>::epsilon())
367 const T fabs_a = std::fabs(a);
368 const T fabs_b = std::fabs(b);
369 const T fabs_diff = std::fabs(a - b);
371 return fabs_diff <= ((fabs_a < fabs_b ? fabs_b : fabs_a) * epsilon);
376 static std::mt19937 & get() {
377 static std::mt19937 rng(time(
nullptr));
383 template <
typename T>
385 typename std::enable_if<
386 std::is_integral<T>::value,
390 std::uniform_int_distribution<T> dist;
391 return dist(RandNumGen::get());
395 template <
typename T>
397 typename std::enable_if<
398 std::is_floating_point<T>::value,
402 std::normal_distribution<T> dist(0, 1000);
403 return dist(RandNumGen::get());
Set of macros for Sparta assertions. Caught by the framework.
Exception class for all of Sparta.
Macros for handling exponential backoff.
Static/global random number generator.