]> git.saurik.com Git - apple/libc.git/blobdiff - stdlib/FreeBSD/random.c
Libc-1158.50.2.tar.gz
[apple/libc.git] / stdlib / FreeBSD / random.c
index e5b587e7752b4dad4c119eb0db39728551e0a45e..1ca75ed6b71649d68455fdf704fc15757a0b8e56 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
 static char sccsid[] = "@(#)random.c   8.2 (Berkeley) 5/19/95";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/random.c,v 1.22 2003/02/04 11:24:08 ache Exp $");
+__FBSDID("$FreeBSD$");
 
+#ifdef __APPLE__
+// Always compile with __DARWIN_UNIX03=1 prototypes.
+// Applications using legacy interfaces (i386 only) use types of the same size:
+//   sizeof(int) == sizeof(long) == sizeof(size_t)
+#undef         __DARWIN_UNIX03
+#define        __DARWIN_UNIX03 1
+#endif // __APPLE__
+
+#include "namespace.h"
 #include "namespace.h"
 #include <sys/time.h>          /* for srandomdev() */
 #include <fcntl.h>             /* for srandomdev() */
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>            /* for srandomdev() */
@@ -61,10 +67,10 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/random.c,v 1.22 2003/02/04 11:24:08 ache
  * congruential generator.  If the amount of state information is less than
  * 32 bytes, a simple linear congruential R.N.G. is used.
  *
- * Internally, the state information is treated as an array of longs; the
+ * Internally, the state information is treated as an array of uint32_t's; the
  * zeroeth element of the array is the type of R.N.G. being used (small
  * integer); the remainder of the array is the state information for the
- * R.N.G.  Thus, 32 bytes of state information will give 7 longs worth of
+ * R.N.G.  Thus, 32 bytes of state information will give 7 ints worth of
  * state information, which will allow a degree seven polynomial.  (Note:
  * the zeroeth word of state information also has some other information
  * stored in it -- see setstate() for details).
@@ -142,10 +148,14 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/random.c,v 1.22 2003/02/04 11:24:08 ache
  */
 #define        MAX_TYPES       5               /* max number of types above */
 
-#define NSHUFF 100      /* to drop part of seed -> 1st value correlation */
+#ifdef  USE_WEAK_SEEDING
+#define NSHUFF 0
+#else   /* !USE_WEAK_SEEDING */
+#define NSHUFF 50       /* to drop some "seed -> 1st value" linearity */
+#endif  /* !USE_WEAK_SEEDING */
 
