aboutsummaryrefslogtreecommitdiff
path: root/stdlib/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/random.c')
-rw-r--r--stdlib/random.c187
1 files changed, 36 insertions, 151 deletions
diff --git a/stdlib/random.c b/stdlib/random.c
index 473a5b1..c3f8eaa 100644
--- a/stdlib/random.c
+++ b/stdlib/random.c
@@ -19,10 +19,9 @@
* This is derived from the Berkeley source:
* @(#)random.c 5.5 (Berkeley) 7/6/88
* It was reworked for the GNU C Library by Roland McGrath.
+ * Rewritten to use reentrent functions by Ulrich Drepper, 1995.
*/
-#include <ansidecl.h>
-#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
@@ -105,10 +104,6 @@
#define MAX_TYPES 5 /* Max number of types above. */
-static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
-static int seps[MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
-
-
/* Initially, everything is set up as if from:
initstate(1, randtbl, 128);
@@ -132,6 +127,9 @@ static long int randtbl[DEG_3 + 1] =
-205601318,
};
+
+static struct random_data unsafe_state =
+ {
/* FPTR and RPTR are two pointers into the state info, a front and a rear
pointer. These two pointers are always rand_sep places aparts, as they
cycle through the state information. (Yes, this does mean we could get
@@ -142,10 +140,8 @@ static long int randtbl[DEG_3 + 1] =
in the initialization of randtbl) because the state table pointer is set
to point to randtbl[1] (as explained below).) */
-static long int *fptr = &randtbl[SEP_3 + 1];
-static long int *rptr = &randtbl[1];
-
-
+ fptr : &randtbl[SEP_3 + 1],
+ rptr : &randtbl[1],
/* The following things are the pointer to the state information table,
the type of the current generator, the degree of the current polynomial
@@ -157,13 +153,14 @@ static long int *rptr = &randtbl[1];
indexing every time to find the address of the last element to see if
the front and rear pointers have wrapped. */
-static long int *state = &randtbl[1];
+ state : &randtbl[1],
-static int rand_type = TYPE_3;
-static int rand_deg = DEG_3;
-static int rand_sep = SEP_3;
+ rand_type : TYPE_3,
+ rand_deg : DEG_3,
+ rand_sep : SEP_3,
-static long int *end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])];
+ end_ptr : &randtbl[sizeof (randtbl) / sizeof (randtbl[0])]
+};
/* Initialize the random number generator based on the given seed. If the
type is the trivial no-state-information type, just remember the seed.
@@ -174,27 +171,10 @@ static long int *end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])];
introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
for default usage relies on values produced by this routine. */
void
-DEFUN(__srandom, (x), unsigned int x)
+__srandom (x)
+ unsigned int x;
{
- state[0] = x;
- if (rand_type != TYPE_0)
- {
- register long int i;
- for (i = 1; i < rand_deg; ++i)
- {
- /* This does:
- state[i] = (16807 * state[i - 1]) % 2147483647;
- but avoids overflowing 31 bits. */
- long int hi = state[i - 1] / 127773;
- long int lo = state[i - 1] % 127773;
- long int test = 16807 * lo - 2836 * hi;
- state[i] = test + (test < 0 ? 2147483647 : 0);
- }
- fptr = &state[rand_sep];
- rptr = &state[0];
- for (i = 0; i < 10 * rand_deg; ++i)
- (void) __random ();
- }
+ (void) __srandom_r (x, &unsafe_state);
}
weak_alias (__srandom, srandom)
@@ -211,60 +191,15 @@ weak_alias (__srandom, srand)
Note: The first thing we do is save the current state, if any, just like
setstate so that it doesn't matter when initstate is called.
Returns a pointer to the old state. */
-PTR
-DEFUN(__initstate, (seed, arg_state, n),
- unsigned int seed AND PTR arg_state AND size_t n)
+void *
+__initstate (seed, arg_state, n)
+ unsigned int seed;
+ void *arg_state;
+ size_t n;
{
- PTR ostate = (PTR) &state[-1];
-
- if (rand_type == TYPE_0)
- state[-1] = rand_type;
- else
- state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
- if (n < BREAK_1)
- {
- if (n < BREAK_0)
- {
- errno = EINVAL;
- return NULL;
- }
- rand_type = TYPE_0;
- rand_deg = DEG_0;
- rand_sep = SEP_0;
- }
- else if (n < BREAK_2)
- {
- rand_type = TYPE_1;
- rand_deg = DEG_1;
- rand_sep = SEP_1;
- }
- else if (n < BREAK_3)
- {
- rand_type = TYPE_2;
- rand_deg = DEG_2;
- rand_sep = SEP_2;
- }
- else if (n < BREAK_4)
- {
- rand_type = TYPE_3;
- rand_deg = DEG_3;
- rand_sep = SEP_3;
- }
- else
- {
- rand_type = TYPE_4;
- rand_deg = DEG_4;
- rand_sep = SEP_4;
- }
-
- state = &((long int *) arg_state)[1]; /* First location. */
- /* Must set END_PTR before srandom. */
- end_ptr = &state[rand_deg];
- __srandom(seed);
- if (rand_type == TYPE_0)
- state[-1] = rand_type;
- else
- state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
+ void *ostate = (void *) &unsafe_state.state[-1];
+
+ __initstate_r (seed, arg_state, n, &unsafe_state);
return ostate;
}
@@ -279,44 +214,14 @@ weak_alias (__initstate, initstate)
to the order in which things are done, it is OK to call setstate with the
same state as the current state
Returns a pointer to the old state information. */
-PTR
-DEFUN(__setstate, (arg_state), PTR arg_state)
+void *
+__setstate (arg_state)
+ void *arg_state;
{
- register long int *new_state = (long int *) arg_state;
- register int type = new_state[0] % MAX_TYPES;
- register int rear = new_state[0] / MAX_TYPES;
- PTR ostate = (PTR) &state[-1];
-
- if (rand_type == TYPE_0)
- state[-1] = rand_type;
- else
- state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
-
- switch (type)
- {
- case TYPE_0:
- case TYPE_1:
- case TYPE_2:
- case TYPE_3:
- case TYPE_4:
- rand_type = type;
- rand_deg = degrees[type];
- rand_sep = seps[type];
- break;
- default:
- /* State info munged. */
- errno = EINVAL;
- return NULL;
- }
-
- state = &new_state[1];
- if (rand_type != TYPE_0)
- {
- rptr = &state[rear];
- fptr = &state[(rear + rand_sep) % rand_deg];
- }
- /* Set end_ptr too. */
- end_ptr = &state[rand_deg];
+ void *ostate = (void *) &unsafe_state.state[-1];
+
+ if (__setstate_r (arg_state, &unsafe_state) < 0)
+ return NULL;
return ostate;
}
@@ -335,33 +240,13 @@ weak_alias (__setstate, setstate)
pointer if the front one has wrapped. Returns a 31-bit random number. */
long int
-DEFUN_VOID(__random)
+__random ()
{
- if (rand_type == TYPE_0)
- {
- state[0] = ((state[0] * 1103515245) + 12345) & LONG_MAX;
- return state[0];
- }
- else
- {
- long int i;
- *fptr += *rptr;
- /* Chucking least random bit. */
- i = (*fptr >> 1) & LONG_MAX;
- ++fptr;
- if (fptr >= end_ptr)
- {
- fptr = state;
- ++rptr;
- }
- else
- {
- ++rptr;
- if (rptr >= end_ptr)
- rptr = state;
- }
- return i;
- }
+ long int retval;
+
+ (void) __random_r (&unsafe_state, &retval);
+
+ return retval;
}
weak_alias (__random, random)