changeset 1609:d0a45cb55b59

[project @ 1995-11-03 05:41:37 by jwe]
author jwe
date Fri, 03 Nov 1995 05:41:37 +0000
parents 65572455466f
children 26a096727e89
files src/rand.cc
diffstat 1 files changed, 144 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/src/rand.cc	Thu Nov 02 13:06:41 1995 +0000
+++ b/src/rand.cc	Fri Nov 03 05:41:37 1995 +0000
@@ -34,13 +34,19 @@
 #include "gripes.h"
 #include "help.h"
 #include "tree-const.h"
+#include "unwind-prot.h"
 #include "utils.h"
 
-// Possible distributions of random numbers.
-enum rand_dist { uniform, normal };
+// Possible distributions of random numbers.  This was handled with an
+// enum, but unwind_protecting that doesn't work so well.
+#define uniform_dist 1
+#define normal_dist 2
 
 // Current distribution of random numbers.
-static rand_dist current_distribution = uniform;
+static int current_distribution = uniform_dist;
+
+// Has the seed been set yet?
+static int initialized = 0;
 
 extern "C"
 {
@@ -53,6 +59,10 @@
   int *F77_FCN (setall, SETALL) (const int&, const int&);
 
   int *F77_FCN (getsd, GETSD) (int&, int&);
+
+  int *F77_FCN (setsd, SETSD) (const int&, const int&);
+
+  int *F77_FCN (setcgn, SETCGN) (const int&);
 }
 
 static double
@@ -87,15 +97,15 @@
   u.d = val;
   int i0 = force_to_fit_range (u.i[0], 1, 2147483563);
   int i1 = force_to_fit_range (u.i[1], 1, 2147483399);
-  F77_FCN (setall, SETALL) (i0, i1);
+  F77_FCN (setsd, SETSD) (i0, i1);
 }
 
 static char *
 curr_rand_dist (void)
 {
-  if (current_distribution == uniform)
+  if (current_distribution == uniform_dist)
     return "uniform";
-  else if (current_distribution == normal)
+  else if (current_distribution == normal_dist)
     return "normal";
   else
     {
@@ -104,66 +114,53 @@
     }
 }
 
-DEFUN_DLD_BUILTIN ("rand", Frand, Srand, 11,
-  "rand                  -- generate a random value\n\
-\n\
-rand (N)              -- generate N x N matrix\n\
-rand (A)              -- generate matrix the size of A\n\
-rand (N, M)           -- generate N x M matrix\n\
-rand (\"dist\")         -- get current distribution\n\
-rand (DISTRIBUTION)   -- set distribution type (\"normal\" or \"uniform\"\n\
-rand (SEED)           -- get current seed\n\
-rand (SEED, N)        -- set seed")
+// Make the random number generator give us a different sequence every
+// time we start octave unless we specifically set the seed.  The
+// technique used below will cycle monthly, but it it does seem to
+// work ok to give fairly different seeds each time Octave starts.
+
+static void
+do_initialization (void)
+{
+#if 0
+  int s0 = 1234567890;
+  int s1 = 123456789;
+#else
+  time_t now;
+  struct tm *tm;
+ 
+  time (&now);
+  tm = localtime (&now);
+ 
+  int hour = tm->tm_hour + 1;
+  int minute = tm->tm_min + 1;
+  int second = tm->tm_sec + 1;
+
+  int s0 = tm->tm_mday * hour * minute * second;
+  int s1 = hour * minute * second;
+#endif
+
+  s0 = force_to_fit_range (s0, 1, 2147483563);
+  s1 = force_to_fit_range (s1, 1, 2147483399);
+
+  F77_FCN (setall, SETALL) (s0, s1);
+
+  initialized = 1;
+}
+
+static Octave_object
+do_rand (const Octave_object& args, int nargin)
 {
   Octave_object retval;
 
-  int nargin = args.length ();
-
-  if (nargin > 2 || nargout > 1)
-    {
-      print_usage ("rand");
-      return retval;
-    }
-
-  static int initialized = 0;
-  if (! initialized)
-    {
-      // Make the random number generator give us a different sequence
-      // every time we start octave unless we specifically set the
-      // seed.  The technique used below will cycle monthly, but it it
-      // does seem to work ok to give fairly different seeds each time
-      // Octave starts.
-
-#if 0
-      int s0 = 1234567890;
-      int s1 = 123456789;
-#else
-      time_t now;
-      struct tm *tm;
- 
-      time (&now);
-      tm = localtime (&now);
- 
-      int hour = tm->tm_hour + 1;
-      int minute = tm->tm_min + 1;
-      int second = tm->tm_sec + 1;
-
-      int s0 = tm->tm_mday * hour * minute * second;
-      int s1 = hour * minute * second;
-#endif
-      s0 = force_to_fit_range (s0, 1, 2147483563);
-      s1 = force_to_fit_range (s1, 1, 2147483399);
-
-      F77_FCN (setall, SETALL) (s0, s1);
-      initialized = 1;
-    }
-
   int n = 0;
   int m = 0;
+
   if (nargin == 0)
     {
       n = 1;
       m = 1;
+
       goto gen_matrix;
     }
   else if (nargin == 1)
@@ -185,9 +182,17 @@
 	      retval(0) = d;
 	    }
 	  else if (strcmp (s_arg, "uniform") == 0)
