changeset 872:fb24794ef0e2

[project @ 1994-11-04 00:59:24 by jwe]
author jwe
date Fri, 04 Nov 1994 00:59:24 +0000
parents 1a137429b26e
children 10882039366f
files src/load-save.cc src/load-save.h src/pt-plot.cc src/pt-plot.h
diffstat 4 files changed, 316 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/src/load-save.cc	Wed Nov 02 21:56:17 1994 +0000
+++ b/src/load-save.cc	Fri Nov 04 00:59:24 1994 +0000
@@ -74,6 +74,12 @@
 LOSE! LOSE!
 #endif
 
+// Used when converting Inf to something that gnuplot can read.
+
+#ifndef OCT_RBV
+#define OCT_RBV DBL_MAX / 100.0
+#endif
+
 enum load_save_format
   {
     LS_ASCII,
@@ -2489,18 +2495,97 @@
   os << type << "\n";
 }
 
+static Matrix
+strip_infnan (const Matrix& m)
+{
+  int nr = m.rows ();
+  int nc = m.columns ();
+
+  Matrix retval (nr, nc);
+
+  int k = 0;
+  for (int i = 0; i < nr; i++)
+    {
+      for (int j = 0; j < nc; j++)
+	{
+	  double d = m.elem (i, j);
+	  if (xisnan (d))
+	    goto next_row;
+	  else
+	    retval.elem (k, j) = xisinf (d) ? (d > 0 ? OCT_RBV : -OCT_RBV) : d;
+	}
+      k++;
+
+    next_row:
+      continue;
+    }
+
+  if (k > 0)
+    retval.resize (k, nc);
+
+  return retval;
+}
+
+static ComplexMatrix
+strip_infnan (const ComplexMatrix& m)
+{
+  int nr = m.rows ();
+  int nc = m.columns ();
+
+  ComplexMatrix retval (nr, nc);
+
+  int k = 0;
+  for (int i = 0; i < nr; i++)
+    {
+      for (int j = 0; j < nc; j++)
+	{
+	  Complex c = m.elem (i, j);
+	  if (xisnan (c))
+	    goto next_row;
+	  else
+	    {
+	      double re = real (c);
+	      double im = imag (c);
+
+	      re = xisinf (re) ? (re > 0 ? OCT_RBV : -OCT_RBV) : re;
+	      im = xisinf (im) ? (im > 0 ? OCT_RBV : -OCT_RBV) : im;
+
+	      retval.elem (k, j) = Complex (re, im);
+	    }
+	}
+      k++;
+
+    next_row:
+      continue;
+    }
+
+  if (k > 0)
+    retval.resize (k, nc);
+
+  return retval;
+}
+
 // Save the data from TC along with the corresponding NAME, and global
 // flag MARK_AS_GLOBAL on stream OS in the plain text format described
 // above for load_ascii_data.  If NAME is null, the name: line is not
 // generated.  PRECISION specifies the number of decimal digits to print. 
