diff options
author | rsc <devnull@localhost> | 2004-12-28 20:01:58 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-12-28 20:01:58 +0000 |
commit | b37396bd1173964d5a3e40cc3e35aad5fef854c5 (patch) | |
tree | 84b536a73e343c2663079803ab30ab6fb7c8d8a5 /src/lib9/lrand.c | |
parent | 4dd07e012c124921328df5d91c272c63e015bdd5 (diff) | |
download | plan9port-b37396bd1173964d5a3e40cc3e35aad5fef854c5.tar.gz plan9port-b37396bd1173964d5a3e40cc3e35aad5fef854c5.tar.bz2 plan9port-b37396bd1173964d5a3e40cc3e35aad5fef854c5.zip |
make these files look like plan 9's
Diffstat (limited to 'src/lib9/lrand.c')
-rw-r--r-- | src/lib9/lrand.c | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/src/lib9/lrand.c b/src/lib9/lrand.c index 47c331d9..2ebb3962 100644 --- a/src/lib9/lrand.c +++ b/src/lib9/lrand.c @@ -1,8 +1,83 @@ #include <u.h> #include <libc.h> +/* + * algorithm by + * D. P. Mitchell & J. A. Reeds + */ + +#define LEN 607 +#define TAP 273 +#define MASK 0x7fffffffL +#define A 48271 +#define M 2147483647 +#define Q 44488 +#define R 3399 +#define NORM (1.0/(1.0+MASK)) + +static ulong rng_vec[LEN]; +static ulong* rng_tap = rng_vec; +static ulong* rng_feed = 0; +static Lock lk; + +static void +isrand(long seed) +{ + long lo, hi, x; + int i; + + rng_tap = rng_vec; + rng_feed = rng_vec+LEN-TAP; + seed = seed%M; + if(seed < 0) + seed += M; + if(seed == 0) + seed = 89482311; + x = seed; + /* + * Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1) + */ + for(i = -20; i < LEN; i++) { + hi = x / Q; + lo = x % Q; + x = A*lo - R*hi; + if(x < 0) + x += M; + if(i >= 0) + rng_vec[i] = x; + } +} + +void +srand(long seed) +{ + lock(&lk); + isrand(seed); + unlock(&lk); +} + long lrand(void) { - return ((rand()<<16)^rand()) & 0x7FFFFFFF; + ulong x; + + lock(&lk); + + rng_tap--; + if(rng_tap < rng_vec) { + if(rng_feed == 0) { + isrand(1); + rng_tap--; + } + rng_tap += LEN; + } + rng_feed--; + if(rng_feed < rng_vec) + rng_feed += LEN; + x = (*rng_feed + *rng_tap) & MASK; + *rng_feed = x; + + unlock(&lk); + + return x; } |