ascii save/load of inf, nan, and na values

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

ascii save/load of inf, nan, and na values

John W. Eaton-6
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  <[hidden email]>

        * 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  <[hidden email]>

        * 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
@@ -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;
@@ -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  <[hidden email]>
 
  * 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
@@ -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;
@@ -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
@@ -39,6 +39,7 @@
 #endif
 
 #include "lo-error.h"
+#include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "lo-utils.h"
 
@@ -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
@@ -25,8 +25,11 @@
 
 #include <cstdio>
 
+#include <iostream>
 #include <string>
 
+#include "oct-cmplx.h"
+
 extern int NINT (double x);
 extern double D_NINT (double x);
 
@@ -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
@@ -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
@@ -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
@@ -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;
@@ -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 ())
     {
@@ -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
@@ -4530,7 +4532,8 @@
       infnan_warned = true;
     }
 
-  os << d << "\n";
+  octave_write_double (os, d);
+  os << "\n";
  }
     }
   else if (tc.is_real_matrix ())
@@ -4575,7 +4578,8 @@
 
       c = Complex (re, im);
 
-      os << c << "\n";
+      octave_write_complex (os, c);
+      os << "\n";
     }
  }
       else
@@ -4586,7 +4590,8 @@
       infnan_warned = true;
     }
 
-  os << c << "\n";
+  octave_write_complex (os, c);
+  os << "\n";
  }
     }
   else if (tc.is_complex_matrix ())