From octave-maintainers-request at bevo dot che dot wisc dot edu Mon Oct 28 15:07:46 2002 Subject: ascii save/load of inf, nan, and na values From: "John W. Eaton" To: octave-maintainers mailing list Date: Mon, 28 Oct 2002 15:06:30 -0600 I've checked in the following changes to CVS. I think it should handle most of what we need. I don't think we should worry about how printf/scanf handle reading and writing these values, at least not yet. If you care about that, then you may have to do more work (i.e., do your own output conversions, and for input, read the file as text and scan it for the special values). I don't think the way I'm reading Inf, NaN, and NA is perfect, but it should handle well-formed files created by save. Improvements welcome. jwe liboctave/ChangeLog: 2002-10-28 John W. Eaton * lo-utils.cc (read_inf_nan_na, octave_read_double, octave_read_complex, octave_write_double, octave_write_complex): New functions. * CMatrix.cc (operator << (std::ostream&, const ComplexMatrix&)): Use octave_write_complex. (operator >> (std::istream&, const ComplexMatrix&)): Use octave_read_complex. * dMatrix.cc (operator << (std::ostream&, double)): Use octave_write_double. (operator >> (std::istream&, double)): Use octave_read_double. src/ChangeLog: 2002-10-28 John W. Eaton * load-save.cc (read_ascii_data): Use octave_read_double and octave_read_complex so that we handle Inf, NaN, and NA. (read_mat_ascii_data): Likewise. (save_ascii_data): Use octave_write_double and octave_write_complex. Index: liboctave/CMatrix.cc =================================================================== RCS file: /usr/local/cvsroot/octave/liboctave/CMatrix.cc,v retrieving revision 1.85 diff -u -r1.85 CMatrix.cc --- liboctave/CMatrix.cc 26 Sep 2002 22:10:06 -0000 1.85 +++ liboctave/CMatrix.cc 28 Oct 2002 20:52:26 -0000 at @ -2726,11 +2726,13 @@ std::ostream& operator << (std::ostream& os, const ComplexMatrix& a) { -// int field_width = os.precision () + 7; for (int i = 0; i < a.rows (); i++) { for (int j = 0; j < a.cols (); j++) - os << " " /* setw (field_width) */ << a.elem (i, j); + { + os << " "; + octave_write_complex (os, a.elem (i, j)); + } os << "\n"; } return os; at @ -2750,7 +2752,7 @@ for (int i = 0; i < nr; i++) for (int j = 0; j < nc; j++) { - is >> tmp; + tmp = octave_read_complex (is); if (is) a.elem (i, j) = tmp; else 2002-10-25 John W. Eaton * oct-kpse.c (octave_kpse_clear_dir_cache): Delete. Index: liboctave/dMatrix.cc =================================================================== RCS file: /usr/local/cvsroot/octave/liboctave/dMatrix.cc,v retrieving revision 1.89 diff -u -r1.89 dMatrix.cc --- liboctave/dMatrix.cc 2 Oct 2002 18:02:23 -0000 1.89 +++ liboctave/dMatrix.cc 28 Oct 2002 20:52:29 -0000 at @ -2216,12 +2216,13 @@ std::ostream& operator << (std::ostream& os, const Matrix& a) { -// int field_width = os.precision () + 7; - for (int i = 0; i < a.rows (); i++) { for (int j = 0; j < a.cols (); j++) - os << " " /* setw (field_width) */ << a.elem (i, j); + { + os << " "; + octave_write_double (os, a.elem (i, j)); + } os << "\n"; } return os; at @ -2241,7 +2242,7 @@ for (int i = 0; i < nr; i++) for (int j = 0; j < nc; j++) { - is >> tmp; + tmp = octave_read_double (is); if (is) a.elem (i, j) = tmp; else Index: liboctave/lo-utils.cc =================================================================== RCS file: /usr/local/cvsroot/octave/liboctave/lo-utils.cc,v retrieving revision 1.6 diff -u -r1.6 lo-utils.cc --- liboctave/lo-utils.cc 2 Jul 2002 04:14:36 -0000 1.6 +++ liboctave/lo-utils.cc 28 Oct 2002 20:52:29 -0000 at @ -39,6 +39,7 @@ #endif #include "lo-error.h" +#include "lo-ieee.h" #include "lo-mappers.h" #include "lo-utils.h" at @ -173,6 +174,142 @@ retval.resize (len-1); return retval; +} + +static inline double +read_inf_nan_na (std::istream& is, char c) +{ + double d = 0.0; + + switch (c) + { + case 'i': case 'I': + { + is >> c; + if (c == 'n' || c == 'N') + { + is >> c; + if (c == 'f' || c == 'F') + d = octave_Inf; + else + is.putback (c); + } + else + is.putback (c); + } + break; + + case 'n': case 'N': + { + is >> c; + if (c == 'a' || c == 'A') + { + is >> c; + if (c == 'n' || c == 'N') + d = octave_NaN; + else + { + is.putback (c); + d = octave_NA; + } + } + else + is.putback (c); + } + break; + + default: + abort (); + } + + return d; +} + +double +octave_read_double (std::istream& is) +{ + double d = 0.0; + + char c = 0; + + is >> c; + switch (c) + { + case 'i': case 'I': + case 'n': case 'N': + d = read_inf_nan_na (is, c); + break; + + default: + is.putback (c); + is >> d; + } + + return d; +} + +Complex +octave_read_complex (std::istream& is) +{ + double re = 0.0, im = 0.0; + + Complex cx = 0.0; + + char ch = 0; + + is >> ch; + + if (ch == '(') + { + re = octave_read_double (is); + is >> ch; + + if (ch == ',') + { + im = octave_read_double (is); + is >> ch; + + if (ch == ')') + cx = Complex (re, im); + else + is.setstate (std::ios::failbit); + } + else if (ch == ')') + cx = re; + else + is.setstate (std::ios::failbit); + } + else + { + is.putback (ch); + cx = octave_read_double (is); + } + + return cx; + +} + +void +octave_write_double (std::ostream& os, double d) +{ + if (lo_ieee_is_NA (d)) + os << "NA"; + else if (lo_ieee_isnan (d)) + os << "NaN"; + else if (lo_ieee_isinf (d)) + os << (d < 0 ? "-Inf" : "Inf"); + else + os << d; +} + +void +octave_write_complex (std::ostream& os, const Complex& c) +{ + os << "("; + octave_write_double (os, real (c)); + os << ","; + octave_write_double (os, imag (c)); + os << ")"; } /* Index: liboctave/lo-utils.h =================================================================== RCS file: /usr/local/cvsroot/octave/liboctave/lo-utils.h,v retrieving revision 1.9 diff -u -r1.9 lo-utils.h --- liboctave/lo-utils.h 2 Jul 2002 04:14:36 -0000 1.9 +++ liboctave/lo-utils.h 28 Oct 2002 20:52:29 -0000 at @ -25,8 +25,11 @@ #include +#include #include +#include "oct-cmplx.h" + extern int NINT (double x); extern double D_NINT (double x); at @ -45,6 +48,12 @@ extern "C" char *oct_strptime (const char *buf, const char *format, struct tm *tm); + +extern double octave_read_double (std::istream& is); +extern Complex octave_read_complex (std::istream& is); + +extern void octave_write_double (std::ostream& os, double d); +extern void octave_write_complex (std::ostream& os, const Complex& c); #endif Index: src/load-save.cc =================================================================== RCS file: /usr/local/cvsroot/octave/src/load-save.cc,v retrieving revision 1.146 diff -u -r1.146 load-save.cc --- src/load-save.cc 19 Sep 2002 04:09:29 -0000 1.146 +++ src/load-save.cc 28 Oct 2002 20:52:38 -0000 at @ -595,8 +595,7 @@ if (strncmp (ptr, "scalar", 6) == 0) { - double tmp; - is >> tmp; + double tmp = octave_read_double (is); if (is) tc = tmp; else at @ -629,8 +628,7 @@ } else if (strncmp (ptr, "complex scalar", 14) == 0) { - Complex tmp; - is >> tmp; + Complex tmp = octave_read_complex (is); if (is) tc = tmp; else at @ -2032,7 +2030,7 @@ for (int j = 0; j < nc; j++) { - tmp_stream >> d; + d = octave_read_double (tmp_stream); if (tmp_stream) tmp.elem (i, j) = d; at @ -4498,10 +4496,13 @@ { ascii_save_type (os, "range", mark_as_global); Range tmp = tc.range_value (); - os << "# base, limit, increment\n" - << tmp.base () << " " - << tmp.limit () << " " - << tmp.inc () << "\n"; + os << "# base, limit, increment\n"; + octave_write_double (os, tmp.base ()); + os << " "; + octave_write_double (os, tmp.limit ()); + os << " "; + octave_write_double (os, tmp.inc ()); + os << "\n"; } else if (tc.is_real_scalar ()) { at @ -4519,7 +4520,8 @@ else { d = xisinf (d) ? (d > 0 ? OCT_RBV : -OCT_RBV) : d; - os << d << "\n"; + octave_write_double (os, d); + os << "\n"; } } else at @ -4530,7 +4532,8 @@ infnan_warned = true; } - os << d << "\n"; + octave_write_double (os, d); + os << "\n"; } } else if (tc.is_real_matrix ()) at @ -4575,7 +4578,8 @@ c = Complex (re, im); - os << c << "\n"; + octave_write_complex (os, c); + os << "\n"; } } else at @ -4586,7 +4590,8 @@ infnan_warned = true; } - os << c << "\n"; + octave_write_complex (os, c); + os << "\n"; } } else if (tc.is_complex_matrix ())