random.c
1 /* ************************************************************************ 2 * File: random.c Part of CircleMUD * 3 * Usage: pseudo-random number generator * 4 ************************************************************************ */ 5 6 /* 7 * I am bothered by the non-portablility of 'rand' and 'random' -- rand 8 * is ANSI C, but on some systems such as Suns, rand has seriously tragic 9 * spectral properties (the low bit alternates between 0 and 1!). random 10 * is better but isn't supported by all systems. So, in my quest for Ultimate 11 * CircleMUD Portability, I decided to include this code for a simple but 12 * relatively effective random number generator. It's not the best RNG code 13 * around, but I like it because it's very short and simple, and for our 14 * purposes it's "random enough". 15 * --Jeremy Elson 2/23/95 16 * 17 * Now that we're using GNU's autoconf, I've coded Circle to always use 18 * random(), and automatically link in this object file if random() isn't 19 * supported on the target system. -JE 2/3/96 20 * 21 * Well, despite autoconf we're back to using this random all the 22 * time. Oh well, there's no harm in changing my mind on this one 23 * from release to release... -JE 10/28/97 24 */ 25 26 /***************************************************************************/ 27 28 /* 29 * 30 * This program is public domain and was written by William S. England 31 * (Oct 1988). It is based on an article by: 32 * 33 * Stephen K. Park and Keith W. Miller. RANDOM NUMBER GENERATORS: 34 * GOOD ONES ARE HARD TO FIND. Communications of the ACM, 35 * New York, NY.,October 1988 p.1192 36 37 The following is a portable c program for generating random numbers. 38 The modulus and multipilier have been extensively tested and should 39 not be changed except by someone who is a professional Lehmer generator 40 writer. THIS GENERATOR REPRESENTS THE MINIMUM STANDARD AGAINST WHICH 41 OTHER GENERATORS SHOULD BE JUDGED. ("Quote from the referenced article's 42 authors. WSE" ) 43 */ 44 45 #define m (unsigned long)2147483647 46 #define q (unsigned long)127773 47 48 #define a (unsigned int)16807 49 #define r (unsigned int)2836 50 51 /* 52 ** F(z) = (az)%m 53 ** = az-m(az/m) 54 ** 55 ** F(z) = G(z)+mT(z) 56 ** G(z) = a(z%q)- r(z/q) 57 ** T(z) = (z/q) - (az/m) 58 ** 59 ** F(z) = a(z%q)- rz/q+ m((z/q) - a(z/m)) 60 ** = a(z%q)- rz/q+ m(z/q) - az 61 */ 62 63 static unsigned long seed; 64 65 /* local functions */ 66 void circle_srandom(unsigned long initial_seed); 67 unsigned long circle_random(void); 68 69 70 void circle_srandom(unsigned long initial_seed) 71 { 72 seed = initial_seed; 73 } 74 75 76 unsigned long circle_random(void) 77 { 78 int lo, hi, test; 79 80 hi = seed/q; 81 lo = seed%q; 82 83 test = a*lo - r*hi; 84 85 if (test > 0) 86 seed = test; 87 else 88 seed = test+ m; 89 90 return (seed); 91 }