1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- #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)
- {
- 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;
- }
|