X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Frandom.c;h=7420a82ecee8392e0658f5026aa0221b2e50f384;hb=e210b20bf6f405637c8c03dd280b5a4a627191b8;hp=0352b602bb585a1b0e48ea95774aa1b0f36a87e8;hpb=def7e6026513a3ee7c2b38416b30a2e890e34311;p=pspp diff --git a/src/random.c b/src/random.c index 0352b602bb..7420a82ece 100644 --- a/src/random.c +++ b/src/random.c @@ -1,5 +1,5 @@ /* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2005 Free Software Foundation, Inc. Written by Ben Pfaff . This program is free software; you can redistribute it and/or @@ -14,234 +14,44 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #include #include "random.h" -#include -#include -#include -#include -#include #include -#include "alloc.h" -#include "magic.h" -#include "settings.h" +#include "xalloc.h" -/* Random number generator. */ -struct rng - { - /* RC4-based random bytes. */ - uint8_t s[256]; - uint8_t i, j; +static gsl_rng *rng; - /* Normal distribution. */ - double next_normal; - }; - - -/* Return a `random' seed by using the real time clock */ -unsigned long -random_seed(void) -{ - time_t t; - - time(&t); - - return (unsigned long) t; -} - -/* Creates a new random number generator, seeds it based on - the current time, and returns it. */ -struct rng * -rng_create (void) -{ - struct rng *rng; - static unsigned long seed=0; - unsigned long s; - - rng = xmalloc (sizeof *rng); - - - if ( seed_is_set(&s) ) - { - seed = s; - } - else if ( seed == 0 ) - { - seed = random_seed(); - } - assert(seed); - /* - if (t == 0 || set_seed_used) - { - if (set_seed == NOT_LONG) - time (&t); - else - t = set_seed; - set_seed_used=0; - } - else - t++; - */ - rng_seed (rng, &seed, sizeof seed); - rng->next_normal = NOT_DOUBLE; - return rng; -} - -/* Destroys RNG. */ void -rng_destroy (struct rng *rng) -{ - free (rng); -} - -/* Swap bytes. */ -static void -swap_byte (uint8_t *a, uint8_t *b) +random_init (void) { - uint8_t t = *a; - *a = *b; - *b = t; } -/* Seeds RNG based on the SIZE bytes in BUF. - At most the first 256 bytes of BUF are used. */ void -rng_seed (struct rng *rng, const void *key_, size_t size) +random_done (void) { - const uint8_t *key = key_; - size_t key_idx; - uint8_t *s; - int i, j; - - assert (rng != NULL); - - s = rng->s; - rng->i = rng->j = 0; - for (i = 0; i < 256; i++) - s[i] = i; - for (key_idx = 0, i = j = 0; i < 256; i++) - { - j = (j + s[i] + key[key_idx]) & 255; - swap_byte (s + i, s + j); - if (++key_idx >= size) - key_idx = 0; - } + if (rng != NULL) + gsl_rng_free (rng); } -/* Reads SIZE random bytes from RNG into BUF. */ -void -rng_get_bytes (struct rng *rng, void *buf_, size_t size) +/* Returns the current random number generator. */ +gsl_rng * +get_rng (void) { - uint8_t *buf = buf_; - uint8_t *s; - uint8_t i, j; - - assert (rng != 0); - - s = rng->s; - i = rng->i; - j = rng->j; - while (size-- > 0) - { - i += 1; - j += s[i]; - swap_byte (s + i, s + j); - *buf++ = s[(s[i] + s[j]) & 255]; - } - rng->i = i; - rng->j = j; -} - -/* Returns a random int in the range [0, INT_MAX]. */ -int -rng_get_int (struct rng *rng) -{ - int value; - - do - { - rng_get_bytes (rng, &value, sizeof value); - value = abs (value); - } - while (value < 0); - - return value; -} - -/* Returns a random unsigned in the range [0, UINT_MAX]. */ -unsigned -rng_get_unsigned (struct rng *rng) -{ - unsigned value; - - rng_get_bytes (rng, &value, sizeof value); - return value; -} - -/* Returns a random number from the uniform distribution with - range [0,1). */ -double -rng_get_double (struct rng *rng) -{ - for (;;) - { - unsigned long ulng; - double dbl; - - rng_get_bytes (rng, &ulng, sizeof ulng); - dbl = ulng / (ULONG_MAX + 1.0); - if (dbl >= 0 && dbl < 1) - return dbl; - } -} - -/* Returns a random number from the distribution with mean 0 and - standard deviation 1. (Multiply the result by the desired - standard deviation, then add the desired mean.) */ -double -rng_get_double_normal (struct rng *rng) -{ - /* Knuth, _The Art of Computer Programming_, Vol. 2, 3.4.1C, - Algorithm P. */ - double this_normal; - - if (rng->next_normal != NOT_DOUBLE) - { - this_normal = rng->next_normal; - rng->next_normal = NOT_DOUBLE; - } - else - { - double v1, v2, s; - - do - { - double u1 = rng_get_double (rng); - double u2 = rng_get_double (rng); - v1 = 2.0 * u1 - 1.0; - v2 = 2.0 * u2 - 1.0; - s = v1 * v1 + v2 * v2; - } - while (s >= 1); - - this_normal = v1 * sqrt (-2. * log (s) / s); - rng->next_normal = v2 * sqrt (-2. * log (s) / s); - } - - return this_normal; + if (rng == NULL) + set_rng (time (0)); + return rng; } -/* Gets an initialized RNG for use in PSPP transformations and - procedures. */ -struct rng * -pspp_rng (void) +/* Initializes or reinitializes the random number generator with + the given SEED. */ +void +set_rng (unsigned long seed) { - static struct rng *rng; - + rng = gsl_rng_alloc (gsl_rng_mt19937); if (rng == NULL) - rng = rng_create (); - return rng; + xalloc_die (); + gsl_rng_set (rng, seed); }