summaryrefslogtreecommitdiff
path: root/stdlib/random.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-09-17 20:23:15 +0000
committerRoland McGrath <roland@gnu.org>1995-09-17 20:23:15 +0000
commit60478656fad8d8a487e9bc52d025f69767c3262b (patch)
tree0ae0836023f1c2f80064e7611f91d19c482208d9 /stdlib/random.c
parent9fd18b6c1b397e1af82a0b544f10f946c73864b6 (diff)
Sat Sep 16 17:47:19 1995 Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de>
* elf/elf.h (AT_GID): Fix typo: Read -> Real. * misc/efgvt_r.c: New file. Reentrant version of [efg]cvt functions. * misc/efgcvt.c: Rewrite to use reentrant functions. * misc/hsearch_r.c: New file. Reentrant version of functions from hsearch family. * misc/hsearch.c, misc/tsearch.c: New files. * misc/Makefile (routines): Add efgcvt_r, hsearch_r, hsearch, tsearch. * posix/unistd.h (ttyname_r): Add prototype for new function. * stdlib/drand48_r.c, stdlib/erand48_r.c, stdlib/jrand48_r.c, stdlib/lrand48_r.c, stdlib/mrand48_r.c, stdlib/nrand48_r.c, stdlib/seed48_r.c, stdlib/srand48_r.c, stdlib/lcong48_r.c, stdlib/drand48-iter.c: New files implementing reentrant versions of functions from drand48 family. * stdlib/seed48.c, stdlib/drand48.c, stdlib/erand48.c, stdlib/jrand48.c, stdlib/lrand48.c, stdlib/mrand48.c, stdlib/nrand48.c, stdlib/srand48.c, stdlib/lcong48.c: Rewrite to use reentrant versions. * stdlib/a64l.c, stdlib/l64a.c: New files. Implement a64l() and l64a() functions from SysV library. * stdlib/Makefile (routines): Add drand48_r, erand48_r, lrand48_r, nrand48_r, mrand48_r, jrand48_r, srand48_r, seed48_r, lcong48_r, drand48-iter, a64l, l64a. * stdlib/stdlib.h: Declare them. * stdlib/random_r.c: New file. Reentrant version of functions from random family. * stdlib/stdlib.h: Declare them. * stdlib/random.c: Rewrite to use reentrant functions. * string/strerror_r.c: New file. Reentrant version. * string/strerror.c: Change for new _strerror_internal form. * string/Makefile (routines): Add strerror_r. * sysdeps/generic/dl-sysdep.c (_dl_sysdep_start): Set default value of user_entry to `_start'. Close AT_ENTRY case with `break'. * sysdeps/generic/strstr.c: New and much faster implementation by Stephen R. van den Berg. * sysdeps/generic/_strerror.c: _strerror_internal now takes three argument and has and explicit buffer length. * sysdeps/mach/_strerror.c: Change for new interface with three arguments. * stdio/perror.c, stdio/vfprintf.c: Callers changed. * sysdeps/mach/hurd/ttyname_r.c: New file. Reentrant version. * sysdeps/posix/ttyname_r.c: New file. Reentrant version. * sysdeps/stub/ttyname_r: New file. Define as dummy function. * sysdeps/posix/utimes.c: Include <utime.h> for prototype. (utimes): First parameter to utime must be file, not path. * sysdeps/posix/sysconf.c (__sysconf): Test for CLK_TCK in case _SC_CLK_TCK and return it when available. Test for STREAM_MAX in case _SC_STREAM_MAX and return it when available. Add case for _SC_2_LOCALEDEF which is now available. * posix/sys/types.h [__USE_SVID] (key_t): New type. * sysvipc/Makefile, sysvipc/ftok.c, sysvipc/sys/ipc.h, sysvipc/sys/msg.h, sysvipc/sys/sem.h, sysvipc/sys/shm.h, sysdeps/stub/sys/msq_buf.h, sysdeps/stub/sys/sem_buf.h, sysdeps/stub/sys/shm_buf.h, sysdeps/stub/sys/ipc_buf.h, sysdeps/stub/semctl.c, sysdeps/stub/semget.c, sysdeps/stub/semop.c, sysdeps/stub/shmat.c, sysdeps/stub/shmctl.c, sysdeps/stub/shmdt.c, sysdeps/stub/shmget.c, sysdeps/stub/msgctl.c, sysdeps/stub/msgget.c, sysdeps/stub/msgrcv.c, sysdeps/stub/msgsnd.c: New files. Add implementation of System V IPC.
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 473a5b13d3..c3f8eaa0a3 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)