Commit | Line | Data |
---|---|---|
56d9fa4b JA |
1 | #include <math.h> |
2 | #include <string.h> | |
3 | #include <stdio.h> | |
4 | #include "../hash.h" | |
5 | #include "gauss.h" | |
6 | ||
7 | #define GAUSS_ITERS 12 | |
8 | ||
9 | static int gauss_dev(struct gauss_state *gs) | |
10 | { | |
11 | unsigned int r; | |
12 | int vr; | |
13 | ||
14 | if (!gs->stddev) | |
15 | return 0; | |
16 | ||
17 | r = __rand(&gs->r); | |
c3546b53 | 18 | vr = gs->stddev * (r / (FRAND32_MAX + 1.0)); |
56d9fa4b JA |
19 | |
20 | return vr - gs->stddev / 2; | |
21 | } | |
22 | ||
23 | unsigned long long gauss_next(struct gauss_state *gs) | |
24 | { | |
25 | unsigned long long sum = 0; | |
26 | int i; | |
27 | ||
28 | for (i = 0; i < GAUSS_ITERS; i++) | |
29 | sum += __rand(&gs->r) % (gs->nranges + 1); | |
30 | ||
31 | sum = (sum + GAUSS_ITERS - 1) / GAUSS_ITERS; | |
32 | ||
33 | if (gs->stddev) { | |
34 | int dev = gauss_dev(gs); | |
35 | ||
36 | while (dev + sum >= gs->nranges) | |
37 | dev /= 2; | |
38 | sum += dev; | |
39 | } | |
40 | ||
8348daf9 | 41 | if (!gs->disable_hash) |
8c5e96a4 | 42 | sum = __hash_u64(sum); |
8348daf9 JA |
43 | |
44 | return sum % gs->nranges; | |
56d9fa4b JA |
45 | } |
46 | ||
f88cd222 | 47 | void gauss_init(struct gauss_state *gs, unsigned long nranges, double dev, |
56d9fa4b JA |
48 | unsigned int seed) |
49 | { | |
50 | memset(gs, 0, sizeof(*gs)); | |
c3546b53 | 51 | init_rand_seed(&gs->r, seed, 0); |
56d9fa4b | 52 | gs->nranges = nranges; |
f88cd222 JA |
53 | |
54 | if (dev != 0.0) { | |
55 | gs->stddev = ceil((double) (nranges * 100.0) / dev); | |
3cdb8cf3 JA |
56 | if (gs->stddev > nranges / 2) |
57 | gs->stddev = nranges / 2; | |
58 | } | |
56d9fa4b | 59 | } |
8348daf9 JA |
60 | |
61 | void gauss_disable_hash(struct gauss_state *gs) | |
62 | { | |
63 | gs->disable_hash = true; | |
64 | } |