Make the expression code a little nicer and fix bugs found
[pspp] / src / random.c
index 163986cc959e319df0b32a26c16fe78b2f6a44b8..e6db94c1501f06f606d8fc1af86c4897dcc8d43f 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <config.h>
 #include "random.h"
-#include <assert.h>
+#include "error.h"
 #include <inttypes.h>
 #include <limits.h>
 #include <math.h>
@@ -40,25 +40,52 @@ struct rng
     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 time_t t=0;
+  static unsigned long seed=0;
+  unsigned long s;
 
   rng = xmalloc (sizeof *rng);
-  if (t == 0 || set_seed == NOT_LONG)
+
+
+  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, &t, sizeof t);
+  */
+  rng_seed (rng, &seed, sizeof seed);
   rng->next_normal = NOT_DOUBLE;
   return rng;
 }
@@ -159,10 +186,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 / (double) 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