rand: add 64-bit tausworthe variant with a 2^258 cycle
[fio.git] / lib / gauss.c
CommitLineData
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
9static 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
23unsigned 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 44void 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}