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 | ||
41 | return __hash_u64(sum) % gs->nranges; | |
42 | } | |
43 | ||
f88cd222 | 44 | void gauss_init(struct gauss_state *gs, unsigned long nranges, double dev, |
56d9fa4b JA |
45 | unsigned int seed) |
46 | { | |
47 | memset(gs, 0, sizeof(*gs)); | |
c3546b53 | 48 | init_rand_seed(&gs->r, seed, 0); |
56d9fa4b | 49 | gs->nranges = nranges; |
f88cd222 JA |
50 | |
51 | if (dev != 0.0) { | |
52 | gs->stddev = ceil((double) (nranges * 100.0) / dev); | |
3cdb8cf3 JA |
53 | if (gs->stddev > nranges / 2) |
54 | gs->stddev = nranges / 2; | |
55 | } | |
56d9fa4b | 56 | } |