From 60478656fad8d8a487e9bc52d025f69767c3262b Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sun, 17 Sep 1995 20:23:15 +0000 Subject: Sat Sep 16 17:47:19 1995 Ulrich Drepper * 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 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. --- stdlib/random.c | 187 +++++++++++--------------------------------------------- 1 file changed, 36 insertions(+), 151 deletions(-) (limited to 'stdlib/random.c') 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 -#include #include #include #include @@ -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) -- cgit v1.1