File Coverage

lib/Random/rand-common.h
Criterion Covered Total %
statement 25 41 60.9
branch 7 14 50.0
condition n/a
subroutine n/a
pod n/a
total 32 55 58.1


line stmt bran cond sub pod time code
1             static uint32_t _rand32();
2             static uint64_t _rand64();
3              
4             // Borrowed from https://www.pcg-random.org/posts/bounded-rands.html
5 100008           static uint32_t _bounded_rand32_lemire(uint32_t range) {
6 100008           uint32_t x = _rand32();
7 100008           uint64_t m = (uint64_t)x * (uint64_t)range;
8 100008           uint32_t l = (uint32_t)m;
9              
10 100008 100         if (l < range) {
11 29962           uint32_t t = -range;
12 29962 50         if (t >= range) {
13 0           t -= range;
14 0 0         if (t >= range)
15 0           t %= range;
16             }
17 30001 100         while (l < t) {
18 39           x = _rand32();
19 39           m = (uint64_t)x * (uint64_t)range;
20 39           l = (uint32_t)m;
21             }
22             }
23              
24 100008           return m >> 32;
25             }
26              
27             // Simple rejection sampling (potentially slow for ranges near 2^64)
28 0           static uint64_t _bounded_rand64_rejection(uint64_t range) {
29 0           uint64_t limit = UINT64_MAX - (UINT64_MAX % range);
30             uint64_t x;
31              
32             // Generate a random number, and then check if it's outside the
33             // limit. If it's outside the limit keep generating new numbers
34             // until the number lands INSIDE the limit
35             do {
36 0           x = _rand64();
37 0 0         } while (x >= limit);
38              
39             // Clean 1:1 mapping, so we can return an unbiased number
40 0           return x % range;
41             }
42              
43             // https://prng.di.unimi.it/#remarks
44 40029           static double _uint64_to_double(uint64_t num, bool inclusive) {
45             // A standard 64bit double floating-point number in IEEE floating point
46             // format has 52 bits of significand. Thus, the representation can actually
47             // store numbers with 53 significant binary digits.
48              
49             double scale;
50 40029 100         if (inclusive) {
51 10000           scale = 1.0 / ((1ULL << 53) - 1); // [0, 1]
52             } else {
53 30029           scale = 1.0 / (1ULL << 53); // [0, 1)
54             }
55              
56 40029           double ret = (num >> 11) * scale; // Top 53 bits divided by 1/2^53
57              
58             //printf("Double: %0.15f\n", ret);
59              
60 40029           return ret;
61             }
62              
63 0           static float _uint32_to_float(uint32_t num, bool inclusive) {
64             float scale;
65 0 0         if (inclusive) {
66 0           scale = 1.0f / ((1U << 24) - 1); // [0, 1]
67             } else {
68 0           scale = 1.0f / (1U << 24); // [0, 1)
69             }
70              
71 0           float ret = (num >> 8) * scale;
72              
73 0           return ret;
74             }
75              
76             // Why This Works
77             // (x + 0.5) offsets each uint32_t value into the center of its floating-point "bin," reducing bias.
78             // Multiplying by 1.0 / 4294967296.0 scales it into the range [0,1).
79 0           static double _uint32_to_double_old(uint32_t x) {
80 0           return (x + 0.5) * (1.0 / 4294967296.0); // 1/2^32
81             }
82              
83             // MurmurHash3 Finalizer (Passes SmallCrush)
84 8           static uint64_t _hash_mur3(uint64_t x) {
85 8           x ^= x >> 33;
86 8           x *= 0xff51afd7ed558ccd;
87 8           x ^= x >> 33;
88 8           x *= 0xc4ceb9fe1a85ec53;
89 8           x ^= x >> 33;
90 8           return x;
91             }