X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Frandom.c;h=cae3f9e70a3fb9f0f05411bfa3114509d9fd768c;hb=60d7d619ee7885ad065f178eb0cf1e5d432b1921;hp=d62c1a3dede81e2a64e789c1cebedc604c25871f;hpb=2bfc3a138f308ffb38634a92b23bdc7b62592324;p=pspp diff --git a/src/random.c b/src/random.c index d62c1a3ded..cae3f9e70a 100644 --- a/src/random.c +++ b/src/random.c @@ -18,6 +18,7 @@ 02111-1307, USA. */ #include +#include "random.h" #include #include #include @@ -26,7 +27,6 @@ #include #include "alloc.h" #include "magic.h" -#include "random.h" #include "settings.h" /* Random number generator. */ @@ -46,17 +46,23 @@ struct rng * rng_create (void) { struct rng *rng; - static time_t t; - - rng = xmalloc (sizeof *rng); - if (t == 0) - time (&t); - else - t++; - rng_seed (rng, &t, sizeof t); - rng->next_normal = NOT_DOUBLE; - return rng; - } + static time_t t=0; + + rng = xmalloc (sizeof *rng); + 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, &t, sizeof t); + rng->next_normal = NOT_DOUBLE; + return rng; +} /* Destroys RNG. */ void @@ -66,7 +72,7 @@ rng_destroy (struct rng *rng) } /* Swap bytes. */ -static inline void +static void swap_byte (uint8_t *a, uint8_t *b) { uint8_t t = *a; @@ -80,7 +86,7 @@ void rng_seed (struct rng *rng, const void *key_, size_t size) { const uint8_t *key = key_; - int key_idx; + size_t key_idx; uint8_t *s; int i, j; @@ -90,7 +96,7 @@ rng_seed (struct rng *rng, const void *key_, size_t size) rng->i = rng->j = 0; for (i = 0; i < 256; i++) s[i] = i; - for (key_idx = 0, i = 0; i < 256; 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); @@ -154,10 +160,16 @@ rng_get_unsigned (struct rng *rng) double rng_get_double (struct rng *rng) { - unsigned long value; - - rng_get_bytes (rng, &value, sizeof value); - return value / ULONG_MAX; + 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