Make the expression code a little nicer and fix bugs found
[pspp] / src / random.c
index ab78b32bb256f19c121c2de34a43529cdb9684d9..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,20 +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;
+  static unsigned long seed=0;
+  unsigned long s;
 
   rng = xmalloc (sizeof *rng);
-  if (t == 0)
-    time (&t);
+
+
+  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;
 }
@@ -154,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 / 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