# HG changeset patch # User jwe # Date 783910764 0 # Node ID fb24794ef0e2bb52f937083438aaddd4efcb2ee9 # Parent 1a137429b26e3051a0208e411b866042a0026b63 [project @ 1994-11-04 00:59:24 by jwe] diff -r 1a137429b26e -r fb24794ef0e2 src/load-save.cc --- 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); diff -r 1a137429b26e -r fb24794ef0e2 src/load-save.h --- 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); diff -r 1a137429b26e -r fb24794ef0e2 src/pt-plot.cc --- 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) { diff -r 1a137429b26e -r fb24794ef0e2 src/pt-plot.h --- 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 +#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: