/* Written in 2018 by Sebastiano Vigna (vigna@acm.org) Interleaves the output of two different sequences emitted by a 128-bit PCG generator starting from two initial states that differs in the high 64 bits. 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 // ------- // 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_128 { pcg128_t state; }; #define PCG_DEFAULT_MULTIPLIER_128 \ PCG_128BIT_CONSTANT(2549297995355413924ULL,4865540595714422341ULL) #define PCG_DEFAULT_INCREMENT_128 \ PCG_128BIT_CONSTANT(6364136223846793005ULL,1442695040888963407ULL) inline void pcg_oneseq_128_step_r(struct pcg_state_128* rng) { rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + PCG_DEFAULT_INCREMENT_128; } 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_oneseq_128_xsh_rs_64_random_r(struct pcg_state_128* rng) { pcg_oneseq_128_step_r(rng); return pcg_output_xsh_rs_128_64(rng->state); } // ------- // Interleaves the output of two different sequences emitted by a 128-bit PCG // generator. Give an initial 128-bit state, an additional alternative // 64 high bits of state for the second generator and pipe the output in // PractRand. int main(int argc, char* argv[]) { if (argc != 4) { fprintf(stderr, "USAGE: %s STATE0 STATE1 ALT0\n", argv[0]); exit(1); } const uint64_t state0 = strtoull(argv[1], NULL, 0); if (errno) { fprintf(stderr, "%s\n", strerror(errno)); exit(1); } const uint64_t state1 = strtoull(argv[2], NULL, 0); if (errno) { fprintf(stderr, "%s\n", strerror(errno)); exit(1); } const uint64_t alt0 = strtoull(argv[3], NULL, 0); if (errno) { fprintf(stderr, "%s\n", strerror(errno)); exit(1); } struct pcg_state_128 rng0, rng1; rng0.state = (__uint128_t)state0 << 64 ^ state1; rng1.state = (__uint128_t)alt0 << 64 ^ state1; for(;;) { uint64_t out = pcg_oneseq_128_xsh_rs_64_random_r(&rng0); fwrite(&out, sizeof out, 1, stdout); // printf("0x%016" PRIx64 "\n", out); out = pcg_oneseq_128_xsh_rs_64_random_r(&rng1); fwrite(&out, sizeof out, 1, stdout); // printf("0x%016" PRIx64 "\n", out); } }