#include #include #include #include #include // Code from Numpy typedef __uint128_t pcg128_t; typedef struct { pcg128_t state; pcg128_t inc; } pcg_state_setseq_128; #define PCG_DEFAULT_MULTIPLIER_HIGH 2549297995355413924ULL #define PCG_DEFAULT_MULTIPLIER_LOW 4865540595714422341ULL #define PCG_128BIT_CONSTANT(high, low) (((pcg128_t)(high) << 64) + low) #define PCG_DEFAULT_MULTIPLIER_128 \ PCG_128BIT_CONSTANT(PCG_DEFAULT_MULTIPLIER_HIGH, PCG_DEFAULT_MULTIPLIER_LOW) #define PCG_DEFAULT_INCREMENT_128 \ PCG_128BIT_CONSTANT(6364136223846793005ULL, 1442695040888963407ULL) #define PCG_STATE_SETSEQ_128_INITIALIZER \ { \ PCG_128BIT_CONSTANT(0x979c9a98d8462005ULL, 0x7d3e9cb6cfe0549bULL) \ , PCG_128BIT_CONSTANT(0x0000000000000001ULL, 0xda3e39cb94b95bdbULL) \ } static inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) { return (value >> rot) | (value << ((-rot) & 63)); } static inline void pcg_setseq_128_step_r(pcg_state_setseq_128 *rng) { rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + rng->inc; } static inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) { return pcg_rotr_64(((uint64_t)(state >> 64u)) ^ (uint64_t)state, state >> 122u); } static inline uint64_t pcg_setseq_128_xsl_rr_64_random_r(pcg_state_setseq_128* rng) { pcg_setseq_128_step_r(rng); return pcg_output_xsl_rr_128_64(rng->state); } static inline void pcg_setseq_128_srandom_r(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); } typedef pcg_state_setseq_128 pcg64_random_t; #define pcg64_random_r pcg_setseq_128_xsl_rr_64_random_r #define pcg64_boundedrand_r pcg_setseq_128_xsl_rr_64_boundedrand_r #define pcg64_srandom_r pcg_setseq_128_srandom_r #define pcg64_advance_r pcg_setseq_128_advance_r #define PCG64_INITIALIZER PCG_STATE_SETSEQ_128_INITIALIZER int main(int argc, char *argv[]) { if (argc != 5) { fprintf(stderr, "USAGE: %s STATE0 STATE1 ALT0 ALT1\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); } const uint64_t alt1 = strtoull(argv[4], NULL, 0); if (errno) { fprintf(stderr, "%s\n", strerror(errno)); exit(1); } pcg_state_setseq_128 rng0, rng1; pcg_setseq_128_srandom_r(&rng0, 0, PCG_128BIT_CONSTANT(0x6d9a8da7167ddfcf, 0xff9e40e62707684a)); pcg_setseq_128_srandom_r(&rng1, 0, PCG_128BIT_CONSTANT(0x6d9a8da7167ddfcf, 0xff9e40e62707684a)); rng0.state = (__uint128_t)state0 << 64 ^ state1; rng1.state = (__uint128_t)alt0 << 64 ^ alt1; // Check that the sequence are non-overlapping for at least 160GB of combined data for(uint64_t i = 0; i < 10000000000ULL; i++) { pcg_setseq_128_xsl_rr_64_random_r(&rng0); if (rng0.state == rng1.state) { fprintf(stderr, "Overlapping sequences\n"); exit(1); } } rng0.state = (__uint128_t)state0 << 64 ^ state1; for(uint64_t i = 0; i < 10000000000ULL; i++) { pcg_setseq_128_xsl_rr_64_random_r(&rng1); if (rng0.state == rng1.state) { fprintf(stderr, "Overlapping sequences\n"); exit(1); } } rng1.state = (__uint128_t)alt0 << 64 ^ alt1; for(;;) { uint64_t out = pcg_setseq_128_xsl_rr_64_random_r(&rng0); fwrite(&out, sizeof out, 1, stdout); // printf("0x%016" PRIx64 "\n", out); out = pcg_setseq_128_xsl_rr_64_random_r(&rng1); fwrite(&out, sizeof out, 1, stdout); // printf("0x%016" PRIx64 "\n", out); } }