/* Written in 2018 by Sebastiano Vigna (vigna@acm.org) Generates two "independent" streams using a PCG generator with multiple streams and interleaves them. The output should look random, but it fails spectacularly several statistical tests from PractRand: rng=RNG_stdin64, seed=0x11af1633 length= 256 megabytes (2^28 bytes), time= 24.4 seconds Test Name Raw Processed Evaluation BCFN_FF(2+0,13-2,T) R=+401986 p = 0 FAIL !!!!!!!! DC6-9x1Bytes-1 R= +7342 p = 1e-3850 FAIL !!!!!!!! ... 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 // ------- // PCG code Copyright by Melissa O'Neill typedef __uint128_t pcg128_t; #define PCG_128BIT_CONSTANT(high,low) ((((pcg128_t)high) << 64) + low) struct pcg_state_setseq_128 { pcg128_t state; pcg128_t inc; }; inline pcg128_t pcg_rotr_128(pcg128_t value, unsigned int rot) { return (value >> rot) | (value << ((- rot) & 127)); } #define PCG_DEFAULT_MULTIPLIER_128 \ PCG_128BIT_CONSTANT(2549297995355413924ULL,4865540595714422341ULL) inline void pcg_setseq_128_step_r(struct pcg_state_setseq_128* rng) { rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + rng->inc; } inline uint64_t pcg_output_xsh_rs_128_64(pcg128_t state) { return (uint64_t)(((state >> 43u) ^ state) >> ((state >> 124u) + 45u)); } inline uint64_t pcg_setseq_128_xsh_rs_64_random_r(struct pcg_state_setseq_128* rng) { pcg_setseq_128_step_r(rng); return pcg_output_xsh_rs_128_64(rng->state); } inline void pcg_setseq_128_srandom_r(struct pcg_state_setseq_128* rng, pcg128_t initstate, pcg128_t initseq) { rng->state = 0U; rng->inc = (initseq << 1u) | 1u; pcg_setseq_128_step_r(rng); rng->state += initstate; pcg_setseq_128_step_r(rng); } // ------- int main(int argc, char* argv[]) { struct pcg_state_setseq_128 rng0, rng1; // Different initial state, different sequences. The streams should look statistically independent. // Pipe the output into PractRand or some other test suite. pcg_setseq_128_srandom_r(&rng0, PCG_128BIT_CONSTANT(0x83EED115C9CBCC30, 0x4C55E45838B75647), PCG_128BIT_CONSTANT(0x3E0897751B1A19E7, 0xD9D50DD3E3A454DC)); pcg_setseq_128_srandom_r(&rng1, PCG_128BIT_CONSTANT(0x7C112EEA363433CF, 0xB3AA1BA7C748A9B9), PCG_128BIT_CONSTANT(0x41F7688AE4E5E618, 0x262AF22C1C5BAB23)); for(;;) { uint64_t out = pcg_setseq_128_xsh_rs_64_random_r(&rng0); fwrite(&out, sizeof out, 1, stdout); //printf("%016llx\n", out); out = pcg_setseq_128_xsh_rs_64_random_r(&rng1); fwrite(&out, sizeof out, 1, stdout); //printf("%016llx\n", out); } }