os161-1.99
 All Data Structures
random.c
00001 /*
00002  * Copyright (c) 1983, 1993
00003  *      The Regents of the University of California.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. All advertising materials mentioning features or use of this software
00014  *    must display the following acknowledgement:
00015  *      This product includes software developed by the University of
00016  *      California, Berkeley and its contributors.
00017  * 4. Neither the name of the University nor the names of its contributors
00018  *    may be used to endorse or promote products derived from this software
00019  *    without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  */
00033 
00034 /*
00035  * From:
00036  *    NetBSD: random.c,v 1.19 2000/01/22 22:19:20 mycroft Exp
00037  *
00038  * Hacked gruesomely for OS/161.
00039  */
00040 
00041 #include <assert.h>
00042 #include <errno.h>
00043 #include <stdlib.h>
00044 
00045 /*
00046  * For a thread-safe libc, declare a lock for this file and change
00047  * these to be nonempty.
00048  */
00049 #define LOCKME()
00050 #define UNLOCKME()
00051 
00052 static void srandom_unlocked(unsigned long);
00053 static long random_unlocked(void);
00054 
00055 
00056 /*
00057  * random.c:
00058  *
00059  * An improved random number generation package.  In addition to the standard
00060  * rand()/srand() like interface, this package also has a special state info
00061  * interface.  The initstate() routine is called with a seed, an array of
00062  * bytes, and a count of how many bytes are being passed in; this array is
00063  * then initialized to contain information for random number generation with
00064  * that much state information.  Good sizes for the amount of state
00065  * information are 32, 64, 128, and 256 bytes.  The state can be switched by
00066  * calling the setstate() routine with the same array as was initiallized
00067  * with initstate().  By default, the package runs with 128 bytes of state
00068  * information and generates far better random numbers than a linear
00069  * congruential generator.  If the amount of state information is less than
00070  * 32 bytes, a simple linear congruential R.N.G. is used.
00071  *
00072  * Internally, the state information is treated as an array of longs; the
00073  * zeroeth element of the array is the type of R.N.G. being used (small
00074  * integer); the remainder of the array is the state information for the
00075  * R.N.G.  Thus, 32 bytes of state information will give 7 longs worth of
00076  * state information, which will allow a degree seven polynomial.  (Note:
00077  * the zeroeth word of state information also has some other information
00078  * stored in it -- see setstate() for details).
00079  * 
00080  * The random number generation technique is a linear feedback shift register
00081  * approach, employing trinomials (since there are fewer terms to sum up that
00082  * way).  In this approach, the least significant bit of all the numbers in
00083  * the state table will act as a linear feedback shift register, and will
00084  * have period 2^deg - 1 (where deg is the degree of the polynomial being
00085  * used, assuming that the polynomial is irreducible and primitive).  The
00086  * higher order bits will have longer periods, since their values are also
00087  * influenced by pseudo-random carries out of the lower bits.  The total
00088  * period of the generator is approximately deg*(2**deg - 1); thus doubling
00089  * the amount of state information has a vast influence on the period of the
00090  * generator.  Note: the deg*(2**deg - 1) is an approximation only good for
00091  * large deg, when the period of the shift register is the dominant factor.
00092  * With deg equal to seven, the period is actually much longer than the
00093  * 7*(2**7 - 1) predicted by this formula.
00094  *
00095  * Modified 28 December 1994 by Jacob S. Rosenberg.
00096  * The following changes have been made:
00097  * All references to the type u_int have been changed to unsigned long.
00098  * All references to type int have been changed to type long.  Other
00099  * cleanups have been made as well.  A warning for both initstate and
00100  * setstate has been inserted to the effect that on Sparc platforms
00101  * the 'arg_state' variable must be forced to begin on word boundaries.
00102  * This can be easily done by casting a long integer array to char *.
00103  * The overall logic has been left STRICTLY alone.  This software was
00104  * tested on both a VAX and Sun SpacsStation with exactly the same
00105  * results.  The new version and the original give IDENTICAL results.
00106  * The new version is somewhat faster than the original.  As the
00107  * documentation says:  "By default, the package runs with 128 bytes of
00108  * state information and generates far better random numbers than a linear
00109  * congruential generator.  If the amount of state information is less than
00110  * 32 bytes, a simple linear congruential R.N.G. is used."  For a buffer of
00111  * 128 bytes, this new version runs about 19 percent faster and for a 16
00112  * byte buffer it is about 5 percent faster.
00113  */
00114 
00115 /*
00116  * For each of the currently supported random number generators, we have a
00117  * break value on the amount of state information (you need at least this
00118  * many bytes of state info to support this random number generator), a degree
00119  * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
00120  * the separation between the two lower order coefficients of the trinomial.
00121  */
00122 #define TYPE_0          0               /* linear congruential */
00123 #define BREAK_0         8
00124 #define DEG_0           0
00125 #define SEP_0           0
00126 
00127 #define TYPE_1          1               /* x**7 + x**3 + 1 */
00128 #define BREAK_1         32
00129 #define DEG_1           7
00130 #define SEP_1           3
00131 
00132 #define TYPE_2          2               /* x**15 + x + 1 */
00133 #define BREAK_2         64
00134 #define DEG_2           15
00135 #define SEP_2           1
00136 
00137 #define TYPE_3          3               /* x**31 + x**3 + 1 */
00138 #define BREAK_3         128
00139 #define DEG_3           31
00140 #define SEP_3           3
00141 
00142 #define TYPE_4          4               /* x**63 + x + 1 */
00143 #define BREAK_4         256
00144 #define DEG_4           63
00145 #define SEP_4           1
00146 
00147 /*
00148  * Array versions of the above information to make code run faster --
00149  * relies on fact that TYPE_i == i.
00150  */
00151 #define MAX_TYPES       5               /* max number of types above */
00152 
00153 static const int degrees[MAX_TYPES] =   { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
00154 static const int seps[MAX_TYPES] =      { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
00155 
00156 /*
00157  * Initially, everything is set up as if from:
00158  *
00159  *      initstate(1, &randtbl, 128);
00160  *
00161  * Note that this initialization takes advantage of the fact that srandom()
00162  * advances the front and rear pointers 10*rand_deg times, and hence the
00163  * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
00164  * element of the state information, which contains info about the current
00165  * position of the rear pointer is just
00166  *
00167  *      MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
00168  */
00169 
00170 static long randtbl[DEG_3 + 1] = {
00171         TYPE_3,
00172         (long)0x9a319039L, (long)0x32d9c024L, (long)0x9b663182L,
00173         (long)0x5da1f342L, (long)0xde3b81e0L, (long)0xdf0a6fb5L,
00174         (long)0xf103bc02L, (long)0x48f340fbL, (long)0x7449e56bL,
00175         (long)0xbeb1dbb0L, (long)0xab5c5918L, (long)0x946554fdL,
00176         (long)0x8c2e680fL, (long)0xeb3d799fL, (long)0xb11ee0b7L,
00177         (long)0x2d436b86L, (long)0xda672e2aL, (long)0x1588ca88L,
00178         (long)0xe369735dL, (long)0x904f35f7L, (long)0xd7158fd6L,
00179         (long)0x6fa6f051L, (long)0x616e6b96L, (long)0xac94efdcL,
00180         (long)0x36413f93L, (long)0xc622c298L, (long)0xf5a42ab8L,
00181         (long)0x8a88d77bL, (long)0xf5ad9d0eL, (long)0x8999220bL,
00182         (long)0x27fb47b9L,
00183 };
00184 
00185 /*
00186  * fptr and rptr are two pointers into the state info, a front and a rear
00187  * pointer.  These two pointers are always rand_sep places aparts, as they
00188  * cycle cyclically through the state information.  (Yes, this does mean we
00189  * could get away with just one pointer, but the code for random() is more
00190  * efficient this way).  The pointers are left positioned as they would be
00191  * from the call
00192  *
00193  *      initstate(1, randtbl, 128);
00194  *
00195  * (The position of the rear pointer, rptr, is really 0 (as explained above
00196  * in the initialization of randtbl) because the state table pointer is set
00197  * to point to randtbl[1] (as explained below).
00198  */
00199 static long *fptr = &randtbl[SEP_3 + 1];
00200 static long *rptr = &randtbl[1];
00201 
00202 /*
00203  * The following things are the pointer to the state information table, the
00204  * type of the current generator, the degree of the current polynomial being
00205  * used, and the separation between the two pointers.  Note that for efficiency
00206  * of random(), we remember the first location of the state information, not
00207  * the zeroeth.  Hence it is valid to access state[-1], which is used to
00208  * store the type of the R.N.G.  Also, we remember the last location, since
00209  * this is more efficient than indexing every time to find the address of
00210  * the last element to see if the front and rear pointers have wrapped.
00211  */
00212 static long *state = &randtbl[1];
00213 static long rand_type = TYPE_3;
00214 static int rand_deg = DEG_3;
00215 static int rand_sep = SEP_3;
00216 static long *end_ptr = &randtbl[DEG_3 + 1];
00217 
00218 /*
00219  * srandom:
00220  *
00221  * Initialize the random number generator based on the given seed.  If the
00222  * type is the trivial no-state-information type, just remember the seed.
00223  * Otherwise, initializes state[] based on the given "seed" via a linear
00224  * congruential generator.  Then, the pointers are set to known locations
00225  * that are exactly rand_sep places apart.  Lastly, it cycles the state
00226  * information a given number of times to get rid of any initial dependencies
00227  * introduced by the L.C.R.N.G.  Note that the initialization of randtbl[]
00228  * for default usage relies on values produced by this routine.
00229  */
00230 static
00231 void
00232 srandom_unlocked(unsigned long x)
00233 {
00234         int i;
00235 
00236         if (rand_type == TYPE_0)
00237                 state[0] = x;
00238         else {
00239                 state[0] = x;
00240                 for (i = 1; i < rand_deg; i++)
00241                         state[i] = 1103515245L * state[i - 1] + 12345L;
00242                 fptr = &state[rand_sep];
00243                 rptr = &state[0];
00244                 for (i = 0; i < 10 * rand_deg; i++)
00245                         (void)random_unlocked();
00246         }
00247 }
00248 
00249 void
00250 srandom(unsigned long x)
00251 {
00252 
00253         LOCKME();
00254         srandom_unlocked(x);
00255         UNLOCKME();
00256 }
00257 
00258 /*
00259  * initstate:
00260  *
00261  * Initialize the state information in the given array of n bytes for future
00262  * random number generation.  Based on the number of bytes we are given, and
00263  * the break values for the different R.N.G.'s, we choose the best (largest)
00264  * one we can and set things up for it.  srandom() is then called to
00265  * initialize the state information.
00266  * 
00267  * Note that on return from srandom(), we set state[-1] to be the type
00268  * multiplexed with the current value of the rear pointer; this is so
00269  * successive calls to initstate() won't lose this information and will be
00270  * able to restart with setstate().
00271  * 
00272  * Note: the first thing we do is save the current state, if any, just like
00273  * setstate() so that it doesn't matter when initstate is called.
00274  *
00275  * Returns a pointer to the old state.
00276  *
00277  * Note: The Sparc platform requires that arg_state begin on a long
00278  * word boundary; otherwise a bus error will occur. Even so, lint will
00279  * complain about mis-alignment, but you should disregard these messages.
00280  */
00281 char *
00282 initstate(
00283         unsigned long seed,             /* seed for R.N.G. */
00284         char *arg_state,                /* pointer to state array */
00285         size_t n)                       /* # bytes of state info */
00286 {
00287         void *ostate = (void *)(&state[-1]);
00288         long *long_arg_state;
00289 
00290         assert(arg_state != NULL);
00291 
00292         long_arg_state = (long *)(void *)arg_state;
00293 
00294         LOCKME();
00295         if (rand_type == TYPE_0)
00296                 state[-1] = rand_type;
00297         else
00298                 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
00299         if (n < BREAK_0) {
00300                 UNLOCKME();
00301                 return (NULL);
00302         } else if (n < BREAK_1) {
00303                 rand_type = TYPE_0;
00304                 rand_deg = DEG_0;
00305                 rand_sep = SEP_0;
00306         } else if (n < BREAK_2) {
00307                 rand_type = TYPE_1;
00308                 rand_deg = DEG_1;
00309                 rand_sep = SEP_1;
00310         } else if (n < BREAK_3) {
00311                 rand_type = TYPE_2;
00312                 rand_deg = DEG_2;
00313                 rand_sep = SEP_2;
00314         } else if (n < BREAK_4) {
00315                 rand_type = TYPE_3;
00316                 rand_deg = DEG_3;
00317                 rand_sep = SEP_3;
00318         } else {
00319                 rand_type = TYPE_4;
00320                 rand_deg = DEG_4;
00321                 rand_sep = SEP_4;
00322         }
00323         state = (long *) (long_arg_state + 1); /* first location */
00324         end_ptr = &state[rand_deg];     /* must set end_ptr before srandom */
00325         srandom_unlocked(seed);
00326         if (rand_type == TYPE_0)
00327                 long_arg_state[0] = rand_type;
00328         else
00329                 long_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
00330         UNLOCKME();
00331         return((char *)ostate);
00332 }
00333 
00334 /*
00335  * setstate:
00336  *
00337  * Restore the state from the given state array.
00338  *
00339  * Note: it is important that we also remember the locations of the pointers
00340  * in the current state information, and restore the locations of the pointers
00341  * from the old state information.  This is done by multiplexing the pointer
00342  * location into the zeroeth word of the state information.
00343  *
00344  * Note that due to the order in which things are done, it is OK to call
00345  * setstate() with the same state as the current state.
00346  *
00347  * Returns a pointer to the old state information.
00348  *
00349  * Note: The Sparc platform requires that arg_state begin on a long
00350  * word boundary; otherwise a bus error will occur. Even so, lint will
00351  * complain about mis-alignment, but you should disregard these messages.
00352  */
00353 char *
00354 setstate(char *arg_state)               /* pointer to state array */
00355 {
00356         long *new_state;
00357         int type;
00358         int rear;
00359         void *ostate = (void *)(&state[-1]);
00360 
00361         assert(arg_state != NULL);
00362 
00363         new_state = (long *)(void *)arg_state;
00364         type = (int)(new_state[0] % MAX_TYPES);
00365         rear = (int)(new_state[0] / MAX_TYPES);
00366 
00367         LOCKME();
00368         if (rand_type == TYPE_0)
00369                 state[-1] = rand_type;
00370         else
00371                 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
00372         switch(type) {
00373         case TYPE_0:
00374         case TYPE_1:
00375         case TYPE_2:
00376         case TYPE_3:
00377         case TYPE_4:
00378                 rand_type = type;
00379                 rand_deg = degrees[type];
00380                 rand_sep = seps[type];
00381                 break;
00382         default:
00383                 UNLOCKME();
00384                 return (NULL);
00385         }
00386         state = (long *) (new_state + 1);
00387         if (rand_type != TYPE_0) {
00388                 rptr = &state[rear];
00389                 fptr = &state[(rear + rand_sep) % rand_deg];
00390         }
00391         end_ptr = &state[rand_deg];             /* set end_ptr too */
00392         UNLOCKME();
00393         return((char *)ostate);
00394 }
00395 
00396 /*
00397  * random:
00398  *
00399  * If we are using the trivial TYPE_0 R.N.G., just do the old linear
00400  * congruential bit.  Otherwise, we do our fancy trinomial stuff, which is
00401  * the same in all the other cases due to all the global variables that have
00402  * been set up.  The basic operation is to add the number at the rear pointer
00403  * into the one at the front pointer.  Then both pointers are advanced to
00404  * the next location cyclically in the table.  The value returned is the sum
00405  * generated, reduced to 31 bits by throwing away the "least random" low bit.
00406  *
00407  * Note: the code takes advantage of the fact that both the front and
00408  * rear pointers can't wrap on the same call by not testing the rear
00409  * pointer if the front one has wrapped.
00410  *
00411  * Returns a 31-bit random number.
00412  */
00413 static
00414 long
00415 random_unlocked(void)
00416 {
00417         long i;
00418         long *f, *r;
00419 
00420         if (rand_type == TYPE_0) {
00421                 i = state[0];
00422                 state[0] = i = (i * 1103515245L + 12345L) & 0x7fffffff;
00423         } else {
00424                 /*
00425                  * Use local variables rather than static variables for speed.
00426                  */
00427                 f = fptr; r = rptr;
00428                 *f += *r;
00429                 /* chucking least random bit */
00430                 i = ((unsigned long)*f >> 1) & 0x7fffffff;
00431                 if (++f >= end_ptr) {
00432                         f = state;
00433                         ++r;
00434                 }
00435                 else if (++r >= end_ptr) {
00436                         r = state;
00437                 }
00438 
00439                 fptr = f; rptr = r;
00440         }
00441         return(i);
00442 }
00443 
00444 long
00445 random(void)
00446 {
00447         long r;
00448 
00449         LOCKME();
00450         r = random_unlocked();
00451         UNLOCKME();
00452         return (r);
00453 }
 All Data Structures