Permalink
Cannot retrieve contributors at this time
Fetching contributors…
| #ifndef RANDOM_GEN_H_ | |
| #define RANDOM_GEN_H_ | |
| #include <stdint.h> | |
| #include "assert_helpers.h" | |
| //#define MERSENNE_TWISTER | |
| #ifndef MERSENNE_TWISTER | |
| /** | |
| * Simple pseudo-random linear congruential generator, a la Numerical | |
| * Recipes. | |
| */ | |
| class RandomSource { | |
| public: | |
| static const uint32_t DEFUALT_A = 1664525; | |
| static const uint32_t DEFUALT_C = 1013904223; | |
| RandomSource() : | |
| a(DEFUALT_A), c(DEFUALT_C), inited_(false) { } | |
| RandomSource(uint32_t _last) : | |
| a(DEFUALT_A), c(DEFUALT_C), last(_last), inited_(true) { } | |
| RandomSource(uint32_t _a, uint32_t _c) : | |
| a(_a), c(_c), inited_(false) { } | |
| void init(uint32_t seed = 0) { | |
| last = seed; | |
| inited_ = true; | |
| lastOff = 30; | |
| } | |
| /** | |
| * Get next unsigned 32-bit or 64-bit integer depending on | |
| * type. Should perhaps use template specialization. | |
| */ | |
| template <typename T> | |
| T nextU() { | |
| if(sizeof(T)>4) { | |
| return nextU64(); | |
| } | |
| return nextU32(); | |
| } | |
| uint32_t nextU32() { | |
| assert(inited_); | |
| uint32_t ret; | |
| last = a * last + c; | |
| ret = last >> 16; | |
| last = a * last + c; | |
| ret ^= last; | |
| lastOff = 0; | |
| return ret; | |
| } | |
| uint64_t nextU64() { | |
| assert(inited_); | |
| uint64_t first = nextU32(); | |
| first = first << 32; | |
| uint64_t second = nextU32(); | |
| return first | second; | |
| } | |
| size_t nextSizeT() { | |
| if(sizeof(size_t) == 4) { | |
| return nextU32(); | |
| } else { | |
| return nextU64(); | |
| } | |
| } | |
| /** | |
| * Return a pseudo-random unsigned 32-bit integer sampled uniformly | |
| * from [lo, hi]. | |
| */ | |
| uint32_t nextU32Range(uint32_t lo, uint32_t hi) { | |
| uint32_t ret = lo; | |
| if(hi > lo) { | |
| ret += (nextU32() % (hi-lo+1)); | |
| } | |
| return ret; | |
| } | |
| /** | |
| * Get next 2-bit unsigned integer. | |
| */ | |
| uint32_t nextU2() { | |
| assert(inited_); | |
| if(lastOff > 30) { | |
| nextU32(); | |
| } | |
| uint32_t ret = (last >> lastOff) & 3; | |
| lastOff += 2; | |
| return ret; | |
| } | |
| /** | |
| * Get next boolean. | |
| */ | |
| bool nextBool() { | |
| assert(inited_); | |
| if(lastOff > 31) { | |
| nextU32(); | |
| } | |
| uint32_t ret = (last >> lastOff) & 1; | |
| lastOff++; | |
| return ret; | |
| } | |
| /** | |
| * Return an unsigned int chosen by picking randomly from among | |
| * options weighted by probabilies supplied as the elements of the | |
| * 'weights' array of length 'numWeights'. The weights should add | |
| * to 1. | |
| */ | |
| uint32_t nextFromProbs( | |
| const float* weights, | |
| size_t numWeights) | |
| { | |
| float f = nextFloat(); | |
| float tot = 0.0f; // total weight seen so far | |
| for(uint32_t i = 0; i < numWeights; i++) { | |
| tot += weights[i]; | |
| if(f < tot) return i; | |
| } | |
| return (uint32_t)(numWeights-1); | |
| } | |
| float nextFloat() { | |
| assert(inited_); | |
| return (float)nextU32() / (float)0xffffffff; | |
| } | |
| static uint32_t nextU32(uint32_t last, | |
| uint32_t a = DEFUALT_A, | |
| uint32_t c = DEFUALT_C) | |
| { | |
| return (a * last) + c; | |
| } | |
| uint32_t currentA() const { return a; } | |
| uint32_t currentC() const { return c; } | |
| uint32_t currentLast() const { return last; } | |
| private: | |
| uint32_t a; | |
| uint32_t c; | |
| uint32_t last; | |
| uint32_t lastOff; | |
| bool inited_; | |
| }; | |
| #else | |
| class RandomSource { // Mersenne Twister random number generator | |
| public: | |
| // default constructor: uses default seed only if this is the first instance | |
| RandomSource() { | |
| reset(); | |
| } | |
| // constructor with 32 bit int as seed | |
| RandomSource(uint32_t s) { | |
| init(s); | |
| } | |
| // constructor with array of size 32 bit ints as seed | |
| RandomSource(const uint32_t* array, int size) { | |
| init(array, size); | |
| } | |
| void reset() { | |
| state_[0] = 0; | |
| p_ = 0; | |
| inited_ = false; | |
| } | |
| virtual ~RandomSource() { } | |
| // the two seed functions | |
| void init(uint32_t); // seed with 32 bit integer | |
| void init(const uint32_t*, int size); // seed with array | |
| /** | |
| * Return next 1-bit unsigned integer. | |
| */ | |
| bool nextBool() { | |
| return (nextU32() & 1) == 0; | |
| } | |
| /** | |
| * Get next unsigned 32-bit or 64-bit integer depending on | |
| * type. Should perhaps use template specialization. | |
| */ | |
| template <typename T> | |
| T nextU() { | |
| if(sizeof(T)>4) { | |
| return nextU64(); | |
| } | |
| return nextU32(); | |
| } | |
| /** | |
| * Get next unsigned 32-bit integer. | |
| */ | |
| inline uint32_t nextU32() { | |
| assert(inited_); | |
| if(p_ == n) { | |
| gen_state(); // new state vector needed | |
| } | |
| // gen_state() is split off to be non-inline, because it is only called once | |
| // in every 624 calls and otherwise irand() would become too big to get inlined | |
| uint32_t x = state_[p_++]; | |
| x ^= (x >> 11); | |
| x ^= (x << 7) & 0x9D2C5680UL; | |
| x ^= (x << 15) & 0xEFC60000UL; | |
| x ^= (x >> 18); | |
| return x; | |
| } | |
| /** | |
| * Return next float between 0 and 1. | |
| */ | |
| float nextFloat() { | |
| assert(inited_); | |
| return (float)nextU32() / (float)0xffffffff; | |
| } | |
| protected: // used by derived classes, otherwise not accessible; use the ()-operator | |
| static const int n = 624, m = 397; // compile time constants | |
| // the variables below are static (no duplicates can exist) | |
| uint32_t state_[n]; // state vector array | |
| int p_; // position in state array | |
| bool inited_; // true if init function has been called | |
| // private functions used to generate the pseudo random numbers | |
| uint32_t twiddle(uint32_t u, uint32_t v) { | |
| return (((u & 0x80000000UL) | (v & 0x7FFFFFFFUL)) >> 1) ^ ((v & 1UL) ? 0x9908B0DFUL : 0x0UL); | |
| } | |
| void gen_state(); // generate new state | |
| }; | |
| #endif | |
| #endif /*RANDOM_GEN_H_*/ |