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