| @@ -17,7 +17,7 @@ From https://prng.di.unimi.it/ | |||||
| Example: | Example: | ||||
| std::random_device rd; | std::random_device rd; | ||||
| random::Xoroshiro128Plus rng(rd()); | |||||
| random::Xoroshiro128Plus rng(rd(), rd()); | |||||
| uint64_t r = rng(); | uint64_t r = rng(); | ||||
| uint32_t r = rng.u32(); | uint32_t r = rng.u32(); | ||||
| @@ -31,22 +31,20 @@ struct Xoroshiro128Plus { | |||||
| uint64_t state[2]; | uint64_t state[2]; | ||||
| Xoroshiro128Plus(uint64_t s0 = 1, uint64_t s1 = 0) { | Xoroshiro128Plus(uint64_t s0 = 1, uint64_t s1 = 0) { | ||||
| seed(s0, s1); | |||||
| } | |||||
| void seed(uint64_t s0 = 1, uint64_t s1 = 0) { | |||||
| state[0] = s0; | state[0] = s0; | ||||
| state[1] = s1; | state[1] = s1; | ||||
| // A bad seed will give a bad first result, so shift the state | |||||
| operator()(); | operator()(); | ||||
| } | } | ||||
| static uint64_t rotl(const uint64_t x, int k) { | |||||
| static uint64_t rotl(uint64_t x, int k) { | |||||
| return (x << k) | (x >> (64 - k)); | return (x << k) | (x >> (64 - k)); | ||||
| } | } | ||||
| uint64_t operator()() { | uint64_t operator()() { | ||||
| const uint64_t s0 = state[0]; | |||||
| uint64_t s0 = state[0]; | |||||
| uint64_t s1 = state[1]; | uint64_t s1 = state[1]; | ||||
| const uint64_t result = s0 + s1; | |||||
| uint64_t result = s0 + s1; | |||||
| s1 ^= s0; | s1 ^= s0; | ||||
| state[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); | state[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); | ||||
| @@ -90,7 +88,7 @@ extern thread_local Xoroshiro128Plus rng; | |||||
| /** Initializes the thread-local RNG state. | /** Initializes the thread-local RNG state. | ||||
| Must call per-thread, otherwise the RNG will always return 0. | |||||
| Must call when creating a thread, otherwise random state is undefined (might always return 0). | |||||
| */ | */ | ||||
| void init(); | void init(); | ||||
| /** Returns a uniform random uint64_t from 0 to UINT64_MAX */ | /** Returns a uniform random uint64_t from 0 to UINT64_MAX */ | ||||