Merge branch 'master' of https://github.com/celestinechen/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 42
a87c90fd 43 return (sum + gs->rand_off) % gs->nranges;
56d9fa4b
JA
44}
45
f88cd222 46void gauss_init(struct gauss_state *gs, unsigned long nranges, double dev,
a87c90fd 47 double center, unsigned int seed)
56d9fa4b
JA
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) {
9853da1d 54 gs->stddev = ceil((double)(nranges * dev) / 100.0);
3cdb8cf3
JA
55 if (gs->stddev > nranges / 2)
56 gs->stddev = nranges / 2;
57 }
a87c90fd
AK
58 if (center == -1)
59 gs->rand_off = 0;
60 else
61 gs->rand_off = nranges * (center - 0.5);
56d9fa4b 62}
8348daf9
JA
63
64void gauss_disable_hash(struct gauss_state *gs)
65{
66 gs->disable_hash = true;
67}