/* * Use ARC4 to generate large random numbers * * Bart 1999/2 * * Modified 2003/4 to support /dev/random */ autoload ARC4; namespace PRNG { import File; global bool setkey = false; public void srandom(int s) /* * Seed the PRNG with 's' */ { ARC4::nsetkey(10, abs (s)); setkey = true; } public void dev_srandom(int nbits) /* * Use 'nbits' of /dev/urandom to seed the PRNG */ { twixt(file f = open("/dev/urandom", "r"); close(f)) { int seed = 0; while (nbits >= 8) { seed = (seed << 8) | getb(f); nbits -= 8; } if (nbits > 0) seed = (seed << nbits) | (getb(f) & ((1 << nbits) - 1)); srandom(seed); } } public int randbits(int n) /* * returns an 'n'-*bit* random number in 0..(2**'n')-1 */ { int q = n >> 3; int r = n & 7; if (!setkey) srandom(0); int acc = ARC4::streambyte() >> (8 - r); while (q > 0) { --q; acc += ARC4::streambyte() << (8 * q + r); } return acc; } public int randint(int n) /* * Returns a random integer in the range 0..'n'-1 */ { return randbits(32 + bit_width (n)) % n; } public void shuffle(&poly[*] a) /* * Randomly shuffle 'a' in place */ { int na = dim(a); for (int i = 0; i < na - 1; i++) { int j = randint(na - i) + i; poly tmp = a[i]; a[i] = a[j]; a[j] = tmp; } } }