diff liboctave/dMatrix.cc @ 2317:8c09c04f7747

[project @ 1996-07-14 22:30:15 by jwe]
author jwe
date Sun, 14 Jul 1996 22:40:35 +0000
parents 1b57120c997b
children b369227ce3d2
line wrap: on
line diff
--- a/liboctave/dMatrix.cc	Fri Jul 12 18:52:41 1996 +0000
+++ b/liboctave/dMatrix.cc	Sun Jul 14 22:40:35 1996 +0000
@@ -30,13 +30,10 @@
 #endif
 
 #include <cfloat>
-#include <cstdio>
-#include <cstring>
 
 #include <iostream.h>
 
-#include <sys/types.h>  // XXX FIXME XXX
-
+#include "byte-swap.h"
 #include "dbleAEPBAL.h"
 #include "dbleDET.h"
 #include "dbleSCHUR.h"
@@ -2521,164 +2518,497 @@
   return is;
 }
 
-// Read an array of data from a file in binary format.
+template <class T>
+static void
+read_int (istream& is, bool swap_bytes, T& val)
+{
+  is.read ((char *) &val, sizeof (T));
+
+  if (swap_bytes)
+    {
+      switch (sizeof (T))
+	{
+	case 1:
+	  break;
+
+	case 2:
+	  swap_2_bytes ((char *) &val);
+	  break;
+
+	case 4:
+	  swap_4_bytes ((char *) &val);
+	  break;
+
+	case 8:
+	  swap_8_bytes ((char *) &val);
+	  break;
+
+	default:
+	  (*current_liboctave_error_handler)
+	    ("read_int: unrecognized data format!");
+	}
+    }
+}
+
+template void read_int (istream&, bool, char&);
+template void read_int (istream&, bool, signed char&);
+template void read_int (istream&, bool, unsigned char&);
+template void read_int (istream&, bool, short&);
+template void read_int (istream&, bool, unsigned short&);
+template void read_int (istream&, bool, int&);
+template void read_int (istream&, bool, unsigned int&);
+template void read_int (istream&, bool, long&);
+template void read_int (istream&, bool, unsigned long&);
+
+static inline bool
+do_read (istream& is, oct_data_conv::data_type dt, 
+	 oct_mach_info::float_format flt_fmt, bool swap_bytes,
+	 bool do_float_conversion, double& val)
+{
+  bool retval = true;
+
+  switch (dt)
+    {
+    case oct_data_conv::dt_char:
+      {
+	char tmp;
+	read_int (is, swap_bytes, tmp);
+	val = tmp;
+      }
+      break;
+
+    case oct_data_conv::dt_schar:
+      {
+	signed char tmp;
+	read_int (is, swap_bytes, tmp);
+	val = tmp;
+      }
+      break;
+
+    case oct_data_conv::dt_uchar:
+      {
+	unsigned char tmp;
+	read_int (is, swap_bytes, tmp);
+	val = tmp;
+      }
+      break;
+
+    case oct_data_conv::dt_short:
+      {
+	short tmp;
+	read_int (is, swap_bytes, tmp);
+	val = tmp;
+      }
+      break;
+
+    case oct_data_conv::dt_ushort:
+      {
+	unsigned short tmp;
+	read_int (is, swap_bytes, tmp);
+	val = tmp;
+      }
+      break;
+
+    case oct_data_conv::dt_int:
+      {
+	int tmp;
+	read_int (is, swap_bytes, tmp);
+	val = tmp;
+      }
+      break;
+
+    case oct_data_conv::dt_uint:
+      {
+	unsigned int tmp;
+	read_int (is, swap_bytes, tmp);
+	val = tmp;
+      }
+      break;
+
+    case oct_data_conv::dt_long:
+      {
+	long tmp;
+	read_int (is, swap_bytes, tmp);
+	val = tmp;
+      }
+      break;
+
+    case oct_data_conv::dt_ulong:
+      {
+	unsigned long tmp;
+	read_int (is, swap_bytes, tmp);
+	val = tmp;
+      }
+      break;
+
+    case oct_data_conv::dt_float:
+      {
+	float f;
+
+	is.read ((char *) &f, sizeof (float));
+
+	if (do_float_conversion)
+	  do_float_format_conversion (&f, 1, flt_fmt);
+
+	val = f;
+      }
+      break;
+
+    case oct_data_conv::dt_double:
+      {
+	is.read ((char *) &val, sizeof (double));
+
+	if (do_float_conversion)
+	  do_double_format_conversion (&val, 1, flt_fmt);
+      }
+      break;
+
+    default:
+      retval = false;
+      (*current_liboctave_error_handler)
+	("read: invalid type specification");
+      break;
+    }
+
+  return retval;
+}
 
 int