-	    current_distribution = uniform;
+	    {
+	      current_distribution = uniform_dist;
+
+	      F77_FCN (setcgn, SETCGN) (uniform_dist);
+	    }
 	  else if (strcmp (s_arg, "normal") == 0)
-	    current_distribution = normal;
+	    {
+	      current_distribution = normal_dist;
+
+	      F77_FCN (setcgn, SETCGN) (normal_dist);
+	    }
 	  else
 	    error ("rand: unrecognized string argument");
 	}
@@ -299,12 +304,12 @@
 	    double val;
 	    switch (current_distribution)
 	      {
-	      case uniform:
+	      case uniform_dist:
 		F77_FCN (dgenunf, DGENUNF) (0.0, 1.0, val);
 		rand_mat.elem (i, j) = val;
 		break;
 
-	      case normal:
+	      case normal_dist:
 		F77_FCN (dgennor, DGENNOR) (0.0, 1.0, val);
 		rand_mat.elem (i, j) = val;
 		break;
@@ -323,6 +328,84 @@
   return retval;
 }
 
+DEFUN_DLD_BUILTIN ("rand", Frand, Srand, 11,
+  "rand            -- generate a random value from a uniform distribution\n\
+\n\
+rand (N)        -- generate N x N matrix\n\
+rand (size (A)) -- generate matrix the size of A\n\
+rand (N, M)     -- generate N x M matrix\n\
+rand (SEED)     -- get current seed\n\
+rand (SEED, N)  -- set seed\n\
+\n\
+See also: randn")
+{
+  Octave_object retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 2 || nargout > 1)
+    print_usage ("rand");
+  else
+    {
+      if (! initialized)
+	do_initialization ();
+
+      retval = do_rand (args, nargin);
+    }
+
+  return retval;
+}
+
+static void
+reset_rand_generator (void *)
+{
+  F77_FCN (setcgn, SETCGN) (current_distribution);
+}
+
+DEFUN_DLD_BUILTIN ("randn", Frandn, Srandn, 11,
+  "randn            -- generate a random value from a normal distribution\n\
+\n\
+randn (N)        -- generate N x N matrix\n\
+randn (size (A)) -- generate matrix the size of A\n\
+randn (N, M)     -- generate N x M matrix\n\
+randn (SEED)     -- get current seed\n\
+randn (SEED, N)  -- set seed\n\
+\n\
+See also: rand")
+{
+  Octave_object retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 2 || nargout > 1)
+    print_usage ("randn");
+  else
+    {
+      if (! initialized)
+	do_initialization ();
+
+      begin_unwind_frame ("randn");
+
+      // This relies on the fact that elements are popped from the
+      // unwind stack in the reverse of the order they are pushed
+      // (i.e. current_distribution will be reset before calling
+      // reset_rand_generator()).
+
+      add_unwind_protect (reset_rand_generator, 0);
+      unwind_protect_int (current_distribution);
+
+      current_distribution = normal_dist;
+
+      F77_FCN (setcgn, SETCGN) (normal_dist);
+
+      retval = do_rand (args, nargin);
+
+      run_unwind_frame ("randn");
+    }
+
+  return retval;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***