#include #include #include "../hash.h" #include "gauss.h" #define GAUSS_ITERS 12 static int gauss_dev(struct gauss_state *gs) { unsigned int r; int vr; if (!gs->stddev) return 0; r = __rand(&gs->r); vr = gs->stddev * (r / (FRAND32_MAX + 1.0)); return vr - gs->stddev / 2; } unsigned long long gauss_next(struct gauss_state *gs) { unsigned long long sum = 0; int i; for (i = 0; i < GAUSS_ITERS; i++) sum += __rand(&gs->r) % (gs->nranges + 1); sum = (sum + GAUSS_ITERS - 1) / GAUSS_ITERS; if (gs->stddev) { int dev = gauss_dev(gs); while (dev + sum >= gs->nranges) dev /= 2; sum += dev; } if (!gs->disable_hash) sum = __hash_u64(sum); return sum % gs->nranges; } void gauss_init(struct gauss_state *gs, unsigned long nranges, double dev, unsigned int seed) { memset(gs, 0, sizeof(*gs)); init_rand_seed(&gs->r, seed, 0); gs->nranges = nranges; if (dev != 0.0) { gs->stddev = ceil((double) (nranges * 100.0) / dev); if (gs->stddev > nranges / 2) gs->stddev = nranges / 2; } } void gauss_disable_hash(struct gauss_state *gs) { gs->disable_hash = true; }