-Matrix::read (FILE *fptr, const char *type)
+Matrix::read (istream& is, int nr, int nc,
+	      oct_data_conv::data_type dt, int skip,
+	      oct_mach_info::float_format flt_fmt)
 {
-  // Allocate buffer pointers.
-
-  union
-    {
-      void *vd;
-      char *ch;
-      u_char *uc;
-      short *sh;
-      u_short *us;
-      int *in;
-      u_int *ui;
-      long *ln;
-      u_long *ul;
-      float *fl;
-      double *db;
-    }
-  buf;
-
-  // Convert data to double.
-
-  if (! type)
+  int retval = -1;
+
+  bool ok = true;
+
+  int count = 0;
+
+  double *data = 0;
+  int max_size = 0;
+
+  int final_nr = 0;
+  int final_nc = 0;
+
+  if (nr > 0)
     {
-      (*current_liboctave_error_handler)
-	("fread: invalid NULL type parameter");
-      return 0;
-    }    
-
-  int count;
-  int nitems = length ();
-
-  double *d = fortran_vec (); // Ensures only one reference to my privates!
-
-#define DO_FREAD(TYPE,ELEM) \
-  do \
-    { \
-      size_t size = sizeof (TYPE); \
-      buf.ch = new char [size * nitems]; \
-      count = fread (buf.ch, size, nitems, fptr); \
-      for (int k = 0; k < count; k++) \
-	d[k] = buf.ELEM[k]; \
-      delete [] buf.ch; \
-    } \
-  while (0)
-
-  if (strcasecmp (type, "double") == 0)
-    DO_FREAD (double, db);
-  else if (strcasecmp (type, "char") == 0)
-    DO_FREAD (char, ch);
-  else if (strcasecmp (type, "uchar") == 0)
-    DO_FREAD (u_char, uc);
-  else if (strcasecmp (type, "short") == 0)
-    DO_FREAD (short, sh);
-  else if (strcasecmp (type, "ushort") == 0)
-    DO_FREAD (u_short, us);
-  else if (strcasecmp (type, "int") == 0)
-    DO_FREAD (int, in);
-  else if (strcasecmp (type, "uint") == 0)
-    DO_FREAD (u_int, ui);
-  else if (strcasecmp (type, "long") == 0)
-    DO_FREAD (long, ul);
-  else if (strcasecmp (type, "float") == 0)
-    DO_FREAD (float, fl);
+      if (nc > 0)
+	{
+	  resize (nr, nc, 0.0);
+	  data = fortran_vec ();
+	  max_size = nr * nc;
+	}
+      else
+	{
+	  resize (nr, 32, 0.0);
+	  data = fortran_vec ();
+	  max_size = nr * 32;
+	}
+    }
   else
     {
-      (*current_liboctave_error_handler)
-	("fread: invalid NULL type parameter");
-      return 0;
+      resize (32, 1, 0.0);
+      data = fortran_vec ();
+      max_size = 32;
+    }
+
+  oct_mach_info::float_format native_flt_fmt
+    = oct_mach_info::float_format ();
+
+  bool do_float_conversion = (flt_fmt != native_flt_fmt);
+
+  // XXX FIXME XXX -- byte order for Cray?
+
+  bool swap_bytes = false;
+
+  if (oct_mach_info::words_big_endian ())
+    swap_bytes = (flt_fmt == oct_mach_info::ieee_little_endian
+		 || flt_fmt == oct_mach_info::vax_g
+		 || flt_fmt == oct_mach_info::vax_g);
+  else
+    swap_bytes = (flt_fmt == oct_mach_info::ieee_big_endian);
+
+  for (;;)
+    {
+      // XXX FIXME XXX -- maybe there should be a special case for
+      // skip == 0.
+
+      if (is)
+	{
+	  if (nr > 0 && nc > 0 && count == max_size)
+	    {
+	      final_nr = nr;
+	      final_nc = nc;
+
+	      break;
+	    }
+
+	  if (skip != 0)
+	    is.seekg (skip, ios::cur);
+
+	  if (is)
+	    {
+	      double tmp = 0.0;
+
+	      ok = do_read (is, dt, flt_fmt, swap_bytes,
+			    do_float_conversion, tmp);
+
+	      if (ok)
+		{
+		  if (is)
+		    {
+		      if (count == max_size)
+			{
+			  max_size *= 2;
+
+			  if (nr > 0)
+			    resize (nr, max_size / 2, 0.0);
+			  else
+			    resize (max_size, 1, 0.0);
+
+			  data = fortran_vec ();
+			}
+
+		      data[count++] = tmp;
+		    }
+		  else
+		    {
+		      if (is.eof ())
+			{
+			  if (nr > 0)
+			    {
+			      if (count > nr)
+				{
+				  final_nr = nr;
+				  final_nc = (count - 1) / nr + 1;
+				}
+			      else
+				{
+				  final_nr = count;
+				  final_nc = 1;
+				}
+			    }
+			  else
+			    {
+			      final_nr = count;
+			      final_nc = 1;
+			    }
+			}
+
+		      break;
+		    }
+		}
+	      else
+		break;
+	    }
+	  else
+	    {
+	      ok = false;
+	      break;
+	    }
+	}
+      else
+	{
+	  ok = false;
+	  break;
+	}
+    }
+
+  if (ok)
+    {
+      resize (final_nr, final_nc, 0.0);
+
+      retval = count;
     }
 
