-
Notifications
You must be signed in to change notification settings - Fork 0
/
rand.h
78 lines (65 loc) · 1.89 KB
/
rand.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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#ifndef RAND_H
#define RAND_H
#include <assert.h>
#include <stdint.h>
/* these two values should be matched;
* these choices come from G. Marsaglia (2003)
* Seeds for Random Number Generators */
#define CMWC_RNG_LAG 16
#if CMWC_RNG_LAG == 16
/* lag-16 has a period of p = approx. 2**540 */
#define CMWC_RNG_MULTIPLIER 487198574u
#elif CMWC_RNG_LAG == 8
/* lag-8 has a period of p = approx. 2**285 */
#define CMWC_RNG_MULTIPLIER 716514398u
#else
#error "No known-good multiplier value for the specified CMWC lag."
#endif
struct cmwc_rng {
int place;
uint32_t carry;
uint32_t state[CMWC_RNG_LAG];
};
void cmwc_init(struct cmwc_rng *rng, uint32_t seed);
void cmwc_init_full(struct cmwc_rng *rng, uint32_t carry, uint32_t *state);
inline uint32_t cmwc_next_i32(struct cmwc_rng *rng) {
assert(rng);
uint32_t result = rng->state[rng->place];
uint64_t t = (uint64_t)result * (uint64_t)CMWC_RNG_MULTIPLIER + (uint64_t)rng->carry;
uint32_t c = t >> 32;
uint32_t x = t;
/* fix-up because b = 2**32 - 1 not 2**32 */
if (t + c < c) {
++c;
++x;
}
rng->state[rng->place] = (uint64_t)0xfffffffeu - t;
rng->carry = c;
rng->place = (rng->place + 1) % CMWC_RNG_LAG;
return result;
}
inline uint64_t cmwc_next_i64(struct cmwc_rng *rng) {
assert(rng);
uint64_t a = cmwc_next_i32(rng);
uint64_t b = cmwc_next_i32(rng);
return (a << 32) | b;
}
/* period 2**128 - 1 */
struct xorshift_rng {
uint32_t x, y, z, w;
};
void xorshift_init(struct xorshift_rng *rng, uint32_t seed);
inline uint32_t xorshift_next_i32(struct xorshift_rng *rng) {
assert(rng);
const uint32_t x = rng->x, y = rng->y, z = rng->z, w = rng->w;
uint32_t t = x^(x<<15); t = (w^(w>>21)) ^ (t^(t>>4));
rng->x = y; rng->y = z; rng->z = w; rng->w = t;
return t;
}
inline uint64_t xorshift_next_i64(struct xorshift_rng *rng) {
assert(rng);
uint64_t a = xorshift_next_i32(rng);
uint64_t b = xorshift_next_i32(rng);
return (a << 32) | b;
}
#endif