-
Notifications
You must be signed in to change notification settings - Fork 0
/
pcg.h
53 lines (45 loc) · 1.42 KB
/
pcg.h
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
// SPDX-License-Identifier: 0BSD OR MIT-0
typedef struct pcg_random {
pcg_ulong_t state, inc;
} pcg_t;
/*
* Initialize a random number generator from the kernel's entropy pool
*/
extern pcg_t pcg_getentropy(void);
/*
* Properly initialize a random number generator
* from raw state and (optional) inc values, e.g.
*
* pcg_t rng = pcg_seed((pcg_t){ .state = 0xacab1213 });
*/
extern pcg_t pcg_seed(pcg_t seed);
/*
* Get a word of random bits from a random number generator
*/
static inline pcg_uint_t pcg_random(pcg_t *rng);
/*
* Get a random floating point number 0.0 <= ... < 1.0
*/
static inline pcg_fp_t pcg_random_fp(pcg_t *rng);
/*
* Write `size` random bytes at `ptr`
*/
extern void pcg_random_bytes(
pcg_t *restrict rng, void *restrict ptr, size_t size);
/*
* Get an unbiased random number less than the given limit
*/
extern pcg_uint_t pcg_rand(pcg_t *rng, pcg_uint_t limit);
/*
* The macro pcg_rand_fast(rng, limit) is like pcg_rand(rng, limit)
* but the fast path is inlined. Don't call pcg_rand_inline() directly.
*/
static inline pcg_uint_t
pcg_rand_inline(pcg_t *rng, pcg_uint_t limit, pcg_uint_t maybe_slow) {
extern pcg_uint_t pcg_rand_slow(
pcg_t *rng, pcg_uint_t limit, pcg_ulong_t hi_lo);
pcg_ulong_t hi_lo = (pcg_ulong_t)pcg_random(rng) * (pcg_ulong_t)limit;
if (maybe_slow && (pcg_uint_t)(hi_lo) < limit)
return (pcg_rand_slow(rng, limit, hi_lo));
return ((pcg_uint_t)(hi_lo >> PCG_UINT_BITS));
}