1 /* 2 * libc pseudo-random number generators, but without locks. 3 */ 4 #include "u.h" 5 #include "../port/lib.h" 6 #include "mem.h" 7 #include "dat.h" 8 #include "fns.h" 9 #include "io.h" 10 #include "ureg.h" 11 #include "pool.h" 12 13 /* stubs to emulate random.c */ 14 ulong randomread(void *,ulong)15randomread(void *, ulong) 16 { 17 return 0; 18 } 19 20 void randominit(void)21randominit(void) 22 { 23 } 24 25 /* 26 * algorithm by 27 * D. P. Mitchell & J. A. Reeds 28 */ 29 30 #define LEN 607 31 #define TAP 273 32 #define MASK 0x7fffffffL 33 #define A 48271 34 #define M 2147483647 35 #define Q 44488 36 #define R 3399 37 #define NORM (1.0/(1.0+MASK)) 38 39 static ulong rng_vec[LEN]; 40 static ulong* rng_tap = rng_vec; 41 static ulong* rng_feed = 0; 42 43 static void isrand(long seed)44isrand(long seed) 45 { 46 long lo, hi, x; 47 int i; 48 49 rng_tap = rng_vec; 50 rng_feed = rng_vec+LEN-TAP; 51 seed = seed%M; 52 if(seed < 0) 53 seed += M; 54 if(seed == 0) 55 seed = 89482311; 56 x = seed; 57 /* 58 * Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1) 59 */ 60 for(i = -20; i < LEN; i++) { 61 hi = x / Q; 62 lo = x % Q; 63 x = A*lo - R*hi; 64 if(x < 0) 65 x += M; 66 if(i >= 0) 67 rng_vec[i] = x; 68 } 69 } 70 71 void srand(long seed)72srand(long seed) 73 { 74 isrand(seed); 75 } 76 77 long lrand(void)78lrand(void) 79 { 80 ulong x; 81 82 rng_tap--; 83 if(rng_tap < rng_vec) { 84 if(rng_feed == 0) { 85 isrand(1); 86 rng_tap--; 87 } 88 rng_tap += LEN; 89 } 90 rng_feed--; 91 if(rng_feed < rng_vec) 92 rng_feed += LEN; 93 x = (*rng_feed + *rng_tap) & MASK; 94 *rng_feed = x; 95 return x; 96 } 97