-
Notifications
You must be signed in to change notification settings - Fork 0
/
pcg.hpp
60 lines (45 loc) · 1.2 KB
/
pcg.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#ifndef PCG_HPP
#define PCG_HPP
#include <cstdint>
#include <cassert>
// http://www.pcg-random.org/download.html#minimal-c-implementation
class pcg32 {
uint64_t state;
const uint64_t inc;
static uint64_t seed() {
static const uint64_t unique = 0;
return (uint64_t)&unique;
}
public:
pcg32(uint64_t state, // = 0x853c49e6748fea9bULL,
uint64_t inc)// = 0xda3e39cb94b95bdbULL)
: state(state),
inc(inc) {
assert( inc % 2 == 1 );
}
pcg32(uint64_t state = seed())
: state(state),
inc(2 * seed() + 1) {
}
uint32_t rand() {
const uint64_t oldstate = state;
// advance internal state
state = oldstate * 6364136223846793005ULL + (inc|1);
// calculate output function (XSH RR), uses old state for max ILP
const uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
const uint32_t rot = oldstate >> 59u;
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}
uint32_t rand(uint32_t bound) {
const uint32_t threshold = -bound % bound;
// eliminate bias by dropping output less than a threshold (RNG
// range must be a multiple of bound)
while(true) {
const uint32_t r = rand();
if (r >= threshold) {
return r % bound;
}
}
}
};
#endif