+// If STRIP_NAN_AND_INF is nonzero, rows containing NaNs are deleted,
+// and Infinite values are converted to +/-OCT_RBV (A Real Big Value,
+// but not so big that gnuplot can't handle it when trying to compute
+// axis ranges, etc.).
+//
+// Assumes ranges and strings cannot contain Inf or NaN values.
+//
+// Returns 1 for success and 0 for failure.
 
 // XXX FIXME XXX -- should probably write the help string here too.
 
 int
 save_ascii_data (ostream& os, const tree_constant& tc,
-		 char *name, int mark_as_global, int precision)
+		 char *name, int strip_nan_and_inf,
+		 int mark_as_global, int precision) 
 {
-  int fail = 0;
+  int success = 1;
 
   if (! precision)
     precision = user_pref.save_precision;
@@ -2514,19 +2599,63 @@
   if (tc.is_real_scalar ())
     {
       ascii_save_type (os, "scalar", mark_as_global);
-      os << tc.double_value () << "\n";
+
+      double d = tc.double_value ();
+      if (strip_nan_and_inf)
+	{
+	  if (xisnan (d))
+	    {
+	      error ("only value to plot is NaN");
+	      success = 0;
+	    }
+	  else
+	    {
+	      d = xisinf (d) ? (d > 0 ? OCT_RBV : -OCT_RBV) : d;
+	      os << d << "\n";
+	    }
+	}
+      else
+	os << d << "\n";
     }
   else if (tc.is_real_matrix ())
     {
       ascii_save_type (os, "matrix", mark_as_global);
       os << "# rows: " << tc.rows () << "\n"
-	 << "# columns: " << tc.columns () << "\n"
-	 << tc.matrix_value () ;
+	 << "# columns: " << tc.columns () << "\n";
+
+      Matrix tmp = tc.matrix_value ();
+      if (strip_nan_and_inf)
+	tmp = strip_infnan (tmp);
+
+      os << tmp;
     }
   else if (tc.is_complex_scalar ())
     {
       ascii_save_type (os, "complex scalar", mark_as_global);
-      os << tc.complex_value () << "\n";
+
+      Complex c = tc.complex_value ();
+      if (strip_nan_and_inf)
+	{
+	  if (xisnan (c))
+	    {
+	      error ("only value to plot is NaN");
+	      success = 0;
+	    }
+	  else
+	    {
+	      double re = real (c);
+	      double im = imag (c);
+
+	      re = xisinf (re) ? (re > 0 ? OCT_RBV : -OCT_RBV) : re;
+	      im = xisinf (im) ? (im > 0 ? OCT_RBV : -OCT_RBV) : im;
+
+	      c = Complex (re, im);
+
+	      os << c << "\n";
+	    }
+	}
+      else
+	os << c << "\n";
     }
   else if (tc.is_complex_matrix ())
     {
@@ -2534,6 +2663,12 @@
       os << "# rows: " << tc.rows () << "\n"
 	 << "# columns: " << tc.columns () << "\n"
 	 << tc.complex_matrix_value () ;
+
+      ComplexMatrix tmp = tc.matrix_value ();
+      if (strip_nan_and_inf)
+	tmp = strip_infnan (tmp);
+
+      os << tmp;
     }
   else if (tc.is_string ())
     {
@@ -2542,7 +2677,7 @@
       os << "# length: " << strlen (tmp) << "\n"
 	 << tmp << "\n";
     }
-  else if (tc.is_string ())
+  else if (tc.is_range ())
     {
       ascii_save_type (os, "range", mark_as_global);
       Range tmp = tc.range_value ();
@@ -2554,12 +2689,12 @@
   else
     {
       gripe_wrong_type_arg ("save", tc);
-      fail = 1;
+      success = 0;
     }
 
   os.precision (old_precision);
 
-  return (os && ! fail);
+  return (os && success);
 }
 
 // Save the info from sr on stream os in the format specified by fmt.
@@ -2585,7 +2720,7 @@
   switch (fmt)
     {
     case LS_ASCII:
-      save_ascii_data (os, tc, name, global);
+      save_ascii_data (os, tc, name, 0, global);
       break;
 
     case LS_BINARY:
@@ -2853,6 +2988,9 @@
 	    warning ("ignoring last %d columns", extras);
 
 	  Matrix tmp = tc.matrix_value ();
+	  tmp = strip_infnan (tmp);
+	  nr = tmp.rows ();
+
 	  for (int i = 0; i < nc-extras; i += 3)
 	    {
 	      os << tmp.extract (0, i, nr-1, i+2);
@@ -2863,6 +3001,9 @@
       else
 	{
 	  Matrix tmp = tc.matrix_value ();
+	  tmp = strip_infnan (tmp);
+	  nr = tmp.rows ();
+
 	  for (int i = 0; i < nc; i++)
 	    {
 	      os << tmp.extract (0, i, nr-1, i);
--- a/src/load-save.h	Wed Nov 02 21:56:17 1994 +0000
+++ b/src/load-save.h	Fri Nov 04 00:59:24 1994 +0000
@@ -28,8 +28,8 @@
 class ostream;
 
 extern int save_ascii_data (ostream& os, const tree_constant& t,
-			    char *name = 0, int mark_as_global = 0,
-			    int precision = 0);
+			    char *name = 0, int strip_nan_and_inf = 0,
+			    int mark_as_global = 0, int precision = 0);
 
 extern int save_three_d (ostream& os, const tree_constant& t,
 			 int parametric = 0);
--- a/src/pt-plot.cc	Wed Nov 02 21:56:17 1994 +0000
+++ b/src/pt-plot.cc	Fri Nov 04 00:59:24 1994 +0000
@@ -482,21 +482,17 @@
 subplot_using::subplot_using (void)
 {
   qualifier_count = 0;
-  x[0] = 0;
-  x[1] = 0;
-  x[2] = 0;
-  x[3] = 0;
+  x[0] = x[1] = x[2] = x[3] = 0;
   scanf_fmt = 0;
+  have_values = 0;
 }
 
-subplot_using::subplot_using (tree_expression *fmt)
+subplot_using::subplot_using (tree_expression *fmt) : val (4, -1)
 {
   qualifier_count = 0;
-  x[0] = 0;
-  x[1] = 0;
-  x[2] = 0;
-  x[3] = 0;
+  x[0] = x[1] = x[2] = x[3] = 0;
   scanf_fmt = fmt;
+  have_values = 0;
 }
 
 subplot_using::~subplot_using (void)
@@ -523,12 +519,18 @@
 }
 
 int
-subplot_using::print (int ndim, int n_max, ostrstream& plot_buf)
+subplot_using::eval (int ndim, int n_max)
 {
   if ((ndim == 2 && qualifier_count > 4)
       || (ndim == 3 && qualifier_count > 3))
     return -1;
 
+  if (have_values)
+    return 1;
+
+  if (qualifier_count > 0)
+    val.resize (qualifier_count);
+
   for (int i = 0; i < qualifier_count; i++)
     {
       if (x[i])
@@ -540,24 +542,22 @@
 	      return -1;
 	    }
 
-	  double val;
+	  double val_tmp;
 	  if (tmp.is_defined ())
 	    {
-	      val = tmp.double_value ();
-	      if (i == 0)
-		plot_buf << " " << GNUPLOT_COMMAND_USING << " ";
-	      else
-		plot_buf << ":";
+	      val_tmp = tmp.double_value ();
 
-	      int n = NINT (val);
+	      if (error_state)
+		return -1;
 
+	      int n = NINT (val_tmp);
 	      if (n < 1 || n_max > 0 && n > n_max)
 		{
 		  ::error ("using: column %d out of range", n); 
 		  return -1;
 		}
 	      else
-		plot_buf << n;
+		val.elem (i) = n;
 	    }
 	  else
 	    return -1;
@@ -569,6 +569,40 @@
   if (scanf_fmt)
     warning ("ignoring scanf format in plot command");
 
+  have_values = 1;
+
+  return 0;
+}
+
+ColumnVector
+subplot_using::values (int ndim, int n_max)
+{
+  int status = eval (ndim, n_max);
+
+  if (status < 0 || ! have_values)
+    return -1;
+
+  return val;
+}
+
+int
+subplot_using::print (int ndim, int n_max, ostrstream& plot_buf)
+{
+  int status = eval (ndim, n_max);
+
+  if (status < 0 || ! have_values)
+    return -1;
+
+  for (int i = 0; i < qualifier_count; i++)
+    {
+      if (i == 0)
+	plot_buf << " " << GNUPLOT_COMMAND_USING << " ";
+      else
+	plot_buf << ":";
+
+      plot_buf << val.elem (i);
+    }
+
   return 0;
 }
 
@@ -665,6 +699,14 @@
   return 0;
 }
 
+int
+subplot_style::errorbars (void)
+{
+  return (style
+	  && (almost_match ("errorbars", style, 1, 0)
+	      || almost_match ("boxerrorbars", style, 5, 0)));
+}
+
 void
 subplot_style::print_code (ostream& os)
 {
@@ -683,25 +725,68 @@
     }
 }
 
+tree_constant
+subplot::extract_plot_data (int ndim, tree_constant& data)
+{
+  tree_constant retval;
+
+  if (using)
+    {
+      ColumnVector val = using->values (ndim);
+
+      Octave_object args;
+      args(1) = val;
+      args(0) = tree_constant::magic_colon_t;
+
+      Octave_object tmp = data.eval (0, 1, args);
+      retval = tmp(0);
+
+      if (error_state)
+	return tree_constant ();
+    }
+  else
+    {
+      retval = data;
+    }
+
+  if (ndim == 2 && style && style->errorbars ())
+    {
+      int nc = retval.columns ();
+
+      if (nc < 3 || nc > 4)
+	{
+	  error ("plots with errorbars require 3 or 4 columns of data");
+	  error ("but %d were provided", nc);
+	  return tree_constant ();
+	}
+    }
+
+  return retval;
+}
+
 int
-subplot::print (int ndim, ostrstream& plot_buf)
+subplot::handle_plot_data (int ndim, ostrstream& plot_buf)
 {
-  int nc = 0;
   if (plot_data)
     {
       tree_constant data = plot_data->eval (0);
+
       if (! error_state && data.is_defined ())
 	{
 	  char *file = 0;
 	  if (data.is_string ())
 	    {
+// Should really try to look at data file to determine n_max.  Can't
+// do much about other arbitrary gnuplot commands though...
+
+	      int n_max = 0;
+
 	      file = tilde_expand (data.string_value ());
 	      ifstream ftmp (file);
 	      if (ftmp)
 		{
 		  plot_buf << " \"" << file << '"';
 		  free (file);
-		  goto have_existing_file_or_command;
 		}
 	      else
 		{
@@ -711,30 +796,45 @@
 // Opening as a file failed.  Let's try passing it along as a plot
 // command.
 		  plot_buf << " " << data.string_value ();
-		  goto have_existing_file_or_command;
+		}
+
+	      if (using)
+		{
+		  int status = using->print (ndim, n_max, plot_buf);
+		  if (status < 0)
+		    return -1;
 		}
 	    }
-
-	  nc = data.columns ();
-	  switch (ndim)
+	  else
 	    {
-	    case 2:
-	      file = save_in_tmp_file (data, ndim);
-	      break;
+// Eliminate the need for printing a using clause to plot_buf.
+
+	      tree_constant tmp_data = extract_plot_data (ndim, data);
+
+	      if (tmp_data.is_defined ())
+		{
+		  switch (ndim)
+		    {
+		    case 2:
+		      file = save_in_tmp_file (tmp_data, ndim);
+		      break;
 
-	    case 3:
-	      file = save_in_tmp_file (data, ndim, parametric_plot);
-	      break;
+		    case 3:
+		      file = save_in_tmp_file (tmp_data, ndim,
+					       parametric_plot);
+		      break;
 
-	    default:
-	      gripe_2_or_3_dim_plot ();
-	      break;
-	    }
+		    default:
+		      gripe_2_or_3_dim_plot ();
+		      break;
+		    }
 
-	  if (file)
-	    {
-	      mark_for_deletion (file);
-	      plot_buf << " \"" << file << '"';
+		  if (file)
+		    {
+		      mark_for_deletion (file);
+		      plot_buf << " \"" << file << '"';
+		    }
+		}
 	    }
 	}
       else
@@ -743,14 +843,16 @@
   else
     return -1;
 
- have_existing_file_or_command:
+  return 0;
+}
 
-  if (using)
-    {
-      int status = using->print (ndim, nc, plot_buf);
-      if (status < 0)
-	return -1;
-    }
+int
+subplot::print (int ndim, ostrstream& plot_buf)
+{
+  int status = handle_plot_data (ndim, plot_buf);
+
+  if (status < 0)
+    return -1;
 
   if (title)
     {
--- a/src/pt-plot.h	Wed Nov 02 21:56:17 1994 +0000
+++ b/src/pt-plot.h	Fri Nov 04 00:59:24 1994 +0000
@@ -41,6 +41,9 @@
 
 #include <SLList.h>
 
+#include "dColVector.h"
+
+#include "idx-vector.h"
 #include "tree-cmd.h"
 #include "tree-expr.h"
 
@@ -117,6 +120,10 @@
 
   subplot_using *add_qualifier (tree_expression *t);
 
+  int eval (int ndim, int n_max);
+
+  ColumnVector values (int ndim, int n_max = 0);
+
   int print (int ndim, int n_max, ostrstream& plot_buf);
 
   void print_code (ostream& os);
@@ -125,6 +132,8 @@
   int qualifier_count;
   tree_expression *x[4];
   tree_expression *scanf_fmt;
+  int have_values;
+  ColumnVector val;
 };
 
 class
@@ -140,6 +149,8 @@
 
   int print (ostrstream& plot_buf);
 
+  int errorbars (void);
+
   void print_code (ostream& os);
 
 private:
@@ -190,6 +201,10 @@
 
   int print (int ndim, ostrstream& plot_buf);
 
+  tree_constant extract_plot_data (int ndim, tree_constant& data);
+
+  int handle_plot_data (int ndim, ostrstream& plot_buf);
+
   void print_code (ostream& os);
 
 private: