Skip to content

Instantly share code, notes, and snippets.

@leok7v
Created October 7, 2024 05:23
Show Gist options
  • Save leok7v/399a402356bcc28b147ab29142b7d3fb to your computer and use it in GitHub Desktop.
Save leok7v/399a402356bcc28b147ab29142b7d3fb to your computer and use it in GitHub Desktop.
random64 Linear Congruential Generator (LCG) and an XOR-based generator (XBG)
// Linear Congruential Generator (LCG) and an XOR-based generator (XBG)
// like xoroshiro or xoshiro
static uint64_t random64(uint64_t* state) {
// Linear Congruential Generator with inline mixing
thread_local static bool initialized;
if (!initialized) { initialized = true; *state |= 1; };
*state = (*state * 0xD1342543DE82EF95uLL) + 1;
uint64_t z = *state;
z = (z ^ (z >> 32)) * 0xDABA0B6EB09322E3uLL;
z = (z ^ (z >> 32)) * 0xDABA0B6EB09322E3uLL;
return z ^ (z >> 32);
}
static double rand64(uint64_t *state) { // [0.0..1.0) exclusive to 1.0
return (double)random64(state) / ((double)UINT64_MAX + 1.0);
}
static void test_random_histogram(void) {
uint64_t seed = 1;
uint64_t k = 0;
uint64_t bit_count[64] = {0};
uint64_t r0 = random64(&seed);
uint64_t r = random64(&seed);
while (r != r0) {
// Count '1' bits at each bit position
for (int i = 0; i < 64; i++) {
if (r & (1ULL << i)) {
bit_count[i]++;
}
}
k++;
if (k % (1uLL + (uint64_t)UINT32_MAX / 1) == 0) {
printf("Cycle: %llu\n", k);
for (int i = 0; i < 64; i++) {
double probability = (double)bit_count[i] / k;
printf("Bit %2d: %0.17f %lld\n", i, probability, bit_count[i]);
}
printf("\n");
break;
}
r = random64(&seed);
}
}
Cycle: 4294967296
Bit 0: 0.49998589232563972 2147423056
Bit 1: 0.50000143051147461 2147489792
Bit 2: 0.49999740417115390 2147472499
Bit 3: 0.49999565887264907 2147465003
Bit 4: 0.50001444178633392 2147545675
Bit 5: 0.50000476720742881 2147504123
Bit 6: 0.50000861682929099 2147520657
Bit 7: 0.49999586888588965 2147465905
Bit 8: 0.50000042538158596 2147485475
Bit 9: 0.50000893371179700 2147522018
Bit 10: 0.49999940744601190 2147481103
Bit 11: 0.50000253831967711 2147494550
Bit 12: 0.49999515013769269 2147462818
Bit 13: 0.49998968304134905 2147439337
Bit 14: 0.50000069104135036 2147486616
Bit 15: 0.50000798888504505 2147517960
Bit 16: 0.49999371636658907 2147456660
Bit 17: 0.49998795567080379 2147431918
Bit 18: 0.49998458870686591 2147417457
Bit 19: 0.49999616341665387 2147467170
Bit 20: 0.50000476674176753 2147504121
Bit 21: 0.50000485498458147 2147504500
Bit 22: 0.49998248787596822 2147408434
Bit 23: 0.50001026154495776 2147527721
Bit 24: 0.49999444629065692 2147459795
Bit 25: 0.50000932672992349 2147523706
Bit 26: 0.49998789886012673 2147431674
Bit 27: 0.50000096694566309 2147487801
Bit 28: 0.49999004090204835 2147440874
Bit 29: 0.49999409914016724 2147458304
Bit 30: 0.50001393142156303 2147543483
Bit 31: 0.49998553236946464 2147421510
Bit 32: 0.49999793572351336 2147474782
Bit 33: 0.50000253831967711 2147494550
Bit 34: 0.50001158402301371 2147533401
Bit 35: 0.50000064610503614 2147486423
Bit 36: 0.49998790048994124 2147431681
Bit 37: 0.50000439374707639 2147502519
Bit 38: 0.49999461835250258 2147460534
Bit 39: 0.49998445971868932 2147416903
Bit 40: 0.50000803242437541 2147518147
Bit 41: 0.50000171083956957 2147490996
Bit 42: 0.49999264394864440 2147452054
Bit 43: 0.49999785609543324 2147474440
Bit 44: 0.49999760487116873 2147473361
Bit 45: 0.49999542487785220 2147463998
Bit 46: 0.49999089399352670 2147444538
Bit 47: 0.49998576729558408 2147422519
Bit 48: 0.50000108336098492 2147488301
Bit 49: 0.49999393848702312 2147457614
Bit 50: 0.49999092193320394 2147444658
Bit 51: 0.50001167505979538 2147533792
Bit 52: 0.50000905920751393 2147522557
Bit 53: 0.49998989840969443 2147440262
Bit 54: 0.50000645313411951 2147511364
Bit 55: 0.50000821589492261 2147518935
Bit 56: 0.50000565615482628 2147507941
Bit 57: 0.49999071238562465 2147443758
Bit 58: 0.49999504676088691 2147462374
Bit 59: 0.50000621424987912 2147510338
Bit 60: 0.50000375509262085 2147499776
Bit 61: 0.50000175368040800 2147491180
Bit 62: 0.49999391078017652 2147457495
Bit 63: 0.50001200661063194 2147535216
@leok7v
Copy link
Author

leok7v commented Oct 7, 2024

static void test_random_cycle(void) {
    uint64_t seed = 1;
    uint64_t k = 0;
    uint64_t r = random64(&seed);
    while (r != random64(&seed)) {
        k++;
        if (k % (1uLL + (uint64_t)UINT32_MAX) == 0 && k < UINT64_MAX / 2) {
            uint64_t p = 1;
            while (k > (1uLL << p)) { p++; }
            printf("0x%016llX 2^%d\n", k, (int)p);
        }
    }
    printf("cycle: %lld\n", k);
}
test_random_cycle     0x0000016A00000000 2^41

...
didn't find a cycle yet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment