summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdlib/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/stdlib/random.c')
-rw-r--r--lib/libc/stdlib/random.c98
1 files changed, 68 insertions, 30 deletions
diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c
index d1ec971..9f5bd2a 100644
--- a/lib/libc/stdlib/random.c
+++ b/lib/libc/stdlib/random.c
@@ -32,7 +32,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)random.c 8.1 (Berkeley) 6/4/93";
+static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95";
#endif /* LIBC_SCCS and not lint */
#ifdef COMPAT_WEAK_SEEDING
@@ -84,6 +84,25 @@ static char sccsid[] = "@(#)random.c 8.1 (Berkeley) 6/4/93";
* large deg, when the period of the shift register is the dominant factor.
* With deg equal to seven, the period is actually much longer than the
* 7*(2**7 - 1) predicted by this formula.
+ *
+ * Modified 28 December 1994 by Jacob S. Rosenberg.
+ * The following changes have been made:
+ * All references to the type u_int have been changed to unsigned long.
+ * All references to type int have been changed to type long. Other
+ * cleanups have been made as well. A warning for both initstate and
+ * setstate has been inserted to the effect that on Sparc platforms
+ * the 'arg_state' variable must be forced to begin on word boundaries.
+ * This can be easily done by casting a long integer array to char *.
+ * The overall logic has been left STRICTLY alone. This software was
+ * tested on both a VAX and Sun SpacsStation with exactly the same
+ * results. The new version and the original give IDENTICAL results.
+ * The new version is somewhat faster than the original. As the
+ * documentation says: "By default, the package runs with 128 bytes of
+ * state information and generates far better random numbers than a linear
+ * congruential generator. If the amount of state information is less than
+ * 32 bytes, a simple linear congruential R.N.G. is used." For a buffer of
+ * 128 bytes, this new version runs about 19 percent faster and for a 16
+ * byte buffer it is about 5 percent faster.
*/
/*
@@ -124,8 +143,8 @@ static char sccsid[] = "@(#)random.c 8.1 (Berkeley) 6/4/93";
*/
#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 };
+static long degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static long seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
/*
* Initially, everything is set up as if from:
@@ -190,9 +209,9 @@ static long *rptr = &randtbl[1];
* the last element to see if the front and rear pointers have wrapped.
*/
static long *state = &randtbl[1];
-static int rand_type = TYPE_3;
-static int rand_deg = DEG_3;
-static int rand_sep = SEP_3;
+static long rand_type = TYPE_3;
+static long rand_deg = DEG_3;
+static long rand_sep = SEP_3;
static long *end_ptr = &randtbl[DEG_3 + 1];
static inline long good_rand __P((long));
@@ -241,9 +260,9 @@ static inline long good_rand (x)
*/
void
srandom(x)
- unsigned int x;
+ unsigned long x;
{
- register int i;
+ register long i;
if (rand_type == TYPE_0)
state[0] = x;
@@ -276,14 +295,19 @@ srandom(x)
* setstate() so that it doesn't matter when initstate is called.
*
* Returns a pointer to the old state.
+ *
+ * Note: The Sparc platform requires that arg_state begin on a long
+ * word boundary; otherwise a bus error will occur. Even so, lint will
+ * complain about mis-alignment, but you should disregard these messages.
*/
char *
initstate(seed, arg_state, n)
- unsigned int seed; /* seed for R.N.G. */
+ unsigned long seed; /* seed for R.N.G. */
char *arg_state; /* pointer to state array */
- int n; /* # bytes of state info */
+ long n; /* # bytes of state info */
{
register char *ostate = (char *)(&state[-1]);
+ register long *long_arg_state = (long *) arg_state;
if (rand_type == TYPE_0)
state[-1] = rand_type;
@@ -291,7 +315,7 @@ initstate(seed, arg_state, n)
state[-1] = MAX_TYPES * (rptr - state) + rand_type;
if (n < BREAK_0) {
(void)fprintf(stderr,
- "random: not enough state (%d bytes); ignored.\n", n);
+ "random: not enough state (%ld bytes); ignored.\n", n);
return(0);
}
if (n < BREAK_1) {
@@ -315,13 +339,13 @@ initstate(seed, arg_state, n)
rand_deg = DEG_4;
rand_sep = SEP_4;
}
- state = &(((long *)arg_state)[1]); /* first location */
+ state = (long *) (long_arg_state + 1); /* first location */
end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
srandom(seed);
if (rand_type == TYPE_0)
- state[-1] = rand_type;
+ long_arg_state[0] = rand_type;
else
- state[-1] = MAX_TYPES*(rptr - state) + rand_type;
+ long_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
return(ostate);
}
@@ -339,14 +363,18 @@ initstate(seed, arg_state, n)
* setstate() with the same state as the current state.
*
* Returns a pointer to the old state information.
+ *
+ * Note: The Sparc platform requires that arg_state begin on a long
+ * word boundary; otherwise a bus error will occur. Even so, lint will
+ * complain about mis-alignment, but you should disregard these messages.
*/
char *
setstate(arg_state)
- char *arg_state;
+ char *arg_state; /* pointer to state array */
{
- register long *new_state = (long *)arg_state;
- register int type = new_state[0] % MAX_TYPES;
- register int rear = new_state[0] / MAX_TYPES;
+ register long *new_state = (long *) arg_state;
+ register long type = new_state[0] % MAX_TYPES;
+ register long rear = new_state[0] / MAX_TYPES;
char *ostate = (char *)(&state[-1]);
if (rand_type == TYPE_0)
@@ -367,7 +395,7 @@ setstate(arg_state)
(void)fprintf(stderr,
"random: state info corrupted; not changed.\n");
}
- state = &new_state[1];
+ state = (long *) (new_state + 1);
if (rand_type != TYPE_0) {
rptr = &state[rear];
fptr = &state[(rear + rand_sep) % rand_deg];
@@ -396,18 +424,28 @@ setstate(arg_state)
long
random()
{
- long i;
+ register long i;
+ register long *f, *r;
- if (rand_type == TYPE_0)
- i = state[0] = good_rand(state[0]) & 0x7fffffff;
- else {
- *fptr += *rptr;
- i = (*fptr >> 1) & 0x7fffffff; /* chucking least random bit */
- if (++fptr >= end_ptr) {
- fptr = state;
- ++rptr;
- } else if (++rptr >= end_ptr)
- rptr = state;
+ if (rand_type == TYPE_0) {
+ i = state[0];
+ state[0] = i = (good_rand(i)) & 0x7fffffff;
+ } else {
+ /*
+ * Use local variables rather than static variables for speed.
+ */
+ f = fptr; r = rptr;
+ *f += *r;
+ i = (*f >> 1) & 0x7fffffff; /* chucking least random bit */
+ if (++f >= end_ptr) {
+ f = state;
+ ++r;
+ }
+ else if (++r >= end_ptr) {
+ r = state;
+ }
+
+ fptr = f; rptr = r;
}
return(i);
}
OpenPOWER on IntegriCloud