-  return count;
+  return retval;
+}
+
+template <class T>
+static void
+write_int (ostream& os, bool swap_bytes, T val)
+{
+  if (swap_bytes)
+    {
+      switch (sizeof (T))
+	{
+	case 1:
+	  break;
+
+	case 2:
+	  swap_2_bytes ((char *) &val);
+	  break;
+
+	case 4:
+	  swap_4_bytes ((char *) &val);
+	  break;
+
+	case 8:
+	  swap_8_bytes ((char *) &val);
+	  break;
+
+	default:
+	  (*current_liboctave_error_handler)
+	    ("write_int: unrecognized data format!");
+	}
+    }
+
+  os.write ((char *) &val, sizeof (T));
 }
 
-// Write the data array to a file in binary format.
+template void write_int (ostream&, bool, char);
+template void write_int (ostream&, bool, signed char);
+template void write_int (ostream&, bool, unsigned char);
+template void write_int (ostream&, bool, short);
+template void write_int (ostream&, bool, unsigned short);
+template void write_int (ostream&, bool, int);
+template void write_int (ostream&, bool, unsigned int);
+template void write_int (ostream&, bool, long);
+template void write_int (ostream&, bool, unsigned long);
+
+static inline bool
+do_write (ostream& os, double d, oct_data_conv::data_type dt,
+	  oct_mach_info::float_format flt_fmt, bool swap_bytes,
+	  bool do_float_conversion)
+{
+  bool retval = true;
+
+  switch (dt)
+    {
+    case oct_data_conv::dt_char:
+      write_int (os, swap_bytes, (char) d);
+      break;
+
+    case oct_data_conv::dt_schar:
+      write_int (os, swap_bytes, (signed char) d);
+      break;
+
+    case oct_data_conv::dt_uchar:
+      write_int (os, swap_bytes, (unsigned char) d);
+      break;
+
+    case oct_data_conv::dt_short:
+      write_int (os, swap_bytes, (short) d);
+      break;
+
+    case oct_data_conv::dt_ushort:
+      write_int (os, swap_bytes, (unsigned short) d);
+      break;
+
+    case oct_data_conv::dt_int:
+      write_int (os, swap_bytes, (int) d);
+      break;
+
+    case oct_data_conv::dt_uint:
+      write_int (os, swap_bytes, (unsigned int) d);
+      break;
+
+    case oct_data_conv::dt_long:
+      write_int (os, swap_bytes, (long) d);
+      break;
+
+    case oct_data_conv::dt_ulong:
+      write_int (os, swap_bytes, (unsigned long) d);
+      break;
+
+    case oct_data_conv::dt_float:
+      {
+	float f = (float) d;
+
+	if (do_float_conversion)
+	  do_float_format_conversion (&f, 1, flt_fmt);
+
+	os.write ((char *) &f, sizeof (float));
+      }
+      break;
+
+    case oct_data_conv::dt_double:
+      {
+	if (do_float_conversion)
+	  do_double_format_conversion (&d, 1, flt_fmt);
+
+	os.write ((char *) &d, sizeof (double));
+      }
+      break;
+
+    default:
+      retval = false;
+      (*current_liboctave_error_handler)
+	("write: invalid type specification");
+      break;
+    }
+
+  return retval;
+}
 
 int
