da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "FEATURE/uwin"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_UWIN || _lib_random
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinvoid _STUB_random(){}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Copyright (c) 1983
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The Regents of the University of California. All rights reserved.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Redistribution and use in source and binary forms, with or without
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * modification, are permitted provided that the following conditions
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * are met:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * 1. Redistributions of source code must retain the above copyright
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * notice, this list of conditions and the following disclaimer.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * 2. Redistributions in binary form must reproduce the above copyright
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * notice, this list of conditions and the following disclaimer in the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * documentation and/or other materials provided with the distribution.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * 3. Neither the name of the University nor the names of its contributors
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * may be used to endorse or promote products derived from this software
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * without specific prior written permission.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * SUCH DAMAGE.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This is derived from the Berkeley source:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @(#)random.c 5.5 (Berkeley) 7/6/88
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * It was reworked for the GNU C Library by Roland McGrath.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define initstate ______initstate
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define random ______random
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define setstate ______setstate
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define srandom ______srandom
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <errno.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <limits.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <stddef.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <stdlib.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef initstate
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef random
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef setstate
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef srandom
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(__EXPORT__)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define extern __EXPORT__
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern long int random();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PTR char*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* An improved random number generation package. In addition to the standard
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand()/srand() like interface, this package also has a special state info
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin interface. The initstate() routine is called with a seed, an array of
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bytes, and a count of how many bytes are being passed in; this array is
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin then initialized to contain information for random number generation with
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin that much state information. Good sizes for the amount of state
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin information are 32, 64, 128, and 256 bytes. The state can be switched by
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin calling the setstate() function with the same array as was initiallized
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin with initstate(). By default, the package runs with 128 bytes of state
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin information and generates far better random numbers than a linear
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin congruential generator. If the amount of state information is less than
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 32 bytes, a simple linear congruential R.N.G. is used. Internally, the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state information is treated as an array of longs; the zeroeth element of
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin the array is the type of R.N.G. being used (small integer); the remainder
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin of the array is the state information for the R.N.G. Thus, 32 bytes of
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state information will give 7 longs worth of state information, which will
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin allow a degree seven polynomial. (Note: The zeroeth word of state
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin information also has some other information stored in it; see setstate
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for details). The random number generation technique is a linear feedback
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin shift register approach, employing trinomials (since there are fewer terms
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin to sum up that way). In this approach, the least significant bit of all
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin the numbers in the state table will act as a linear feedback shift register,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin and will have period 2^deg - 1 (where deg is the degree of the polynomial
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin being used, assuming that the polynomial is irreducible and primitive).
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin The higher order bits will have longer periods, since their values are
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin also influenced by pseudo-random carries out of the lower bits. The
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin total period of the generator is approximately deg*(2**deg - 1); thus
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin doubling the amount of state information has a vast influence on the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin period of the generator. Note: The deg*(2**deg - 1) is an approximation
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin only good for large deg, when the period of the shift register is the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dominant factor. With deg equal to seven, the period is actually much
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin longer than the 7*(2**7 - 1) predicted by this formula. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* For each of the currently supported random number generators, we have a
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break value on the amount of state information (you need at least thi
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bytes of state info to support this random number generator), a degree for
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin the polynomial (actually a trinomial) that the R.N.G. is based on, and
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin separation between the two lower order coefficients of the trinomial. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Linear congruential. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define TYPE_0 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BREAK_0 8
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEG_0 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SEP_0 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* x**7 + x**3 + 1. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define TYPE_1 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BREAK_1 32
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEG_1 7
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SEP_1 3
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* x**15 + x + 1. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define TYPE_2 2
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BREAK_2 64
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEG_2 15
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SEP_2 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* x**31 + x**3 + 1. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define TYPE_3 3
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BREAK_3 128
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEG_3 31
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SEP_3 3
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* x**63 + x + 1. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define TYPE_4 4
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BREAK_4 256
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEG_4 63
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SEP_4 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Array versions of the above information to make code run faster.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Relies on fact that TYPE_i == i. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define MAX_TYPES 5 /* Max number of types above. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int seps[MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Initially, everything is set up as if from:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin initstate(1, randtbl, 128);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Note that this initialization takes advantage of the fact that srandom
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin advances the front and rear pointers 10*rand_deg times, and hence the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rear pointer which starts at 0 will also end up at zero; thus the zeroeth
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin element of the state information, which contains info about the current
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin position of the rear pointer is just
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic long int randtbl[DEG_3 + 1] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin TYPE_3,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin -851904987, -43806228, -2029755270, 1390239686, -1912102820,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin -485608943, 1969813258, -1590463333, -1944053249, 455935928, 508023712,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin -1714531963, 1800685987, -2015299881, 654595283, -1149023258,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin -1470005550, -1143256056, -1325577603, -1568001885, 1275120390,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin -607508183, -205999574, -1696891592, 1492211999, -1528267240,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin -952028296, -189082757, 362343714, 1424981831, 2039449641,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin };
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* FPTR and RPTR are two pointers into the state info, a front and a rear
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pointer. These two pointers are always rand_sep places aparts, as they
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cycle through the state information. (Yes, this does mean we could get
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin away with just one pointer, but the code for random is more efficient
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin this way). The pointers are left positioned as they would be from the call:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin initstate(1, randtbl, 128);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (The position of the rear pointer, rptr, is really 0 (as explained above
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin in the initialization of randtbl) because the state table pointer is set
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin to point to randtbl[1] (as explained below).) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic long int *fptr = &randtbl[SEP_3 + 1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic long int *rptr = &randtbl[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* The following things are the pointer to the state information table,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin the type of the current generator, the degree of the current polynomial
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin being used, and the separation between the two pointers.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Note that for efficiency of random, we remember the first location of
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin the state information, not the zeroeth. Hence it is valid to access
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state[-1], which is used to store the type of the R.N.G.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Also, we remember the last location, since this is more efficient than
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin indexing every time to find the address of the last element to see if
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin the front and rear pointers have wrapped. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic long int *state = &randtbl[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int rand_type = TYPE_3;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int rand_deg = DEG_3;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int rand_sep = SEP_3;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic long int *end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Initialize the random number generator based on the given seed. If the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin type is the trivial no-state-information type, just remember the seed.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Otherwise, initializes state[] based on the given "seed" via a linear
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin congruential generator. Then, the pointers are set to known locations
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin that are exactly rand_sep places apart. Lastly, it cycles the state
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin information a given number of times to get rid of any initial dependencies
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for default usage relies on values produced by this routine. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern void srandom(unsigned int x)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state[0] = x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (rand_type != TYPE_0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register long int i;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 1; i < rand_deg; ++i)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state[i] = (1103515145 * state[i - 1]) + 12345;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fptr = &state[rand_sep];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rptr = &state[0];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i < 10 * rand_deg; ++i)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void) random();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Initialize the state information in the given array of N bytes for
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin future random number generation. Based on the number of bytes we
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin are given, and the break values for the different R.N.G.'s, we choose
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin the best (largest) one we can and set things up for it. srandom is
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin then called to initialize the state information. Note that on return
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin from srandom, we set state[-1] to be the type multiplexed with the current
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin value of the rear pointer; this is so successive calls to initstate won't
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lose this information and will be able to restart with setstate.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Note: The first thing we do is save the current state, if any, just like
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin setstate so that it doesn't matter when initstate is called.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Returns a pointer to the old state. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern char* initstate(unsigned int seed, char* arg_state, size_t n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin PTR ostate = (PTR) &state[-1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (rand_type == TYPE_0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state[-1] = rand_type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n < BREAK_1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n < BREAK_0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno = EINVAL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return NULL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_type = TYPE_0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_deg = DEG_0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_sep = SEP_0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (n < BREAK_2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_type = TYPE_1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_deg = DEG_1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_sep = SEP_1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (n < BREAK_3)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_type = TYPE_2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_deg = DEG_2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_sep = SEP_2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (n < BREAK_4)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_type = TYPE_3;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_deg = DEG_3;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_sep = SEP_3;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_type = TYPE_4;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_deg = DEG_4;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_sep = SEP_4;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state = &((long int *) arg_state)[1]; /* First location. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Must set END_PTR before srandom. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin end_ptr = &state[rand_deg];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin srandom(seed);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (rand_type == TYPE_0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state[-1] = rand_type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return ostate;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Restore the state from the given state array.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Note: It is important that we also remember the locations of the pointers
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin in the current state information, and restore the locations of the pointers
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin from the old state information. This is done by multiplexing the pointer
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin location into the zeroeth word of the state information. Note that due
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin to the order in which things are done, it is OK to call setstate with the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin same state as the current state
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Returns a pointer to the old state information. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern char *setstate(const char *arg_state)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register long int *new_state = (long int *) arg_state;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int type = new_state[0] % MAX_TYPES;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int rear = new_state[0] / MAX_TYPES;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin PTR ostate = (PTR) &state[-1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (rand_type == TYPE_0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state[-1] = rand_type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TYPE_0:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TYPE_1:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TYPE_2:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TYPE_3:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TYPE_4:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_type = type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_deg = degrees[type];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rand_sep = seps[type];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* State info munged. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno = EINVAL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return NULL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state = &new_state[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (rand_type != TYPE_0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rptr = &state[rear];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fptr = &state[(rear + rand_sep) % rand_deg];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Set end_ptr too. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin end_ptr = &state[rand_deg];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return ostate;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin congruential bit. Otherwise, we do our fancy trinomial stuff, which is the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin same in all ther other cases due to all the global variables that have been
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin set up. The basic operation is to add the number at the rear pointer into
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin the one at the front pointer. Then both pointers are advanced to the next
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin location cyclically in the table. The value returned is the sum generated,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reduced to 31 bits by throwing away the "least random" low bit.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Note: The code takes advantage of the fact that both the front and
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rear pointers can't wrap on the same call by not testing the rear
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pointer if the front one has wrapped. Returns a 31-bit random number. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern long int random()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (rand_type == TYPE_0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state[0] = ((state[0] * 1103515245) + 12345) & LONG_MAX;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return state[0];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin long int i;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *fptr += *rptr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Chucking least random bit. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin i = (*fptr >> 1) & LONG_MAX;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ++fptr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (fptr >= end_ptr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fptr = state;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ++rptr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ++rptr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (rptr >= end_ptr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rptr = state;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return i;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif