/* Based on uncpcg.cpp, written in 2018 by Sebastiano Vigna (vigna@acm.org)
adapted for XorWow by Melissa O'Neill (oneill@acm.org)
Performs a correlation test on a XorShift generator with "wow" in the name.
According to Vigna, the output of this program "should" look random for
some large enough value of the command-line parameter. But this never
happens.
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See . */
#include
#include
#include
#include
#include
#include
#include
/* Code taken from https://en.wikipedia.org/wiki/Xorshift#xorwow */
/* The state array must be initialized to not be all zero in the first four
words */
uint32_t xorwow(uint32_t state[static 5])
{
/* Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs" */
uint32_t s, t = state[3];
t ^= t >> 2;
t ^= t << 1;
state[3] = state[2]; state[2] = state[1]; state[1] = s = state[0];
t ^= s;
t ^= s << 4;
state[0] = t;
return t + (state[4] += 362437);
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "USAGE: %s N\n", argv[0]);
exit(1);
}
const uint64_t n = strtoull(argv[1], NULL, 0);
if (errno) {
fprintf(stderr, "%s\n", strerror(errno));
exit(1);
}
// Make two generators in the same state
uint32_t rng0[5] = { time(NULL), 0, 0, 0, 0 };
for (int i = 0; i < 17; ++i)
(void)xorwow(rng0);
// Copy first into second.
uint32_t rng1[5] = { rng0[0], rng0[1], rng0[2], rng0[3], rng0[4] };
rng1[4] ^= 0x80000000; // Flip one bit of state
for(int i = 0; i < n; i++) { // Advance n times to uncorrelate
(void)xorwow(rng0);
(void)xorwow(rng1);
}
for(;;) {
const uint32_t x = xorwow(rng0);
fwrite(&x, sizeof x, 1, stdout);
// printf("%08" PRIx32 "\n", x);
const uint32_t y = xorwow(rng1);
fwrite(&y, sizeof y, 1, stdout);
// printf("%08" PRIx32 "\n", y);
}
}