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); 18 vr = gs->stddev * (r / (FRAND32_MAX + 1.0)); 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 if (!gs->disable_hash) 42 sum = __hash_u64(sum); 43 44 return sum % gs->nranges; 45 } 46 47 void gauss_init(struct gauss_state *gs, unsigned long nranges, double dev, 48 unsigned int seed) 49 { 50 memset(gs, 0, sizeof(*gs)); 51 init_rand_seed(&gs->r, seed, 0); 52 gs->nranges = nranges; 53 54 if (dev != 0.0) { 55 gs->stddev = ceil((double) (nranges * 100.0) / dev); 56 if (gs->stddev > nranges / 2) 57 gs->stddev = nranges / 2; 58 } 59 } 60 61 void gauss_disable_hash(struct gauss_state *gs) 62 { 63 gs->disable_hash = true; 64 } 65