... , , -
.
,
, "" n-
. , , 1:1
; , , ,
.
,
,
, -
(
, - ),
.
, , , ,
. :
uint64_t mix(uint64_t x, uint64_t k) {
const int s0 = BITS * 4 / 5;
const int s1 = BITS / 5 + (k & 1);
const int s2 = BITS * 2 / 5;
k |= 1;
x *= k;
x ^= (x & BITMASK) >> s0;
x ^= (x << s1) & BITMASK;
x ^= (x & BITMASK) >> s2;
x += 0x9e3779b97f4a7c15;
return x & BITMASK;
}
, , :
uint64_t unmix(uint64_t x, uint64_t k) {
const int s0 = BITS * 4 / 5;
const int s1 = BITS / 5 + (k & 1);
const int s2 = BITS * 2 / 5;
k |= 1;
uint64_t kp = k * k;
while ((kp & BITMASK) > 1) {
k *= kp;
kp *= kp;
}
x -= 0x9e3779b97f4a7c15;
x ^= ((x & BITMASK) >> s2) ^ ((x & BITMASK) >> s2 * 2);
x ^= (x << s1) ^ (x << s1 * 2) ^ (x << s1 * 3) ^ (x << s1 * 4) ^ (x << s1 * 5);
x ^= (x & BITMASK) >> s0;
x *= k;
return x & BITMASK;
}
PRNG :
uint64_t key[ROUNDS];
uint64_t seed = 0;
uint64_t rand_no_rep(void) {
uint64_t x = seed++;
do {
for (int i = 0; i < ROUNDS; i++) x = mix(x, key[i]);
} while (x >= RANGE);
return x;
}
seed key , .
, seed
rand_no_rep() ; .
, a,
b. ROUNDS==1 50% (
a b; 0, 1 - ). ,
k, a --b k
( ).
,
. k .
50% 25%, , ( , ). , , . , , 36% 37%. ", ", , , , , .
ROUNDS==2, ,
.
, ,
. , mix()
(, , mod RANGE).
/
, . ,
, , ,
, , .
, ,
. -
b -follows- a c,
c a b.
- , 50% c
a b, k, b
a. , 25% a b
( , ,
, ), 25%
k.
, , ,
c a b.
a/b ( ,
-
), a, b c
( ).
,
, , .
; , , , ,
.
, , , ; PRNG.
PRNG, SIMD .