/* 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); } }