diff --git a/c_src/pcg32.c b/c_src/pcg32.c index 0def108..d56e89a 100644 --- a/c_src/pcg32.c +++ b/c_src/pcg32.c @@ -35,26 +35,36 @@ #include "rdtsc.h" #endif +static __thread uint64_t state = 5573589319906701683ULL; + +static uint32_t pcg32(void) +{ + uint64_t oldstate = state; + state = oldstate * 6364136223846793005ULL; + uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; + uint32_t rot = oldstate >> 59u; + uint32_t v = (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); + return v; +} + uint32_t uniform32(void) { static __thread bool seeded = false; - static __thread uint64_t state; if (unlikely(!seeded)) { + uint64_t t; #ifdef HAVE_RDRAND - state = rdrand64(); + t = rdrand64(); #else uint64_t u; - rdtsc(&state, &u); + rdtsc(&t, &u); #endif + pcg32(); + state += t; + pcg32(); seeded = true; } - uint64_t oldstate = state; - state = oldstate * 6364136223846793005ULL; - uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; - uint32_t rot = oldstate >> 59u; - uint32_t v = (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); - return v; + return pcg32(); } ERL_NIF_TERM uniform_1(ErlNifEnv *env, diff --git a/c_src/stub.c b/c_src/stub.c index b2d8a3a..957c884 100644 --- a/c_src/stub.c +++ b/c_src/stub.c @@ -50,7 +50,7 @@ int main(void) int main(void) { - uint32_t modulus = uniform32(); + uint32_t modulus = uniform32() || uniform32(); for (size_t i = 0; i < 10000000UL; ++i) uniform_1(NULL, 1, (const ERL_NIF_TERM[]){modulus}); return 0;