#ifndef UTIL_RANDOM_H #define UTIL_RANDOM_H #include <stdint.h> #include <sys/time.h> #include <time.h> // Taken from // http://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/ namespace util { namespace internal { inline uint32_t time_seed() { timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec ^ tv.tv_usec; } inline int_fast16_t rand(uint32_t setseed) { static uint32_t mySeed = (uint32_t)(-1); if (setseed != (uint32_t)(-2)) mySeed = setseed; if (mySeed == (uint32_t)(-1)) mySeed = time_seed(); mySeed = 214013 * mySeed + 2531011; return (mySeed >> 16) & 0x7FFF; } } inline int_fast16_t urand() { return internal::rand(-2); } inline int_fast16_t urandn(int32_t n) { return urand() % n; } inline void usrand(uint64_t seed) { internal::rand(seed); } class Random { private: static uint32_t auto_seed(uint32_t setSeed); uint32_t mySeed; public: Random(); Random(uint64_t seed); int_fast16_t rand(); int_fast16_t rand(int32_t n); int_fast16_t operator()(); int_fast16_t operator()(int32_t n); void srand(uint64_t seed); }; inline uint32_t Random::auto_seed(uint32_t setSeed) { static uint32_t internalSeed = 0; if (setSeed == 0) return internalSeed; uint32_t result = internalSeed; internalSeed = setSeed; return result; } inline Random::Random() { if (auto_seed(0) == 0) auto_seed(internal::time_seed()); mySeed = auto_seed(0); auto_seed((rand() << 16) ^ (rand()) ^ internal::time_seed()); } inline Random::Random(uint64_t seed) : mySeed(seed) { } inline void Random::srand(uint64_t seed) { mySeed = seed; } inline int_fast16_t Random::rand() { mySeed = 214013 * mySeed + 2531011; return (mySeed >> 16) & 0x7FFF; } inline int_fast16_t Random::rand(int32_t n) { return rand() % n; } inline int_fast16_t Random::operator()() { return rand(); } inline int_fast16_t Random::operator()(int32_t n) { return rand(n); } } // namespace util #endif // UTIL_RANDOM_H