-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 };
+static const int degrees[MAX_TYPES] =  { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static const int seps [MAX_TYPES] =    { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
 
 /*
  * Initially, everything is set up as if from:
@@ -161,7 +171,7 @@ static long seps [MAX_TYPES] =      { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
  *     MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
  */
 
-static long randtbl[DEG_3 + 1] = {
+static uint32_t randtbl[DEG_3 + 1] = {
        TYPE_3,
 #ifdef  USE_WEAK_SEEDING
 /* Historic implementation compatibility */
@@ -196,8 +206,8 @@ static long 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 *fptr = &randtbl[SEP_3 + 1];
-static long *rptr = &randtbl[1];
+static uint32_t *fptr = &randtbl[SEP_3 + 1];
+static uint32_t *rptr = &randtbl[1];
 
 /*
  * The following things are the pointer to the state information table, the
@@ -209,16 +219,14 @@ static long *rptr = &randtbl[1];
  * this is more efficient than indexing every time to find the address of
  * the last element to see if the front and rear pointers have wrapped.
  */
-static long *state = &randtbl[1];
-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(long);
-
-static inline long good_rand (x)
-       long x;
+static uint32_t *state = &randtbl[1];
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+static uint32_t *end_ptr = &randtbl[DEG_3 + 1];
+
+static inline uint32_t
+good_rand(int32_t x)
 {
 #ifdef  USE_WEAK_SEEDING
 /*
@@ -236,7 +244,7 @@ static inline long good_rand (x)
  * Park and Miller, Communications of the ACM, vol. 31, no. 10,
  * October 1988, p. 1195.
  */
-       long hi, lo;
+       int32_t hi, lo;
 
        /* Can't be initialized with 0, so use another value. */
        if (x == 0)
@@ -263,12 +271,15 @@ static inline long good_rand (x)
  * for default usage relies on values produced by this routine.
  */
 void
-srandom(x)
-       unsigned long x;
+#ifdef __APPLE__
+srandom(unsigned int x)
+#else
+srandom(unsigned long x)
+#endif
 {
-       long i, lim;
+       int i, lim;
 
-       state[0] = x;
+       state[0] = (uint32_t)x;
        if (rand_type == TYPE_0)
                lim = NSHUFF;
        else {
@@ -294,7 +305,7 @@ srandom(x)
  * a fixed seed.
  */
 void
-srandomdev()
+srandomdev(void)
 {
        int fd, done;
        size_t len;
@@ -305,7 +316,7 @@ srandomdev()
                len = rand_deg * sizeof state[0];
 
        done = 0;
-       fd = _open("/dev/random", O_RDONLY, 0);
+       fd = _open("/dev/random", O_RDONLY | O_CLOEXEC, 0);
        if (fd >= 0) {
                if (_read(fd, (void *) state, len) == (ssize_t) len)
                        done = 1;
@@ -314,10 +325,9 @@ srandomdev()
 
        if (!done) {
                struct timeval tv;
-               unsigned long junk;
 
                gettimeofday(&tv, NULL);
-               srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
+               srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec);
                return;
        }
 
@@ -346,18 +356,19 @@ srandomdev()
  *
  * Returns a pointer to the old state.
  *
- * Note: The Sparc platform requires that arg_state begin on a long
+ * Note: The Sparc platform requires that arg_state begin on an int
  * 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 long seed;             /* seed for R.N.G. */
-       char *arg_state;                /* pointer to state array */
-       long n;                         /* # bytes of state info */
+#ifdef __APPLE__
+initstate(unsigned int seed, char *arg_state, size_t n)
+#else
+initstate(unsigned long seed, char *arg_state, long n)
+#endif
 {
        char *ostate = (char *)(&state[-1]);
-       long *long_arg_state = (long *) arg_state;
+       uint32_t *int_arg_state = (uint32_t *)arg_state;
 
        if (rand_type == TYPE_0)
                state[-1] = rand_type;
@@ -366,7 +377,7 @@ initstate(seed, arg_state, n)
        if (n < BREAK_0) {
                (void)fprintf(stderr,
                    "random: not enough state (%ld bytes); ignored.\n", n);
-               return(0);
+               return (0);
        }
        if (n < BREAK_1) {
                rand_type = TYPE_0;
@@ -389,14 +400,14 @@ initstate(seed, arg_state, n)
                rand_deg = DEG_4;
                rand_sep = SEP_4;
        }
-       state = (long *) (long_arg_state + 1); /* first location */
+       state = int_arg_state + 1; /* first location */
        end_ptr = &state[rand_deg];     /* must set end_ptr before srandom */
        srandom(seed);
        if (rand_type == TYPE_0)
-               long_arg_state[0] = rand_type;
+               int_arg_state[0] = rand_type;
        else
-               long_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
-       return(ostate);
+               int_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
+       return (ostate);
 }
 
 /*
@@ -414,17 +425,16 @@ initstate(seed, arg_state, n)
  *
  * Returns a pointer to the old state information.
  *
- * Note: The Sparc platform requires that arg_state begin on a long
+ * Note: The Sparc platform requires that arg_state begin on an int
  * 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;                /* pointer to state array */
+setstate(const char *arg_state)
 {
-       long *new_state = (long *) arg_state;
-       long type = new_state[0] % MAX_TYPES;
-       long rear = new_state[0] / MAX_TYPES;
+       uint32_t *new_state = (uint32_t *)arg_state;
+       uint32_t type = new_state[0] % MAX_TYPES;
+       uint32_t rear = new_state[0] / MAX_TYPES;
        char *ostate = (char *)(&state[-1]);
 
        if (rand_type == TYPE_0)
@@ -445,13 +455,13 @@ setstate(arg_state)
                (void)fprintf(stderr,
                    "random: state info corrupted; not changed.\n");
        }
-       state = (long *) (new_state + 1);
+       state = new_state + 1;
        if (rand_type != TYPE_0) {
                rptr = &state[rear];
                fptr = &state[(rear + rand_sep) % rand_deg];
        }
        end_ptr = &state[rand_deg];             /* set end_ptr too */
-       return(ostate);
+       return (ostate);
 }
 
 /*
@@ -472,10 +482,10 @@ setstate(arg_state)
  * Returns a 31-bit random number.
  */
 long
-random()
+random(void)
 {
-       long i;
-       long *f, *r;
+       uint32_t i;
+       uint32_t *f, *r;
 
        if (rand_type == TYPE_0) {
                i = state[0];
@@ -497,5 +507,5 @@ random()
 
                fptr = f; rptr = r;
        }
-       return(i);
+       return ((long)i);
 }