#define MODULE "rand" #include "rand/Mersenne.h" #include "assert.h" #include typedef uint64_t word_t; static const int STATE_SIZE = 312; static const int MIDDLE = 156; static const int INIT_SHIFT = 62; static const uint64_t TWIST_MASK = 0xb5026f5aa96619e9; static const uint64_t INIT_FACT = 6364136223846793005; static const int SHIFT1 = 29; static const uint64_t MASK1 = 0x5555555555555555; static const int SHIFT2 = 17; static const uint64_t MASK2 = 0x71d67fffeda60000; static const int SHIFT3 = 37; static const uint64_t MASK3 = 0xfff7eee000000000; static const int SHIFT4 = 43; static const word_t LOWER_MASK = 0x7fffffff; static const word_t UPPER_MASK = (~(word_t)LOWER_MASK); static word_t state[STATE_SIZE]; static size_t index = STATE_SIZE + 1; void Mersenne::seed(uint64_t s) { index = STATE_SIZE; state[0] = s; for (size_t i = 1; i < STATE_SIZE; i++) state[i] = (INIT_FACT * (state[i - 1] ^ (state[i - 1] >> INIT_SHIFT))) + i; } static void twist() { for (size_t i = 0; i < STATE_SIZE; i++) { word_t x = (state[i] & UPPER_MASK) | (state[(i + 1) % STATE_SIZE] & LOWER_MASK); x = (x >> 1) ^ (x & 1 ? TWIST_MASK : 0); state[i] = state[(i + MIDDLE) % STATE_SIZE] ^ x; } index = 0; } uint64_t Mersenne::get() { if (index >= STATE_SIZE) { ASSERT(index == STATE_SIZE && "Mersenne generator was never seeded"); twist(); } word_t y = state[index]; y ^= (y >> SHIFT1) & MASK1; y ^= (y << SHIFT2) & MASK2; y ^= (y << SHIFT3) & MASK3; y ^= y >> SHIFT4; index++; return y; }