-Matrix::write (FILE *fptr, const char *type)
+Matrix::write (ostream& os, oct_data_conv::data_type dt, int skip,
+	       oct_mach_info::float_format flt_fmt)
 {
-  // Allocate buffer pointers.
-
-  union
-    {
-      void *vd;
-      char *ch;
-      u_char *uc;
-      short *sh;
-      u_short *us;
-      int *in;
-      u_int *ui;
-      long *ln;
-      u_long *ul;
-      float *fl;
-      double *db;
-    }
-  buf;
-
-  int nitems = length ();
-
-  double *d = fortran_vec ();
-
-  // Convert from double to correct size.
-
-  if (! type)
+  int retval = -1;
+
+  bool ok = true;
+
+  int count = 0;
+
+  const double *d = data ();
+
+  int n = length ();
+
+  oct_mach_info::float_format native_flt_fmt
+    = oct_mach_info::float_format ();
+
+  bool do_float_conversion = (flt_fmt != native_flt_fmt);
+
+  // XXX FIXME XXX -- byte order for Cray?
+
+  bool swap_bytes = false;
+
+  if (oct_mach_info::words_big_endian ())
+    swap_bytes = (flt_fmt == oct_mach_info::ieee_little_endian
+		 || flt_fmt == oct_mach_info::vax_g
+		 || flt_fmt == oct_mach_info::vax_g);
+  else
+    swap_bytes = (flt_fmt == oct_mach_info::ieee_big_endian);
+
+  for (int i = 0; i < n; i++)
     {
-      (*current_liboctave_error_handler)
-	("fwrite: invalid NULL type parameter");
-      return 0;
-    }    
-
-  size_t size;
-  int count;
-
-#define DO_FWRITE(TYPE,ELEM) \
-  do \
-    { \
-      size = sizeof (TYPE); \
-      buf.ELEM = new TYPE [nitems]; \
-      for (int k = 0; k < nitems; k++) \
-	buf.ELEM[k] = (TYPE) d[k]; \
-      count = fwrite (buf.ELEM, size, nitems, fptr); \
-      delete [] buf.ELEM; \
-    } \
-  while (0)
-
-  if (strcasecmp (type, "double") == 0)
-    DO_FWRITE (double, db);
-  else if (strcasecmp (type, "char") == 0)
-    DO_FWRITE (char, ch);
-  else if (strcasecmp (type, "uchar") == 0)
-    DO_FWRITE (u_char, uc);
-  else if (strcasecmp (type, "short") == 0)
-    DO_FWRITE (short, sh);
-  else if (strcasecmp (type, "ushort") == 0)
-    DO_FWRITE (u_short, us);
-  else if (strcasecmp (type, "int") == 0)
-    DO_FWRITE (int, in);
-  else if (strcasecmp (type, "uint") == 0)
-    DO_FWRITE (u_int, ui);
-  else if (strcasecmp (type, "long") == 0)
-    DO_FWRITE (long, ln);
-  else if (strcasecmp (type, "ulong") == 0)
-    DO_FWRITE (u_long, ul);
-  else if (strcasecmp (type, "float") == 0)
-    DO_FWRITE (float, fl);
-  else
-    {
-      (*current_liboctave_error_handler)
-	("fwrite: unrecognized type parameter %s", type);
-      return 0;
+      if (os)
+	{
+	  if (skip != 0)
+	    os.seekp (skip, ios::cur);
+
+	  if (os)
+	    {
+	      ok = do_write (os, d[i], dt, flt_fmt, swap_bytes,
+			     do_float_conversion);
+
+	      if (os && ok)
+		count++;
+	      else
+		break;
+	    }
+	  else
+	    {
+	      ok = false;
+	      break;
+	    }
+	}
+      else
+	{
+	  ok = false;
+	  break;
+	}
     }
 
-  return count;
+  if (ok)
+    retval = count;
+
+  return retval;
 }
 
+
+
 Matrix
 Givens (double x, double y)
 {