diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2005-12-12 22:43:16 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2005-12-12 22:43:16 +0000 |
commit | c5174f6fb2af2801895c90122e07139f4de5412d (patch) | |
tree | f871e4b64413aef23ed01e4d1661a933c17f51c9 /src | |
parent | b22d6cc592e5488619a7d3d7875d360465f714d3 (diff) | |
download | coreutils-c5174f6fb2af2801895c90122e07139f4de5412d.tar.xz |
(struct irand_state, irand_init, irand32, irand_mod): Moved back here,
from rand-isaac.c.
Diffstat (limited to 'src')
-rw-r--r-- | src/shred.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/src/shred.c b/src/shred.c index 54bc49cb4..3e47aad1c 100644 --- a/src/shred.c +++ b/src/shred.c @@ -227,6 +227,66 @@ to be recovered later.\n\ exit (status); } +/* Single-word RNG built on top of ISAAC */ +struct irand_state +{ + uint32_t r[ISAAC_WORDS]; + unsigned int numleft; + struct isaac_state *s; +}; + +static void +irand_init (struct irand_state *r, struct isaac_state *s) +{ + r->numleft = 0; + r->s = s; +} + +/* + * We take from the end of the block deliberately, so if we need + * only a small number of values, we choose the final ones which are + * marginally better mixed than the initial ones. + */ +static uint32_t +irand32 (struct irand_state *r) +{ + if (!r->numleft) + { + isaac_refill (r->s, r->r); + r->numleft = ISAAC_WORDS; + } + return r->r[--r->numleft]; +} + +/* + * Return a uniformly distributed random number between 0 and n, + * inclusive. Thus, the result is modulo n+1. + * + * Theory of operation: as x steps through every possible 32-bit number, + * x % n takes each value at least 2^32 / n times (rounded down), but + * the values less than 2^32 % n are taken one additional time. Thus, + * x % n is not perfectly uniform. To fix this, the values of x less + * than 2^32 % n are disallowed, and if the RNG produces one, we ask + * for a new value. + */ +static uint32_t +irand_mod (struct irand_state *r, uint32_t n) +{ + uint32_t x; + uint32_t lim; + + if (!++n) + return irand32 (r); + + lim = -n % n; /* == (2**32-n) % n == 2**32 % n */ + do + { + x = irand32 (r); + } + while (x < lim); + return x % n; +} + /* * Fill a buffer with a fixed pattern. * |