Browse Source

moved matlab-IO from fast-hik to vislearning

Alexander Freytag 12 years ago
parent
commit
988beabfc3

+ 143 - 0
matlabAccess/ImageNetData.cpp

@@ -0,0 +1,143 @@
+/** 
+* @file ImageNetData.cpp
+* @brief wrapper class for matlab IO with ImageNet data
+* @author Erik Rodner
+* @date 02/03/2012
+
+*/
+#include <iostream>
+#include <vector>
+
+#include <core/basics/Exception.h>
+#include <core/vector/VectorT.h>
+
+#include "ImageNetData.h"
+
+using namespace NICE;
+using namespace std;
+
+
+ImageNetData::ImageNetData( const string & imageNetRoot )
+{
+  this->imageNetRoot = imageNetRoot;
+}
+
+ImageNetData::~ImageNetData()
+{
+}
+
+void ImageNetData::getBatchData ( sparse_t & data, Vector & y, const string & fileTag, const string & variableTag )
+{
+  string filename = imageNetRoot + "/demo." + fileTag + ".mat";
+  string vn_data = variableTag + "_instance_matrix";
+  string vn_y = variableTag + "_label_vector";
+  MatFileIO matfileIO (filename,MAT_ACC_RDONLY);
+  matfileIO.getSparseVariableViaName(data,vn_data);
+  matfileIO.getVectorViaName(y,vn_y);
+}
+
+void ImageNetData::preloadData ( const string & fileTag, const string & variableTag )
+{
+  sparse_t m_XPreload;
+  getBatchData ( m_XPreload, yPreload, fileTag, variableTag ); 
+
+  XPreload.resize ( yPreload.size() );
+  cerr << "ImageNetData: converting data ... " << yPreload.size() << " examples" << endl;
+  for ( int i = 0; i < m_XPreload.njc-1; i++ ) //walk over dimensions
+	{
+		for ( int j = m_XPreload.jc[i]; j < m_XPreload.jc[i+1] && j < m_XPreload.ndata; j++ )
+    {
+      int exampleIndex = m_XPreload.ir[ j];
+      if ( exampleIndex < 0 || exampleIndex >= (int)XPreload.size() )
+        fthrow(Exception, "Label and data file seem to mismatch according the sizes: " << XPreload.size() << " vs. " << exampleIndex);
+      XPreload[exampleIndex].insert ( pair<int, double> ( i, ((double *)m_XPreload.data)[j] ) );
+    }
+  }
+  cerr << "ImageNetData: data conversion finished." << endl;
+}
+
+void ImageNetData::loadDataAsLabeledSetVector( OBJREC::LabeledSetVector & lsVector, const std::string & fileTag, const std::string & variableTag )
+{
+  sparse_t m_XPreload;
+  
+  //load raw data
+  getBatchData ( m_XPreload, yPreload, fileTag, variableTag ); 
+  
+  //tmp storage 
+  std::vector<NICE::Vector> dataTmp;
+  dataTmp.resize(yPreload.size());
+  
+  
+  //initialize every entries with zero
+  NICE::Vector vZero (yPreload.size(), 0.0);
+  for (uint i = 0; i < yPreload.size(); i++)
+  {
+    dataTmp[i] = vZero;
+  }
+ 
+  //set non-zero entries according to the stored values
+  std::cerr << "ImageNetData: converting data ... " << yPreload.size() << " examples" << std::endl;
+  for ( int i = 0; i < m_XPreload.njc-1; i++ ) //walk over dimensions
+  {
+    for ( int j = m_XPreload.jc[i]; j < m_XPreload.jc[i+1] && j < m_XPreload.ndata; j++ ) //and over every non-zero entry in this dimension
+    {
+      //what is the original index?
+      int exampleIndex = m_XPreload.ir[ j];
+      if ( exampleIndex < 0 || exampleIndex >= (int)yPreload.size() )
+        fthrow(Exception, "Label and data file seem to mismatch according the sizes: " << yPreload.size() << " vs. " << exampleIndex);      
+      
+      //insert at the original index and the corresponding dimension
+      dataTmp[exampleIndex][i] =  ((double *)m_XPreload.data)[j];
+    }
+  }
+
+  std::cerr << "ImageNetData: data conversion finished." << std::endl;
+  
+  lsVector.clear();
+  for (uint i = 0; i < yPreload.size(); i++)
+  {
+        lsVector.add( yPreload[i], dataTmp[i] );
+  }
+}
+
+const SparseVector & ImageNetData::getPreloadedExample ( int index ) const
+{
+  if ( index >= (int)XPreload.size() || index < 0 )
+    fthrow(Exception, "Invalid index!");
+  return XPreload[index];
+}
+
+double ImageNetData::getPreloadedLabel ( int index ) const
+{
+  if ( index < 0 || index >= (int)yPreload.size() )
+    fthrow(Exception, "Invalid index!");
+  return yPreload[index];
+}
+
+int ImageNetData::getNumPreloadedExamples () const
+{
+  return yPreload.size();
+}
+
+void ImageNetData::loadExternalLabels ( const string & fn, int n )
+{
+  if ( n <= 0  && yPreload.size() == 0 ) {
+    fthrow(Exception, "Please initialize with preloadData() first, or use the second optional argument to give the number of examples.");
+  }
+  if ( n >= 0 )
+    yPreload.resize( n );
+
+  ifstream ifs ( fn.c_str(), ios::in );
+  if ( ! ifs.good() )
+    fthrow(Exception, "Unable to read " << fn );
+
+  int value;
+  int i = 0;
+  while ( (i < yPreload.size()) && (ifs >> value) ) 
+    yPreload[i++] = value;
+
+  ifs.close();
+
+  if ( (XPreload.size() > 0) && (yPreload.size() != XPreload.size()) )
+    fthrow(Exception, "Size of the label vector and the size of the data structure do not match.");
+}

+ 110 - 0
matlabAccess/ImageNetData.h

@@ -0,0 +1,110 @@
+/** 
+* @file ImageNetData.h
+* @author Erik Rodner
+* @date 02/03/2012
+
+*/
+#ifndef _NICE_IMAGENETDATAINCLUDE
+#define _NICE_IMAGENETDATAINCLUDE
+
+#include <string>
+
+#include <core/vector/VectorT.h>
+#include <core/vector/SparseVector.h>
+
+#include "vislearning/cbaselib/LabeledSet.h"
+
+#include "fast-hik/MatFileIO.h"
+
+namespace NICE {
+  
+/** @class ImageNetData
+ * wrapper class for matlab IO with ImageNet data 
+ *
+ * @author Erik Rodner
+ */
+class ImageNetData
+{
+
+  protected:
+    std::string imageNetRoot;
+
+    std::vector< SparseVector > XPreload;
+    Vector yPreload;
+
+  public:
+
+    /** simple constructor */
+    ImageNetData( const std::string & imageNetRoot = "/home/dbv/bilder/imagenet/devkit-1.0/demo/" );
+      
+    /** simple destructor */
+    virtual ~ImageNetData();
+
+    /**
+    * @brief get a bulk of (training) data with labels
+    *
+    * @param data feature vectors
+    * @param y label vector
+    * @param fileTag demo.<tag>.mat will be accessed
+    * @param variableTag variables are named <tag>_instance_matrix and <tag>_label_vector
+    */
+    void getBatchData ( sparse_t & data, Vector & y, const std::string & fileTag = "train", const std::string & variableTag = "training" );
+
+
+    /**
+    * @brief load the data specified for later access using the get functions
+    *
+    * @param fileTag
+    * @param variableTag
+    */
+    void preloadData ( const std::string & fileTag = "val", const std::string & variableTag = "testing" );
+    
+    /**
+    * @brief load the data specified for later access using the get functions, give everything as a LabeledSetVector object which is usefull for objects of type KernelClassifier (as used in vislearning)
+    *
+    * @date 23-05-2012 (dd-mm-yyyy)
+    * @param fileTag
+    * @param variableTag
+    * @param lsVector
+    */    
+    void loadDataAsLabeledSetVector( OBJREC::LabeledSetVector & lsVector, const std::string & fileTag = "train", const std::string & variableTag = "training" );
+
+    /**
+    * @brief get a specific feature vector
+    *
+    * @param index index of the example
+    * @return constant reference to the SparseVector
+    */
+    const SparseVector & getPreloadedExample ( int index ) const;
+
+    /**
+    * @brief get the label of a specific example
+    *
+    * @param index index of the example
+    *
+    * @return label of the example (can be continous)
+    */
+    double getPreloadedLabel ( int index ) const;
+
+    /**
+    * @brief get number of examples
+    */
+    int getNumPreloadedExamples () const;
+
+  
+    /**
+    * @brief load external labels
+    *
+    * @param fn file name of the external labels
+    * @param n number of examples, if this parameter is set to -1 we assume that 
+    * the data is already loaded
+    */
+    void loadExternalLabels ( const std::string & fn, int n = -1 );
+    
+    std::vector< SparseVector > getPreloadedData() { return XPreload;};
+    NICE::Vector getPreloadedLabels()const {return yPreload;};    
+};
+
+}
+
+#endif

+ 8 - 0
matlabAccess/Makefile

@@ -0,0 +1,8 @@
+#TARGETS_FROM:=$(notdir $(patsubst %/,%,$(shell pwd)))/$(TARGETS_FROM)
+#$(info recursivly going up: $(TARGETS_FROM) ($(shell pwd)))
+
+all:
+
+%:
+	$(MAKE) TARGETS_FROM=$(notdir $(patsubst %/,%,$(shell pwd)))/$(TARGETS_FROM) -C .. $@
+

+ 103 - 0
matlabAccess/Makefile.inc

@@ -0,0 +1,103 @@
+# LIBRARY-DIRECTORY-MAKEFILE
+# conventions:
+# - all subdirectories containing a "Makefile.inc" are considered sublibraries
+#   exception: "progs/" and "tests/" subdirectories!
+# - all ".C", ".cpp" and ".c" files in the current directory are linked to a
+#   library
+# - the library depends on all sublibraries 
+# - the library name is created with $(LIBNAME), i.e. it will be somehow
+#   related to the directory name and with the extension .a
+#   (e.g. lib1/sublib -> lib1_sublib.a)
+# - the library will be added to the default build list ALL_LIBRARIES
+
+# --------------------------------
+# - remember the last subdirectory
+#
+# set the variable $(SUBDIR) correctly to the current subdirectory. this
+# variable can be used throughout the current makefile.inc. The many 
+# SUBDIR_before, _add, and everything are only required so that we can recover
+# the previous content of SUBDIR before exitting the makefile.inc
+
+SUBDIR_add:=$(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
+SUBDIR_before:=$(SUBDIR)
+SUBDIR:=$(strip $(SUBDIR_add))
+SUBDIR_before_$(SUBDIR):=$(SUBDIR_before)
+ifeq "$(SUBDIR)" "./"
+SUBDIR:=
+endif
+
+# ------------------------
+# - include subdirectories
+#
+# note the variables $(SUBDIRS_OF_$(SUBDIR)) are required later on to recover
+# the dependencies automatically. if you handle dependencies on your own, you
+# can also dump the $(SUBDIRS_OF_$(SUBDIR)) variable, and include the
+# makefile.inc of the subdirectories on your own...
+
+SUBDIRS_OF_$(SUBDIR):=$(patsubst %/Makefile.inc,%,$(wildcard $(SUBDIR)*/Makefile.inc))
+include $(SUBDIRS_OF_$(SUBDIR):%=%/Makefile.inc)
+
+# ----------------------------
+# - include local dependencies
+#
+# you can specify libraries needed by the individual objects or by the whole
+# directory. the object specific additional libraries are only considered
+# when compiling the specific object files
+# TODO: update documentation...
+
+-include $(SUBDIR)libdepend.inc
+
+$(foreach d,$(filter-out %progs %tests,$(SUBDIRS_OF_$(SUBDIR))),$(eval $(call PKG_DEPEND_INT,$(d))))
+
+# ---------------------------
+# - objects in this directory
+#
+# the use of the variable $(OBJS) is not mandatory. it is mandatory however
+# to update $(ALL_OBJS) in a way that it contains the path and name of
+# all objects. otherwise we can not include the appropriate .d files.
+
+OBJS:=$(patsubst %.cpp,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.cpp))) \
+      $(patsubst %.C,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.C))) \
+	  $(shell grep -ls Q_OBJECT $(SUBDIR)*.h | sed -e's@^@/@;s@.*/@$(OBJDIR)moc_@;s@\.h$$@.o@') \
+      $(patsubst %.c,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.c)))
+ALL_OBJS += $(OBJS)
+
+# ----------------------------
+# - binaries in this directory
+#
+# output of binaries in this directory. none of the variables has to be used.
+# but everything you add to $(ALL_LIBRARIES) and $(ALL_BINARIES) will be
+# compiled with `make all`. be sure again to add the files with full path.
+
+LIBRARY_BASENAME:=$(call LIBNAME,$(SUBDIR))
+ifneq "$(SUBDIR)" ""
+ALL_LIBRARIES+=$(LIBDIR)$(LIBRARY_BASENAME).$(LINK_FILE_EXTENSION)
+endif
+
+# ---------------------
+# - binary dependencies
+#
+# there is no way of determining the binary dependencies automatically, so we
+# follow conventions. the current library depends on all sublibraries.
+# all other dependencies have to be added manually by specifying, that the
+# current .pc file depends on some other .pc file. binaries depending on
+# libraries should exclusivelly use the .pc files as well.
+
+ifeq "$(SKIP_BUILD_$(OBJDIR))" "1"
+$(LIBDIR)$(LIBRARY_BASENAME).a:
+else
+$(LIBDIR)$(LIBRARY_BASENAME).a:$(OBJS) \
+	$(call PRINT_INTLIB_DEPS,$(PKGDIR)$(LIBRARY_BASENAME).a,.$(LINK_FILE_EXTENSION))
+endif
+
+$(PKGDIR)$(LIBRARY_BASENAME).pc: \
+	$(call PRINT_INTLIB_DEPS,$(PKGDIR)$(LIBRARY_BASENAME).pc,.pc)
+
+# -------------------
+# - subdir management
+#
+# as the last step, always add this line to correctly recover the subdirectory
+# of the makefile including this one!
+
+SUBDIR:=$(SUBDIR_before_$(SUBDIR))
+

+ 657 - 0
matlabAccess/MatFileIO.cpp

@@ -0,0 +1,657 @@
+/** 
+* @file MatFileIO.cpp
+* @brief Read and write mat-files
+* @author Paul Bodesheim
+* @date 06-01-2012 (dd-mm-yyyy)
+*/
+
+#include "MatFileIO.h"
+
+namespace NICE {
+  
+      //------------------------------------------------------
+      // several constructors and destructors
+      //------------------------------------------------------
+
+       
+      // Default constructor
+      MatFileIO::MatFileIO() { mat = 0; }
+      
+      // Recommended constructor
+      MatFileIO::MatFileIO(std::string _filename, const mat_acc mode) { 
+	
+	mat = Mat_Open(_filename.c_str(),mode); 
+	
+	if (mat == NULL && mode == MAT_ACC_RDONLY) {
+	 
+	  fthrow(Exception, "MatFileIO::MatFileIO(const char * _filename, int mode): mat-file does not exist");
+	  
+	}
+      } 
+      
+      // Default destructor
+      MatFileIO::~MatFileIO() {}
+      
+      //------------------------------------------------------
+      // count number of stored variables
+      //------------------------------------------------------     
+      
+      int MatFileIO::getNumberOfVariables() {
+	
+	Mat_Rewind(mat); // get back to first variable
+	int count = 0;
+	matvar_t * matvar = Mat_VarReadNextInfo(mat);
+	
+	while (matvar != NULL) {
+	  
+	  count++;
+	  matvar = Mat_VarReadNextInfo(mat);
+	}
+	
+	Mat_VarFree(matvar);
+	
+	return count;
+      }
+      
+      //------------------------------------------------------
+      // several methods for reading data
+      //------------------------------------------------------     
+      
+      matvar_t * MatFileIO::getVariableViaName(std::string _name) {
+      
+// 	std::cout << "MatFileIO::getVariableViaName: method entered" << std::endl;
+	char * cString = new char[256];
+// 	std::cout << "MatFileIO::getVariableViaName: cString init done" << std::endl;
+	return Mat_VarRead(mat,strcpy(cString,_name.c_str()));
+	
+      }
+      
+      void MatFileIO::getSparseVariableViaName(sparse_t & sparseVariable, std::string _name) {
+	
+	matvar_t * matvar = getVariableViaName(_name);
+	
+	if (matvar == NULL) {
+	  
+	  fthrow(Exception, "MatFileIO::getSparseVariableViaName(sparse_t & sparseVariable, std::string _name): variable with specified name does not exist");
+	  return;
+	}
+
+	if (matvar->class_type != MAT_C_SPARSE) {
+	  
+	  fthrow(Exception, "MatFileIO::getSparseVariableViaName(sparse_t & sparseVariable, std::string _name): format of variable is not sparse");
+	  return;
+	}
+	
+	sparseVariable = *((sparse_t*)matvar->data);
+	sparseVariable.data = (double*) sparseVariable.data;
+      }
+
+      
+      void MatFileIO::getFeatureMatrixViaName(std::vector<std::vector<double> > & features, std::string _name, const feature_matrix_order order) {
+	
+	matvar_t * matvar = getVariableViaName(_name);
+	
+	if (matvar == NULL) {
+	  
+	  fthrow(Exception, "MatFileIO::getFeatureMatrixViaName(char * _name, feature_matrix_order order): variable with specified name does not exist");
+	  return;
+	}
+	
+	if (matvar->rank != 2) {
+	  
+	  fthrow(Exception, "MatFileIO::getFeatureMatrixViaName(char * _name, feature_matrix_order order): dimension of variable != 2");
+	  return;
+	}
+	
+	features.clear();
+	std::vector<double> currentFeature;
+	currentFeature.clear();
+	
+	// case 1: feature vectors in the rows of matrix
+	if (order == NxD) {
+	  
+	  // depending on the class type of data elements, we have to treat several cases and cast the data elements correctly
+          switch (matvar->data_type) {
+	    
+            case MAT_T_DOUBLE:
+	      
+  
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  currentFeature.push_back( ((double*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;
+	      
+            case MAT_T_SINGLE:
+	  
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  currentFeature.push_back( ((float*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;
+	      
+#ifdef HAVE_MAT_INT64_T
+            case MAT_T_INT64:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  currentFeature.push_back( ((signed long long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }	            
+
+	      break;
+#endif
+#ifdef HAVE_MAT_UINT64_T	      
+            case MAT_T_UINT64:
+
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  currentFeature.push_back( ((unsigned long long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }	
+
+	      break; 
+#endif
+            case MAT_T_INT32:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  currentFeature.push_back( ((signed long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;	      
+
+            case MAT_T_UINT32:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  currentFeature.push_back( ((unsigned long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;	      
+	      
+            case MAT_T_INT16:
+
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  currentFeature.push_back( ((signed short*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;
+	      
+            case MAT_T_UINT16:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  currentFeature.push_back( ((unsigned short*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;	      
+	      
+            case MAT_T_INT8:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  currentFeature.push_back( ((signed char*)matvar->data)[matvar->dims[0]*j+i] );
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;	      
+
+            case MAT_T_UINT8:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  currentFeature.push_back( ((unsigned char*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;
+	  }   
+
+	// case 2: feature vectors in the columns of matrix
+	} else if (order == DxN) {
+	  
+	  // depending on the class type of data elements, we have to treat several cases and cast the data elements correctly
+          switch (matvar->data_type) {
+	    
+            case MAT_T_DOUBLE:
+	  
+	      for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		  
+		  currentFeature.push_back( ((double*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;
+	      
+            case MAT_T_SINGLE:
+	  
+	      for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		  
+		  currentFeature.push_back( ((float*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;
+	      
+#ifdef HAVE_MAT_INT64_T
+            case MAT_T_INT64:
+	      
+	      for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		  
+		  currentFeature.push_back( ((signed long long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }	            
+
+	      break;
+#endif
+#ifdef HAVE_MAT_UINT64_T	      
+            case MAT_T_UINT64:
+
+	      for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		  
+		  currentFeature.push_back( ((unsigned long long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }	
+
+	      break;
+#endif
+            case MAT_T_INT32:
+	      
+	      for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		  
+		  currentFeature.push_back( ((signed long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;	      
+
+            case MAT_T_UINT32:
+	      
+	      for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		  
+		  currentFeature.push_back( ((unsigned long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;	      
+	      
+            case MAT_T_INT16:
+
+	      for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		  
+		  currentFeature.push_back( ((signed short*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;
+	      
+            case MAT_T_UINT16:
+	      
+	      for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		  
+		  currentFeature.push_back( ((unsigned short*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;	      
+	      
+            case MAT_T_INT8:
+	      
+	      for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		  
+		  currentFeature.push_back( ((signed char*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;	      
+
+            case MAT_T_UINT8:
+	      
+	      for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		  
+		  currentFeature.push_back( ((unsigned char*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+		  
+		  features.push_back(currentFeature);
+		  currentFeature.clear();
+	      }
+	      
+	      break;
+	  }            
+          
+	} else {
+	  
+	  fthrow(Exception, "MatFileIO::getFeatureMatrixViaName(char * _name, feature_matrix_order order): wrong feature_matrix_order specified");
+	  return;
+	}	
+	
+      }
+      
+      void MatFileIO::getVectorViaName(NICE::Vector & vec, std::string _name) {
+	
+	matvar_t * matvar = getVariableViaName(_name);
+	
+	if (matvar == NULL) {
+	  
+	  fthrow(Exception, "MatFileIO::getFeatureMatrixViaName(char * _name, feature_matrix_order order): variable with specified name does not exist");
+	  return;
+	}
+	
+	// it can happen that a vector is treated as (N x 1) or (1 x N) matrix with two dimensions
+	if (matvar->rank > 2 || ( (matvar->rank == 2) && (matvar->dims[0] != 1) && (matvar->dims[1] != 1) ) ) {
+	  
+	  fthrow(Exception, "MatFileIO::getFeatureMatrixViaName(char * _name, feature_matrix_order order): dimension of variable > 1");
+	  return;
+	}  
+	
+	std::vector<double> v;
+	v.clear();
+	
+	// vector is stored as a variable with one dimensional 
+	if (matvar->rank == 1) {
+	  
+          switch( matvar->data_type ) {
+	    
+            case MAT_T_DOUBLE:
+	  
+	      for ( int i = 0; i < matvar->nbytes/matvar->data_size; i++ ) {
+		  
+		  v.push_back( ((double*)matvar->data)[i] );	      
+	      }
+	      
+	      break;
+	      
+            case MAT_T_SINGLE:
+	  
+	      for ( int i = 0; i < matvar->nbytes/matvar->data_size; i++ ) {
+		  
+		  v.push_back( ((float*)matvar->data)[i] );	      
+	      }
+	      
+	      break;
+	      
+#ifdef HAVE_MAT_INT64_T
+            case MAT_T_INT64:
+	      
+	      for ( int i = 0; i < matvar->nbytes/matvar->data_size; i++ ) {
+		  
+		  v.push_back( ((signed long long*)matvar->data)[i] );	      
+	      }            
+
+	      break;
+#endif
+#ifdef HAVE_MAT_UINT64_T	      
+            case MAT_T_UINT64:
+
+	      for ( int i = 0; i < matvar->nbytes/matvar->data_size; i++ ) {
+		  
+		  v.push_back( ((unsigned long long*)matvar->data)[i] );	      
+	      }
+
+	      break;
+#endif
+            case MAT_T_INT32:
+	      
+	      for ( int i = 0; i < matvar->nbytes/matvar->data_size; i++ ) {
+		  
+		  v.push_back( ((signed long*)matvar->data)[i] );	      
+	      }
+	      
+	      break;	      
+
+            case MAT_T_UINT32:
+	      
+	      for ( int i = 0; i < matvar->nbytes/matvar->data_size; i++ ) {
+		  
+		  v.push_back( ((unsigned long*)matvar->data)[i] );	      
+	      }
+	      
+	      break;	      
+	      
+            case MAT_T_INT16:
+
+	      for ( int i = 0; i < matvar->nbytes/matvar->data_size; i++ ) {
+		  
+		  v.push_back( ((signed short*)matvar->data)[i] );	      
+	      }
+	      
+	      break;
+	      
+            case MAT_T_UINT16:
+	      
+	      for ( int i = 0; i < matvar->nbytes/matvar->data_size; i++ ) {
+		  
+		  v.push_back( ((unsigned short*)matvar->data)[i] );	      
+	      }
+	      
+	      break;	      
+	      
+            case MAT_T_INT8:
+	      
+	      for ( int i = 0; i < matvar->nbytes/matvar->data_size; i++ ) {
+		  
+		  v.push_back( ((signed char*)matvar->data)[i] );	      
+	      }
+	      
+	      break;	      
+
+            case MAT_T_UINT8:
+	      
+	      for ( int i = 0; i < matvar->nbytes/matvar->data_size; i++ ) {
+		  
+		  v.push_back( ((unsigned char*)matvar->data)[i] );	      
+	      }
+	      
+	      break;
+	  } 	  
+	  
+	// it can happen that a vector is treated as (N x 1) or (1 x N) matrix with two dimensions, here we handle this case
+	} else {
+	  
+          switch( matvar->data_type ) {
+	    
+            case MAT_T_DOUBLE:
+	  
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  v.push_back( ((double*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+	      }
+	      
+	      break;
+	      
+            case MAT_T_SINGLE:
+	  
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  v.push_back( ((float*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+	      }
+	      
+	      break;
+	      
+#ifdef HAVE_MAT_INT64_T
+            case MAT_T_INT64:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  v.push_back( ((signed long long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+	      }	            
+
+	      break;
+#endif
+#ifdef HAVE_MAT_UINT64_T	      
+            case MAT_T_UINT64:
+
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  v.push_back( ((unsigned long long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+	      }	
+
+	      break;
+#endif
+            case MAT_T_INT32:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  v.push_back( ((signed long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+	      }
+	      
+	      break;	      
+
+            case MAT_T_UINT32:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  v.push_back( ((unsigned long*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+	      }
+	      
+	      break;	      
+	      
+            case MAT_T_INT16:
+
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  v.push_back( ((signed short*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+	      }
+	      
+	      break;
+	      
+            case MAT_T_UINT16:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  v.push_back( ((unsigned short*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+	      }
+	      
+	      break;	      
+	      
+            case MAT_T_INT8:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  v.push_back( ((signed char*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+	      }
+	      
+	      break;	      
+
+            case MAT_T_UINT8:
+	      
+	      for ( int i = 0; i < matvar->dims[0]; i++ ) {
+		for ( int j = 0; j < matvar->dims[1]; j++ ) {
+		  
+		  v.push_back( ((unsigned char*)matvar->data)[matvar->dims[0]*j+i] );	      
+		}
+	      }
+	      
+	      break;
+	  } 	  
+	  
+	}
+	
+	vec = NICE::Vector(v);	
+      }
+}

+ 134 - 0
matlabAccess/MatFileIO.h

@@ -0,0 +1,134 @@
+/** 
+* @file MatFileIO.h
+* @brief Read and write mat-files
+* @author Paul Bodesheim
+* @date 06-01-2012 (dd-mm-yyyy)
+*/
+#ifndef MATFILEIOH_INCLUDE
+#define MATFILEIOH_INCLUDE
+
+#include <cstdlib>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "matio/src/matio.h"
+
+#include "vector"
+#include <core/basics/Exception.h>
+#include "core/vector/VectorT.h"
+
+
+namespace NICE {
+  
+  class MatFileIO {
+       
+    protected:
+      
+      mat_t *mat; // struct for the mat-file, defined in matio.h
+      
+    public:
+
+      //------------------------------------------------------
+      // several constructors and destructors
+      //------------------------------------------------------
+
+      /** 
+      * @brief Default constructor
+      * @author Paul Bodesheim
+      * @date 06-01-2012 (dd-mm-yyyy)
+      */
+      MatFileIO(); 
+      
+      /** 
+      * @brief Recommended constructor
+      * @author Paul Bodesheim
+      * @date 06-01-2012 (dd-mm-yyyy)
+      * @param _filename name of the mat-file, if mode = MAT_ACC_RDWR and _filename does not exist, a new file will be created
+      * @param mode file access mode: MAT_ACC_RDONLY (read only) or MAT_ACC_RDWR (read + write)
+      */
+      MatFileIO(std::string _filename, const mat_acc mode);  
+      
+      /** 
+      * @brief Default destructor
+      * @author Paul Bodesheim
+      * @date 06-01-2012 (dd-mm-yyyy)
+      */
+      ~MatFileIO();
+             
+      //------------------------------------------------------
+      // enumeration
+      //------------------------------------------------------           
+      
+      /** 
+      * @brief feature matrix order
+      * @author Paul Bodesheim
+      * @date 09-01-2012 (dd-mm-yyyy)
+      */
+      enum feature_matrix_order {
+	NxD = 1,  /**< @brief Read only file access                */
+	DxN   = 2   /**< @brief Read/Write file access               */
+      };
+            
+      //------------------------------------------------------
+      // count number of stored variables
+      //------------------------------------------------------     
+      
+      /** 
+      * @brief get the number of variables stored in the mat-file referenced by mat
+      * @author Paul Bodesheim
+      * @date 06-01-2012 (dd-mm-yyyy)
+      * @return number of variables
+      */
+      int getNumberOfVariables();
+      
+      //------------------------------------------------------
+      // several methods for reading data
+      //------------------------------------------------------     
+ 
+      /** 
+      * @brief get the variable with name _name stored in the mat-file referenced by mat
+      * @author Paul Bodesheim
+      * @date 06-01-2012 (dd-mm-yyyy)
+      * @param _name name of the variable
+      * @return variable with name _name in the matvar_t format
+      */  
+      matvar_t * getVariableViaName(std::string _name);
+      
+      
+      /**
+       * @brief get the sparsely stored variable with name _name stored in the mat-file referenced by mat
+       * @author Paul Bodesheim
+       * @date 10-01-2012 (dd-mm-yyyy)
+       * @param sparseVariable result: sparse variable with name _name in sparse matio-format sparse_t (see matio/src/matio.h)
+       * @param _name name of the variable
+       **/
+      void getSparseVariableViaName(sparse_t & sparseVariable, std::string _name);
+      
+      /** 
+      * @brief get the feature matrix with name _name stored in the mat-file referenced by mat
+      * @author Paul Bodesheim
+      * @date 09-01-2012 (dd-mm-yyyy)
+      * @param _name name of the variable
+      * @param order organization of the feature matrix: NxD (each feature in a row and each feature dimension in a coliumn)or DxN (vice versa)
+      * @param features result: feature matrix with name _name in the fast-HIK format: std::vector<std::vector<double> >
+      */  
+      void getFeatureMatrixViaName(std::vector<std::vector<double> > & features, std::string _name, const feature_matrix_order order = NxD);
+ 
+      /** 
+      * @brief get vector with name _name stored in the mat-file referenced by mat
+      * @author Paul Bodesheim
+      * @date 09-01-2012 (dd-mm-yyyy)
+      * @param _name name of the variable
+      * @param vec result: vector with name _name in format NICE::Vector 
+      */ 
+      void getVectorViaName(NICE::Vector & vec, std::string _name);
+      
+      
+  }; // class
+  
+} // namespace
+
+
+#endif

+ 1 - 0
matlabAccess/libdepend.inc

@@ -0,0 +1 @@
+$(call PKG_DEPEND_INT,core/)

+ 103 - 0
matlabAccess/matio/Makefile.inc

@@ -0,0 +1,103 @@
+# LIBRARY-DIRECTORY-MAKEFILE
+# conventions:
+# - all subdirectories containing a "Makefile.inc" are considered sublibraries
+#   exception: "progs/" and "tests/" subdirectories!
+# - all ".C", ".cpp" and ".c" files in the current directory are linked to a
+#   library
+# - the library depends on all sublibraries 
+# - the library name is created with $(LIBNAME), i.e. it will be somehow
+#   related to the directory name and with the extension .a
+#   (e.g. lib1/sublib -> lib1_sublib.a)
+# - the library will be added to the default build list ALL_LIBRARIES
+
+# --------------------------------
+# - remember the last subdirectory
+#
+# set the variable $(SUBDIR) correctly to the current subdirectory. this
+# variable can be used throughout the current makefile.inc. The many 
+# SUBDIR_before, _add, and everything are only required so that we can recover
+# the previous content of SUBDIR before exitting the makefile.inc
+
+SUBDIR_add:=$(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
+SUBDIR_before:=$(SUBDIR)
+SUBDIR:=$(strip $(SUBDIR_add))
+SUBDIR_before_$(SUBDIR):=$(SUBDIR_before)
+ifeq "$(SUBDIR)" "./"
+SUBDIR:=
+endif
+
+# ------------------------
+# - include subdirectories
+#
+# note the variables $(SUBDIRS_OF_$(SUBDIR)) are required later on to recover
+# the dependencies automatically. if you handle dependencies on your own, you
+# can also dump the $(SUBDIRS_OF_$(SUBDIR)) variable, and include the
+# makefile.inc of the subdirectories on your own...
+
+SUBDIRS_OF_$(SUBDIR):=$(patsubst %/Makefile.inc,%,$(wildcard $(SUBDIR)*/Makefile.inc))
+include $(SUBDIRS_OF_$(SUBDIR):%=%/Makefile.inc)
+
+# ----------------------------
+# - include local dependencies
+#
+# you can specify libraries needed by the individual objects or by the whole
+# directory. the object specific additional libraries are only considered
+# when compiling the specific object files
+# TODO: update documentation...
+
+-include $(SUBDIR)libdepend.inc
+
+$(foreach d,$(filter-out %progs %tests,$(SUBDIRS_OF_$(SUBDIR))),$(eval $(call PKG_DEPEND_INT,$(d))))
+
+# ---------------------------
+# - objects in this directory
+#
+# the use of the variable $(OBJS) is not mandatory. it is mandatory however
+# to update $(ALL_OBJS) in a way that it contains the path and name of
+# all objects. otherwise we can not include the appropriate .d files.
+
+OBJS:=$(patsubst %.cpp,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.cpp))) \
+      $(patsubst %.C,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.C))) \
+	  $(shell grep -ls Q_OBJECT $(SUBDIR)*.h | sed -e's@^@/@;s@.*/@$(OBJDIR)moc_@;s@\.h$$@.o@') \
+      $(patsubst %.c,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.c)))
+ALL_OBJS += $(OBJS)
+
+# ----------------------------
+# - binaries in this directory
+#
+# output of binaries in this directory. none of the variables has to be used.
+# but everything you add to $(ALL_LIBRARIES) and $(ALL_BINARIES) will be
+# compiled with `make all`. be sure again to add the files with full path.
+
+LIBRARY_BASENAME:=$(call LIBNAME,$(SUBDIR))
+ifneq "$(SUBDIR)" ""
+ALL_LIBRARIES+=$(LIBDIR)$(LIBRARY_BASENAME).$(LINK_FILE_EXTENSION)
+endif
+
+# ---------------------
+# - binary dependencies
+#
+# there is no way of determining the binary dependencies automatically, so we
+# follow conventions. the current library depends on all sublibraries.
+# all other dependencies have to be added manually by specifying, that the
+# current .pc file depends on some other .pc file. binaries depending on
+# libraries should exclusivelly use the .pc files as well.
+
+ifeq "$(SKIP_BUILD_$(OBJDIR))" "1"
+$(LIBDIR)$(LIBRARY_BASENAME).a:
+else
+$(LIBDIR)$(LIBRARY_BASENAME).a:$(OBJS) \
+	$(call PRINT_INTLIB_DEPS,$(PKGDIR)$(LIBRARY_BASENAME).a,.$(LINK_FILE_EXTENSION))
+endif
+
+$(PKGDIR)$(LIBRARY_BASENAME).pc: \
+	$(call PRINT_INTLIB_DEPS,$(PKGDIR)$(LIBRARY_BASENAME).pc,.pc)
+
+# -------------------
+# - subdir management
+#
+# as the last step, always add this line to correctly recover the subdirectory
+# of the makefile including this one!
+
+SUBDIR:=$(SUBDIR_before_$(SUBDIR))
+

+ 79 - 0
matlabAccess/matio/README

@@ -0,0 +1,79 @@
+LIBMATIO Matlab MAT file I/O library
+
+libmatio is an open-source library for reading/writing Matlab MAT files.  This
+library is designed for use by programs/libraries that do not have access or
+do not want to rely on Matlab's libmat shared library.
+
+Contact:
+    You can contact me (Christopher Hulbert) through email at cch@isl-inc.com
+
+Acknowledgements:
+    Thank you to Jacco van Beek for helping me get the software running under
+solaris and for providing test files to get byteswapping verified.
+
+Contributing:
+    Part of my reason for releasing this software is I have many other projects
+to work on and have many features I would still like to implement.  If you
+make changes, I would appreciate your contributions and more than likely will
+include them in future releases.  If you are interested in collaborations,
+contact me via email at cch@isl-inc.com.
+
+Building:
+    Four of the builds currently supported make use of the GNU autotools,
+and thus you should have them.  There is a build script in the top-level
+directory for the four builds including the following supported platforms:
+cygwin, mingw, linux, and solaris.  You can of course configure and build
+your own way.  A Visual C 7 Solution has been created in the build-vc7
+direcotry and a Visual C 6 workspace in the build-vc6 directory.
+These should be self containing, just open and build.  There are multiple
+configurations supported, but I recommend the LIB Release or the
+DLL Release.  The build-windows directory contains a batch file to build using
+nmake.  This makes it easier to set variables and install the software.
+Doxygen is required to build the documentation.  Since not all platforms
+support doxygen (mingw and Visual C come to mind) I have included the API
+documentation in the top-level directory as a pdf.
+
+ZLIB:
+    To support compressed MAT files, zlib 1.2.2 or greater is required.  If zlib
+1.2.2 is used, there is a bug in inflate.c.  A patch file (inflate.patch) is
+included in the patches directory and should be applied before creating the zlib
+library or libmatio will likely crash at some point.  The latest release of zlib
+already has this patch applied. A minimal zlib 1.2.3 has been included.  This
+does not have ALL build targets and does not include the contrib directory.
+This is simply because of size requirements on the File Exchange.
+    Due to some linking problems under linux/solaris, when shared libraries are
+compiled against the static zlib and a program (like Matlab) loads in zlib
+symbols, it uses those symbols instead of the static ones.  This should not
+affect stand-alone programs or static libraries (unless linked against from
+something like a mex file).  Therefore, when building libmatio, it is
+recommended to use the built-in zlib 1.2.3 or to compile the zlib with
+-DZ_PREFIX which only changes the symbol names to add z_ to external symbols.
+This eliminates the possibility of using zlib symbols from a shared library.  To
+build zlib with the z prefix, you can use:
+CFLAGS=-DZ_PREFIX ./configure;make;make install
+
+the build scripts provided already make the zlib that is included with this
+distribution and set the flags to use that as appropriate.
+
+Targets:
+    The library has been tested/used on linux and windows little-endian
+architectures, as well as solarix big-endian.  Again, thanks to Jacco for using
+a big-endian system and providing some test files for that as well as testing
+reading little-endian files on a big-endian system.
+
+Copyright Notice:
+    Copyright (C) 2005-2006   Christopher C. Hulbert
+
+     This library is free software; you can redistribute it and/or
+     modify it under the terms of the GNU Lesser General Public
+     License as published by the Free Software Foundation; either
+     version 2.1 of the License, or (at your option) any later version.
+
+     This library is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Lesser General Public License for more details.
+
+     You should have received a copy of the GNU Lesser General Public
+     License along with this library; if not, write to the Free Software
+     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

BIN
matlabAccess/matio/src/.libs/libmatio.a


+ 1 - 0
matlabAccess/matio/src/.libs/libmatio.la

@@ -0,0 +1 @@
+../libmatio.la

+ 41 - 0
matlabAccess/matio/src/.libs/libmatio.lai

@@ -0,0 +1,41 @@
+# libmatio.la - a libtool library file
+# Generated by ltmain.sh (GNU libtool) 2.2.6b Debian-2.2.6b-2
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname=''
+
+# Names of this library.
+library_names=''
+
+# The name of the static archive.
+old_library='libmatio.a'
+
+# Linker flags that can not go in dependency_libs.
+inherited_linker_flags=''
+
+# Libraries that this one depends upon.
+dependency_libs=' -lm'
+
+# Names of additional weak libraries provided by this library
+weak_library_names=''
+
+# Version information for libmatio.
+current=0
+age=0
+revision=0
+
+# Is this an already installed library?
+installed=yes
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=no
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir='/usr/local/lib'

+ 103 - 0
matlabAccess/matio/src/Makefile.inc

@@ -0,0 +1,103 @@
+# LIBRARY-DIRECTORY-MAKEFILE
+# conventions:
+# - all subdirectories containing a "Makefile.inc" are considered sublibraries
+#   exception: "progs/" and "tests/" subdirectories!
+# - all ".C", ".cpp" and ".c" files in the current directory are linked to a
+#   library
+# - the library depends on all sublibraries 
+# - the library name is created with $(LIBNAME), i.e. it will be somehow
+#   related to the directory name and with the extension .a
+#   (e.g. lib1/sublib -> lib1_sublib.a)
+# - the library will be added to the default build list ALL_LIBRARIES
+
+# --------------------------------
+# - remember the last subdirectory
+#
+# set the variable $(SUBDIR) correctly to the current subdirectory. this
+# variable can be used throughout the current makefile.inc. The many 
+# SUBDIR_before, _add, and everything are only required so that we can recover
+# the previous content of SUBDIR before exitting the makefile.inc
+
+SUBDIR_add:=$(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
+SUBDIR_before:=$(SUBDIR)
+SUBDIR:=$(strip $(SUBDIR_add))
+SUBDIR_before_$(SUBDIR):=$(SUBDIR_before)
+ifeq "$(SUBDIR)" "./"
+SUBDIR:=
+endif
+
+# ------------------------
+# - include subdirectories
+#
+# note the variables $(SUBDIRS_OF_$(SUBDIR)) are required later on to recover
+# the dependencies automatically. if you handle dependencies on your own, you
+# can also dump the $(SUBDIRS_OF_$(SUBDIR)) variable, and include the
+# makefile.inc of the subdirectories on your own...
+
+SUBDIRS_OF_$(SUBDIR):=$(patsubst %/Makefile.inc,%,$(wildcard $(SUBDIR)*/Makefile.inc))
+include $(SUBDIRS_OF_$(SUBDIR):%=%/Makefile.inc)
+
+# ----------------------------
+# - include local dependencies
+#
+# you can specify libraries needed by the individual objects or by the whole
+# directory. the object specific additional libraries are only considered
+# when compiling the specific object files
+# TODO: update documentation...
+
+-include $(SUBDIR)libdepend.inc
+
+$(foreach d,$(filter-out %progs %tests,$(SUBDIRS_OF_$(SUBDIR))),$(eval $(call PKG_DEPEND_INT,$(d))))
+
+# ---------------------------
+# - objects in this directory
+#
+# the use of the variable $(OBJS) is not mandatory. it is mandatory however
+# to update $(ALL_OBJS) in a way that it contains the path and name of
+# all objects. otherwise we can not include the appropriate .d files.
+
+OBJS:=$(patsubst %.cpp,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.cpp))) \
+      $(patsubst %.C,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.C))) \
+	  $(shell grep -ls Q_OBJECT $(SUBDIR)*.h | sed -e's@^@/@;s@.*/@$(OBJDIR)moc_@;s@\.h$$@.o@') \
+      $(patsubst %.c,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.c)))
+ALL_OBJS += $(OBJS)
+
+# ----------------------------
+# - binaries in this directory
+#
+# output of binaries in this directory. none of the variables has to be used.
+# but everything you add to $(ALL_LIBRARIES) and $(ALL_BINARIES) will be
+# compiled with `make all`. be sure again to add the files with full path.
+
+LIBRARY_BASENAME:=$(call LIBNAME,$(SUBDIR))
+ifneq "$(SUBDIR)" ""
+ALL_LIBRARIES+=$(LIBDIR)$(LIBRARY_BASENAME).$(LINK_FILE_EXTENSION)
+endif
+
+# ---------------------
+# - binary dependencies
+#
+# there is no way of determining the binary dependencies automatically, so we
+# follow conventions. the current library depends on all sublibraries.
+# all other dependencies have to be added manually by specifying, that the
+# current .pc file depends on some other .pc file. binaries depending on
+# libraries should exclusivelly use the .pc files as well.
+
+ifeq "$(SKIP_BUILD_$(OBJDIR))" "1"
+$(LIBDIR)$(LIBRARY_BASENAME).a:
+else
+$(LIBDIR)$(LIBRARY_BASENAME).a:$(OBJS) \
+	$(call PRINT_INTLIB_DEPS,$(PKGDIR)$(LIBRARY_BASENAME).a,.$(LINK_FILE_EXTENSION))
+endif
+
+$(PKGDIR)$(LIBRARY_BASENAME).pc: \
+	$(call PRINT_INTLIB_DEPS,$(PKGDIR)$(LIBRARY_BASENAME).pc,.pc)
+
+# -------------------
+# - subdir management
+#
+# as the last step, always add this line to correctly recover the subdirectory
+# of the makefile including this one!
+
+SUBDIR:=$(SUBDIR_before_$(SUBDIR))
+

+ 248 - 0
matlabAccess/matio/src/endian.c

@@ -0,0 +1,248 @@
+/** @file endian.c
+ * @brief Functions to handle endian specifics
+ */
+/*
+ * Copyright (C) 2005-2006   Christopher C. Hulbert
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <stdlib.h>
+#include "matio.h"
+#include "matio_private.h"
+
+/** @brief swap the bytes @c a and @c b
+ * @ingroup mat_internal
+ */
+#define swap(a,b)   a^=b;b^=a;a^=b
+
+#ifdef HAVE_MAT_INT64_T
+/** @brief swap the bytes of a 64-bit signed integer
+ * @ingroup mat_internal
+ * @param a pointer to integer to swap
+ * @return the swapped integer
+ */
+mat_int64_t
+Mat_int64Swap( mat_int64_t *a )
+{
+
+    union {
+        mat_int8_t    i1[8]; 
+        mat_int64_t   i8;
+    } tmp;
+
+    tmp.i8 = *a;
+
+    swap( tmp.i1[0], tmp.i1[7] );
+    swap( tmp.i1[1], tmp.i1[6] );
+    swap( tmp.i1[2], tmp.i1[5] );
+    swap( tmp.i1[3], tmp.i1[4] );
+
+    *a = tmp.i8;
+
+    return *a;
+
+}
+#endif /* HAVE_MAT_INT64_T */
+
+#ifdef HAVE_MAT_UINT64_T
+/** @brief swap the bytes of a 64-bit unsigned integer
+ * @ingroup mat_internal
+ * @param a pointer to integer to swap
+ * @return the swapped integer
+ */
+mat_uint64_t
+Mat_uint64Swap( mat_uint64_t *a )
+{
+
+    union {
+        mat_uint8_t    i1[8]; 
+        mat_uint64_t   i8;
+    } tmp;
+
+    tmp.i8 = *a;
+
+    swap( tmp.i1[0], tmp.i1[7] );
+    swap( tmp.i1[1], tmp.i1[6] );
+    swap( tmp.i1[2], tmp.i1[5] );
+    swap( tmp.i1[3], tmp.i1[4] );
+
+    *a = tmp.i8;
+
+    return *a;
+
+}
+#endif /* HAVE_MAT_UINT64_T */
+
+/** @brief swap the bytes of a 32-bit signed integer
+ * @ingroup mat_internal
+ * @param a pointer to integer to swap
+ * @return the swapped integer
+ */
+mat_int32_t
+Mat_int32Swap( mat_int32_t *a )
+{
+
+    union {
+        mat_int8_t    i1[4]; 
+        mat_int32_t   i4;
+    } tmp;
+
+    tmp.i4 = *a;
+
+    swap( tmp.i1[0], tmp.i1[3] );
+    swap( tmp.i1[1], tmp.i1[2] );
+
+    *a = tmp.i4;
+
+    return *a;
+
+}
+
+/** @brief swap the bytes of a 32-bit unsigned integer
+ * @ingroup mat_internal
+ * @param a pointer to integer to swap
+ * @return the swapped integer
+ */
+mat_uint32_t
+Mat_uint32Swap( mat_uint32_t *a )
+{
+
+    union {
+        mat_uint8_t    i1[4]; 
+        mat_uint32_t   i4;
+    } tmp;
+
+    tmp.i4 = *a;
+
+    swap( tmp.i1[0], tmp.i1[3] );
+    swap( tmp.i1[1], tmp.i1[2] );
+
+    *a = tmp.i4;
+
+    return *a;
+
+}
+
+/** @brief swap the bytes of a 16-bit signed integer
+ * @ingroup mat_internal
+ * @param a pointer to integer to swap
+ * @return the swapped integer
+ */
+mat_int16_t
+Mat_int16Swap( mat_int16_t *a ) 
+{
+
+    union {
+        mat_int8_t   i1[2];
+        mat_int16_t  i2;
+    } tmp;
+
+    tmp.i2 = *a;
+
+    swap( tmp.i1[0], tmp.i1[1] );
+
+    *a = tmp.i2;
+    return *a;
+
+}
+
+/** @brief swap the bytes of a 16-bit unsigned integer
+ * @ingroup mat_internal
+ * @param a pointer to integer to swap
+ * @return the swapped integer
+ */
+mat_uint16_t
+Mat_uint16Swap( mat_uint16_t *a ) 
+{
+
+    union {
+        mat_uint8_t   i1[2];
+        mat_uint16_t  i2;
+    } tmp;
+
+    tmp.i2 = *a;
+
+    swap( tmp.i1[0], tmp.i1[1] );
+
+    *a = tmp.i2;
+    return *a;
+
+}
+
+/** @brief swap the bytes of a 4 byte single-precision float
+ * @ingroup mat_internal
+ * @param a pointer to integer to swap
+ * @return the swapped integer
+ */
+float
+Mat_floatSwap( float *a )
+{
+
+    union {
+        char  i1[4];
+        float r4;
+    } tmp;
+
+    tmp.r4 = *a;
+
+    swap( tmp.i1[0], tmp.i1[3] );
+    swap( tmp.i1[1], tmp.i1[2] );
+
+    *a = tmp.r4;
+    return *a;
+
+}
+
+/** @brief swap the bytes of a 4 or 8 byte double-precision float
+ * @ingroup mat_internal
+ * @param a pointer to integer to swap
+ * @return the swapped integer
+ */
+double
+Mat_doubleSwap( double *a )
+{
+#ifndef SIZEOF_DOUBLE
+#define SIZEOF_DOUBLE 8
+#endif
+
+    union {
+        char   a[SIZEOF_DOUBLE];
+        double b;
+    } tmp;
+
+    tmp.b = *a;
+
+#if SIZEOF_DOUBLE == 4
+    swap( tmp.a[0], tmp.a[3] );
+    swap( tmp.a[1], tmp.a[2] );
+#elif SIZEOF_DOUBLE == 8
+    swap( tmp.a[0], tmp.a[7] );
+    swap( tmp.a[1], tmp.a[6] );
+    swap( tmp.a[2], tmp.a[5] );
+    swap( tmp.a[3], tmp.a[4] );
+#elif SIZEOF_DOUBLE == 16
+    swap( tmp.a[0], tmp.a[15] );
+    swap( tmp.a[1], tmp.a[14] );
+    swap( tmp.a[2], tmp.a[13] );
+    swap( tmp.a[3], tmp.a[12] );
+    swap( tmp.a[4], tmp.a[11] );
+    swap( tmp.a[5], tmp.a[10] );
+    swap( tmp.a[6], tmp.a[9] );
+    swap( tmp.a[7], tmp.a[8] );
+#endif
+    *a = tmp.b;
+    return *a;
+
+}

+ 840 - 0
matlabAccess/matio/src/inflate.c

@@ -0,0 +1,840 @@
+/** @file inflate.c
+ * @brief Functions to inflate data/tags
+ * @ingroup MAT
+ */
+/*
+ * Copyright (C) 2005-2006   Christopher C. Hulbert
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <stdlib.h>
+#include "matio.h"
+#include "matio_private.h"
+
+/** @brief Inflate the data until @c nbytes of uncompressed data has been
+ *         inflated
+ *
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param z zlib compression stream
+ * @param nbytes Number of uncompressed bytes to skip
+ * @return Number of bytes read from the file
+ */
+int 
+InflateSkip(mat_t *mat, z_stream *z, int nbytes)
+{
+    mat_uint8_t comp_buf[512],uncomp_buf[512];
+    int     bytesread = 0, n,err, cnt = 0;
+
+    if ( nbytes < 1 )
+        return 0;
+
+    n = (nbytes<512) ? nbytes : 512;
+    if ( !z->avail_in ) {
+        z->next_in = comp_buf;
+        z->avail_in += fread(comp_buf,1,n,mat->fp);
+        bytesread   += z->avail_in;
+    }
+    z->avail_out = n;
+    z->next_out  = uncomp_buf;
+    err = inflate(z,Z_FULL_FLUSH);
+    if ( err == Z_STREAM_END ) {
+        return bytesread;
+    } else if ( err != Z_OK ) {
+        Mat_Critical("InflateSkip: inflate returned %d",err);
+        return bytesread;
+    }
+    if ( !z->avail_out ) {
+        cnt += n;
+        n = ((nbytes-cnt)<512) ? nbytes-cnt : 512;
+        z->avail_out = n;
+        z->next_out  = uncomp_buf;
+    }
+    while ( cnt < nbytes ) {
+        if ( !z->avail_in ) {
+            z->next_in   = comp_buf;
+            z->avail_in += fread(comp_buf,1,n,mat->fp);
+            bytesread   += z->avail_in;
+        }
+        err = inflate(z,Z_FULL_FLUSH);
+        if ( err == Z_STREAM_END ) {
+            break;
+        } else if ( err != Z_OK ) {
+            Mat_Critical("InflateSkip: inflate returned %d",err);
+            break;
+        }
+        if ( !z->avail_out ) {
+            cnt         += n;
+            n            = ((nbytes-cnt)<512) ? nbytes-cnt : 512;
+            z->avail_out = n;
+            z->next_out  = uncomp_buf;
+        }
+    }
+
+    if ( z->avail_in ) {
+        long offset = -(long)z->avail_in;
+        fseek(mat->fp,offset,SEEK_CUR);
+        bytesread -= z->avail_in;
+        z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Inflate the data until @c nbytes of compressed data has been
+ *         inflated
+ *
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param z zlib compression stream
+ * @param nbytes Number of uncompressed bytes to skip
+ * @return Number of bytes read from the file
+ */
+int
+InflateSkip2(mat_t *mat, matvar_t *matvar, int nbytes)
+{
+    mat_uint8_t comp_buf[32],uncomp_buf[32];
+    int     bytesread = 0, err, cnt = 0;
+
+    if ( !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    matvar->z->avail_out = 1;
+    matvar->z->next_out = uncomp_buf;
+    err = inflate(matvar->z,Z_NO_FLUSH);
+    if ( err != Z_OK ) {
+        Mat_Critical("InflateSkip2: %s - inflate returned %d",matvar->name,err);
+        return bytesread;
+    }
+    if ( !matvar->z->avail_out ) {
+        matvar->z->avail_out = 1;
+        matvar->z->next_out = uncomp_buf;
+    }
+    while ( cnt < nbytes ) {
+        if ( !matvar->z->avail_in ) {
+            matvar->z->avail_in = 1;
+            matvar->z->next_in = comp_buf;
+            bytesread += fread(comp_buf,1,1,mat->fp);
+            cnt++;
+        }
+        err = inflate(matvar->z,Z_NO_FLUSH);
+        if ( err != Z_OK ) {
+            Mat_Critical("InflateSkip2: %s - inflate returned %d",matvar->name,err);
+            return bytesread;
+        }
+        if ( !matvar->z->avail_out ) {
+            matvar->z->avail_out = 1;
+            matvar->z->next_out = uncomp_buf;
+        }
+    }
+
+    if ( matvar->z->avail_in ) {
+        fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+        bytesread -= matvar->z->avail_in;
+        matvar->z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Inflate the data until @c len elements of compressed data with data
+ *         type @c data_type has been inflated
+ *
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param z zlib compression stream
+ * @param data_type Data type (matio_types enumerations)
+ * @param len Number of elements of datatype @c data_type to skip
+ * @return Number of bytes read from the file
+ */
+int
+InflateSkipData(mat_t *mat,z_stream *z,int data_type,int len)
+{
+    int data_size = 0;
+
+    if ( (mat == NULL) || (z == NULL) )
+        return 0;
+    else if ( len < 1 )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+            data_size = sizeof(double);
+            break;
+        case MAT_T_SINGLE:
+            data_size = sizeof(float);
+            break;
+#ifdef HAVE_MAT_INT64_T
+        case MAT_T_INT64:
+            data_size = sizeof(mat_int64_t);
+            break;
+#endif /* HAVE_MAT_INT64_T */
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_T_UINT64:
+            data_size = sizeof(mat_uint64_t);
+            break;
+#endif /* HAVE_MAT_UINT64_T */
+        case MAT_T_INT32:
+            data_size = sizeof(mat_int32_t);
+            break;
+        case MAT_T_UINT32:
+            data_size = sizeof(mat_uint32_t);
+            break;
+        case MAT_T_INT16:
+            data_size = sizeof(mat_int16_t);
+            break;
+        case MAT_T_UINT16:
+            data_size = sizeof(mat_uint16_t);
+            break;
+        case MAT_T_UINT8:
+            data_size = sizeof(mat_uint8_t);
+            break;
+        case MAT_T_INT8:
+            data_size = sizeof(mat_int8_t);
+            break;
+    }
+    InflateSkip(mat,z,len*data_size);
+    return len;
+}
+
+/** @brief Inflates the variable's tag.
+ *
+ * @c buf must hold at least 8 bytes
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param matvar Pointer to the MAT variable
+ * @param buf Pointer to store the 8-byte variable tag 
+ * @return Number of bytes read from the file
+ */
+int
+InflateVarTag(mat_t *mat, matvar_t *matvar, void *buf)
+{
+    mat_uint8_t comp_buf[32];
+    int     bytesread = 0, err;
+
+    if (buf == NULL)
+        return 0;
+
+    if ( !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    matvar->z->avail_out = 8;
+    matvar->z->next_out = buf;
+    err = inflate(matvar->z,Z_NO_FLUSH);
+    if ( err != Z_OK ) {
+        Mat_Critical("InflateVarTag: inflate returned %d",err);
+        return bytesread;
+    }
+    while ( matvar->z->avail_out && !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+        err = inflate(matvar->z,Z_NO_FLUSH);
+        if ( err != Z_OK ) {
+            Mat_Critical("InflateVarTag: inflate returned %d",err);
+            return bytesread;
+        }
+    }
+
+    if ( matvar->z->avail_in ) {
+        fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+        bytesread -= matvar->z->avail_in;
+        matvar->z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Inflates the Array Flags Tag and the Array Flags data.
+ *
+ * @c buf must hold at least 16 bytes
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param matvar Pointer to the MAT variable
+ * @param buf Pointer to store the 16-byte array flags tag and data 
+ * @return Number of bytes read from the file
+ */
+int
+InflateArrayFlags(mat_t *mat, matvar_t *matvar, void *buf)
+{
+    mat_uint8_t comp_buf[32];
+    int     bytesread = 0, err;
+
+    if (buf == NULL) return 0;
+
+    if ( !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    matvar->z->avail_out = 16;
+    matvar->z->next_out = buf;
+    err = inflate(matvar->z,Z_NO_FLUSH);
+    if ( err != Z_OK ) {
+        Mat_Critical("InflateArrayFlags: inflate returned %d",err);
+        return bytesread;
+    }
+    while ( matvar->z->avail_out && !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+        err = inflate(matvar->z,Z_NO_FLUSH);
+        if ( err != Z_OK ) {
+            Mat_Critical("InflateArrayFlags: inflate returned %d",err);
+            return bytesread;
+        }
+    }
+
+    if ( matvar->z->avail_in ) {
+        fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+        bytesread -= matvar->z->avail_in;
+        matvar->z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Inflates the dimensions tag and the dimensions data
+ *
+ * @c buf must hold at least (8+4*rank) bytes where rank is the number of
+ * dimensions. If the end of the dimensions data is not aligned on an 8-byte
+ * boundary, this function eats up those bytes and stores then in @c buf.
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param matvar Pointer to the MAT variable
+ * @param buf Pointer to store the dimensions flag and data 
+ * @return Number of bytes read from the file
+ */
+int
+InflateDimensions(mat_t *mat, matvar_t *matvar, void *buf)
+{
+    mat_uint8_t comp_buf[32];
+    mat_int32_t tag[2];
+    int     bytesread = 0, err, rank, i;
+
+    if ( buf == NULL )
+        return 0;
+
+    if ( !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    matvar->z->avail_out = 8;
+    matvar->z->next_out = buf;
+    err = inflate(matvar->z,Z_NO_FLUSH);
+    if ( err != Z_OK ) {
+        Mat_Critical("InflateDimensions: inflate returned %d",err);
+        return bytesread;
+    }
+    while ( matvar->z->avail_out && !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+        err = inflate(matvar->z,Z_NO_FLUSH);
+        if ( err != Z_OK ) {
+            Mat_Critical("InflateDimensions: inflate returned %d",err);
+            return bytesread;
+        }
+    }
+    tag[0] = *(int *)buf;
+    tag[1] = *((int *)buf+1);
+    if ( mat->byteswap ) {
+        Mat_int32Swap(tag);
+        Mat_int32Swap(tag+1);
+    }
+    if ( (tag[0] & 0x0000ffff) != MAT_T_INT32 ) {
+        Mat_Critical("InflateDimensions: Reading dimensions expected type MAT_T_INT32");
+        return bytesread;
+    }
+    rank = tag[1];
+    if ( rank % 8 != 0 )
+        i = 8-(rank %8);
+    else
+        i = 0;
+    rank+=i;
+
+    if ( !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    matvar->z->avail_out = rank;
+    matvar->z->next_out = (void *)((mat_int32_t *)buf+2);
+    err = inflate(matvar->z,Z_NO_FLUSH);
+    if ( err != Z_OK ) {
+        Mat_Critical("InflateDimensions: inflate returned %d",err);
+        return bytesread;
+    }
+    while ( matvar->z->avail_out && !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+        err = inflate(matvar->z,Z_NO_FLUSH);
+        if ( err != Z_OK ) {
+            Mat_Critical("InflateDimensions: inflate returned %d",err);
+            return bytesread;
+        }
+    }
+
+    if ( matvar->z->avail_in ) {
+        fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+        bytesread -= matvar->z->avail_in;
+        matvar->z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Inflates the variable name tag
+ *
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param matvar Pointer to the MAT variable
+ * @param buf Pointer to store the variables name tag 
+ * @return Number of bytes read from the file
+ */
+int
+InflateVarNameTag(mat_t *mat, matvar_t *matvar, void *buf)
+{
+    mat_uint8_t comp_buf[32];
+    int     bytesread = 0, err;
+
+    if ( buf == NULL )
+        return 0;
+
+    if ( !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    matvar->z->avail_out = 8;
+    matvar->z->next_out = buf;
+    err = inflate(matvar->z,Z_NO_FLUSH);
+    if ( err != Z_OK ) {
+        Mat_Critical("InflateVarNameTag: inflate returned %d",err);
+        return bytesread;
+    }
+    while ( matvar->z->avail_out && !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+        err = inflate(matvar->z,Z_NO_FLUSH);
+        if ( err != Z_OK ) {
+            Mat_Critical("InflateVarNameTag: inflate returned %d",err);
+            return bytesread;
+        }
+    }
+
+    if ( matvar->z->avail_in ) {
+        fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+        bytesread -= matvar->z->avail_in;
+        matvar->z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Inflates the variable name
+ *
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param matvar Pointer to the MAT variable
+ * @param buf Pointer to store the variables name 
+ * @param N Number of characters in the name
+ * @return Number of bytes read from the file
+ */
+int
+InflateVarName(mat_t *mat, matvar_t *matvar, void *buf, int N)
+{
+    mat_uint8_t comp_buf[32];
+    int     bytesread = 0, err;
+
+    if ( buf == NULL )
+        return 0;
+
+    if ( !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    matvar->z->avail_out = N;
+    matvar->z->next_out = buf;
+    err = inflate(matvar->z,Z_NO_FLUSH);
+    if ( err != Z_OK ) {
+        Mat_Critical("InflateVarName: inflate returned %d",err);
+        return bytesread;
+    }
+    while ( matvar->z->avail_out && !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+        err = inflate(matvar->z,Z_NO_FLUSH);
+        if ( err != Z_OK ) {
+            Mat_Critical("InflateVarName: inflate returned %d",err);
+            return bytesread;
+        }
+    }
+
+    if ( matvar->z->avail_in ) {
+        fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+        bytesread -= matvar->z->avail_in;
+        matvar->z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Inflates the data's tag
+ *
+ * buf must hold at least 8 bytes
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param matvar Pointer to the MAT variable
+ * @param buf Pointer to store the data tag 
+ * @return Number of bytes read from the file
+ */
+int
+InflateDataTag(mat_t *mat, matvar_t *matvar, void *buf)
+{
+    mat_uint8_t comp_buf[32];
+    int     bytesread = 0, err;
+
+    if ( buf == NULL )
+        return 0;
+
+   if ( !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    matvar->z->avail_out = 8;
+    matvar->z->next_out = buf;
+    err = inflate(matvar->z,Z_NO_FLUSH);
+    if ( err == Z_STREAM_END ) {
+        return bytesread;
+    } else if ( err != Z_OK ) {
+        Mat_Critical("InflateDataTag: %s - inflate returned %d",matvar->name,err);
+        return bytesread;
+    }
+    while ( matvar->z->avail_out && !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+        err = inflate(matvar->z,Z_NO_FLUSH);
+        if ( err == Z_STREAM_END ) {
+            break;
+        } else if ( err != Z_OK ) {
+            Mat_Critical("InflateDataTag: %s - inflate returned %d",matvar->name,err);
+            return bytesread;
+        }
+    }
+
+    if ( matvar->z->avail_in ) {
+        fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+        bytesread -= matvar->z->avail_in;
+        matvar->z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Inflates the data's type
+ *
+ * buf must hold at least 4 bytes
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param matvar Pointer to the MAT variable
+ * @param buf Pointer to store the data type 
+ * @return Number of bytes read from the file
+ */
+int
+InflateDataType(mat_t *mat, z_stream *z, void *buf)
+{
+    mat_uint8_t comp_buf[32];
+    int     bytesread = 0, err;
+
+    if ( buf == NULL )
+        return 0;
+
+    if ( !z->avail_in ) {
+        z->avail_in = 1;
+        z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    z->avail_out = 4;
+    z->next_out = buf;
+    err = inflate(z,Z_NO_FLUSH);
+    if ( err != Z_OK ) {
+        Mat_Critical("InflateDataType: inflate returned %d",err);
+        return bytesread;
+    }
+    while ( z->avail_out && !z->avail_in ) {
+        z->avail_in = 1;
+        z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+        err = inflate(z,Z_NO_FLUSH);
+        if ( err != Z_OK ) {
+            Mat_Critical("InflateDataType: inflate returned %d",err);
+            return bytesread;
+        }
+    }
+
+    if ( z->avail_in ) {
+        fseek(mat->fp,-(int)z->avail_in,SEEK_CUR);
+        bytesread -= z->avail_in;
+        z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Inflates the data
+ *
+ * buf must hold at least @c nBytes bytes
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param z zlib compression stream
+ * @param buf Pointer to store the data type 
+ * @param nBytes Number of bytes to inflate
+ * @return Number of bytes read from the file
+ */
+int
+InflateData(mat_t *mat, z_stream *z, void *buf, int nBytes)
+{
+    mat_uint8_t comp_buf[1024];
+    int     bytesread = 0, err;
+
+    if ( buf == NULL )
+        return 0;
+    if ( nBytes < 1 ) {
+        Mat_Critical("InflateData: nBytes must be > 0");
+        return bytesread;
+    }
+
+    if ( !z->avail_in ) {
+        if ( nBytes > 1024 ) {
+            z->avail_in = fread(comp_buf,1,1024,mat->fp);
+            bytesread += z->avail_in;
+            z->next_in = comp_buf;
+        } else {
+            z->avail_in = fread(comp_buf,1,nBytes,mat->fp);
+            bytesread  += z->avail_in;
+            z->next_in  = comp_buf;
+        }
+    }
+    z->avail_out = nBytes;
+    z->next_out = buf;
+    err = inflate(z,Z_FULL_FLUSH);
+    if ( err == Z_STREAM_END ) {
+        return bytesread;
+    } else if ( err != Z_OK ) {
+        Mat_Critical("InflateData: inflate returned %d",err);
+        return bytesread;
+    }
+    while ( z->avail_out && !z->avail_in ) {
+        if ( (nBytes-bytesread) > 1024 ) {
+            z->avail_in = fread(comp_buf,1,1024,mat->fp);
+            bytesread += z->avail_in;
+            z->next_in = comp_buf;
+        } else if ( (nBytes-bytesread) < 1 ) { /* Read a byte at a time */
+            z->avail_in = fread(comp_buf,1,1,mat->fp);
+            bytesread  += z->avail_in;
+            z->next_in  = comp_buf;
+        } else {
+            z->avail_in = fread(comp_buf,1,nBytes,mat->fp);
+            bytesread  += z->avail_in;
+            z->next_in  = comp_buf;
+        }
+        err = inflate(z,Z_FULL_FLUSH);
+        if ( err == Z_STREAM_END ) {
+            break;
+        } else if ( err != Z_OK && err != Z_BUF_ERROR ) {
+            Mat_Critical("InflateData: inflate returned %d",err);
+            break;
+        }
+    }
+
+    if ( z->avail_in ) {
+        long offset = -(long)z->avail_in;
+        fseek(mat->fp,offset,SEEK_CUR);
+        bytesread -= z->avail_in;
+        z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Inflates the structure's fieldname length
+ *
+ * buf must hold at least 8 bytes
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param matvar Pointer to the MAT variable
+ * @param buf Pointer to store the fieldname length 
+ * @return Number of bytes read from the file
+ */
+int
+InflateFieldNameLength(mat_t *mat, matvar_t *matvar, void *buf)
+{
+    mat_uint8_t comp_buf[32];
+    int     bytesread = 0, err;
+
+    if ( buf == NULL )
+        return 0;
+
+    if ( !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    matvar->z->avail_out = 8;
+    matvar->z->next_out = buf;
+    err = inflate(matvar->z,Z_NO_FLUSH);
+    if ( err != Z_OK ) {
+        Mat_Critical("InflateFieldNameLength: inflate returned %d",err);
+        return bytesread;
+    }
+    while ( matvar->z->avail_out && !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+        err = inflate(matvar->z,Z_NO_FLUSH);
+        if ( err != Z_OK ) {
+            Mat_Critical("InflateFieldNameLength: inflate returned %d",err);
+            return bytesread;
+        }
+    }
+
+    if ( matvar->z->avail_in ) {
+        fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+        bytesread -= matvar->z->avail_in;
+        matvar->z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Inflates the structure's fieldname tag
+ *
+ * buf must hold at least 8 bytes
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param matvar Pointer to the MAT variable
+ * @param buf Pointer to store the fieldname tag 
+ * @return Number of bytes read from the file
+ */
+int
+InflateFieldNamesTag(mat_t *mat, matvar_t *matvar, void *buf)
+{
+    mat_uint8_t comp_buf[32];
+    int     bytesread = 0, err;
+
+    if ( buf == NULL )
+        return 0;
+
+    if ( !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    matvar->z->avail_out = 8;
+    matvar->z->next_out = buf;
+    err = inflate(matvar->z,Z_NO_FLUSH);
+    if ( err != Z_OK ) {
+        Mat_Critical("InflateFieldNamesTag: inflate returned %d",err);
+        return bytesread;
+    }
+    while ( matvar->z->avail_out && !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+        err = inflate(matvar->z,Z_NO_FLUSH);
+        if ( err != Z_OK ) {
+            Mat_Critical("InflateFieldNamesTag: inflate returned %d",err);
+            return bytesread;
+        }
+    }
+
+    if ( matvar->z->avail_in ) {
+        fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+        bytesread -= matvar->z->avail_in;
+        matvar->z->avail_in = 0;
+    }
+
+    return bytesread;
+}
+
+/*
+ * Inflates the structure's fieldname length.  buf must hold at least
+ * nfields*fieldname_length bytes
+ */
+/** @brief Inflates the structure's fieldnames
+ *
+ * buf must hold at least @c nfields * @c fieldname_length bytes
+ * @ingroup mat_internal
+ * @param mat Pointer to the MAT file
+ * @param matvar Pointer to the MAT variable
+ * @param buf Pointer to store the fieldnames 
+ * @param nfields Number of fields
+ * @param fieldname_length Maximum length in bytes of each field
+ * @param padding Number of padding bytes
+ * @return Number of bytes read from the file
+ */
+int
+InflateFieldNames(mat_t *mat,matvar_t *matvar,void *buf,int nfields,
+                  int fieldname_length,int padding)
+{
+    mat_uint8_t comp_buf[32];
+    int     bytesread = 0, err;
+
+    if ( buf == NULL )
+        return 0;
+
+    if ( !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+    }
+    matvar->z->avail_out = nfields*fieldname_length+padding;
+    matvar->z->next_out = buf;
+    err = inflate(matvar->z,Z_NO_FLUSH);
+    if ( err != Z_OK ) {
+        Mat_Critical("InflateFieldNames: inflate returned %d",err);
+        return bytesread;
+    }
+    while ( matvar->z->avail_out && !matvar->z->avail_in ) {
+        matvar->z->avail_in = 1;
+        matvar->z->next_in = comp_buf;
+        bytesread += fread(comp_buf,1,1,mat->fp);
+        err = inflate(matvar->z,Z_NO_FLUSH);
+        if ( err != Z_OK ) {
+            Mat_Critical("InflateFieldNames: inflate returned %d",err);
+            return bytesread;
+        }
+    }
+
+    if ( matvar->z->avail_in ) {
+        fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+        bytesread -= matvar->z->avail_in;
+        matvar->z->avail_in = 0;
+    }
+
+    return bytesread;
+}

+ 423 - 0
matlabAccess/matio/src/io.c

@@ -0,0 +1,423 @@
+/** @file io.c
+ * MAT I/O Functions
+ * @ingroup MAT
+ */
+/*
+ * Copyright (C) 2005-2006   Christopher C. Hulbert
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include "matio.h"
+
+#if !defined(HAVE_VA_COPY) && defined(HAVE___VA_COPY)
+#    define va_copy(d,s) __va_copy(d,s)
+#elif !defined(HAVE_VA_COPY)
+#    define va_copy(d,s) memcpy(&(d),&(s),sizeof(va_list))
+#endif
+#ifndef HAVE_VSNPRINTF
+#    define vsnprintf mat_vsnprintf
+#    ifdef  __cplusplus
+         extern "C" int vsnprintf(char *,size_t,const char *,va_list);
+#    else
+         extern int vsnprintf(char *,size_t,const char *,va_list);
+#    endif
+#endif
+#ifndef HAVE_SNPRINTF
+#    define snprintf mat_snprintf
+#    ifdef  __cplusplus
+         extern "C" int snprintf(char *str,size_t size,const char *format,...);
+#    else
+         extern int snprintf(char *str,size_t size,const char *format,...);
+#    endif
+#endif
+#ifndef HAVE_VASPRINTF
+#    define vasprintf mat_vasprintf
+#endif
+#ifndef HAVE_ASPRINTF
+#    define asprintf mat_asprintf
+#endif
+
+/** @cond 0 */
+#define LOG_LEVEL_ERROR    1
+#define LOG_LEVEL_CRITICAL 1 << 1
+#define LOG_LEVEL_WARNING  1 << 2
+#define LOG_LEVEL_MESSAGE  1 << 3
+#define LOG_LEVEL_DEBUG    1 << 4
+/** @endif */
+
+static void (*logfunc)(int log_level, char *message ) = NULL;
+static char *progname = NULL;
+
+/** @brief Allocates and prints to a new string
+ *
+ * @param format format string
+ * @param ap variable argument list
+ * @return Newly allocated string with format printed to it
+ */
+char *
+strdup_vprintf(const char* format, va_list ap)
+{
+  va_list ap2;
+  int size;
+  char* buffer;
+
+  va_copy(ap2, ap);
+  size = vsnprintf(NULL, 0, format, ap2)+1;
+  va_end(ap2);
+
+  buffer = malloc(size+1);
+  if ( !buffer )
+      return NULL;
+
+  vsnprintf(buffer, size, format, ap);
+  return buffer;
+}
+
+char *
+strdup_printf(const char* format, ...)
+{
+  char* buffer;
+  va_list ap;
+  va_start(ap, format);
+  buffer = strdup_vprintf(format, ap);
+  va_end(ap);
+  return buffer;
+}
+
+static void
+matio_error_func( int log_level, char *message )
+{
+
+    if ( progname ) {
+        if ( log_level & LOG_LEVEL_CRITICAL) {
+            fprintf(stderr,"-E- %s: %s\n", progname, message);
+            fflush(stderr);
+        } else if ( log_level & LOG_LEVEL_ERROR ) {
+            fprintf(stderr,"-E- %s: %s\n", progname, message);
+            fflush(stderr);
+            abort();
+        } else if ( log_level & LOG_LEVEL_WARNING ) {
+            fprintf(stderr,"-W- %s: %s\n", progname, message);
+            fflush(stderr);
+        } else if ( log_level & LOG_LEVEL_DEBUG ) {
+            fprintf(stderr,"-D- %s: %s\n", progname, message);
+            fflush(stderr);
+        } else if ( log_level & LOG_LEVEL_MESSAGE ) {
+            fprintf(stdout,"%s\n", message);
+            fflush(stdout);
+        }
+    } else {
+        if ( log_level & LOG_LEVEL_CRITICAL) {
+            fprintf(stderr,"-E- : %s\n", message);
+            fflush(stderr);
+        } else if ( log_level & LOG_LEVEL_ERROR ) {
+            fprintf(stderr,"-E- : %s\n", message);
+            fflush(stderr);
+            abort();
+        } else if ( log_level & LOG_LEVEL_WARNING ) {
+            fprintf(stderr,"-W- : %s\n", message);
+            fflush(stderr);
+        } else if ( log_level & LOG_LEVEL_DEBUG ) {
+            fprintf(stderr,"-D- : %s\n", message);
+            fflush(stderr);
+        } else if ( log_level & LOG_LEVEL_MESSAGE ) {
+            fprintf(stdout,"%s\n", message);
+            fflush(stdout);
+        }
+    }
+
+}
+
+static void
+scats_log(int loglevel, const char *format, va_list ap)
+{
+    char* buffer;
+
+    if ( !logfunc ) return;
+    buffer = strdup_vprintf(format, ap);
+    (*logfunc)(loglevel,buffer);
+    free(buffer);
+    return;
+}
+
+
+/** @var debug
+ *  @brief holds the verbose level set in @ref SetVerbose
+ *  This variable is used to determine if information should be printed to
+ *  the screen
+ *  @ingroup libscatsio
+ */
+static int debug = 0;
+
+/** @var verbose
+ *  @brief holds the verbose level set in @ref SetVerbose
+ *  This variable is used to determine if information should be printed to
+ *  the screen
+ *  @ingroup libscatsio
+ */
+static int verbose = 0;
+/** @var silent
+ *  @brief holds the silent level set in @ref SetVerbose
+ *  If set, all output which is not an error is not displayed regardless
+ *  of verbose level
+ *  @ingroup libscatsio
+ */
+static int silent = 0;
+/** @brief Sets verbose parameters
+ *
+ *  Sets the verbose level and silent level.  These values are used by
+ *  programs to determine what information should be printed to the screen
+ *  @ingroup libscatsio
+ *  @param verb sets logging verbosity level
+ *  @param s sets logging silent level
+ */
+int Mat_SetVerbose( int verb, int s )
+{
+
+    verbose = verb;
+    silent  = s;
+
+    return 0;
+}
+
+/** @brief Sets verbose parameters
+ *
+ *  Sets the verbose level and silent level.  These values are used by
+ *  programs to determine what information should be printed to the screen
+ *  @ingroup libscatsio
+ *  @param verb sets logging verbosity level
+ *  @param s sets logging silent level
+ */
+int Mat_SetDebug( int d )
+{
+    debug = d;
+    return 0;
+}
+
+/** @brief Log a message unless silent
+ *
+ * Logs the message unless the silent option is set (See @ref SetVerbose).
+ * To log a message based on the verbose level, use @ref Mat_VerbMessage
+ * @ingroup libscatsio
+ * @param format message format
+ */
+int Mat_Message( const char *format, ... )
+{
+    va_list ap;
+
+    if ( silent ) return 0;
+    if ( !logfunc ) return 0;
+
+    va_start(ap, format );
+    scats_log(LOG_LEVEL_MESSAGE, format, ap );
+    va_end(ap);
+    return 0;
+}
+
+/** @brief Log a message based on verbose level
+ *
+ *  If @e level is less than or equal to the set verbose level, the message
+ *  is printed.  If the level is higher than the set verbose level nothing
+ *  is displayed.
+ *  @ingroup libscatsio
+ *  @param level verbose level
+ *  @param format message format
+ */
+int Mat_DebugMessage( int level, const char *format, ... )
+{
+    va_list ap;
+
+    if ( silent ) return 0;
+    if ( level > debug ) return 0;
+
+    va_start(ap, format );
+    scats_log(LOG_LEVEL_DEBUG, format, ap );
+    va_end(ap);
+    return 0;
+}
+
+/** @brief Log a message based on verbose level
+ *
+ *  If @e level is less than or equal to the set verbose level, the message
+ *  is printed.  If the level is higher than the set verbose level nothing
+ *  is displayed.
+ *  @ingroup libscatsio
+ *  @param level verbose level
+ *  @param format message format
+ */
+int Mat_VerbMessage( int level, const char *format, ... )
+{
+    va_list ap;
+
+    if ( silent ) return 0;
+    if ( level > verbose ) return 0;
+
+    va_start(ap, format );
+    scats_log(LOG_LEVEL_MESSAGE, format, ap );
+    va_end(ap);
+    return 0;
+}
+
+/** @brief Logs a Critical message and returns to the user
+ *
+ * Logs a Critical message and returns to the user.  If the program should
+ * stop running, use @ref Mat_Error
+ * @ingroup libscatsio
+ * @param format format string identical to printf format
+ * @param ... arguments to the format string
+ */
+void Mat_Critical( const char *format, ... )
+{
+    va_list ap;
+
+    va_start(ap, format );
+    scats_log(LOG_LEVEL_CRITICAL, format, ap );
+    va_end(ap);
+}
+
+/** @brief Logs a Critical message and aborts the program
+ *
+ * Logs an Error message and aborts
+ * @ingroup libscatsio
+ * @param format format string identical to printf format
+ * @param ... arguments to the format string
+ */
+void Mat_Error( const char *format, ... )
+{
+    va_list ap;
+
+    va_start(ap, format );
+    scats_log( LOG_LEVEL_ERROR, format, ap );
+    va_end(ap);
+}
+
+/** @brief Prints a helpstring to stdout and exits with status 1
+ *
+ * Prints the array of strings to stdout and exits with status 1.  The array
+ * of strings should have NULL as its last element
+ * @code
+ * char *helpstr[] = {"My Help string line1","My help string line 2",NULL};
+ * Mat_Help(helpstr);
+ * @endcode
+ * @ingroup libscatsio
+ * @param helpstr array of strings with NULL as its last element
+ */
+void Mat_Help( const char *helpstr[] )
+{
+    int i;
+    for (i = 0; helpstr[i] != NULL; i++)
+        printf("%s\n",helpstr[i]);
+    exit(EXIT_SUCCESS);
+}
+
+/** @brief Closes the logging system
+ *
+ * @retval 1
+ */
+int
+Mat_LogClose( )
+{
+    logfunc = NULL;
+    return 1;
+}
+
+/** @brief Intializes the logging system
+ *
+ * @ingroup libscatsio
+ * @param prog_name Name of the program initializing the logging functions
+ * @return 0 on success
+ */
+int
+Mat_LogInit( char *prog_name )
+{
+    logfunc = &matio_error_func;
+
+    verbose = 0;
+    silent  = 0;
+
+    return 0;
+}
+
+/** @brief Intializes the logging system
+ *
+ * @ingroup libscatsio
+ * @param prog_name Name of the program initializing the logging functions
+ * @param log_func pointer to the function to do the logging
+ * @return 0 on success
+ */
+int
+Mat_LogInitFunc(char *prog_name,void (*log_func)(int log_level,char *message))
+{
+    logfunc = log_func;
+    progname = prog_name;
+
+    verbose = 0;
+    silent  = 0;
+    return 0;
+}
+
+/** @brief Prints a warning message to stdout
+ *
+ * Logs a warning message then returns
+ * @ingroup libscatsio
+ * @param format format string identical to printf format
+ * @param ... arguments to the format string
+ */
+void Mat_Warning( const char *format, ... )
+{
+    va_list ap;
+
+    va_start(ap, format );
+    scats_log(LOG_LEVEL_WARNING, format, ap );
+    va_end(ap);
+}
+
+size_t
+Mat_SizeOf(int data_type)
+{
+    switch (data_type) {
+        case MAT_T_DOUBLE:
+            return sizeof(double);
+        case MAT_T_SINGLE:
+            return sizeof(float);
+#ifdef HAVE_MAT_INT64_T
+        case MAT_T_INT64:
+            return sizeof(mat_int64_t);
+#endif
+#ifdef HAVE_MAT_INT64_T
+        case MAT_T_UINT64:
+            return sizeof(mat_uint64_t);
+#endif
+        case MAT_T_INT32:
+            return sizeof(mat_int32_t);
+        case MAT_T_UINT32:
+            return sizeof(mat_uint32_t);
+        case MAT_T_INT16:
+            return sizeof(mat_int16_t);
+        case MAT_T_UINT16:
+            return sizeof(mat_uint16_t);
+        case MAT_T_INT8:
+            return sizeof(mat_int8_t);
+        case MAT_T_UINT8:
+            return sizeof(mat_uint8_t);
+        default:
+            return 0;
+    }
+}

+ 1932 - 0
matlabAccess/matio/src/mat.c

@@ -0,0 +1,1932 @@
+/** @file mat.c
+ * Matlab MAT version 5 file functions
+ * @ingroup MAT
+ */
+/*
+ * Copyright (C) 2005-2006   Christopher C. Hulbert
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* FIXME: Implement Unicode support */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+#include "matio.h"
+#include "mat5.h"
+#include "mat4.h"
+#include "matio_private.h"
+
+static void
+ReadData(mat_t *mat, matvar_t *matvar)
+{
+    if ( mat == NULL || matvar == NULL || mat->fp == NULL )
+        return;
+    else if ( mat->version != MAT_FT_MAT4 )
+        Read5(mat,matvar);
+    else if ( mat->version == MAT_FT_MAT4 )
+        Read4(mat,matvar);
+    return;
+}
+
+/*
+ *====================================================================
+ *                 Public Functions
+ *====================================================================
+ */
+
+/** @brief Creates a new Matlab MAT file
+ *
+ * Tries to create a new Matlab MAT file with the given name and optional
+ * header string.  If no header string is given, the default string
+ * is used containing the software, version, and date in it.  If a header
+ * string is given, at most the first 116 characters is written to the file.
+ * The given header string need not be the full 116 characters, but MUST be
+ * NULL terminated.
+ * @ingroup MAT
+ * @param matname Name of MAT file to create
+ * @param hdr_str Optional header string, NULL to use default
+ * @return A pointer to the MAT file or NULL if it failed.  This is not a
+ * simple FILE * and should not be used as one.
+ */
+mat_t *
+Mat_Create(const char *matname,const char *hdr_str)
+{
+    FILE *fp = NULL;
+    mat_int16_t endian = 0, version;
+    mat_t *mat = NULL;
+    size_t err;
+    time_t t;
+
+    fp = fopen(matname,"wb");
+    if ( !fp )
+        return NULL;
+
+    mat = malloc(sizeof(*mat));
+    if ( !mat ) {
+        fclose(fp);
+        return NULL;
+    }
+
+    mat->fp            = NULL;
+    mat->header        = NULL;
+    mat->subsys_offset = NULL;
+    mat->filename      = NULL;
+    mat->version       = 0;
+    mat->byteswap      = 0;
+    mat->mode          = 0;
+    mat->bof           = 0;
+
+    t = time(NULL);
+    mat->fp = fp;
+    mat->filename = strdup_printf("%s",matname);
+    mat->mode     = MAT_ACC_RDWR;
+    mat->byteswap = 0;
+    mat->header   = calloc(1,128);
+    mat->subsys_offset = calloc(1,16);
+    memset(mat->header,' ',128);
+    if ( hdr_str == NULL ) {
+        err = mat_snprintf(mat->header,116,"MATLAB 5.0 MAT-file, Platform: %s, "
+                "Created By: libmatio v%d.%d.%d on %s", MATIO_PLATFORM,
+                MATIO_MAJOR_VERSION, MATIO_MINOR_VERSION, MATIO_RELEASE_LEVEL,
+                ctime(&t));
+        mat->header[115] = '\0';    /* Just to make sure it's NULL terminated */
+    } else {
+        err = mat_snprintf(mat->header,116,"%s",hdr_str);
+    }
+    mat->header[err] = ' ';
+    mat_snprintf(mat->subsys_offset,15,"            ");
+    mat->version = (int)0x0100;
+    endian = 0x4d49;
+
+    version = 0x0100;
+
+    err = fwrite(mat->header,1,116,mat->fp);
+    err = fwrite(mat->subsys_offset,1,8,mat->fp);
+    err = fwrite(&version,2,1,mat->fp);
+    err = fwrite(&endian,2,1,mat->fp);
+
+    return mat;
+}
+
+/** @brief Opens an existing Matlab MAT file
+ *
+ * Tries to open a Matlab MAT file with the given name
+ * @ingroup MAT
+ * @param matname Name of MAT file to open
+ * @param mode File access mode (MAT_ACC_RDONLY,MAT_ACC_RDWR,etc).
+ * @return A pointer to the MAT file or NULL if it failed.  This is not a
+ * simple FILE * and should not be used as one.
+ */
+mat_t *
+Mat_Open(const char *matname,int mode)
+{
+    FILE *fp = NULL;
+    mat_int16_t tmp, tmp2;
+    int     err;
+    mat_t *mat = NULL;
+
+    if ( (mode & 0x000000ff) == MAT_ACC_RDONLY ) {
+        fp = fopen( matname, "rb" );
+        if ( !fp )
+            return NULL;
+    } else if ( (mode & 0x000000ff) == MAT_ACC_RDWR ) {
+        fp = fopen( matname, "r+b" );
+        if ( !fp ) {
+            mat = Mat_Create(matname,NULL);
+            return mat;
+        }
+    } else {
+        mat = Mat_Create(matname,NULL);
+        return mat;
+    }
+
+    mat = malloc(sizeof(mat_t));
+    if ( !mat ) {
+        Mat_Critical("Couldn't allocate memory for the MAT file");
+        fclose(fp);
+        return NULL;
+    }
+
+    mat->fp = fp;
+    if ( mode & MAT_FT_MAT4 ) {
+        mat->header        = NULL;
+        mat->subsys_offset = NULL;
+        mat->version       = MAT_FT_MAT4;
+        mat->byteswap      = 0;
+        mat->mode          = mode;
+        mat->filename = strdup_printf("%s",matname);
+        mat->bof           = ftell(mat->fp);
+    } else {
+        mat->header        = malloc(128);
+        mat->subsys_offset = malloc(8);
+        mat->filename      = NULL;
+
+        err = fread(mat->header,1,116,fp);
+        mat->header[116] = '\0';
+        err = fread(mat->subsys_offset,1,8,fp);
+        err = fread(&tmp2,2,1,fp);
+        fread (&tmp,1,2,fp);
+        mat->bof = ftell(mat->fp);
+
+        mat->byteswap = -1;
+        if (tmp == 0x4d49)
+            mat->byteswap = 0;
+        else if (tmp == 0x494d) {
+            mat->byteswap = 1;
+            Mat_int16Swap(&tmp2);
+        }
+        mat->version = (int)tmp2;
+
+        if ( mat->byteswap < 0 ) {
+            Mat_Critical("%s does not seem to be a valid MAT file",matname);
+            Mat_Close(mat);
+            mat=NULL;
+        } else if ( mat->version != 0x0100 ) {
+            Mat_Critical("%s is not a version 5 MAT file", matname);
+            Mat_Close(mat);
+            mat=NULL;
+        } else {
+            mat->filename = strdup_printf("%s",matname);
+            mat->mode = mode;
+        }
+    }
+
+    return mat;
+}
+
+/** @brief Closes an open Matlab MAT file
+ *
+ * Closes the given Matlab MAT file and frees any memory with it.
+ * @ingroup MAT
+ * @param mat Pointer to the MAT file
+ * @retval 0
+ */
+int
+Mat_Close( mat_t *mat )
+{
+    if ( NULL != mat ) {
+        if ( mat->fp )
+            fclose(mat->fp);
+        if ( mat->header )
+            free(mat->header);
+        if ( mat->subsys_offset )
+            free(mat->subsys_offset);
+        if ( mat->filename )
+            free(mat->filename);
+        free(mat);
+    }
+    return 0;
+}
+
+/** @brief Rewinds a Matlab MAT file to the first variable
+ *
+ * Rewinds a Matlab MAT file to the first variable
+ * @ingroup MAT
+ * @param mat Pointer to the MAT file
+ * @retval 0 on success
+ */
+int
+Mat_Rewind( mat_t *mat )
+{
+    if ( mat->version != MAT_FT_MAT4 )
+        fseek(mat->fp,128L,SEEK_SET);
+    else
+        fseek(mat->fp,0L,SEEK_SET);
+    return 0;
+}
+
+/** @brief Returns the size of a Matlab Class
+ *
+ * Returns the size (in bytes) of the matlab class class_type
+ * @ingroup MAT
+ * @param class_type Matlab class type (MAT_C_*)
+ * @returns Size of the class
+ */
+size_t
+Mat_SizeOfClass(int class_type)
+{
+    switch (class_type) {
+        case MAT_C_DOUBLE:
+            return sizeof(double);
+        case MAT_C_SINGLE:
+            return sizeof(float);
+#ifdef HAVE_MAT_INT64_T
+        case MAT_C_INT64:
+            return sizeof(mat_int64_t);
+#endif
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_C_UINT64:
+            return sizeof(mat_uint64_t);
+#endif
+        case MAT_C_INT32:
+            return sizeof(mat_int32_t);
+        case MAT_C_UINT32:
+            return sizeof(mat_uint32_t);
+        case MAT_C_INT16:
+            return sizeof(mat_int16_t);
+        case MAT_C_UINT16:
+            return sizeof(mat_uint16_t);
+        case MAT_C_INT8:
+            return sizeof(mat_int8_t);
+        case MAT_C_UINT8:
+            return sizeof(mat_uint8_t);
+        case MAT_C_CHAR:
+            return sizeof(mat_int16_t);
+        default:
+            return 0;
+    }
+}
+
+/*
+ *===================================================================
+ *    MAT Variable Functions
+ *===================================================================
+ */
+
+/** @brief Allocates memory for a new matvar_t and initializes all the fields
+ *
+ * @ingroup MAT
+ * @return A newly allocated matvar_t
+ */
+matvar_t *
+Mat_VarCalloc(void)
+{
+    matvar_t *matvar;
+
+    matvar = malloc(sizeof(*matvar));
+
+    if ( NULL != matvar ) {
+        matvar->nbytes       = 0;
+        matvar->rank         = 0;
+        matvar->data_type    = 0;
+        matvar->data_size    = 0;
+        matvar->class_type   = 0;
+        matvar->isComplex    = 0;
+        matvar->isGlobal     = 0;
+        matvar->isLogical    = 0;
+        matvar->dims         = NULL;
+        matvar->name         = NULL;
+        matvar->data         = NULL;
+        matvar->mem_conserve = 0;
+        matvar->compression  = 0;
+        matvar->fpos         = 0;
+        matvar->datapos      = 0;
+        matvar->fp           = NULL;
+#if defined(HAVE_ZLIB)
+        matvar->z            = NULL;
+#endif
+    }
+
+    return matvar;
+}
+
+/** @brief Creates a MAT Variable with the given name and (optionally) data
+ *
+ * Creates a MAT variable that can be written to a Matlab MAT file with the
+ * given name, data type, dimensions and data.  Rank should always be 2 or more.
+ * i.e. Scalar values would have rank=2 and dims[2] = {1,1}.  Data type is
+ * one of the MAT_T types.  MAT adds MAT_T_STRUCT and MAT_T_CELL to create
+ * Structures and Cell Arrays respectively.  For MAT_T_STRUCT, data should be a
+ * NULL terminated array of matvar_t * variables (i.e. for a 3x2 structure with
+ * 10 fields, there should be 61 matvar_t * variables where the last one is
+ * NULL).  For cell arrays, the NULL termination isn't necessary.  So to create
+ * a cell array of size 3x2, data would be the address of an array of 6
+ * matvar_t * variables.
+ *
+ * EXAMPLE:
+ *   To create a struct of size 3x2 with 3 fields:
+ * @code
+ *     int rank=2, dims[2] = {3,2}, nfields = 3;
+ *     matvar_t **vars;
+ *
+ *     vars = malloc((3*2*nfields+1)*sizeof(matvar_t *));
+ *     vars[0]             = Mat_VarCreate(...);
+ *        :
+ *     vars[3*2*nfields-1] = Mat_VarCreate(...);
+ *     vars[3*2*nfields]   = NULL;
+ * @endcode
+ *
+ * EXAMPLE:
+ *   To create a cell array of size 3x2:
+ * @code
+ *     int rank=2, dims[2] = {3,2};
+ *     matvar_t **vars;
+ *
+ *     vars = malloc(3*2*sizeof(matvar_t *));
+ *     vars[0]             = Mat_VarCreate(...);
+ *        :
+ *     vars[5] = Mat_VarCreate(...);
+ * @endcode
+ *
+ * @ingroup MAT
+ * @param name Name of the variable to create
+ * @param class_type class type of the variable in Matlab(one of the mx Classes)
+ * @param data_type data type of the variable (one of the MAT_T_ Types)
+ * @param rank Rank of the variable
+ * @param dims array of dimensions of the variable of size rank
+ * @param data pointer to the data
+ * @param opt 0, or bitwise or of the following options:
+ * - MEM_CONSERVE to just use the pointer to the data and not copy the data
+ *       itself.  Note that the pointer should not be freed until you are done
+ *       with the mat variable.  The Mat_VarFree function will NOT free
+ *       data that was created with MEM_CONSERVE, so free it yourself.
+ * - MAT_F_COMPLEX to specify that the data is complex.  The data variable should
+ *       be a contigouse piece of memory with the real part written first and
+ *       the imaginary second
+ * - MAT_F_GLOBAL to assign the variable as a global variable
+ * - MAT_F_LOGICAL to specify that it is a logical variable
+ * @return A MAT variable that can be written to a file or otherwise used
+ */
+matvar_t *
+Mat_VarCreate(const char *name,int class_type,int data_type,int rank,int *dims,
+      void *data,int opt)
+{
+    int i, nmemb = 1, nfields = 0;
+    matvar_t *matvar = NULL;
+
+    if (dims == NULL) return NULL;
+
+    matvar = Mat_VarCalloc();
+    if ( NULL == matvar )
+        return NULL;
+
+    matvar->compression = COMPRESSION_NONE;
+    matvar->isComplex   = opt & MAT_F_COMPLEX;
+    matvar->isGlobal    = opt & MAT_F_GLOBAL;
+    matvar->isLogical   = opt & MAT_F_LOGICAL;
+    if ( name )
+        matvar->name = strdup_printf("%s",name);
+    matvar->rank = rank;
+    matvar->dims = malloc(matvar->rank*sizeof(int));
+    for ( i = 0; i < matvar->rank; i++ ) {
+        matvar->dims[i] = dims[i];
+        nmemb *= dims[i];
+    }
+    matvar->class_type = class_type;
+    matvar->data_type  = data_type;
+    switch ( data_type ) {
+        case MAT_T_INT8:
+            matvar->data_size = 1;
+            break;
+        case MAT_T_UINT8:
+            matvar->data_size = 1;
+            break;
+        case MAT_T_INT16:
+            matvar->data_size = 2;
+            break;
+        case MAT_T_UINT16:
+            matvar->data_size = 2;
+            break;
+        case MAT_T_INT64:
+            matvar->data_size = 8;
+            break;
+        case MAT_T_UINT64:
+            matvar->data_size = 8;
+            break;
+        case MAT_T_INT32:
+            matvar->data_size = 4;
+            break;
+        case MAT_T_UINT32:
+            matvar->data_size = 4;
+            break;
+        case MAT_T_SINGLE:
+            matvar->data_size = sizeof(float);
+            break;
+        case MAT_T_DOUBLE:
+            matvar->data_size = sizeof(double);
+            break;
+        case MAT_T_UTF8:
+            matvar->data_size = 1;
+            break;
+        case MAT_T_UTF16:
+            matvar->data_size = 2;
+            break;
+        case MAT_T_UTF32:
+            matvar->data_size = 4;
+            break;
+        case MAT_T_CELL:
+            matvar->data_size = sizeof(matvar_t **);
+            break;
+        case MAT_T_STRUCT:
+        {
+            matvar_t **fields;
+
+            if ( data == NULL )
+                break;
+            fields = data;
+            nfields = 0;
+            while ( fields[nfields] != NULL )
+                nfields++;
+            matvar->data_size = sizeof(matvar_t **);
+            nmemb = nfields; /* nfields is really nmemb*nfields */
+            break;
+        }
+        default:
+            Mat_Error("Unrecognized data_type");
+            Mat_VarFree(matvar);
+            return NULL;
+    }
+    if ( matvar->class_type == MAT_C_CHAR ) {
+#if 0
+        matvar->data_size = 1;
+        nmemb++;
+#endif
+        matvar->nbytes = nmemb*matvar->data_size;
+    } else if ( matvar->class_type == MAT_C_SPARSE ) {
+        matvar->data_size = sizeof(sparse_t);
+        matvar->nbytes = nmemb*matvar->data_size;
+    } else {
+        matvar->nbytes = nmemb*matvar->data_size;
+    }
+    if ( data == NULL ) {
+        matvar->data = NULL;
+    } else if ( opt & MEM_CONSERVE ) {
+        if ( matvar->isComplex ) {
+            matvar->data   = malloc(sizeof(struct ComplexSplit));
+            if ( NULL != data ) {
+                struct ComplexSplit *complex_data    = matvar->data;
+                struct ComplexSplit *complex_data_in = data;
+
+                *complex_data = *complex_data_in;
+            }
+        } else {
+            matvar->data         = (void*)data;
+        }
+        matvar->mem_conserve = 1;
+    } else {
+        if ( matvar->isComplex ) {
+            matvar->data   = malloc(sizeof(struct ComplexSplit));
+            if ( NULL != matvar->data ) {
+                struct ComplexSplit *complex_data    = matvar->data;
+                struct ComplexSplit *complex_data_in = data;
+
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL != complex_data->Re )
+                    memcpy(complex_data->Re,complex_data_in->Re,matvar->nbytes);
+                if ( NULL != complex_data->Im )
+                    memcpy(complex_data->Im,complex_data_in->Im,matvar->nbytes);
+            }
+        } else {
+            matvar->data   = malloc(matvar->nbytes);
+            if ( NULL != matvar->data )
+                memcpy(matvar->data,data,matvar->nbytes);
+        }
+        matvar->mem_conserve = 0;
+    }
+
+    return matvar;
+}
+
+/** @brief Deletes a variable from a file
+ *
+ * @ingroup MAT
+ * @param mat Pointer to the mat_t file structure
+ * @param name Name of the variable to delete
+ * @returns 0 on success
+ */
+int
+Mat_VarDelete(mat_t *mat, char *name)
+{
+    int   err = 1;
+    char *tmp_name, *new_name, *temp;
+    mat_t *tmp;
+    matvar_t *matvar;
+
+    temp     = strdup_printf("XXXXXX");
+    tmp_name = mktemp(temp);
+    tmp      = Mat_Create(tmp_name,mat->header);
+    if ( tmp != NULL ) {
+        while ( NULL != (matvar = Mat_VarReadNext(mat)) ) {
+            if ( strcmp(matvar->name,name) )
+                Mat_VarWrite(tmp,matvar,0);
+            else
+                err = 0;
+            Mat_VarFree(matvar);
+        }
+        /* FIXME: Memory leak */
+        new_name = strdup_printf("%s",mat->filename);
+        fclose(mat->fp);
+		
+        if ( (err = remove(new_name)) == -1 ) {
+            Mat_Critical("remove of %s failed",new_name);
+        } else if ( !Mat_Close(tmp) && (err=rename(tmp_name,new_name))==-1) {
+            Mat_Critical("rename failed oldname=%s,newname=%s",tmp_name,
+                new_name);
+        } else {
+            tmp = Mat_Open(new_name,mat->mode);
+            memcpy(mat,tmp,sizeof(mat_t));
+        }
+        free(tmp);
+        free(new_name);
+    }
+    free(temp);
+    return err;
+}
+
+/** @brief Duplicates a matvar_t structure
+ *
+ * Provides a clean function for duplicating a matvar_t structure.
+ * @ingroup MAT
+ * @param in pointer to the matvar_t structure to be duplicated
+ * @param opt 0 does a shallow duplicate and only assigns the data pointer to
+ *            the duplicated array.  1 will do a deep duplicate and actually
+ *            duplicate the contents of the data.  Warning: If you do a shallow
+ *            copy and free both structures, the data will be freed twice and
+ *            memory will be corrupted.  This may be fixed in a later release.
+ * @returns Pointer to the duplicated matvar_t structure.
+ */
+matvar_t *
+Mat_VarDuplicate(const matvar_t *in, int opt)
+{
+    matvar_t *out;
+    int i;
+
+    out = malloc(sizeof(matvar_t));
+    if ( out == NULL )
+        return NULL;
+
+    out->nbytes       = in->nbytes;
+    out->rank         = in->rank;
+    out->data_type    = in->data_type;
+    out->data_size    = in->data_size;
+    out->class_type   = in->class_type;
+    out->isComplex    = in->isComplex;
+    out->isGlobal     = in->isGlobal;
+    out->isLogical    = in->isLogical;
+    out->mem_conserve = in->mem_conserve;
+    out->compression  = in->compression;
+    out->fpos         = in->fpos;
+    out->datapos      = in->datapos;
+
+    out->name = NULL;
+    out->dims = NULL;
+    out->data = NULL;
+#if defined(HAVE_ZLIB)
+    out->z    = NULL;
+#endif
+
+    if (in->name != NULL && (NULL != (out->name = malloc(strlen(in->name)+1))))
+        memcpy(out->name,in->name,strlen(in->name)+1);
+
+    out->dims = malloc(in->rank*sizeof(int));
+    if ( out->dims != NULL )
+        memcpy(out->dims,in->dims,in->rank*sizeof(int));
+#if defined(HAVE_ZLIB)
+    if ( (in->z != NULL) && (NULL != (out->z = malloc(sizeof(z_stream)))) )
+        inflateCopy(out->z,in->z);
+#endif
+
+    if ( !opt ) {
+        out->data = in->data;
+    } else if ( (in->data != NULL) && (in->class_type == MAT_C_STRUCT) ) {
+        matvar_t **infields, **outfields;
+        int nfields = 0; 
+
+        out->data = malloc(in->nbytes);
+        if ( out->data != NULL && in->data_size > 0 ) {
+            nfields   = in->nbytes / in->data_size;
+            infields  = (matvar_t **)in->data;
+            outfields = (matvar_t **)out->data;
+            for ( i = 0; i < nfields; i++ ) {
+                outfields[i] = Mat_VarDuplicate(infields[i],opt);
+            } 
+        }
+    } else if ( (in->data != NULL) && (in->class_type == MAT_C_CELL) ) {
+        matvar_t **incells, **outcells;
+        int ncells = 0; 
+
+        out->data = malloc(in->nbytes);
+        if ( out->data != NULL && in->data_size > 0 ) {
+            ncells   = in->nbytes / in->data_size;
+            incells  = (matvar_t **)in->data;
+            outcells = (matvar_t **)out->data;
+            for ( i = 0; i < ncells; i++ ) {
+                outcells[i] = Mat_VarDuplicate(incells[i],opt);
+            } 
+        }
+    } else if ( in->data != NULL ) {
+        if ( out->isComplex ) {
+            out->data = malloc(sizeof(struct ComplexSplit));
+            if ( out->data != NULL ) {
+                struct ComplexSplit *out_data = out->data;
+                struct ComplexSplit *in_data  = in->data;
+                out_data->Re = malloc(out->nbytes);
+                if ( NULL != out_data->Re )
+                    memcpy(out_data->Re,in_data->Re,out->nbytes);
+                out_data->Im = malloc(out->nbytes);
+                if ( NULL != out_data->Im )
+                    memcpy(out_data->Im,in_data->Im,out->nbytes);
+            }
+        } else {
+            out->data = malloc(in->nbytes);
+            if ( out->data != NULL )
+                memcpy(out->data,in->data,in->nbytes);
+        }
+    }
+    return out;
+}
+
+/** @brief Frees all the allocated memory associated with the structure
+ *
+ * Frees memory used by a MAT variable.  Frees the data associated with a
+ * MAT variable if it's non-NULL and MEM_CONSERVE was not used.
+ * @ingroup MAT
+ * @param matvar Pointer to the matvar_t structure
+ */
+void
+Mat_VarFree(matvar_t *matvar)
+{
+    if ( !matvar )
+        return;
+    if ( matvar->dims )
+        free(matvar->dims);
+    if ( matvar->name )
+        free(matvar->name);
+    if ( (matvar->data != NULL) && (matvar->class_type == MAT_C_STRUCT || 
+          matvar->class_type == MAT_C_CELL) && matvar->data_size > 0 ) {
+        int i;
+        matvar_t **fields = matvar->data;
+        int nfields = matvar->nbytes / matvar->data_size;
+        for ( i = 0; i < nfields; i++ )
+            Mat_VarFree(fields[i]);
+        free(matvar->data);
+    } else if ( (matvar->data != NULL) && (!matvar->mem_conserve) &&
+                (matvar->class_type == MAT_C_SPARSE) ) {
+        sparse_t *sparse;
+        sparse = matvar->data;
+        if ( sparse->ir != NULL )
+            free(sparse->ir);
+        if ( sparse->jc != NULL )
+            free(sparse->jc);
+        if ( sparse->data != NULL )
+            free(sparse->data);
+        free(sparse);
+    } else {
+        if ( matvar->isComplex && NULL != matvar->data ) {
+            struct ComplexSplit *complex_data = matvar->data;
+            if ( !matvar->mem_conserve ) {
+                free(complex_data->Re);
+                free(complex_data->Im);
+            }
+            free(complex_data);
+        } else {
+            if ( matvar->data && !matvar->mem_conserve )
+                free(matvar->data);
+        }
+    }
+#if defined(HAVE_ZLIB)
+    if ( matvar->compression == COMPRESSION_ZLIB ) {
+        inflateEnd(matvar->z);
+        free(matvar->z);
+    }
+#endif
+    /* FIXME: Why does this cause a SEGV? */
+#if 0
+    memset(matvar,0,sizeof(matvar_t));
+#endif
+    free(matvar);
+}
+
+void
+Mat_VarFree2(matvar_t *matvar)
+{
+    if ( !matvar )
+        return;
+    if ( matvar->dims )
+        free(matvar->dims);
+    if ( matvar->name )
+        free(matvar->name);
+    if ( (matvar->data != NULL) && (matvar->class_type == MAT_C_STRUCT || 
+          matvar->class_type == MAT_C_CELL) && matvar->data_size > 0 ) {
+        int i;
+        matvar_t **fields = (matvar_t **)matvar->data;
+        int nfields = matvar->nbytes / matvar->data_size;
+        for ( i = 0; i < nfields; i++ )
+            Mat_VarFree(fields[i]);
+        free(matvar->data);
+    } else if ( (matvar->data != NULL) && (!matvar->mem_conserve) &&
+                (matvar->class_type == MAT_C_SPARSE) ) {
+        sparse_t *sparse;
+        sparse = matvar->data;
+        if ( sparse->ir != NULL )
+            free(sparse->ir);
+        if ( sparse->jc != NULL )
+            free(sparse->jc);
+        if ( sparse->data != NULL )
+            free(sparse->data);
+        free(sparse);
+    } else {
+        if ( matvar->data && !matvar->mem_conserve )
+            free(matvar->data);
+    }
+#if defined(HAVE_ZLIB)
+    if ( matvar->compression == COMPRESSION_ZLIB )
+        inflateEnd(matvar->z);
+#endif
+    /* FIXME: Why does this cause a SEGV? */
+#if 0
+    memset(matvar,0,sizeof(matvar_t));
+#endif
+}
+
+/** @brief Calculate a single subscript from a set of subscript values
+ *
+ * Calculates a single linear subscript (0-relative) given a 1-relative
+ * subscript for each dimension.  The calculation uses the formula below where
+ * index is the linear index, s is an array of length RANK where each element
+ * is the subscript for the correspondind dimension, D is an array whose
+ * elements are the dimensions of the variable.
+ * \f[
+ *   index = \sum\limits_{k=0}^{RANK-1} [(s_k - 1) \prod\limits_{l=0}^{k} D_l ]
+ * \f]
+ * @ingroup MAT
+ * @param rank Rank of the variable
+ * @param dims dimensions of the variable
+ * @param subs Dimension subscripts
+ * @return Single (linear) subscript
+ */
+int
+Mat_CalcSingleSubscript(int rank,int *dims,int *subs)
+{
+    int index = 0, i, j, k, err = 0;
+
+    for ( i = 0; i < rank; i++ ) {
+        k = subs[i];
+        if ( k > dims[i] ) {
+            err = 1;
+            Mat_Critical("Mat_CalcSingleSubscript: index out of bounds");
+            break;
+        } else if ( k < 1 ) {
+            err = 1;
+            break;
+        }
+        k--;
+        for ( j = i; j--; )
+            k *= dims[j];
+        index += k;
+    }
+    if ( err )
+        index = -1;
+
+    return index;
+}
+
+
+/** @brief Calculate a set of subscript values from a single(linear) subscript
+ *
+ * Calculates 1-relative subscripts for each dimension given a 0-relative
+ * linear index.  Subscripts are calculated as follows where s is the array
+ * of dimension subscripts, D is the array of dimensions, and index is the
+ * linear index.
+ * \f[
+ *   s_k = \lfloor\frac{1}{L} \prod\limits_{l = 0}^{k} D_l\rfloor + 1
+ * \f]
+ * \f[
+ *   L = index - \sum\limits_{l = k}^{RANK - 1} s_k \prod\limits_{m = 0}^{k} D_m
+ * \f]
+ * @ingroup MAT
+ * @param rank Rank of the variable
+ * @param dims dimensions of the variable
+ * @param index linear index
+ * @return Array of dimension subscripts
+ */
+int *
+Mat_CalcSubscripts(int rank,int *dims,int index)
+{
+    int i, j, k, *subs;
+    double l;
+
+    subs = malloc(rank*sizeof(int));
+    l = index;
+    for ( i = rank; i--; ) {
+        k = 1;
+        for ( j = i; j--; )
+            k *= dims[j];
+        subs[i] = floor(l / (double)k);
+        l -= subs[i]*k;
+        subs[i]++;
+    }
+
+    return subs;
+}
+
+/** @brief Returns a pointer to the Cell array at a specific index
+ *
+ * Returns a pointer to the Cell Array Field at the given 1-relative index.
+ * MAT file must be a version 5 matlab file.
+ * @ingroup MAT
+ * @param matvar Pointer to the Cell Array MAT variable
+ * @param index linear index of cell to return
+ * @return Pointer to the Cell Array Field on success, NULL on error
+ */
+matvar_t *
+Mat_VarGetCell(matvar_t *matvar,int index)
+{
+    int       nmemb = 1, i;
+    matvar_t *cell = NULL;
+
+    if ( matvar == NULL )
+        return NULL;
+
+    for ( i = 0; i < matvar->rank; i++ )
+        nmemb *= matvar->dims[i];
+
+    if ( index < nmemb )
+        cell = *((matvar_t **)matvar->data + index);
+
+    return cell;
+}
+
+/** @brief Indexes a cell array
+ *
+ * Finds cells of a cell array given a start, stride, and edge for each.
+ * dimension.  The cells are placed in a pointer array.  The cells should not
+ * be freed, but the array of pointers should be.  If copies are needed,
+ * use Mat_VarDuplicate on each cell.
+ * MAT File version must be 5.
+ * @ingroup MAT
+ * @param matvar Cell Array matlab variable
+ * @param start vector of length rank with 0-relative starting coordinates for
+ *              each diemnsion.
+ * @param stride vector of length rank with strides for each diemnsion.
+ * @param edge vector of length rank with the number of elements to read in
+ *              each diemnsion.
+ * @returns an array of pointers to the cells
+ */
+matvar_t **
+Mat_VarGetCells(matvar_t *matvar,int *start,
+    int *stride,int *edge)
+{
+    int i, j, N, I = 0;
+    int inc[10] = {0,}, cnt[10] = {0,}, dimp[10] = {0,};
+    matvar_t **cells;
+
+    if ( (matvar == NULL) || (start == NULL) || (stride == NULL) ||  
+         (edge == NULL) ) {
+        return NULL;
+    } else if ( matvar->rank > 10 ) {
+        return NULL;
+    }
+
+    inc[0] = stride[0]-1;
+    dimp[0] = matvar->dims[0];
+    N = edge[0];
+    I = start[0];
+    for ( i = 1; i < matvar->rank; i++ ) {
+        inc[i]  = stride[i]-1;
+        dimp[i] = matvar->dims[i-1];
+        for ( j = i ; j--; ) {
+            inc[i]  *= matvar->dims[j];
+            dimp[i] *= matvar->dims[j+1];
+        }
+        N *= edge[i];
+        if ( start[i] > 0 )
+            I += start[i]*dimp[i-1];
+    }
+    cells = malloc(N*sizeof(matvar_t *));
+    for ( i = 0; i < N; i+=edge[0] ) {
+        for ( j = 0; j < edge[0]; j++ ) {
+            cells[i+j] = *((matvar_t **)matvar->data + I);
+            I += stride[0];
+        }
+        for ( j = 1; j < matvar->rank-1; j++ ) {
+            cnt[j]++;
+            if ( (cnt[j] % edge[j]) == 0 ) {
+                cnt[j] = 0;
+                if ( (I % dimp[j]) != 0 ) {
+                    I += dimp[j]-(I % dimp[j]);
+                }
+            } else {
+                I += matvar->dims[0]-edge[0]*stride[0]-start[0];
+                I += inc[j];
+                break;
+            }
+        }
+    }
+    return cells;
+}
+
+/** @brief Indexes a cell array
+ *
+ * Finds cells of a cell array given a linear indexed start, stride, and edge.
+ * The cells are placed in a pointer array.  The cells themself should not
+ * be freed as they are part of the original cell array, but the pointer array
+ * should be.  If copies are needed, use Mat_VarDuplicate on each of the cells.
+ * MAT file version must be 5.
+ * @ingroup MAT
+ * @param matvar Cell Array matlab variable
+ * @param start starting index
+ * @param stride stride
+ * @param edge Number of cells to get
+ * @returns an array of pointers to the cells
+ */
+matvar_t **
+Mat_VarGetCellsLinear(matvar_t *matvar,int start,int stride,int edge)
+{
+    int i, I = 0;
+    matvar_t **cells;
+
+    if ( matvar == NULL || matvar->rank > 10 ) {
+        cells = NULL;
+    } else {
+        cells = malloc(edge*sizeof(matvar_t *));
+        for ( i = 0; i < edge; i++ ) {
+            cells[i] = *((matvar_t **)matvar->data + I);
+            I += stride;
+        }
+    }
+    return cells;
+}
+
+/** @brief Calculates the size of a matlab variable in bytes
+ *
+ * @ingroup MAT
+ * @param matvar matlab variable
+ * @returns size of the variable in bytes
+ */
+size_t
+Mat_VarGetSize(matvar_t *matvar)
+{
+    int nmemb, i;
+    size_t bytes = 0;
+
+    if ( matvar->class_type == MAT_C_STRUCT ) {
+        int nfields;
+        matvar_t **fields;
+        /* This is really nmemb*nfields, but we'll get a 
+         * more accurate count of the bytes by loopoing over all of them
+         */
+        nfields = matvar->nbytes / matvar->data_size;
+        fields  = matvar->data;
+        for ( i = 0; i < nfields; i++ )
+            bytes += Mat_VarGetSize(fields[i]);
+    } else if ( matvar->class_type == MAT_C_CELL ) {
+        int ncells;
+        matvar_t **cells;
+
+        ncells = matvar->nbytes / matvar->data_size;
+        cells  = matvar->data;
+        for ( i = 0; i < ncells; i++ )
+            bytes += Mat_VarGetSize(cells[i]);
+    } else {
+        nmemb = 1;
+        for ( i = 0; i < matvar->rank; i++ )
+            nmemb *= matvar->dims[i];
+        bytes += nmemb*Mat_SizeOfClass(matvar->class_type);
+    }
+    return bytes;
+}
+
+/** @brief Adds a field to a structure
+ *
+ * Adds the given field to the structure. fields should be an array of matvar_t
+ * pointers of the same size as the structure (i.e. 1 field per structure
+ * element).
+ * @ingroup MAT
+ * @param matvar Pointer to the Structure MAT variable
+ * @param fields Array of fields to be added
+ * @retval 0 on success
+ */
+int
+Mat_VarAddStructField(matvar_t *matvar,matvar_t **fields)
+{
+    int       i, f, nfields, nmemb, cnt = 0;
+    matvar_t **new_data,**old_data;
+
+    if ( matvar == NULL || fields == NULL )
+        return -1;
+    nmemb = 1;
+    for ( i = 0; i < matvar->rank; i++ )
+        nmemb *= matvar->dims[i];
+
+    nfields = matvar->nbytes / (nmemb*sizeof(matvar_t *));
+
+    new_data = malloc((nfields+1)*nmemb*sizeof(matvar_t *));
+    if ( new_data == NULL )
+        return -1;
+
+    old_data = matvar->data;
+    for ( i = 0; i < nmemb; i++ ) {
+        for ( f = 0; f < nfields; f++ )
+            new_data[cnt++] = old_data[i*nfields+f];
+        new_data[cnt++] = fields[i];
+    }
+
+    free(matvar->data);
+    matvar->data = new_data;
+    matvar->nbytes = (nfields+1)*nmemb*sizeof(matvar_t *);
+
+    return 0;
+}
+
+/** @brief Returns the number of fields in a structure variable
+ *
+ * Returns the number of fields in the given structure.
+ * MAT file version must be 5.
+ * @ingroup MAT
+ * @param matvar Structure matlab variable
+ * @returns Number of fields, or a negative number on error
+ */
+int
+Mat_VarGetNumberOfFields(matvar_t *matvar)
+{
+    int i, nfields, nmemb = 1;
+    if ( matvar == NULL || matvar->class_type != MAT_C_STRUCT   ||
+         matvar->data_size == 0 ) {
+        nfields = -1;
+    } else {
+        for ( i = 0; i < matvar->rank; i++ )
+            nmemb *= matvar->dims[i];
+        nfields = matvar->nbytes / (nmemb*matvar->data_size);
+    }
+    return nfields;
+}
+
+/** @brief Finds a field of a structure
+ *
+ * Returns a pointer to the structure field at the given 0-relative index. MAT
+ * file version must be 5.
+ * @ingroup MAT
+ * @param matvar Pointer to the Structure MAT variable
+ * @param name_or_index Name of the field, or the 1-relative index of the field.
+ * If the index is used, it should be the address of an integer variable whose
+ * value is the index number.
+ * @param opt BY_NAME if the name_or_index is the name or BY_INDEX if the index
+ * was passed.
+ * @param index linear index of the structure to find the field of
+ * @return Pointer to the Structure Field on success, NULL on error
+ */
+matvar_t *
+Mat_VarGetStructField(matvar_t *matvar,void *name_or_index,int opt,int index)
+{
+    int       i, err = 0, nfields, nmemb;
+    matvar_t *field = NULL;
+
+    nmemb = 1;
+    for ( i = 0; i < matvar->rank; i++ )
+        nmemb *= matvar->dims[i];
+
+    nfields = matvar->nbytes / (nmemb*sizeof(matvar_t *));
+
+    if ( index >= nmemb || index < 0)
+        err = 1;
+
+    if ( !err && (opt == BY_INDEX) ) {
+        int field_index;
+
+        field_index = *(int *)name_or_index;
+
+        if ( field_index > nfields || field_index < 1 )
+            Mat_Critical("Mat_VarGetStructField: field index out of bounds");
+        else
+            field = *((matvar_t **)matvar->data+index*nfields+field_index - 1);
+    } else if ( !err && (opt == BY_NAME) ) {
+        char *field_name;
+
+        field_name = (char *)name_or_index;
+
+        for ( i = 0; i < nfields; i++ ) {
+            field = *((matvar_t **)matvar->data+index*nfields+i);
+            if ( !strcmp(field->name,field_name) )
+                break;
+            else
+                field = NULL;
+        }
+    }
+
+    return field;
+}
+
+/** @brief Indexes a structure
+ *
+ * Finds structures of a structure array given a start, stride, and edge for
+ * each dimension.  The structures are placed in a new structure array.  If
+ * copy_fields is non-zero, the indexed structures are copied and should be
+ * freed, but if copy_fields is zero, the indexed structures are pointers to
+ * the original, but should still be freed since the mem_conserve flag is set
+ * so that the structures are not freed.
+ * MAT File version must be 5.
+ * @ingroup MAT
+ * @param matvar Structure matlab variable
+ * @param start vector of length rank with 0-relative starting coordinates for
+ *              each diemnsion.
+ * @param stride vector of length rank with strides for each diemnsion.
+ * @param edge vector of length rank with the number of elements to read in
+ *              each diemnsion.
+ * @param copy_fields 1 to copy the fields, 0 to just set pointers to them.
+ *        If 0 is used, the fields should not be freed themselves.
+ * @returns A new structure with fields indexed from matvar.
+ */
+matvar_t *
+Mat_VarGetStructs(matvar_t *matvar,int *start,int *stride,int *edge,
+    int copy_fields)
+{
+    int i, j, N, I = 0;
+    int inc[10] = {0,}, cnt[10] = {0,}, dimp[10] = {0,};
+    int nfields, field;
+    matvar_t **fields, *struct_slab;
+
+    if ( (matvar == NULL) || (start == NULL) || (stride == NULL) ||  
+         (edge == NULL) ) {
+        return NULL;
+    } else if ( matvar->rank > 10 ) {
+        return NULL;
+    } else if ( matvar->class_type != MAT_C_STRUCT ) {
+        return NULL;
+    }
+
+    struct_slab = Mat_VarDuplicate(matvar,0);
+    if ( !copy_fields )
+        struct_slab->mem_conserve = 1;
+
+    nfields = matvar->nbytes / matvar->data_size;
+    for ( i = 0; i < matvar->rank; i++ )
+        nfields = nfields / matvar->dims[i];
+
+    inc[0] = stride[0]-1;
+    dimp[0] = matvar->dims[0];
+    N = edge[0];
+    I = start[0]*nfields;
+    for ( i = 1; i < matvar->rank; i++ ) {
+        inc[i]  = stride[i]-1;
+        dimp[i] = matvar->dims[i-1];
+        for ( j = i ; j--; ) {
+            inc[i]  *= matvar->dims[j]*nfields;
+            dimp[i] *= matvar->dims[j+1];
+        }
+        N *= edge[i];
+        if ( start[i] > 0 )
+            I += start[i]*dimp[i-1]*nfields;
+    }
+    struct_slab->nbytes    = N*nfields*sizeof(matvar_t *);
+    struct_slab->data = malloc(struct_slab->nbytes);
+    if ( struct_slab->data == NULL ) {
+        Mat_VarFree(struct_slab);
+        return NULL;
+    }
+    fields = struct_slab->data;
+    for ( i = 0; i < N; i+=edge[0] ) {
+        for ( j = 0; j < edge[0]; j++ ) {
+            for ( field = 0; field < nfields; field++ ) {
+                if ( copy_fields )
+                    fields[(i+j)*nfields+field] = 
+                         Mat_VarDuplicate(*((matvar_t **)matvar->data + I),1);
+                else
+                    fields[(i+j)*nfields+field] = 
+                                               *((matvar_t **)matvar->data + I);
+                I++;
+            }
+            I += stride[0]*nfields;
+        }
+        for ( j = 1; j < matvar->rank-1; j++ ) {
+            cnt[j]++;
+            if ( (cnt[j] % edge[j]) == 0 ) {
+                cnt[j] = 0;
+                if ( (I % dimp[j]) != 0 ) {
+                    I += dimp[j]-(I % dimp[j]);
+                }
+            } else {
+                I += matvar->dims[0]-edge[0]*stride[0]-start[0];
+                I += inc[j];
+                break;
+            }
+        }
+    }
+    return struct_slab;
+}
+
+/** @brief Indexes a structure
+ *
+ * Finds structures of a structure array given a single (linear)start, stride,
+ * and edge.  The structures are placed in a new structure array.  If
+ * copy_fields is non-zero, the indexed structures are copied and should be
+ * freed, but if copy_fields is zero, the indexed structures are pointers to
+ * the original, but should still be freed since the mem_conserve flag is set
+ * so that the structures are not freed.
+ * MAT File version must be 5.
+ * @ingroup MAT
+ * @param matvar Structure matlab variable
+ * @param start starting index
+ * @param stride stride
+ * @param edge Number of structures to get
+ * @param copy_fields 1 to copy the fields, 0 to just set pointers to them.
+ *        If 0 is used, the fields should not be freed themselves.
+ * @returns A new structure with fields indexed from matvar
+ */
+matvar_t *
+Mat_VarGetStructsLinear(matvar_t *matvar,int start,int stride,int edge,
+    int copy_fields)
+{
+    int i, I = 0, field, nfields;
+    matvar_t *struct_slab, **fields;
+
+    /* FIXME: Check allocations */
+    if ( matvar == NULL || matvar->rank > 10 ) {
+       struct_slab = NULL;
+    } else {
+
+        struct_slab = Mat_VarDuplicate(matvar,0);
+        if ( !copy_fields )
+            struct_slab->mem_conserve = 1;
+
+        nfields = matvar->nbytes / matvar->data_size;
+        for ( i = 0; i < matvar->rank; i++ )
+            nfields = nfields / matvar->dims[i];
+
+        struct_slab->nbytes = edge*nfields*sizeof(matvar_t *);
+        struct_slab->data = malloc(struct_slab->nbytes);
+        fields = struct_slab->data;
+        for ( i = 0; i < edge; i++ ) {
+            if ( copy_fields ) {
+                for ( field = 0; field < nfields; field++ ) {
+                    fields[i*nfields+field] = 
+                        Mat_VarDuplicate(*((matvar_t **)matvar->data+I),1);
+                    I++;
+                }
+            } else {
+                for ( field = 0; field < nfields; field++ ) {
+                    fields[i+field] = *((matvar_t **)matvar->data + I);
+                    I++;
+                }
+            }
+            I += stride;
+        }
+    }
+    return struct_slab;
+}
+
+/** @brief Prints the variable information
+ *
+ * Prints to stdout the values of the @ref matvar_t structure
+ * @ingroup MAT
+ * @param matvar Pointer to the matvar_t structure
+ * @param printdata set to 1 if the Variables data should be printed, else 0
+ */
+void
+Mat_VarPrint( matvar_t *matvar, int printdata )
+{
+    if ( matvar == NULL || matvar->fp == NULL )
+        return;
+    else if ( matvar->fp->version != MAT_FT_MAT4 )
+        Mat_VarPrint5(matvar,printdata);
+    else if ( matvar->fp->version == MAT_FT_MAT4 )
+        Mat_VarPrint4(matvar,printdata);
+    return;
+}
+
+/** @brief Reads MAT variable data from a file
+ *
+ * Reads data from a MAT variable.  The variable must have been read by
+ * Mat_VarReadInfo.
+ * @ingroup MAT
+ * @param mat MAT file to read data from
+ * @param matvar MAT variable information
+ * @param data pointer to store data in (must be pre-allocated)
+ * @param start array of starting indeces
+ * @param stride stride of data
+ * @param edge array specifying the number to read in each direction
+ * @retval 0 on success
+ */
+int
+Mat_VarReadData(mat_t *mat,matvar_t *matvar,void *data,
+      int *start,int *stride,int *edge)
+{
+    int err = 0;
+
+    if ( mat->version != MAT_FT_MAT4 )
+        err = ReadData5(mat,matvar,data,start,stride,edge);
+    else
+        err = ReadData4(mat,matvar,data,start,stride,edge);
+    return err;
+}
+
+/** @brief Reads all the data for a matlab variable
+ *
+ * Allocates memory for an reads the data for a given matlab variable.
+ * @ingroup MAT
+ * @param mat Matlab MAT file structure pointer
+ * @param matvar Variable whose data is to be read
+ * @returns non-zero on error
+ */
+int
+Mat_VarReadDataAll(mat_t *mat,matvar_t *matvar)
+{
+    int err = 0;
+
+    if ( (mat == NULL) || (matvar == NULL) )
+        err = 1;
+    else
+        ReadData(mat,matvar);
+
+    return err;
+}
+
+/** @brief Reads MAT variable data from a file
+ *
+ * Reads data from a MAT variable using a linear indexingmode. The variable
+ * must have been read by Mat_VarReadInfo.
+ * @ingroup MAT
+ * @param mat MAT file to read data from
+ * @param matvar MAT variable information
+ * @param data pointer to store data in (must be pre-allocated)
+ * @param start starting index
+ * @param stride stride of data
+ * @param edge number of elements to read
+ * @retval 0 on success
+ */
+int
+Mat_VarReadDataLinear(mat_t *mat,matvar_t *matvar,void *data,int start,
+    int stride,int edge)
+{
+    int err = 0, nmemb = 1, i, data_type;
+    mat_int32_t tag[2];
+
+    if ( mat->version == MAT_FT_MAT4 )
+        return -1;
+    fseek(mat->fp,matvar->datapos,SEEK_SET);
+    if ( matvar->compression == COMPRESSION_NONE ) {
+        fread(tag,4,2,mat->fp);
+        if ( mat->byteswap ) {
+            Mat_int32Swap(tag);
+            Mat_int32Swap(tag+1);
+        }
+        data_type = tag[0] & 0x000000ff;
+        if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
+            fseek(mat->fp,-4,SEEK_CUR);
+        }
+#if defined(HAVE_ZLIB)
+    } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+        matvar->z->avail_in = 0;
+        InflateDataType(mat,matvar,tag);
+        if ( mat->byteswap ) {
+            Mat_int32Swap(tag);
+            Mat_int32Swap(tag+1);
+        }
+        data_type = tag[0] & 0x000000ff;
+        if ( !(tag[0] & 0xffff0000) ) {/* Data is NOT packed in the tag */
+            InflateSkip(mat,matvar->z,4);
+        }
+#endif
+    }
+
+    for ( i = 0; i < matvar->rank; i++ )
+        nmemb *= matvar->dims[i];
+
+    if ( stride*(edge-1)+start+1 > nmemb ) {
+        err = 1;
+    } else {
+        stride--;
+        switch(matvar->class_type) {
+            case MAT_C_DOUBLE:
+                matvar->data_type = MAT_T_DOUBLE;
+                matvar->data_size = sizeof(double);
+                if ( matvar->compression == COMPRESSION_NONE ) {
+                    stride *= Mat_SizeOf(data_type);
+                    fseek(mat->fp,start,SEEK_CUR);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadDoubleData(mat,(double*)data+i,data_type,1);
+                        fseek(mat->fp,stride,SEEK_CUR);
+                    }
+#if defined(HAVE_ZLIB)
+                } else {
+                    z_stream z_copy;
+
+                    err = inflateCopy(&z_copy,matvar->z);
+                    InflateSkipData(mat,&z_copy,data_type,start);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadCompressedDoubleData(mat,&z_copy,(double*)data+i,
+                            data_type,1);
+                        InflateSkipData(mat,&z_copy,data_type,stride);
+                    }
+                    inflateEnd(&z_copy);
+#endif
+                }
+                break;
+            case MAT_C_SINGLE:
+                matvar->data_type = MAT_T_SINGLE;
+                matvar->data_size = sizeof(float);
+                if ( matvar->compression == COMPRESSION_NONE ) {
+                    stride *= Mat_SizeOf(data_type);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadSingleData(mat,(float*)data+i,data_type,1);
+                        fseek(mat->fp,stride,SEEK_CUR);
+                    }
+#if defined(HAVE_ZLIB)
+                } else {
+                    z_stream z_copy;
+
+                    err = inflateCopy(&z_copy,matvar->z);
+                    InflateSkipData(mat,&z_copy,data_type,start);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadCompressedSingleData(mat,&z_copy,(float*)data+i,
+                            data_type,1);
+                        InflateSkipData(mat,&z_copy,data_type,stride);
+                    }
+                    inflateEnd(&z_copy);
+#endif
+                }
+                break;
+#ifdef HAVE_MAT_INT64_T
+            case MAT_C_INT64:
+                matvar->data_type = MAT_T_INT64;
+                matvar->data_size = sizeof(mat_int64_t);
+                if ( matvar->compression == COMPRESSION_NONE ) {
+                    stride *= Mat_SizeOf(data_type);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadInt64Data(mat,(mat_int64_t*)data+i,data_type,1);
+                        fseek(mat->fp,stride,SEEK_CUR);
+                    }
+#if defined(HAVE_ZLIB)
+                } else {
+                    z_stream z_copy;
+
+                    err = inflateCopy(&z_copy,matvar->z);
+                    InflateSkipData(mat,&z_copy,data_type,start);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadCompressedInt64Data(mat,&z_copy,(mat_int64_t*)data+i,
+                            data_type,1);
+                        InflateSkipData(mat,&z_copy,data_type,stride);
+                    }
+                    inflateEnd(&z_copy);
+#endif
+                }
+                break;
+#endif /* HAVE_MAT_INT64_T */
+#ifdef HAVE_MAT_UINT64_T
+            case MAT_C_UINT64:
+                matvar->data_type = MAT_T_UINT64;
+                matvar->data_size = sizeof(mat_uint64_t);
+                if ( matvar->compression == COMPRESSION_NONE ) {
+                    stride *= Mat_SizeOf(data_type);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadInt64Data(mat,(mat_int64_t*)data+i,data_type,1);
+                        fseek(mat->fp,stride,SEEK_CUR);
+                    }
+#if defined(HAVE_ZLIB)
+                } else {
+                    z_stream z_copy;
+
+                    err = inflateCopy(&z_copy,matvar->z);
+                    InflateSkipData(mat,&z_copy,data_type,start);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadCompressedInt64Data(mat,&z_copy,(mat_int64_t*)data+i,
+                            data_type,1);
+                        InflateSkipData(mat,&z_copy,data_type,stride);
+                    }
+                    inflateEnd(&z_copy);
+#endif
+                }
+                break;
+#endif /* HAVE_MAT_UINT64_T */
+            case MAT_C_INT32:
+                matvar->data_type = MAT_T_INT32;
+                matvar->data_size = sizeof(mat_int32_t);
+                if ( matvar->compression == COMPRESSION_NONE ) {
+                    stride *= Mat_SizeOf(data_type);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadInt32Data(mat,(mat_int32_t*)data+i,data_type,1);
+                        fseek(mat->fp,stride,SEEK_CUR);
+                    }
+#if defined(HAVE_ZLIB)
+                } else {
+                    z_stream z_copy;
+
+                    err = inflateCopy(&z_copy,matvar->z);
+                    InflateSkipData(mat,&z_copy,data_type,start);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadCompressedInt32Data(mat,&z_copy,(mat_int32_t*)data+i,
+                            data_type,1);
+                        InflateSkipData(mat,&z_copy,data_type,stride);
+                    }
+                    inflateEnd(&z_copy);
+#endif
+                }
+                break;
+            case MAT_C_UINT32:
+                matvar->data_type = MAT_T_UINT32;
+                matvar->data_size = sizeof(mat_uint32_t);
+                if ( matvar->compression == COMPRESSION_NONE ) {
+                    stride *= Mat_SizeOf(data_type);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadInt32Data(mat,(mat_int32_t*)data+i,data_type,1);
+                        fseek(mat->fp,stride,SEEK_CUR);
+                    }
+#if defined(HAVE_ZLIB)
+                } else {
+                    z_stream z_copy;
+
+                    err = inflateCopy(&z_copy,matvar->z);
+                    InflateSkipData(mat,&z_copy,data_type,start);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadCompressedInt32Data(mat,&z_copy,(mat_int32_t*)data+i,
+                            data_type,1);
+                        InflateSkipData(mat,&z_copy,data_type,stride);
+                    }
+                    inflateEnd(&z_copy);
+#endif
+                }
+                break;
+            case MAT_C_INT16:
+                matvar->data_type = MAT_T_INT16;
+                matvar->data_size = sizeof(mat_int16_t);
+                if ( matvar->compression == COMPRESSION_NONE ) {
+                    stride *= Mat_SizeOf(data_type);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadInt16Data(mat,(mat_int16_t*)data+i,data_type,1);
+                        fseek(mat->fp,stride,SEEK_CUR);
+                    }
+#if defined(HAVE_ZLIB)
+                } else {
+                    z_stream z_copy;
+
+                    err = inflateCopy(&z_copy,matvar->z);
+                    InflateSkipData(mat,&z_copy,data_type,start);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadCompressedInt16Data(mat,&z_copy,(mat_int16_t*)data+i,
+                            data_type,1);
+                        InflateSkipData(mat,&z_copy,data_type,stride);
+                    }
+                    inflateEnd(&z_copy);
+#endif
+                }
+                break;
+            case MAT_C_UINT16:
+                matvar->data_type = MAT_T_UINT16;
+                matvar->data_size = sizeof(mat_uint16_t);
+                if ( matvar->compression == COMPRESSION_NONE ) {
+                    stride *= Mat_SizeOf(data_type);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadInt16Data(mat,(mat_int16_t*)data+i,data_type,1);
+                        fseek(mat->fp,stride,SEEK_CUR);
+                    }
+#if defined(HAVE_ZLIB)
+                } else {
+                    z_stream z_copy;
+
+                    err = inflateCopy(&z_copy,matvar->z);
+                    InflateSkipData(mat,&z_copy,data_type,start);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadCompressedInt16Data(mat,&z_copy,(mat_int16_t*)data+i,
+                            data_type,1);
+                        InflateSkipData(mat,&z_copy,data_type,stride);
+                    }
+                    inflateEnd(&z_copy);
+#endif
+                }
+                break;
+            case MAT_C_INT8:
+                matvar->data_type = MAT_T_INT8;
+                matvar->data_size = sizeof(mat_int8_t);
+                if ( matvar->compression == COMPRESSION_NONE ) {
+                    stride *= Mat_SizeOf(data_type);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadInt8Data(mat,(mat_int8_t*)data+i,data_type,1);
+                        fseek(mat->fp,stride,SEEK_CUR);
+                    }
+#if defined(HAVE_ZLIB)
+                } else {
+                    z_stream z_copy;
+
+                    err = inflateCopy(&z_copy,matvar->z);
+                    InflateSkipData(mat,&z_copy,data_type,start);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadCompressedInt8Data(mat,&z_copy,(mat_int8_t*)data+i,
+                            data_type,1);
+                        InflateSkipData(mat,&z_copy,data_type,stride);
+                    }
+                    inflateEnd(&z_copy);
+#endif
+                }
+                break;
+            case MAT_C_UINT8:
+                matvar->data_type = MAT_T_UINT8;
+                matvar->data_size = sizeof(mat_uint8_t);
+                if ( matvar->compression == COMPRESSION_NONE ) {
+                    stride *= Mat_SizeOf(data_type);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadInt8Data(mat,(mat_int8_t*)data+i,data_type,1);
+                        fseek(mat->fp,stride,SEEK_CUR);
+                    }
+#if defined(HAVE_ZLIB)
+                } else {
+                    z_stream z_copy;
+
+                    err = inflateCopy(&z_copy,matvar->z);
+                    InflateSkipData(mat,&z_copy,data_type,start);
+                    for ( i = 0; i < edge; i++ ) {
+                        ReadCompressedInt8Data(mat,&z_copy,(mat_int8_t*)data+i,
+                            data_type,1);
+                        InflateSkipData(mat,&z_copy,data_type,stride);
+                    }
+                    inflateEnd(&z_copy);
+#endif
+                }
+                break;
+        }
+    }
+
+    return err;
+}
+
+/** @brief Reads the information of the next variable in a MAT file
+ *
+ * Reads the next variable's information (class,flags-complex/global/logical,
+ * rank,dimensions, name, etc) from the Matlab MAT file.  After reading, the MAT
+ * file is positioned past the current variable.
+ * @ingroup MAT
+ * @param mat Pointer to the MAT file
+ * @return Pointer to the @ref matvar_t structure containing the MAT
+ * variable information
+ */
+matvar_t *
+Mat_VarReadNextInfo( mat_t *mat )
+{
+    if( mat == NULL )
+        return NULL;
+    else if ( mat->version == 0x0100 )
+        return Mat_VarReadNextInfo5(mat);
+    else
+        return Mat_VarReadNextInfo4(mat);
+
+    return NULL;
+}
+
+/** @brief Reads the information of a variable with the given name from a MAT file
+ *
+ * Reads the named variable (or the next variable if name is NULL) information
+ * (class,flags-complex/global/logical,rank,dimensions,and name) from the
+ * Matlab MAT file
+ * @ingroup MAT
+ * @param mat Pointer to the MAT file
+ * @param name Name of the variable to read
+ * @return Pointer to the @ref matvar_t structure containing the MAT
+ * variable information
+ */
+matvar_t *
+Mat_VarReadInfo( mat_t *mat, char *name )
+{
+
+    long  fpos;
+    matvar_t *matvar = NULL;
+
+    if ( (mat == NULL) || (name == NULL) )
+        return NULL;
+
+    fpos = ftell(mat->fp);
+
+    fseek(mat->fp,mat->bof,SEEK_SET);
+    do {
+#if 0
+        err = fread(&data_type,4,1,mat->fp);
+        if ( !err )
+            return NULL;
+        err = fread(&nBytes,4,1,mat->fp);
+        if ( mat->byteswap ) {
+            Mat_int32Swap(&data_type);
+            Mat_int32Swap(&nBytes);
+        }
+        curpos = ftell(mat->fp);
+        fseek(mat->fp,-8,SEEK_CUR);
+#endif
+        matvar = Mat_VarReadNextInfo(mat);
+        if ( matvar != NULL ) {
+            if ( !matvar->name ) {
+                Mat_VarFree(matvar);
+                matvar = NULL;
+            } else if ( strcmp(matvar->name,name) ) {
+                Mat_VarFree(matvar);
+                matvar = NULL;
+            }
+        } else {
+            Mat_Critical("An error occurred in reading the MAT file");
+            break;
+        }
+#if 0
+        fseek(mat->fp,curpos+nBytes,SEEK_SET);
+#endif
+    } while ( !matvar && !feof(mat->fp) );
+
+    fseek(mat->fp,fpos,SEEK_SET);
+    return matvar;
+}
+
+/** @brief Reads the variable with the given name from a MAT file
+ *
+ * Reads the next variable in the Matlab MAT file
+ * @ingroup MAT
+ * @param mat Pointer to the MAT file
+ * @param name Name of the variable to read
+ * @return Pointer to the @ref matvar_t structure containing the MAT
+ * variable information
+ */
+matvar_t *
+Mat_VarRead( mat_t *mat, char *name )
+{
+    long  fpos;
+    matvar_t *matvar = NULL;;
+
+    if ( (mat == NULL) || (name == NULL) )
+        return NULL;
+
+    fpos = ftell(mat->fp);
+    matvar = Mat_VarReadInfo(mat,name);
+    if ( matvar )
+        ReadData(mat,matvar);
+    fseek(mat->fp,fpos,SEEK_SET);
+    return matvar;
+}
+
+/** @brief Reads the next variable in a MAT file
+ *
+ * Reads the next variable in the Matlab MAT file
+ * @ingroup MAT
+ * @param mat Pointer to the MAT file
+ * @return Pointer to the @ref matvar_t structure containing the MAT
+ * variable information
+ */
+matvar_t *
+Mat_VarReadNext( mat_t *mat )
+{
+    long fpos;
+    matvar_t *matvar = NULL;
+
+    if ( feof(mat->fp) )
+        return NULL;
+    /* Read position so we can reset the file position if an error occurs */
+    fpos = ftell(mat->fp);
+    matvar = Mat_VarReadNextInfo(mat);
+    if ( matvar != NULL)
+        ReadData(mat,matvar);
+    else
+        fseek(mat->fp,fpos,SEEK_SET);
+    return matvar;
+}
+
+/** @brief Writes the given MAT variable to a MAT file
+ *
+ * Writes the MAT variable information stored in matvar to the given MAT file.
+ * The variable will be written to the end of the file.
+ * @ingroup MAT
+ * @param mat MAT file to write to
+ * @param matvar MAT variable information to write
+ * @retval 0 on success
+ */
+int
+Mat_VarWriteInfo(mat_t *mat, matvar_t *matvar )
+{
+    if ( mat == NULL || matvar == NULL || mat->fp == NULL )
+        return -1;
+    else if ( mat->version != MAT_FT_MAT4 )
+        WriteInfo5(mat,matvar);
+#if 0
+    else if ( mat->version == MAT_FT_MAT4 )
+        WriteInfo4(mat,matvar);
+#endif
+
+    return 0;
+}
+
+/** @brief Writes the given data to the MAT variable
+ *
+ * Writes data to a MAT variable.  The variable must have previously been
+ * written with Mat_VarWriteInfo.
+ * @ingroup MAT
+ * @param mat MAT file to write to
+ * @param matvar MAT variable information to write
+ * @param data pointer to the data to write
+ * @param start array of starting indeces
+ * @param stride stride of data
+ * @param edge array specifying the number to read in each direction
+ * @retval 0 on success
+ */
+int
+Mat_VarWriteData(mat_t *mat,matvar_t *matvar,void *data,
+      int *start,int *stride,int *edge)
+{
+    int err = 0, k, N = 1;
+
+    fseek(mat->fp,matvar->datapos+8,SEEK_SET);
+
+    if ( mat == NULL || matvar == NULL || data == NULL ) {
+        err = -1;
+    } else if ( start == NULL && stride == NULL && edge == NULL ) {
+        for ( k = 0; k < matvar->rank; k++ )
+            N *= matvar->dims[k];
+        if ( matvar->compression == COMPRESSION_NONE )
+            WriteData(mat,data,N,matvar->data_type);
+#if 0
+        else if ( matvar->compression == COMPRESSION_ZLIB ) {
+            WriteCompressedData(mat,matvar->z,data,N,matvar->data_type);
+            (void)deflateEnd(matvar->z);
+            free(matvar->z);
+            matvar->z = NULL;
+        }
+#endif
+    } else if ( matvar->rank == 2 ) {
+        if ( stride[0]*(edge[0]-1)+start[0]+1 > matvar->dims[0] ) {
+            err = 1;
+        } else if ( stride[1]*(edge[1]-1)+start[1]+1 > matvar->dims[1] ) {
+            err = 1;
+        } else {
+            switch ( matvar->class_type ) {
+                case MAT_C_DOUBLE:
+                case MAT_C_SINGLE:
+                case MAT_C_INT64:
+                case MAT_C_UINT64:
+                case MAT_C_INT32:
+                case MAT_C_UINT32:
+                case MAT_C_INT16:
+                case MAT_C_UINT16:
+                case MAT_C_INT8:
+                case MAT_C_UINT8:
+                    WriteDataSlab2(mat,data,matvar->data_type,matvar->dims,
+                                   start,stride,edge);
+                    break;
+                case MAT_C_CHAR:
+                    WriteCharDataSlab2(mat,data,matvar->data_type,matvar->dims,
+                                   start,stride,edge);
+                    break;
+            }
+        }
+    }
+
+    return err;
+}
+
+/** @brief Writes the given MAT variable to a MAT file
+ *
+ * Writes the MAT variable information stored in matvar to the given MAT file.
+ * The variable will be written to the end of the file.
+ * @ingroup MAT
+ * @param mat MAT file to write to
+ * @param matvar MAT variable information to write
+ * @param compress Whether or not to compress the data
+ *        (Only valid for version 5 MAT files and variables with numeric data)
+ * @retval 0 on success
+ */
+int
+Mat_VarWrite( mat_t *mat, matvar_t *matvar, int compress )
+{
+    if ( mat == NULL || matvar == NULL )
+        return -1;
+    else if ( mat->version != MAT_FT_MAT4 )
+        Write5(mat,matvar,compress);
+
+    return 0;
+}

+ 744 - 0
matlabAccess/matio/src/mat4.c

@@ -0,0 +1,744 @@
+/** @file mat4.c
+ * Matlab MAT version 4 file functions
+ * @ingroup MAT
+ */
+/*
+ * Copyright (C) 2005-2006   Christopher C. Hulbert
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "matio.h"
+#include "mat4.h"
+#include "matio_private.h"
+
+static const char *v4_class_type_desc[16] = {
+       "Undefined","Cell Array","Structure",
+       "Object","Character Array","Sparse Array","Double Precision Array",
+       "Single Precision Array", "8-bit, signed Integer Array",
+       "8-bit, Unsigned Integer Array","16-bit, signed Integer Array",
+       "16-bit, unsigned Integer Array","32-bit, signed Integer Array",
+       "32-bit, unsigned Integer Array","Matlab Array","Compressed Data"
+};
+static const char *v4_data_type_desc[23] = {
+       "Unknown","8-bit, signed integer",
+       "8-bit, unsigned integer","16-bit, signed integer",
+       "16-bit, unsigned integer","32-bit, signed integer",
+       "32-bit, unsigned integer","IEEE 754 single-precision","RESERVED",
+       "IEEE 754 double-precision","RESERVED","RESERVED",
+       "64-bit, signed integer","64-bit, unsigned integer", "Matlab Array",
+       "Compressed Data","Unicode UTF-8 Encoded Character Data",
+       "Unicode UTF-16 Encoded Character Data",
+       "Unicode UTF-32 Encoded Character Data","","String","Cell Array",
+       "Structure"
+};
+
+void
+Read4(mat_t *mat,matvar_t *matvar)
+{
+    unsigned int N;
+    if ( fseek(mat->fp,matvar->datapos,SEEK_SET) )
+        return;
+
+    N = matvar->dims[0]*matvar->dims[1];
+    switch ( matvar->data_type ) {
+        case MAT_T_DOUBLE:
+            matvar->data_size = sizeof(double);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes   = N*sizeof(double);
+                complex_data     = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                matvar->data     = complex_data;
+                if ( complex_data != NULL &&
+                     complex_data->Re != NULL && complex_data->Im != NULL ) {
+                    fread(complex_data->Re,N,sizeof(double),mat->fp);
+                    fread(complex_data->Im,N,sizeof(double),mat->fp);
+                }
+            } else {
+                matvar->nbytes = N*sizeof(double);
+                matvar->data   = malloc(matvar->nbytes);
+                if ( matvar->data != NULL )
+                    fread(matvar->data,N,sizeof(double),mat->fp);
+            }
+            break;
+        case MAT_T_SINGLE:
+            matvar->data_size = sizeof(float);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes   = N*sizeof(float);
+                complex_data     = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                matvar->data     = complex_data;
+                if ( complex_data != NULL &&
+                     complex_data->Re != NULL && complex_data->Im != NULL ) {
+                    fread(complex_data->Re,N,sizeof(float),mat->fp);
+                    fread(complex_data->Im,N,sizeof(float),mat->fp);
+                }
+            } else {
+                matvar->nbytes = N*sizeof(float);
+                matvar->data   = malloc(matvar->nbytes);
+                if ( matvar->data != NULL )
+                    fread(matvar->data,N,sizeof(float),mat->fp);
+            }
+            break;
+        case MAT_T_INT32:
+            matvar->data_size = sizeof(mat_int32_t);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes   = N*sizeof(mat_int32_t);
+                complex_data     = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                matvar->data     = complex_data;
+                if ( complex_data != NULL &&
+                     complex_data->Re != NULL && complex_data->Im != NULL ) {
+                    fread(complex_data->Re,N,sizeof(mat_int32_t),mat->fp);
+                    fread(complex_data->Im,N,sizeof(mat_int32_t),mat->fp);
+                }
+            } else {
+                matvar->nbytes = N*sizeof(mat_int32_t);
+                matvar->data   = malloc(matvar->nbytes);
+                if ( matvar->data != NULL )
+                    fread(matvar->data,N,sizeof(mat_int32_t),mat->fp);
+            }
+            break;
+        case MAT_T_INT16:
+            matvar->data_size = sizeof(mat_int16_t);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes   = N*sizeof(mat_int16_t);
+                complex_data     = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                matvar->data     = complex_data;
+                if ( complex_data != NULL &&
+                     complex_data->Re != NULL && complex_data->Im != NULL ) {
+                    fread(complex_data->Re,N,sizeof(mat_int16_t),mat->fp);
+                    fread(complex_data->Im,N,sizeof(mat_int16_t),mat->fp);
+                }
+            } else {
+                matvar->nbytes = N*sizeof(mat_int16_t);
+                matvar->data   = malloc(matvar->nbytes);
+                if ( matvar->data != NULL )
+                    fread(matvar->data,N,sizeof(mat_int16_t),mat->fp);
+            }
+            break;
+        case MAT_T_UINT16:
+            matvar->data_size = sizeof(mat_uint16_t);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes   = N*sizeof(mat_uint16_t);
+                complex_data     = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                matvar->data     = complex_data;
+                if ( complex_data != NULL &&
+                     complex_data->Re != NULL && complex_data->Im != NULL ) {
+                    fread(complex_data->Re,N,sizeof(mat_uint16_t),mat->fp);
+                    fread(complex_data->Im,N,sizeof(mat_uint16_t),mat->fp);
+                }
+            } else {
+                matvar->nbytes = N*sizeof(mat_uint16_t);
+                matvar->data   = malloc(matvar->nbytes);
+                if ( matvar->data != NULL )
+                    fread(matvar->data,N,sizeof(mat_uint16_t),mat->fp);
+            }
+            break;
+        case MAT_T_UINT8:
+            matvar->data_size = sizeof(mat_uint8_t);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes   = N*sizeof(mat_uint8_t);
+                complex_data     = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                matvar->data     = complex_data;
+                if ( complex_data != NULL &&
+                     complex_data->Re != NULL && complex_data->Im != NULL ) {
+                    fread(complex_data->Re,N,sizeof(mat_uint8_t),mat->fp);
+                    fread(complex_data->Im,N,sizeof(mat_uint8_t),mat->fp);
+                }
+            } else {
+                matvar->nbytes = N*sizeof(mat_uint8_t);
+                matvar->data   = malloc(matvar->nbytes);
+                if ( matvar->data != NULL )
+                    fread(matvar->data,N,sizeof(mat_uint8_t),mat->fp);
+            }
+            break;
+        default:
+            Mat_Critical("MAT V4 data type error");
+            return;
+    }
+
+    return;
+}
+
+/* Reads a slab of data from the variable */
+int
+ReadData4(mat_t *mat,matvar_t *matvar,void *data,
+      int *start,int *stride,int *edge)
+{
+    int err = 0, class_type;
+
+    fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+    switch( matvar->data_type ) {
+        case MAT_T_DOUBLE:
+            class_type = MAT_C_DOUBLE;
+            break;
+        case MAT_T_SINGLE:
+            class_type = MAT_C_SINGLE;
+            break;
+        case MAT_T_INT32:
+            class_type = MAT_C_INT32;
+            break;
+        case MAT_T_INT16:
+            class_type = MAT_C_INT16;
+            break;
+        case MAT_T_UINT16:
+            class_type = MAT_C_UINT16;
+            break;
+        case MAT_T_UINT8:
+            class_type = MAT_C_UINT8;
+            break;
+    }
+
+    if ( matvar->rank == 2 ) {
+        if ( stride[0]*(edge[0]-1)+start[0]+1 > matvar->dims[0] )
+            err = 1;
+        else if ( stride[1]*(edge[1]-1)+start[1]+1 > matvar->dims[1] )
+            err = 1;
+        if ( matvar->isComplex ) {
+            struct ComplexSplit *cdata = data;
+            long nbytes = edge[0]*edge[1]*Mat_SizeOf(matvar->data_type);
+
+            ReadDataSlab2(mat,cdata->Re,class_type,matvar->data_type,
+                    matvar->dims,start,stride,edge);
+            fseek(mat->fp,matvar->datapos+nbytes,SEEK_SET);
+            ReadDataSlab2(mat,cdata->Im,class_type,
+                matvar->data_type,matvar->dims,start,stride,edge);
+        } else {
+            ReadDataSlab2(mat,data,class_type,matvar->data_type,
+                    matvar->dims,start,stride,edge);
+        }
+    } else {
+        if ( matvar->isComplex ) {
+            int i;
+            struct ComplexSplit *cdata = data;
+            long nbytes = Mat_SizeOf(matvar->data_type);
+
+            for ( i = 0; i < matvar->rank; i++ )
+                nbytes *= edge[i];
+
+            ReadDataSlabN(mat,cdata->Re,class_type,matvar->data_type,
+                matvar->rank,matvar->dims,start,stride,edge);
+            fseek(mat->fp,matvar->datapos+nbytes,SEEK_SET);
+            ReadDataSlab2(mat,cdata->Im,class_type,
+                matvar->data_type,matvar->dims,start,stride,edge);
+        } else {
+            ReadDataSlabN(mat,data,class_type,matvar->data_type,
+                matvar->rank,matvar->dims,start,stride,edge);
+        }
+    }
+    return err;
+}
+
+matvar_t *
+Mat_VarReadNextInfo4(mat_t *mat)
+{       
+    int       tmp;
+    int       M,O;
+    long      nBytes;
+    size_t    err;
+    matvar_t *matvar = NULL;
+
+    if ( mat == NULL || mat->fp == NULL )
+        return NULL;
+    else if ( NULL == (matvar = calloc(1,sizeof(*matvar))) )
+        return NULL;
+
+    matvar->dims = NULL;
+    matvar->data = NULL;
+    matvar->name = NULL;
+    matvar->fp   = mat;
+#if defined(HAVE_ZLIB)
+    matvar->z    = NULL;
+#endif
+
+    matvar->fpos = ftell(mat->fp);
+
+    err = fread(&tmp,sizeof(int),1,mat->fp);
+    if ( !err ) {
+        free(matvar);
+        return NULL;
+    }
+    M = floor(tmp / 1000.0);
+    tmp -= M*1000;
+    O = floor(tmp / 100.0);
+    tmp -= O*100;
+    matvar->data_type = floor(tmp / 10.0);
+    tmp -= matvar->data_type*10;
+    /* Convert the V4 data type */
+    switch ( matvar->data_type ) {
+        case 0:
+            matvar->data_type = MAT_T_DOUBLE;
+            break;
+        case 1:
+            matvar->data_type = MAT_T_SINGLE;
+            break;
+        case 2:
+            matvar->data_type = MAT_T_INT32;
+            break;
+        case 3:
+            matvar->data_type = MAT_T_INT16;
+            break;
+        case 4:
+            matvar->data_type = MAT_T_UINT16;
+            break;
+        case 5:
+            matvar->data_type = MAT_T_UINT8;
+            break;
+        default:
+            matvar->data_type = -1;
+            break;
+    }
+    matvar->class_type = floor(tmp);
+    switch ( matvar->class_type ) {
+        case 0:
+            matvar->class_type = MAT_C_DOUBLE;
+            break;
+        case 1:
+            matvar->class_type = MAT_C_CHAR;
+            break;
+        case 2:
+            matvar->class_type = MAT_C_SPARSE;
+            break;
+    }
+    matvar->rank = 2;
+    /* FIXME: Check allocation */
+    matvar->dims = malloc(2*sizeof(int));
+    err = fread(matvar->dims,sizeof(int),1,mat->fp);
+    if ( !err ) {
+        Mat_VarFree(matvar);
+        return NULL;
+    }
+    err = fread(matvar->dims+1,sizeof(int),1,mat->fp);
+    if ( !err ) {
+        Mat_VarFree(matvar);
+        return NULL;
+    }
+    err = fread(&(matvar->isComplex),sizeof(int),1,mat->fp);
+    if ( !err ) {
+        Mat_VarFree(matvar);
+        return NULL;
+    }
+    err = fread(&tmp,sizeof(int),1,mat->fp);
+    if ( !err ) {
+        Mat_VarFree(matvar);
+        return NULL;
+    }
+    /* FIXME: Check allocation */
+    matvar->name = malloc(tmp);
+    err = fread(matvar->name,1,tmp,mat->fp);
+    if ( !err ) {
+        Mat_VarFree(matvar);
+        return NULL;
+    }
+
+    matvar->datapos = ftell(mat->fp);
+    nBytes = matvar->dims[0]*matvar->dims[1]*Mat_SizeOf(matvar->data_type);
+    if ( matvar->isComplex )
+        nBytes *= 2;
+    fseek(mat->fp,nBytes,SEEK_CUR);
+                
+    return matvar;  
+}
+
+void
+Mat_VarPrint4(matvar_t *matvar,int printdata)
+{
+    int i, j;
+
+    if ( matvar == NULL )
+        return;
+    if ( matvar->name )
+        Mat_Message("      Name: %s", matvar->name);
+    Mat_Message("      Rank: %d", matvar->rank);
+    if ( matvar->rank == 0 )
+        return;
+    if ( matvar->isComplex )
+        Mat_Message("Class Type: %s (complex)",v4_class_type_desc[matvar->class_type]);
+    else
+        Mat_Message("Class Type: %s",v4_class_type_desc[matvar->class_type]);
+    if ( matvar->data_type )
+        Mat_Message(" Data Type: %s",v4_data_type_desc[matvar->data_type]);
+    if ( matvar->data != NULL && matvar->data_size > 0 ) {
+        switch( matvar->class_type ) {
+            case MAT_C_DOUBLE:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) && 
+                           matvar->isComplex ) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    double *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%f + %fi ",re[matvar->dims[0]*j+i],
+                                               im[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%f ", ((double*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 && matvar->isComplex) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    double *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%f + %fi ",re[matvar->dims[0]*j+i],
+                                               im[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%f ", ((double*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                }
+                break;
+            case MAT_C_SINGLE:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) && 
+                           matvar->isComplex ) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    float *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%f + %fi",
+                                re[matvar->dims[0]*j+i],
+                                im[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%f ", ((float*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 && matvar->isComplex) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    float *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%f + %fi ",re[matvar->dims[0]*j+i],
+                                               im[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%f ", ((float*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                }
+                break;
+            case MAT_C_INT32:
+            {
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) && 
+                           matvar->isComplex ) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    mat_int32_t *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%d + %di ",re[matvar->dims[0]*j+i],
+                                               im[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    mat_int32_t *data = matvar->data;
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%d ",data[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 && matvar->isComplex) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    mat_int32_t *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%d + %di ",re[matvar->dims[0]*j+i],
+                                               im[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else if ( matvar->rank == 2 ) {
+                    mat_int32_t *data = matvar->data;
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%d ", data[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                }
+                break;
+            }
+            case MAT_C_INT16:
+            {
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) && 
+                           matvar->isComplex ) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    mat_int16_t *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hd + %hdi ",re[matvar->dims[0]*j+i],
+                                   im[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    mat_int16_t *data = matvar->data;
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hd ",data[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 && matvar->isComplex) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    mat_int16_t *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hd + %hdi ",re[matvar->dims[0]*j+i],
+                                im[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else if ( matvar->rank == 2 ) {
+                    mat_int16_t *data = matvar->data;
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hd ", data[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                }
+                break;
+            }
+            case MAT_C_UINT16:
+            {
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) && 
+                           matvar->isComplex ) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    mat_uint16_t *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hu + %hui ",re[matvar->dims[0]*j+i],
+                                                 im[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    mat_int16_t *data = matvar->data;
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hu ",data[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 && matvar->isComplex) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    mat_uint16_t *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hu + %hui ",re[matvar->dims[0]*j+i],
+                                                 im[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else if ( matvar->rank == 2 ) {
+                    mat_int16_t *data = matvar->data;
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hu ", data[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                }
+                break;
+            }
+            case MAT_C_UINT8:
+            {
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) && 
+                           matvar->isComplex ) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    mat_int8_t *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hu + %hui ",re[matvar->dims[0]*j+i],
+                                                 im[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if (matvar->rank == 2 &&
+                           (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    mat_int8_t *data = matvar->data;
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hu ",(mat_uint16_t)data[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 && matvar->isComplex) {
+                    int N;
+                    struct ComplexSplit *cdata = matvar->data;
+                    mat_int8_t *re = cdata->Re,*im = cdata->Im;
+                    N = matvar->dims[0]*matvar->dims[1];
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hu + %hui ",re[matvar->dims[0]*j+i],
+                                                 im[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else if ( matvar->rank == 2 ) {
+                    mat_int8_t *data = matvar->data;
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hu ",(mat_uint16_t)data[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                }
+                break;
+            }
+        }
+    }
+    return;
+}

+ 30 - 0
matlabAccess/matio/src/mat4.h

@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2008   Christopher C. Hulbert
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef MAT4_H
+#define MAT4_H
+
+#include "matio.h"
+
+void Read4(mat_t *mat, matvar_t *matvar);
+int  ReadData4(mat_t *mat,matvar_t *matvar,void *data,
+         int *start,int *stride,int *edge);
+
+void Mat_VarPrint4( matvar_t *matvar, int printdata );
+matvar_t *Mat_VarReadNextInfo4(mat_t *mat);
+
+#endif

+ 7103 - 0
matlabAccess/matio/src/mat5.c

@@ -0,0 +1,7103 @@
+/** @file mat5.c
+ * Matlab MAT version 5 file functions
+ * @ingroup MAT
+ */
+/*
+ * Copyright (C) 2005-2006   Christopher C. Hulbert
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* FIXME: Implement Unicode support */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+#include "matio.h"
+#include "mat5.h"
+#include "matio_private.h"
+
+static const char *class_type_desc[16] = {"Undefined","Cell Array","Structure",
+       "Object","Character Array","Sparse Array","Double Precision Array",
+       "Single Precision Array", "8-bit, signed Integer Array",
+       "8-bit, Unsigned Integer Array","16-bit, signed Integer Array",
+       "16-bit, unsigned Integer Array","32-bit, signed Integer Array",
+       "32-bit, unsigned Integer Array","Matlab Array","Compressed Data"};
+static const char *data_type_desc[23] = {"Unknown","8-bit, signed integer",
+       "8-bit, unsigned integer","16-bit, signed integer",
+       "16-bit, unsigned integer","32-bit, signed integer",
+       "32-bit, unsigned integer","IEEE 754 single-precision","RESERVED",
+       "IEEE 754 double-precision","RESERVED","RESERVED",
+       "64-bit, signed integer","64-bit, unsigned integer", "Matlab Array",
+       "Compressed Data","Unicode UTF-8 Encoded Character Data",
+       "Unicode UTF-16 Encoded Character Data",
+       "Unicode UTF-32 Encoded Character Data","","String","Cell Array",
+       "Structure"};
+
+/*
+ * -------------------------------------------------------------
+ *   Private Functions
+ * -------------------------------------------------------------
+ */
+
+static size_t GetMatrixMaxBufSize(matvar_t *matvar);
+static size_t GetStructFieldBufSize(matvar_t *matvar);
+static size_t GetCellArrayFieldBufSize(matvar_t *matvar);
+
+/** @brief determines the number of bytes needed to store the given struct field
+ *
+ * @ingroup mat_internal
+ * @param matvar field of a structure
+ * @return the number of bytes needed to store the struct field
+ */
+static size_t
+GetStructFieldBufSize(matvar_t *matvar)
+{
+    size_t nBytes = 0,len;
+    size_t tag_size = 8, array_flags_size = 8;
+    int    nmemb = 1, i;
+
+    if ( matvar == NULL )
+        return nBytes;
+
+    /* Have to account for the matrix tag in a struct field */
+    nBytes += tag_size;
+
+    /* Add the Array Flags tag and space to the number of bytes */
+    nBytes += tag_size + array_flags_size;
+
+    /* In a struct field, the name is just a tag with 0 bytes */
+    nBytes += tag_size;
+
+    /* Add rank and dimensions, padded to an 8 byte block */
+    for ( i = 0, len = 0; i < matvar->rank; i++ )
+        nmemb *= matvar->dims[i];
+    if ( matvar->rank % 2 )
+        nBytes += tag_size + matvar->rank*4 + 4;
+    else
+        nBytes += tag_size + matvar->rank*4;
+
+    if ( matvar->class_type == MAT_C_STRUCT ) {
+        matvar_t **fields = matvar->data;
+        int i, nfields;
+        size_t maxlen = 0;
+
+        nfields = matvar->nbytes / (nmemb*matvar->data_size);
+        for ( i = 0; i < nfields; i++ ) {
+            if ( NULL != fields[i]->name && strlen(fields[i]->name) > maxlen )
+                maxlen = strlen(fields[i]->name);
+        }
+        maxlen++;
+        while ( nfields*maxlen % 8 != 0 )
+            maxlen++;
+
+        nBytes += tag_size + tag_size + maxlen*nfields;
+
+        /* FIXME: Add bytes for the fieldnames */
+        if ( NULL != fields && nfields > 0 ) {
+            for ( i = 0; i < nfields*nmemb; i++ )
+                nBytes += GetStructFieldBufSize(fields[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_CELL ) {
+        matvar_t **cells = matvar->data;
+        int i, ncells = matvar->nbytes / matvar->data_size;
+
+        if ( NULL != cells && ncells > 0 ) {
+            for ( i = 0; i < ncells; i++ )
+                nBytes += GetCellArrayFieldBufSize(cells[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_SPARSE ) {
+        sparse_t *sparse = matvar->data;
+
+        nBytes += tag_size + sparse->njc*sizeof(mat_int32_t) +
+                  tag_size + sparse->nir*sizeof(mat_int32_t) +
+                  tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+        if ( matvar->isComplex )
+            nBytes += tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+    } else {
+        nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+        if (nmemb*Mat_SizeOf(matvar->data_type) % 8) {
+            nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+          }
+        if ( matvar->isComplex ) {
+            nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+            if (nmemb*Mat_SizeOf(matvar->data_type) % 8) {
+                nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+              }
+          }
+    }
+    
+    return nBytes;
+}
+
+/** @brief determines the number of bytes needed to store the cell array element
+ *
+ * @ingroup mat_internal
+ * @param matvar MAT variable
+ * @return the number of bytes needed to store the variable
+ */
+static size_t
+GetCellArrayFieldBufSize(matvar_t *matvar)
+{
+    size_t nBytes = 0,len;
+    size_t tag_size = 8, array_flags_size = 8;
+    int    nmemb = 1, i;
+
+    if ( matvar == NULL )
+        return nBytes;
+
+    /* Have to account for the matrix tag in a struct field */
+    nBytes += tag_size;
+
+    /* Add the Array Flags tag and space to the number of bytes */
+    nBytes += tag_size + array_flags_size;
+
+    /* Get size of variable name, pad it to an 8 byte block, and add it to nBytes */
+    if ( NULL != matvar->name )
+        len = strlen(matvar->name);
+    else
+        len=4;
+
+    if ( len <= 4 ) {
+        nBytes += tag_size;
+    } else {
+        if ( len % 8 )
+            len = len + (8 - len % 8);
+        nBytes += tag_size + len;
+    }
+
+    /* Add rank and dimensions, padded to an 8 byte block */
+    for ( i = 0, len = 0; i < matvar->rank; i++ )
+        nmemb *= matvar->dims[i];
+    if ( matvar->rank % 2 )
+        nBytes += tag_size + matvar->rank*4 + 4;
+    else
+        nBytes += tag_size + matvar->rank*4;
+
+    if ( matvar->class_type == MAT_C_STRUCT ) {
+        matvar_t **fields = matvar->data;
+        int i, nfields;
+        size_t maxlen = 0;
+
+        nfields = matvar->nbytes / (nmemb*matvar->data_size);
+        for ( i = 0; i < nfields; i++ ) {
+            if ( NULL != fields[i]->name && strlen(fields[i]->name) > maxlen )
+                maxlen = strlen(fields[i]->name);
+        }
+        maxlen++;
+        while ( nfields*maxlen % 8 != 0 )
+            maxlen++;
+
+        nBytes += tag_size + tag_size + maxlen*nfields;
+
+        if ( NULL != fields && nfields > 0 ) {
+            for ( i = 0; i < nfields*nmemb; i++ )
+                nBytes += GetStructFieldBufSize(fields[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_CELL ) {
+        matvar_t **cells = matvar->data;
+        int i, ncells = matvar->nbytes / matvar->data_size;
+
+        if ( NULL != cells && ncells > 0 ) {
+            for ( i = 0; i < ncells; i++ )
+                nBytes += GetCellArrayFieldBufSize(cells[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_SPARSE ) {
+        sparse_t *sparse = matvar->data;
+
+        nBytes += tag_size + sparse->njc*sizeof(mat_int32_t) +
+                  tag_size + sparse->nir*sizeof(mat_int32_t) +
+                  tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+        if ( matvar->isComplex )
+            nBytes += tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+    } else {
+        nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+        if ( nmemb*Mat_SizeOf(matvar->data_type) % 8 ) {
+            nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+          }
+        if ( matvar->isComplex ) {
+            nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+            if ( nmemb*Mat_SizeOf(matvar->data_type) % 8 ) {
+                nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+              }
+          }
+    }
+    
+    return nBytes;
+}
+
+/** @brief determines the number of bytes needed to store the given variable
+ *
+ * @ingroup mat_internal
+ * @param matvar MAT variable
+ * @return the number of bytes needed to store the variable
+ */
+static size_t
+GetMatrixMaxBufSize(matvar_t *matvar)
+{
+    size_t nBytes = 0,len;
+    size_t tag_size = 8, array_flags_size = 8;
+    int    nmemb = 1, i;
+
+    if ( matvar == NULL )
+        return nBytes;
+
+    /* Add the Array Flags tag and space to the number of bytes */
+    nBytes += tag_size + array_flags_size;
+
+    /* Get size of variable name, pad it to an 8 byte block, and add it to nBytes */
+    if ( NULL != matvar->name )
+        len = strlen(matvar->name);
+    else
+        len=8;
+
+    if ( len <= 4 ) {
+        nBytes += tag_size;
+    } else {
+        if ( len % 8 )
+            len = len + (8 - len % 8);
+        nBytes += tag_size + len;
+    }
+
+    /* Add rank and dimensions, padded to an 8 byte block */
+    for ( i = 0, len = 0; i < matvar->rank; i++ )
+        nmemb *= matvar->dims[i];
+    if ( matvar->rank % 2 )
+        nBytes += tag_size + matvar->rank*4 + 4;
+    else
+        nBytes += tag_size + matvar->rank*4;
+
+    if ( matvar->class_type == MAT_C_STRUCT ) {
+        matvar_t **fields = matvar->data;
+        int i, nfields;
+        size_t maxlen = 0;
+
+        nfields = matvar->nbytes / (nmemb*matvar->data_size);
+        for ( i = 0; i < nfields; i++ ) {
+            if ( NULL != fields[i]->name && strlen(fields[i]->name) > maxlen )
+                maxlen = strlen(fields[i]->name);
+        }
+        maxlen++;
+        while ( nfields*maxlen % 8 != 0 )
+            maxlen++;
+
+        nBytes += tag_size + tag_size + maxlen*nfields;
+
+        /* FIXME: Add bytes for the fieldnames */
+        if ( NULL != fields && nfields > 0 ) {
+            for ( i = 0; i < nfields*nmemb; i++ )
+                nBytes += GetStructFieldBufSize(fields[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_CELL ) {
+        matvar_t **cells = matvar->data;
+        int i, ncells = matvar->nbytes / matvar->data_size;
+
+        if ( NULL != cells && ncells > 0 ) {
+            for ( i = 0; i < ncells; i++ )
+                nBytes += GetCellArrayFieldBufSize(cells[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_SPARSE ) {
+        sparse_t *sparse = matvar->data;
+
+        nBytes += tag_size + sparse->njc*sizeof(mat_int32_t) +
+                  tag_size + sparse->nir*sizeof(mat_int32_t) +
+                  tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+        if ( matvar->isComplex )
+            nBytes += tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+    } else {
+        nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+        if ( nmemb*Mat_SizeOf(matvar->data_type) % 8 ) {
+            nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+          }
+        if ( matvar->isComplex ) {
+            nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+            if ( nmemb*Mat_SizeOf(matvar->data_type) % 8 ) {
+                nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+              }
+          }
+    }
+    
+    return nBytes;
+}
+
+/** @brief Writes @c data as character data
+ *
+ * This function uses the knowledge that the data is part of a character class
+ * to avoid some pitfalls with Matlab listed below.
+ *   @li Matlab character data cannot be unsigned 8-bit integers, it needs at
+ *       least unsigned 16-bit integers
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data character data to write
+ * @param N Number of elements to write
+ * @param data_type character data type (enum matio_types)
+ * @return number of bytes written
+ */ 
+int
+WriteCharData(mat_t *mat, void *data, int N,int data_type)
+{
+    int nBytes = 0, bytesread = 0, i;
+    mat_int8_t pad1 = 0;
+
+    switch ( data_type ) {
+        case MAT_T_UINT16:
+        {
+            nBytes = N*2;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            fwrite(data,2,N,mat->fp);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT8:
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t *ptr;
+            mat_uint16_t c;
+
+            /* Matlab can't read MAT_C_CHAR as uint8, needs uint16 */
+            nBytes = N*2;
+            data_type = MAT_T_UINT16;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            ptr = data;
+            for ( i = 0; i < N; i++ ) {
+                c = (mat_uint16_t)*(char *)ptr;
+                fwrite(&c,2,1,mat->fp);
+                ptr++;
+            }
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            break;
+        }
+        case MAT_T_UTF8:
+        {
+            mat_uint8_t *ptr;
+
+            nBytes = N;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            ptr = data;
+            fwrite(ptr,1,nBytes,mat->fp);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            break;
+        }
+    }
+    bytesread+=nBytes;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Writes @c data as compressed character data
+ *
+ * This function uses the knowledge that the data is part of a character class
+ * to avoid some pitfalls with Matlab listed below.
+ *   @li Matlab character data cannot be unsigned 8-bit integers, it needs at
+ *       least unsigned 16-bit integers
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z pointer to the zlib compression stream
+ * @param data character data to write
+ * @param N Number of elements to write
+ * @param data_type character data type (enum matio_types)
+ * @return number of bytes written
+ */ 
+size_t
+WriteCompressedCharData(mat_t *mat,z_stream *z,void *data,int N,int data_type)
+{
+    int nBytes = 0, data_size, data_tag[2], err, byteswritten = 0;
+    int buf_size = 1024, i;
+    mat_uint8_t   buf[1024], pad[8] = {0,};
+
+    if ((mat == NULL) || (data == NULL) || (mat->fp == NULL))
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_UINT16:
+        {
+            data_size = 2;
+            data_tag[0]  = MAT_T_UINT16;
+            data_tag[1]  = N*data_size;
+            z->next_in   = data_tag;
+            z->avail_in  = 8;
+            z->next_out  = buf;
+            z->avail_out = buf_size;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            z->next_in   = data;
+            z->avail_in  = data_size*N;
+            do {
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            } while ( z->avail_out == 0 );
+            /* Add/Compress padding to pad to 8-byte boundary */
+            if ( N*data_size % 8 ) {
+                z->next_in   = pad;
+                z->avail_in  = 8 - (N*data_size % 8);
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t *ptr;
+            mat_uint16_t c;
+
+            /* Matlab can't read MAT_C_CHAR as uint8, needs uint16 */
+            data_size    = 2;
+            data_tag[0]  = MAT_T_UINT16;
+            data_tag[1]  = N*data_size;
+            z->next_in   = data_tag;
+            z->avail_in  = 8;
+            z->next_out  = buf;
+            z->avail_out = buf_size;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            z->next_in   = data;
+            z->avail_in  = data_size*N;
+            ptr = data;
+            for ( i = 0; i < N; i++ ) {
+                c = (mat_uint16_t)*(char *)ptr;
+                z->next_in   = &c;
+                z->avail_in  = 2;
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+                ptr++;
+            }
+            /* Add/Compress padding to pad to 8-byte boundary */
+            if ( N*data_size % 8 ) {
+                z->next_in   = pad;
+                z->avail_in  = 8 - (N*data_size % 8);
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            }
+            break;
+        }
+        case MAT_T_UTF8:
+        {
+            data_size = 1;
+            data_tag[0]  = MAT_T_UTF8;
+            data_tag[1]  = N*data_size;
+            z->next_in   = data_tag;
+            z->avail_in  = 8;
+            z->next_out  = buf;
+            z->avail_out = buf_size;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            z->next_in   = data;
+            z->avail_in  = data_size*N;
+            do {
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            } while ( z->avail_out == 0 );
+            /* Add/Compress padding to pad to 8-byte boundary */
+            if ( N*data_size % 8 ) {
+                z->next_in   = pad;
+                z->avail_in  = 8 - (N*data_size % 8);
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            }
+            break;
+        }
+    }
+    return byteswritten;
+}
+#endif
+
+/** @brief Writes empty characters to the MAT file
+ *
+ * This function uses the knowledge that the data is part of a character class
+ * to avoid some pitfalls with Matlab listed below.
+ *   @li Matlab character data cannot be unsigned 8-bit integers, it needs at
+ *       least unsigned 16-bit integers
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data character data to write
+ * @param N Number of elements to write
+ * @param data_type character data type (enum matio_types)
+ * @return number of bytes written
+ */ 
+int
+WriteEmptyCharData(mat_t *mat, int N, int data_type)
+{
+    int nBytes = 0, bytesread = 0, i;
+    mat_int8_t pad1 = 0;
+
+    switch ( data_type ) {
+        case MAT_T_UINT8: /* Matlab MAT_C_CHAR needs uint16 */
+        case MAT_T_INT8:  /* Matlab MAT_C_CHAR needs uint16 */
+            data_type = MAT_T_UINT16;
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t u16 = 0;
+            nBytes = N*sizeof(mat_uint16_t);
+            fwrite(&data_type,sizeof(mat_int32_t),1,mat->fp);
+            fwrite(&nBytes,sizeof(mat_int32_t),1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&u16,sizeof(mat_uint16_t),1,mat->fp);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            break;
+        }
+        case MAT_T_UTF8:
+        {
+            mat_uint8_t u8 = 0;
+            nBytes = N;
+            fwrite(&data_type,sizeof(mat_int32_t),1,mat->fp);
+            fwrite(&nBytes,sizeof(mat_int32_t),1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&u8,sizeof(mat_uint8_t),1,mat->fp);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            break;
+        }
+    }
+    bytesread+=nBytes;
+    return bytesread;
+}
+
+/* @brief Writes the data tags and empty data to the file
+ *
+ * Writes the data tags and empty data to the file to save space for the
+ * variable when the actual data is written
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param N number of elements to write
+ * @param data_type data type to write
+ * @return Number of bytes written
+ */
+int
+WriteEmptyData(mat_t *mat,int N,int data_type)
+{
+    int nBytes = 0, data_size, i;
+
+    if ( (mat == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d = 0.0;
+
+            data_size = sizeof(double);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&d,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f = 0.0;
+
+            data_size = sizeof(float);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&f,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8 = 0;
+
+            data_size = sizeof(mat_int8_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i8,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8 = 0;
+
+            data_size = sizeof(mat_uint8_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui8,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16 = 0;
+
+            data_size = sizeof(mat_int16_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i16,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16 = 0;
+
+            data_size = sizeof(mat_uint16_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui16,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32 = 0;
+
+            data_size = sizeof(mat_int32_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i32,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32 = 0;
+
+            data_size = sizeof(mat_uint32_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui32,data_size,1,mat->fp);
+            break;
+        }
+#ifdef HAVE_MAT_INT64_T
+        case MAT_T_INT64:
+        {
+            mat_int64_t i64 = 0;
+
+            data_size = sizeof(mat_int64_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i64,data_size,1,mat->fp);
+            break;
+        }
+#endif
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_T_UINT64:
+        {
+            mat_uint64_t ui64 = 0;
+
+            data_size = sizeof(mat_uint64_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui64,data_size,1,mat->fp);
+            break;
+        }
+#endif
+        default:
+            nBytes = 0;
+    }
+    return nBytes;
+}
+
+#if defined(HAVE_ZLIB)
+int
+WriteCompressedEmptyData(mat_t *mat,z_stream *z,int N,int data_type)
+{
+    int nBytes = 0, data_size, i, err, byteswritten = 0;
+
+    if ( (mat == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            mat_uint32_t uncomp_buf[32] = {0,};
+            mat_uint32_t comp_buf[32] = {0,};
+            double data_uncomp_buf[4] = {0.0,};
+
+            data_size = sizeof(double);
+            nBytes = N*data_size;
+            uncomp_buf[0] = data_type;
+            uncomp_buf[1] = 0;
+            z->next_out  = comp_buf;
+            z->next_in   = uncomp_buf;
+            z->avail_out = 32*sizeof(*comp_buf);
+            z->avail_in  = 8;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,32*sizeof(*comp_buf)-z->avail_out,mat->fp);
+            for ( i = 0; i < N; i++ ) {
+                z->next_out  = comp_buf;
+                z->next_in   = data_uncomp_buf;
+                z->avail_out = 32*sizeof(*comp_buf);
+                z->avail_in  = 8;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,32*sizeof(*comp_buf)-z->avail_out,1,mat->fp);
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f = 0.0;
+
+            data_size = sizeof(float);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&f,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8 = 0;
+
+            data_size = sizeof(mat_int8_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i8,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8 = 0;
+
+            data_size = sizeof(mat_uint8_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui8,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16 = 0;
+
+            data_size = sizeof(mat_int16_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i16,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16 = 0;
+
+            data_size = sizeof(mat_uint16_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui16,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32 = 0;
+
+            data_size = sizeof(mat_int32_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i32,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32 = 0;
+
+            data_size = sizeof(mat_uint32_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui32,data_size,1,mat->fp);
+            break;
+        }
+#ifdef HAVE_MAT_INT64_T
+        case MAT_T_INT64:
+        {
+            mat_int64_t i64 = 0;
+
+            data_size = sizeof(mat_int64_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i64,data_size,1,mat->fp);
+            break;
+        }
+#endif
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_T_UINT64:
+        {
+            mat_uint64_t ui64 = 0;
+
+            data_size = sizeof(mat_uint64_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui64,data_size,1,mat->fp);
+            break;
+        }
+#endif
+        default:
+            nBytes = 0;
+    }
+    return byteswritten;
+}
+#endif
+
+/** @param Writes a 2-D slab of data to the MAT file
+ *
+ * @ingroup mat_internal
+ * @fixme should return the number of bytes written, but currently returns 0
+ * @param mat MAT file pointer
+ * @param data pointer to the slab of data
+ * @param data_type data type of the data (enum matio_types)
+ * @param dims dimensions of the dataset
+ * @param start index to start writing the data in each dimension
+ * @param stride write data every @c stride elements
+ * @param edge number of elements to write in each dimension
+ * @return number of byteswritten
+ */
+int
+WriteDataSlab2(mat_t *mat,void *data,int data_type,int *dims,int *start,
+              int *stride,int *edge)
+{
+    int nBytes = 0, data_size, i, j;
+    long pos, row_stride, col_stride;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
+         (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
+        return 0;
+    }
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double *ptr;
+
+            data_size = sizeof(double);
+            ptr = (double *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float *ptr;
+
+            data_size = sizeof(float);
+            ptr = (float *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+#ifdef HAVE_MAT_INT64_T
+        case MAT_T_INT64:
+        {
+            mat_int64_t *ptr;
+
+            data_size = sizeof(mat_int64_t);
+            ptr = (mat_int64_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+#endif
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_T_UINT64:
+        {
+            mat_uint64_t *ptr;
+
+            data_size = sizeof(mat_uint64_t);
+            ptr = (mat_uint64_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+#endif
+        case MAT_T_INT32:
+        {
+            mat_int32_t *ptr;
+
+            data_size = sizeof(mat_int32_t);
+            ptr = (mat_int32_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t *ptr;
+
+            data_size = sizeof(mat_uint32_t);
+            ptr = (mat_uint32_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t *ptr;
+
+            data_size = sizeof(mat_int16_t);
+            ptr = (mat_int16_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t *ptr;
+
+            data_size = sizeof(mat_uint16_t);
+            ptr = (mat_uint16_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t *ptr;
+
+            data_size = sizeof(mat_int8_t);
+            ptr = (mat_int8_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t *ptr;
+
+            data_size = sizeof(mat_uint8_t);
+            ptr = (mat_uint8_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        default:
+            nBytes = 0;
+    }
+    return nBytes;
+}
+
+/** @param Writes a 2-D slab of character data to the MAT file
+ *
+ * This function uses the knowledge that the data is part of a character class
+ * to avoid some pitfalls with Matlab listed below.
+ *   @li Matlab character data cannot be unsigned 8-bit integers, it needs at
+ *       least unsigned 16-bit integers
+ * @ingroup mat_internal
+ * @fixme should return the number of bytes written, but currently returns 0
+ * @param mat MAT file pointer
+ * @param data pointer to the slab of data
+ * @param data_type data type of the data (enum matio_types)
+ * @param dims dimensions of the dataset
+ * @param start index to start writing the data in each dimension
+ * @param stride write data every @c stride elements
+ * @param edge number of elements to write in each dimension
+ * @return number of byteswritten
+ */
+int
+WriteCharDataSlab2(mat_t *mat,void *data,int data_type,int *dims,int *start,
+              int *stride,int *edge)
+{
+    int nBytes = 0, data_size, i, j;
+    long pos, row_stride, col_stride;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
+         (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
+        return 0;
+    }
+
+    switch ( data_type ) {
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t *ptr;
+
+            data_size = sizeof(mat_uint16_t);
+            ptr = data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        case MAT_T_UINT8:
+        {
+            /* Matlab can't read MAT_C_CHAR as uint8, needs uint16 */
+            mat_uint8_t *ptr;
+            mat_uint16_t c;
+
+            data_size = sizeof(mat_uint16_t);
+            ptr = data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++,ptr++ ) {
+                    c = *ptr;
+                    fwrite(&c,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_UTF8:
+        {
+            mat_uint8_t *ptr;
+
+            data_size = sizeof(mat_uint8_t);
+            ptr = data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++,ptr++ ) {
+                    fwrite(ptr,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        default:
+            nBytes = 0;
+    }
+    return nBytes;
+}
+
+/** @brief Writes the data buffer to the file
+ *
+ * @param mat MAT file pointer
+ * @param data pointer to the data to write
+ * @param N number of elements to write
+ * @param data_type data type of the data
+ * @return number of bytes written
+ */
+int
+WriteData(mat_t *mat,void *data,int N,int data_type)
+{
+    int nBytes = 0, data_size;
+
+    if ((mat == NULL) || (mat->fp == NULL) || (data == NULL && N > 0))
+        return 0;
+
+    data_size = Mat_SizeOf(data_type);
+    nBytes    = N*data_size;
+    fwrite(&data_type,4,1,mat->fp);
+    fwrite(&nBytes,4,1,mat->fp);
+    fwrite(data,data_size,N,mat->fp);
+
+    return nBytes;
+}
+
+#if defined(HAVE_ZLIB)
+/* Compresses the data buffer and writes it to the file */
+size_t
+WriteCompressedData(mat_t *mat,z_stream *z,void *data,int N,int data_type)
+{
+    int nBytes = 0, data_size, data_tag[2], err, byteswritten = 0;
+    int buf_size = 1024;
+    mat_uint8_t   buf[1024], pad[8] = {0,};
+
+    if ((mat == NULL) || (data == NULL) || (mat->fp == NULL))
+        return 0;
+
+    data_size = Mat_SizeOf(data_type);
+
+    data_tag[0]  = data_type;
+    data_tag[1]  = data_size*N;
+    z->next_in   = data_tag;
+    z->avail_in  = 8;
+    z->next_out  = buf;
+    z->avail_out = buf_size;
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+    z->next_in   = data;
+    z->avail_in  = N*data_size;
+    do {
+        z->next_out  = buf;
+        z->avail_out = buf_size;
+        err = deflate(z,Z_NO_FLUSH);
+        byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+    } while ( z->avail_out == 0 );
+    /* Add/Compress padding to pad to 8-byte boundary */
+    if ( N*data_size % 8 ) {
+        z->next_in   = pad;
+        z->avail_in  = 8 - (N*data_size % 8);
+        z->next_out  = buf;
+        z->avail_out = buf_size;
+        err = deflate(z,Z_NO_FLUSH);
+        byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+    }
+    nBytes = byteswritten;
+    return nBytes;
+}
+#endif
+
+/** @brief Reads the next cell of the cell array in @c matvar
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar MAT variable pointer
+ * @return Number of bytes read
+ */
+int
+ReadNextCell( mat_t *mat, matvar_t *matvar )
+{
+    int ncells, bytesread = 0, i, err;
+    matvar_t **cells = NULL;
+
+    if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+        mat_uint32_t uncomp_buf[16] = {0,};
+        int      nbytes;
+        mat_uint32_t array_flags; 
+
+        ncells = 1;
+        for ( i = 0; i < matvar->rank; i++ )
+            ncells *= matvar->dims[i];
+        matvar->data_size = sizeof(matvar_t *);
+        matvar->nbytes    = ncells*matvar->data_size;
+        matvar->data = malloc(matvar->nbytes);
+        if ( !matvar->data )
+            return bytesread;
+        cells = matvar->data;
+        for ( i = 0; i < ncells; i++ ) {
+            cells[i] = Mat_VarCalloc();
+            if ( NULL == cells[i] ) {
+                Mat_Critical("Couldn't allocate memory for cell %d", i);
+                continue;
+            }
+
+            cells[i]->fpos = ftell(mat->fp)-matvar->z->avail_in;
+
+            /* Read variable tag for cell */
+            bytesread += InflateVarTag(mat,matvar,uncomp_buf);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            nbytes = uncomp_buf[1];
+            if ( uncomp_buf[0] != MAT_T_MATRIX ) {
+                Mat_Critical("cells[%d], Uncompressed type not MAT_T_MATRIX",i);
+                Mat_VarFree(cells[i]);
+                cells[i] = NULL;
+                return -1;
+            }
+            cells[i]->compression = 1;
+            bytesread += InflateArrayFlags(mat,matvar,uncomp_buf);
+            nbytes -= 16;
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+                (void)Mat_uint32Swap(uncomp_buf+2);
+                (void)Mat_uint32Swap(uncomp_buf+3);
+            }
+            /* Array Flags */
+            if ( uncomp_buf[0] == MAT_T_UINT32 ) {
+               array_flags = uncomp_buf[2];
+               cells[i]->class_type  = (array_flags & MAT_F_CLASS_T);
+               cells[i]->isComplex   = (array_flags & MAT_F_COMPLEX);
+               cells[i]->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               cells[i]->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( cells[i]->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   cells[i]->nbytes      = uncomp_buf[3];
+               }
+            } else {
+                Mat_Critical("Expected MAT_T_UINT32 for Array Tags, got %d",
+                               uncomp_buf[0]);
+                bytesread+=InflateSkip(mat,matvar->z,nbytes);
+            }
+            bytesread += InflateDimensions(mat,matvar,uncomp_buf);
+            nbytes -= 8;
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            /* Rank and Dimension */
+            if ( uncomp_buf[0] == MAT_T_INT32 ) {
+                int j = 0;
+
+                cells[i]->rank = uncomp_buf[1];
+                nbytes -= cells[i]->rank;
+                cells[i]->rank /= 4;
+                cells[i]->dims = malloc(cells[i]->rank*sizeof(int));
+                if ( mat->byteswap ) {
+                    for ( j = 0; j < cells[i]->rank; j++ )
+                        cells[i]->dims[j] = Mat_uint32Swap(uncomp_buf+2+j);
+                } else {
+                    for ( j = 0; j < cells[i]->rank; j++ )
+                        cells[i]->dims[j] = uncomp_buf[2+j];
+                }
+                if ( cells[i]->rank % 2 != 0 )
+                    nbytes -= 4;
+            }
+            bytesread += InflateVarNameTag(mat,matvar,uncomp_buf);
+            nbytes -= 8;
+            cells[i]->z = calloc(1,sizeof(z_stream));
+            err = inflateCopy(cells[i]->z,matvar->z);
+            if ( err != Z_OK )
+                Mat_Critical("inflateCopy returned error %d",err);
+            cells[i]->datapos = ftell(mat->fp)-matvar->z->avail_in;
+            if ( cells[i]->class_type == MAT_C_STRUCT )
+                bytesread+=ReadNextStructField(mat,cells[i]);
+            else if ( cells[i]->class_type == MAT_C_CELL )
+                bytesread+=ReadNextCell(mat,cells[i]);
+            fseek(mat->fp,cells[i]->datapos,SEEK_SET);
+            bytesread+=InflateSkip(mat,matvar->z,nbytes);
+        }
+#else
+        Mat_Critical("Not compiled with zlib support");
+#endif
+
+    } else {
+        int ncells;
+        mat_uint32_t buf[16];
+        int      nbytes,nBytes;
+        mat_uint32_t array_flags; 
+
+        ncells = 1;
+        for ( i = 0; i < matvar->rank; i++ )
+            ncells *= matvar->dims[i];
+        matvar->data_size = sizeof(matvar_t *);
+        matvar->nbytes    = ncells*matvar->data_size;
+        matvar->data = malloc(matvar->nbytes);
+        if ( !matvar->data ) {
+            Mat_Critical("Couldn't allocate memory for %s->data",matvar->name);
+            return bytesread;
+        }
+        cells = (matvar_t **)matvar->data;
+        for ( i = 0; i < ncells; i++ ) {
+            cells[i] = Mat_VarCalloc();
+            if ( !cells[i] ) {
+                Mat_Critical("Couldn't allocate memory for cell %d", i);
+                continue;
+            }
+
+            cells[i]->fpos = ftell(mat->fp);
+
+            /* Read variable tag for cell */
+            bytesread += fread(buf,4,2,mat->fp);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(buf);
+                (void)Mat_uint32Swap(buf+1);
+            }
+            nBytes = buf[1];
+            if ( buf[0] != MAT_T_MATRIX ) {
+                Mat_Critical("cells[%d] not MAT_T_MATRIX, fpos = %ld",i,ftell(mat->fp));
+                Mat_VarFree(cells[i]);
+                cells[i] = NULL;
+                continue;
+            }
+            cells[i]->compression = 0;
+#if defined(HAVE_ZLIB)
+            cells[i]->z = NULL;
+#endif
+
+            /* Read Array Flags and The Dimensions Tag */
+            bytesread  += fread(buf,4,6,mat->fp);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(buf);
+                (void)Mat_uint32Swap(buf+1);
+                (void)Mat_uint32Swap(buf+2);
+                (void)Mat_uint32Swap(buf+3);
+                (void)Mat_uint32Swap(buf+4);
+                (void)Mat_uint32Swap(buf+5);
+            }
+            nBytes-=24;
+            /* Array Flags */
+            if ( buf[0] == MAT_T_UINT32 ) {
+               array_flags = buf[2];
+               cells[i]->class_type  = (array_flags & MAT_F_CLASS_T);
+               cells[i]->isComplex   = (array_flags & MAT_F_COMPLEX);
+               cells[i]->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               cells[i]->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( cells[i]->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   cells[i]->nbytes      = buf[3];
+               }
+            }
+            /* Rank and Dimension */
+            if ( buf[4] == MAT_T_INT32 ) {
+                int j;
+                nbytes = buf[5];
+                nBytes-=nbytes;
+
+                cells[i]->rank = nbytes / 4;
+                cells[i]->dims = malloc(cells[i]->rank*sizeof(int));
+
+                /* Assumes rank <= 16 */
+                if ( cells[i]->rank % 2 != 0 ) {
+                    bytesread+=fread(buf,4,cells[i]->rank+1,mat->fp);
+                    nBytes-=4;
+                } else
+                    bytesread+=fread(buf,4,cells[i]->rank,mat->fp);
+
+                if ( mat->byteswap ) {
+                    for ( j = 0; j < cells[i]->rank; j++ )
+                        cells[i]->dims[j] = Mat_uint32Swap(buf+j);
+                } else {
+                    for ( j = 0; j < cells[i]->rank; j++ )
+                        cells[i]->dims[j] = buf[j];
+                }
+            }
+            /* Variable Name Tag */
+            bytesread+=fread(buf,1,8,mat->fp);
+            nBytes-=8;
+            cells[i]->datapos = ftell(mat->fp);
+            if ( cells[i]->class_type == MAT_C_STRUCT )
+                bytesread+=ReadNextStructField(mat,cells[i]);
+            if ( cells[i]->class_type == MAT_C_CELL )
+                bytesread+=ReadNextCell(mat,cells[i]);
+            fseek(mat->fp,cells[i]->datapos+nBytes,SEEK_SET);
+        }
+    }
+
+    return bytesread;
+}
+
+/** @brief Reads the next struct field of the structure in @c matvar
+ *
+ * Reads the next struct fields (fieldname length,names,data headers for all
+ * the fields
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar MAT variable pointer
+ * @return Number of bytes read
+ */
+int
+ReadNextStructField( mat_t *mat, matvar_t *matvar )
+{
+    int fieldname_size,nfields, bytesread = 0, i, err;
+    matvar_t **fields = NULL;
+
+    if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+        char    *ptr;
+        mat_uint32_t uncomp_buf[16] = {0,};
+        int      nbytes, j, nmemb = 1;
+        mat_uint32_t array_flags; 
+
+        for ( i = 0; i < matvar->rank; i++ )
+            nmemb *= matvar->dims[i];
+
+        /* Inflate Field name length */
+        bytesread += InflateFieldNameLength(mat,matvar,uncomp_buf);
+        if ( mat->byteswap ) {
+            (void)Mat_uint32Swap(uncomp_buf);
+            (void)Mat_uint32Swap(uncomp_buf+1);
+        }
+        if ( (uncomp_buf[0] & 0x0000ffff) == MAT_T_INT32 ) {
+            fieldname_size = uncomp_buf[1];
+        } else {
+            Mat_Warning("Error getting fieldname size");
+            return bytesread;
+        }
+
+        bytesread += InflateFieldNamesTag(mat,matvar,uncomp_buf);
+        if ( mat->byteswap ) {
+            (void)Mat_uint32Swap(uncomp_buf);
+            (void)Mat_uint32Swap(uncomp_buf+1);
+        }
+        nfields = uncomp_buf[1];
+        nfields = nfields / fieldname_size;
+        matvar->data_size = sizeof(matvar_t *);
+        matvar->nbytes    = nmemb*nfields*matvar->data_size;
+        matvar->data      = malloc(matvar->nbytes);
+        if ( !matvar->data )
+            return 1;
+        fields = matvar->data;
+        if ( nfields*fieldname_size % 8 != 0 )
+            i = 8-(nfields*fieldname_size % 8);
+        else
+            i = 0;
+        ptr = malloc(nfields*fieldname_size+i);
+        bytesread += InflateFieldNames(mat,matvar,ptr,nfields,fieldname_size,i);
+        for ( i = 0; i < nfields; i++ ) {
+            fields[i]       = calloc(1,sizeof(matvar_t));
+            fields[i]->name = malloc(fieldname_size);
+            memcpy(fields[i]->name,ptr+i*fieldname_size,fieldname_size);
+            fields[i]->name[fieldname_size-1] = '\0';
+        }
+        for ( i = 1; i < nmemb; i++ ) {
+            for ( j = 0; j < nfields; j++ ) {
+                fields[i*nfields+j] = calloc(1,sizeof(matvar_t));
+                fields[i*nfields+j]->name = strdup_printf("%s",fields[j]->name);
+            }
+        }
+
+        for ( i = 0; i < nmemb*nfields; i++ ) {
+            fields[i]->fpos = ftell(mat->fp)-matvar->z->avail_in;
+            /* Read variable tag for struct field */
+            bytesread += InflateVarTag(mat,matvar,uncomp_buf);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            nbytes = uncomp_buf[1];
+            if ( uncomp_buf[0] != MAT_T_MATRIX ) {
+                Mat_Critical("fields[%d], Uncompressed type not MAT_T_MATRIX",i);
+                Mat_VarFree(fields[i]);
+                fields[i] = NULL;
+                continue;
+            } else if ( nbytes == 0 ) {
+                fields[i]->rank = 0;
+                continue;
+            }
+            fields[i]->compression = COMPRESSION_ZLIB;
+            bytesread += InflateArrayFlags(mat,matvar,uncomp_buf);
+            nbytes -= 16;
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+                (void)Mat_uint32Swap(uncomp_buf+2);
+                (void)Mat_uint32Swap(uncomp_buf+3);
+            }
+            /* Array Flags */
+            if ( uncomp_buf[0] == MAT_T_UINT32 ) {
+               array_flags = uncomp_buf[2];
+               fields[i]->class_type  = (array_flags & MAT_F_CLASS_T);
+               fields[i]->isComplex   = (array_flags & MAT_F_COMPLEX);
+               fields[i]->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               fields[i]->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( fields[i]->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   fields[i]->nbytes      = uncomp_buf[3];
+               }
+            } else {
+                Mat_Critical("Expected MAT_T_UINT32 for Array Tags, got %d",
+                    uncomp_buf[0]);
+                bytesread+=InflateSkip(mat,matvar->z,nbytes);
+            }
+            bytesread += InflateDimensions(mat,matvar,uncomp_buf);
+            nbytes -= 8;
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            /* Rank and Dimension */
+            if ( uncomp_buf[0] == MAT_T_INT32 ) {
+                int j = 0;
+
+                fields[i]->rank = uncomp_buf[1];
+                nbytes -= fields[i]->rank;
+                fields[i]->rank /= 4;
+                fields[i]->dims = malloc(fields[i]->rank*sizeof(int));
+                if ( mat->byteswap ) {
+                    for ( j = 0; j < fields[i]->rank; j++ )
+                        fields[i]->dims[j] = Mat_uint32Swap(uncomp_buf+2+j);
+                } else {
+                    for ( j = 0; j < fields[i]->rank; j++ )
+                        fields[i]->dims[j] = uncomp_buf[2+j];
+                }
+                if ( fields[i]->rank % 2 != 0 )
+                    nbytes -= 4;
+            }
+            bytesread += InflateVarNameTag(mat,matvar,uncomp_buf);
+            nbytes -= 8;
+            fields[i]->z = calloc(1,sizeof(z_stream));
+            err = inflateCopy(fields[i]->z,matvar->z);
+            if ( err != Z_OK ) {
+                Mat_Critical("inflateCopy returned error %d",err);
+            }
+            fields[i]->datapos = ftell(mat->fp)-matvar->z->avail_in;
+            if ( fields[i]->class_type == MAT_C_STRUCT )
+                bytesread+=ReadNextStructField(mat,fields[i]);
+            else if ( fields[i]->class_type == MAT_C_CELL )
+                bytesread+=ReadNextCell(mat,fields[i]);
+            fseek(mat->fp,fields[i]->datapos,SEEK_SET);
+            bytesread+=InflateSkip(mat,matvar->z,nbytes);
+        }
+        free(ptr);
+#else
+        Mat_Critical("Not compiled with zlib support");
+#endif
+    } else {
+        int fieldname_size,nfields;
+        mat_uint32_t buf[16] = {0,};
+        int      nbytes,nBytes,nmemb=1,j;
+        mat_uint32_t array_flags; 
+
+        for ( i = 0; i < matvar->rank; i++ )
+            nmemb *= matvar->dims[i];
+
+        bytesread+=fread(buf,4,2,mat->fp);
+        if ( mat->byteswap ) {
+            (void)Mat_uint32Swap(buf);
+            (void)Mat_uint32Swap(buf+1);
+        }
+        if ( (buf[0] & 0x0000ffff) == MAT_T_INT32 ) {
+            fieldname_size = buf[1];
+        } else {
+            Mat_Warning("Error getting fieldname size");
+            return bytesread;
+        }
+        bytesread+=fread(buf,4,2,mat->fp);
+        if ( mat->byteswap ) {
+            (void)Mat_uint32Swap(buf);
+            (void)Mat_uint32Swap(buf+1);
+        }
+        nfields = buf[1];
+        nfields = nfields / fieldname_size;
+        matvar->data_size = sizeof(matvar_t *);
+        matvar->nbytes    = nmemb*nfields*matvar->data_size;
+        matvar->data = malloc(matvar->nbytes);
+        if ( !matvar->data )
+            return bytesread;
+        fields = (matvar_t **)matvar->data;
+        for ( i = 0; i < nfields; i++ ) {
+            fields[i] = calloc(1,sizeof(matvar_t));
+            fields[i]->name = malloc(fieldname_size);
+            bytesread+=fread(fields[i]->name,1,fieldname_size,mat->fp);
+            fields[i]->name[fieldname_size-1] = '\0';
+        }
+        for ( i = 1; i < nmemb; i++ ) {
+            for ( j = 0; j < nfields; j++ ) {
+                fields[i*nfields+j] = calloc(1,sizeof(matvar_t));
+                fields[i*nfields+j]->name = strdup_printf("%s",fields[j]->name);
+            }
+        }
+        if ( (nfields*fieldname_size) % 8 ) {
+            fseek(mat->fp,8-((nfields*fieldname_size) % 8),SEEK_CUR);
+            bytesread+=8-((nfields*fieldname_size) % 8);
+        }
+        for ( i = 0; i < nmemb*nfields; i++ ) {
+
+            fields[i]->fpos = ftell(mat->fp);
+
+            /* Read variable tag for struct field */
+            bytesread += fread(buf,4,2,mat->fp);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(buf);
+                (void)Mat_uint32Swap(buf+1);
+            }
+            nBytes = buf[1];
+            if ( buf[0] != MAT_T_MATRIX ) {
+                Mat_Critical("fields[%d] not MAT_T_MATRIX, fpos = %ld",i,ftell(mat->fp));
+                Mat_VarFree(fields[i]);
+                fields[i] = NULL;
+                return bytesread;
+            } else if ( nBytes == 0 ) {
+                fields[i]->rank = 0;
+                continue;
+            }
+            fields[i]->compression = 0;
+#if defined(HAVE_ZLIB)
+            fields[i]->z = NULL;
+#endif
+
+            /* Read Array Flags and The Dimensions Tag */
+            bytesread  += fread(buf,4,6,mat->fp);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(buf);
+                (void)Mat_uint32Swap(buf+1);
+                (void)Mat_uint32Swap(buf+2);
+                (void)Mat_uint32Swap(buf+3);
+                (void)Mat_uint32Swap(buf+4);
+                (void)Mat_uint32Swap(buf+5);
+            }
+            nBytes-=24;
+            /* Array Flags */
+            if ( buf[0] == MAT_T_UINT32 ) {
+               array_flags = buf[2];
+               fields[i]->class_type  = (array_flags & MAT_F_CLASS_T);
+               fields[i]->isComplex   = (array_flags & MAT_F_COMPLEX);
+               fields[i]->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               fields[i]->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( fields[i]->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   fields[i]->nbytes      = buf[3];
+               }
+            }
+            /* Rank and Dimension */
+            if ( buf[4] == MAT_T_INT32 ) {
+                int j;
+
+                nbytes = buf[5];
+                nBytes-=nbytes;
+
+                fields[i]->rank = nbytes / 4;
+                fields[i]->dims = malloc(fields[i]->rank*sizeof(int));
+
+                /* Assumes rank <= 16 */
+                if ( fields[i]->rank % 2 != 0 ) {
+                    bytesread+=fread(buf,4,fields[i]->rank+1,mat->fp);
+                    nBytes-=4;
+                } else
+                    bytesread+=fread(buf,4,fields[i]->rank,mat->fp);
+
+                if ( mat->byteswap ) {
+                    for ( j = 0; j < fields[i]->rank; j++ )
+                        fields[i]->dims[j] = Mat_uint32Swap(buf+j);
+                } else {
+                    for ( j = 0; j < fields[i]->rank; j++ )
+                        fields[i]->dims[j] = buf[j];
+                }
+            }
+            /* Variable Name Tag */
+            bytesread+=fread(buf,1,8,mat->fp);
+            nBytes-=8;
+            fields[i]->datapos = ftell(mat->fp);
+            if ( fields[i]->class_type == MAT_C_STRUCT )
+                bytesread+=ReadNextStructField(mat,fields[i]);
+            else if ( fields[i]->class_type == MAT_C_CELL )
+                bytesread+=ReadNextCell(mat,fields[i]);
+            fseek(mat->fp,fields[i]->datapos+nBytes,SEEK_SET);
+        }
+    }
+
+    return bytesread;
+}
+
+/** @brief Reads the function handle data of the function handle in @c matvar
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar MAT variable pointer
+ * @return Number of bytes read
+ */
+int
+ReadNextFunctionHandle(mat_t *mat, matvar_t *matvar)
+{
+    int nfunctions = 1, bytesread = 0, i;
+    matvar_t **functions = NULL;
+
+    for ( i = 0; i < matvar->rank; i++ )
+        nfunctions *= matvar->dims[i];
+
+    matvar->data = malloc(nfunctions*sizeof(matvar_t *));
+    if ( matvar->data != NULL ) {
+        matvar->data_size = sizeof(matvar_t *);
+        matvar->nbytes    = nfunctions*matvar->data_size;
+        functions = matvar->data;
+        for ( i = 0 ; i < nfunctions; i++ )
+            functions[i] = Mat_VarReadNextInfo(mat);
+    } else {
+        bytesread = 0;
+        matvar->data_size = 0;
+        matvar->nbytes    = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Writes the header and blank data for a cell array
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @return number of bytes written
+ */
+int
+WriteCellArrayFieldInfo(mat_t *mat,matvar_t *matvar)
+{
+    mat_uint32_t array_flags = 0x0; 
+    mat_int16_t  array_name_type = MAT_T_INT8;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
+    mat_int8_t   pad1 = 0;
+    int      nBytes, i, nmemb = 1;
+    long     start = 0, end = 0;
+
+    if ((matvar == NULL) || (mat == NULL))
+        return 0;
+
+#if 0
+    nBytes = GetMatrixMaxBufSize(matvar);
+#endif
+
+    fwrite(&matrix_type,4,1,mat->fp);
+    fwrite(&pad4,4,1,mat->fp);
+    start = ftell(mat->fp);
+
+    /* Array Flags */
+    if ( matvar->rank > 1 && ( matvar->dims[0] > 1 || matvar->dims[1] > 1 ) &&
+         matvar->class_type == MAT_C_INT32 ) {
+        array_flags = MAT_C_DOUBLE & MAT_F_CLASS_T;
+    } else {
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+    }
+    if ( matvar->isComplex )
+        array_flags |= MAT_F_COMPLEX;
+    if ( matvar->isGlobal )
+        array_flags |= MAT_F_GLOBAL;
+    if ( matvar->isLogical )
+        array_flags |= MAT_F_LOGICAL;
+
+    if ( mat->byteswap )
+        array_flags = Mat_int32Swap((mat_int32_t*)&array_flags);
+    fwrite(&array_flags_type,4,1,mat->fp);
+    fwrite(&array_flags_size,4,1,mat->fp);
+    fwrite(&array_flags,4,1,mat->fp);
+    fwrite(&pad4,4,1,mat->fp);
+    /* Rank and Dimension */
+    nBytes = matvar->rank * 4;
+    fwrite(&dims_array_type,4,1,mat->fp);
+    fwrite(&nBytes,4,1,mat->fp);
+    for ( i = 0; i < matvar->rank; i++ ) {
+        mat_int32_t dim;
+        dim = matvar->dims[i];
+        nmemb *= dim;
+        fwrite(&dim,4,1,mat->fp);
+    }
+    if ( matvar->rank % 2 != 0 )
+        fwrite(&pad4,4,1,mat->fp);
+    /* Name of variable */
+    if ( !matvar->name ) {
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+    } else if ( strlen(matvar->name) <= 4 ) {
+        mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
+        mat_int8_t  pad1 = 0;
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&array_name_len,2,1,mat->fp);
+        fwrite(matvar->name,1,array_name_len,mat->fp);
+        for ( i = array_name_len; i < 4; i++ )
+            fwrite(&pad1,1,1,mat->fp);
+    } else {
+        mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
+        mat_int8_t  pad1 = 0;
+
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&array_name_len,4,1,mat->fp);
+        fwrite(matvar->name,1,array_name_len,mat->fp);
+        if ( array_name_len % 8 )
+            for ( i = array_name_len % 8; i < 8; i++ )
+                fwrite(&pad1,1,1,mat->fp);
+    }
+
+    matvar->datapos = ftell(mat->fp);
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+        case MAT_C_SINGLE:
+        case MAT_C_INT64:
+        case MAT_C_UINT64:
+        case MAT_C_INT32:
+        case MAT_C_UINT32:
+        case MAT_C_INT16:
+        case MAT_C_UINT16:
+        case MAT_C_INT8:
+        case MAT_C_UINT8:
+            nBytes = WriteEmptyData(mat,nmemb,matvar->data_type);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            if ( matvar->isComplex ) {
+                nBytes = WriteEmptyData(mat,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+            }
+            break;
+        case MAT_C_CHAR:
+        {
+            WriteEmptyCharData(mat,nmemb,matvar->data_type);
+            break;
+        }
+        case MAT_C_CELL:
+        {
+            int nfields = matvar->nbytes / matvar->data_size;
+            matvar_t **fields = (matvar_t **)matvar->data;
+
+            for ( i = 0; i < nfields; i++ )
+                WriteCellArrayFieldInfo(mat,fields[i]);
+            break;
+        }
+        /* FIXME: Structures */
+    }
+    end = ftell(mat->fp);
+    nBytes = (int)(end-start);
+    fseek(mat->fp,(long)-(nBytes+4),SEEK_CUR);
+    fwrite(&nBytes,4,1,mat->fp);
+    fseek(mat->fp,end,SEEK_SET);
+    return 0;
+}
+
+/** @brief Writes the header and data for an element of a cell array
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @retval 0 on success
+ */
+int
+WriteCellArrayField(mat_t *mat,matvar_t *matvar )
+{
+    mat_uint32_t array_flags = 0x0; 
+    mat_int16_t  array_name_type = MAT_T_INT8,fieldname_type = MAT_T_INT32,fieldname_data_size=4;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
+    mat_int8_t   pad1 = 0;
+    int      nBytes, i, nmemb = 1, nzmax = 0;
+    long     start = 0, end = 0;
+
+    if ((matvar == NULL) || (mat == NULL))
+        return 1;
+
+#if 0
+    nBytes = GetMatrixMaxBufSize(matvar);
+#endif
+
+    fwrite(&matrix_type,4,1,mat->fp);
+    fwrite(&pad4,4,1,mat->fp);
+    start = ftell(mat->fp);
+
+    /* Array Flags */
+    if ( matvar->rank > 1 && ( matvar->dims[0] > 1 || matvar->dims[1] > 1 ) &&
+         matvar->class_type == MAT_C_INT32 ) {
+        array_flags = MAT_C_DOUBLE & MAT_F_CLASS_T;
+    } else {
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+    }
+    if ( matvar->isComplex )
+        array_flags |= MAT_F_COMPLEX;
+    if ( matvar->isGlobal )
+        array_flags |= MAT_F_GLOBAL;
+    if ( matvar->isLogical )
+        array_flags |= MAT_F_LOGICAL;
+    if ( matvar->class_type == MAT_C_SPARSE )
+        nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+    if ( mat->byteswap )
+        array_flags = Mat_int32Swap((mat_int32_t*)&array_flags);
+    fwrite(&array_flags_type,4,1,mat->fp);
+    fwrite(&array_flags_size,4,1,mat->fp);
+    fwrite(&array_flags,4,1,mat->fp);
+    fwrite(&nzmax,4,1,mat->fp);
+    /* Rank and Dimension */
+    nBytes = matvar->rank * 4;
+    fwrite(&dims_array_type,4,1,mat->fp);
+    fwrite(&nBytes,4,1,mat->fp);
+    for ( i = 0; i < matvar->rank; i++ ) {
+        mat_int32_t dim;
+        dim = matvar->dims[i];
+        nmemb *= dim;
+        fwrite(&dim,4,1,mat->fp);
+    }
+    if ( matvar->rank % 2 != 0 )
+        fwrite(&pad4,4,1,mat->fp);
+    /* Name of variable */
+    if ( !matvar->name ) {
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+    } else if ( strlen(matvar->name) <= 4 ) {
+        mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
+        mat_int8_t  pad1 = 0;
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&array_name_len,2,1,mat->fp);
+        fwrite(matvar->name,1,array_name_len,mat->fp);
+        for ( i = array_name_len; i < 4; i++ )
+            fwrite(&pad1,1,1,mat->fp);
+    } else {
+        mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
+        mat_int8_t  pad1 = 0;
+
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&array_name_len,4,1,mat->fp);
+        fwrite(matvar->name,1,array_name_len,mat->fp);
+        if ( array_name_len % 8 )
+            for ( i = array_name_len % 8; i < 8; i++ )
+                fwrite(&pad1,1,1,mat->fp);
+    }
+
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+        case MAT_C_SINGLE:
+        case MAT_C_INT64:
+        case MAT_C_UINT64:
+        case MAT_C_INT32:
+        case MAT_C_UINT32:
+        case MAT_C_INT16:
+        case MAT_C_UINT16:
+        case MAT_C_INT8:
+        case MAT_C_UINT8:
+        {
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = matvar->data;
+
+
+                nBytes=WriteData(mat,complex_data->Re,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                nBytes=WriteData(mat,complex_data->Im,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+            } else {
+                nBytes = WriteData(mat,matvar->data,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+            }
+            break;
+        }
+        case MAT_C_CHAR:
+            WriteCharData(mat,matvar->data,nmemb,matvar->data_type);
+            break;
+        case MAT_C_CELL:
+        {
+            int nfields = matvar->nbytes / matvar->data_size;
+            matvar_t **fields = (matvar_t **)matvar->data;
+
+            for ( i = 0; i < nfields; i++ )
+                WriteCellArrayField(mat,fields[i]);
+            break;
+        }
+        case MAT_C_STRUCT:
+        {
+            char **fieldnames, *padzero;
+            int    fieldname_size, nfields;
+            size_t maxlen = 0;
+            matvar_t **fields = (matvar_t **)matvar->data;
+            unsigned fieldname;
+
+            nfields = matvar->nbytes / (nmemb*matvar->data_size);
+            fieldnames = malloc(nfields*sizeof(char *));
+            for ( i = 0; i < nfields; i++ ) {
+                fieldnames[i] = fields[i]->name;
+                if ( strlen(fieldnames[i]) > maxlen )
+                    maxlen = strlen(fieldnames[i]);
+            }
+            maxlen++;
+            fieldname_size = maxlen;
+            while ( nfields*fieldname_size % 8 != 0 )
+                fieldname_size++;
+#if 0
+            fwrite(&fieldname_type,2,1,mat->fp);
+            fwrite(&fieldname_data_size,2,1,mat->fp);
+#else
+            fieldname = (fieldname_data_size<<16) | fieldname_type;
+            fwrite(&fieldname,4,1,mat->fp);
+#endif
+            fwrite(&fieldname_size,4,1,mat->fp);
+            fwrite(&array_name_type,2,1,mat->fp);
+            fwrite(&pad1,1,1,mat->fp);
+            fwrite(&pad1,1,1,mat->fp);
+            nBytes = nfields*fieldname_size;
+            fwrite(&nBytes,4,1,mat->fp);
+            padzero = calloc(fieldname_size,1);
+            for ( i = 0; i < nfields; i++ ) {
+                fwrite(fieldnames[i],1,strlen(fieldnames[i]),mat->fp);
+                fwrite(padzero,1,fieldname_size-strlen(fieldnames[i]),mat->fp);
+            }
+            free(fieldnames);
+            free(padzero);
+            for ( i = 0; i < nmemb*nfields; i++ )
+                WriteStructField(mat,fields[i]);
+            break;
+        }
+        case MAT_C_SPARSE:
+        {
+            sparse_t *sparse = matvar->data;
+
+            nBytes = WriteData(mat,sparse->ir,sparse->nir,MAT_T_INT32);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            nBytes = WriteData(mat,sparse->jc,sparse->njc,MAT_T_INT32);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            nBytes = WriteData(mat,sparse->data,sparse->ndata,matvar->data_type);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+        }
+    }
+    end = ftell(mat->fp);
+    nBytes = (int)(end-start);
+    fseek(mat->fp,(long)-(nBytes+4),SEEK_CUR);
+    fwrite(&nBytes,4,1,mat->fp);
+    fseek(mat->fp,end,SEEK_SET);
+    return 0;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Writes the header and data for a field of a compressed cell array
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @return number of bytes written to the MAT file
+ */
+size_t
+WriteCompressedCellArrayField(mat_t *mat,matvar_t *matvar,z_stream *z)
+{
+    mat_uint32_t array_flags = 0x0; 
+    mat_int16_t  array_name_type     = MAT_T_INT8;
+    mat_int16_t  fieldname_type      = MAT_T_INT32;
+    mat_int16_t  fieldname_data_size = 4;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0;
+    mat_int8_t   pad1 = 0;
+    int      nBytes, i, nmemb = 1, nzmax = 0;
+    long     start = 0;
+
+    mat_uint32_t comp_buf[512];
+    mat_uint32_t uncomp_buf[512] = {0,};
+    int buf_size = 512, err;
+    size_t byteswritten = 0;
+
+    if ( NULL == matvar || NULL == mat || NULL == z)
+        return 0;
+
+    start = ftell(mat->fp);
+
+    /* Array Flags */
+    array_flags = matvar->class_type & MAT_F_CLASS_T;
+    if ( matvar->isComplex )
+        array_flags |= MAT_F_COMPLEX;
+    if ( matvar->isGlobal )
+        array_flags |= MAT_F_GLOBAL;
+    if ( matvar->isLogical )
+        array_flags |= MAT_F_LOGICAL;
+    if ( matvar->class_type == MAT_C_SPARSE )
+        nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+    uncomp_buf[0] = MAT_T_MATRIX;
+    uncomp_buf[1] = (int)GetMatrixMaxBufSize(matvar);
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = 8;
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+    uncomp_buf[0] = array_flags_type;
+    uncomp_buf[1] = array_flags_size;
+    uncomp_buf[2] = array_flags;
+    uncomp_buf[3] = nzmax;
+    /* Rank and Dimension */
+    nBytes = matvar->rank * 4;
+    uncomp_buf[4] = dims_array_type;
+    uncomp_buf[5] = nBytes;
+    for ( i = 0; i < matvar->rank; i++ ) {
+        mat_int32_t dim;
+        dim = matvar->dims[i];
+        nmemb *= dim;
+        uncomp_buf[6+i] = dim;
+    }
+    if ( matvar->rank % 2 != 0 ) {
+        uncomp_buf[6+i] = pad4;
+        i++;
+    }
+
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = (6+i)*sizeof(*uncomp_buf);
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+    /* Name of variable */
+    uncomp_buf[0] = array_name_type;
+    uncomp_buf[1] = 0;
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = 8;
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+
+    matvar->datapos = ftell(mat->fp);
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+        case MAT_C_SINGLE:
+        case MAT_C_INT64:
+        case MAT_C_UINT64:
+        case MAT_C_INT32:
+        case MAT_C_UINT32:
+        case MAT_C_INT16:
+        case MAT_C_UINT16:
+        case MAT_C_INT8:
+        case MAT_C_UINT8:
+        {
+            /* WriteCompressedData makes sure uncomressed data is aligned
+             * on an 8-byte boundary */
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = matvar->data;
+
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Re,nmemb,matvar->data_type);
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Im,nmemb,matvar->data_type);
+            } else {
+                byteswritten += WriteCompressedData(mat,z,
+                    matvar->data,nmemb,matvar->data_type);
+            }
+            break;
+        }
+        case MAT_C_CHAR:
+        {
+            /* Check for a NULL character array */
+            if ( matvar->data != NULL && nmemb > 0 )
+                byteswritten += WriteCompressedCharData(mat,z,matvar->data,
+                    nmemb,matvar->data_type);
+            break;
+        }
+        case MAT_C_CELL:
+        {
+            int        ncells;
+            matvar_t **cells = (matvar_t **)matvar->data;
+
+            /* Check for an empty cell array */
+            if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                 matvar->data   == NULL )
+                break;
+            ncells  = matvar->nbytes / matvar->data_size;
+            for ( i = 0; i < ncells; i++ )
+                WriteCompressedCellArrayField(mat,cells[i],z);
+            break;
+        }
+        case MAT_C_STRUCT:
+        {
+            char     **fieldnames;
+            unsigned char *padzero;
+            int        fieldname_size, nfields;
+            size_t     maxlen = 0;
+            mat_int32_t array_name_type = MAT_T_INT8;
+            matvar_t **fields = (matvar_t **)matvar->data;
+
+            /* Check for a structure with no fields */
+            if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                 matvar->data   == NULL ) {
+                fieldname_size = 1;
+                uncomp_buf[0] = (fieldname_data_size << 16) | 
+                                 fieldname_type;
+                uncomp_buf[1] = 1;
+                uncomp_buf[2] = array_name_type;
+                uncomp_buf[3] = 0;
+                z->next_out  = comp_buf;
+                z->next_in   = uncomp_buf;
+                z->avail_out = buf_size*sizeof(*comp_buf);
+                z->avail_in  = 32;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,1,buf_size*
+                    sizeof(*comp_buf)-z->avail_out,mat->fp);
+                break;
+            }
+            nfields = matvar->nbytes / (nmemb*matvar->data_size);
+            fieldnames = malloc(nfields*sizeof(char *));
+            for ( i = 0; i < nfields; i++ ) {
+                fieldnames[i] = fields[i]->name;
+                if ( strlen(fieldnames[i]) > maxlen )
+                    maxlen = strlen(fieldnames[i]);
+            }
+            maxlen++;
+            fieldname_size = maxlen;
+            while ( nfields*fieldname_size % 8 != 0 )
+                fieldname_size++;
+            uncomp_buf[0] = (fieldname_data_size << 16) | fieldname_type;
+            uncomp_buf[1] = fieldname_size;
+            uncomp_buf[2] = array_name_type;
+            uncomp_buf[3] = nfields*fieldname_size;
+
+            padzero = calloc(fieldname_size,1);
+            z->next_out  = comp_buf;
+            z->next_in   = uncomp_buf;
+            z->avail_out = buf_size*sizeof(*comp_buf);
+            z->avail_in  = 16;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,
+                    buf_size*sizeof(*comp_buf)-z->avail_out,mat->fp);
+            for ( i = 0; i < nfields; i++ ) {
+                memset(padzero,'\0',fieldname_size);
+                memcpy(padzero,fieldnames[i],strlen(fieldnames[i]));
+                z->next_out  = comp_buf;
+                z->next_in   = padzero;
+                z->avail_out = buf_size*sizeof(*comp_buf);
+                z->avail_in  = fieldname_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,1,
+                        buf_size*sizeof(*comp_buf)-z->avail_out,mat->fp);
+            }
+            free(fieldnames);
+            free(padzero);
+            for ( i = 0; i < nmemb*nfields; i++ )
+                byteswritten +=
+                    WriteCompressedStructField(mat,fields[i],z);
+            break;
+        }
+        case MAT_C_SPARSE:
+        {
+            sparse_t *sparse = matvar->data;
+
+            byteswritten += WriteCompressedData(mat,z,sparse->ir,
+                sparse->nir,MAT_T_INT32);
+            byteswritten += WriteCompressedData(mat,z,sparse->jc,
+                sparse->njc,MAT_T_INT32);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = sparse->data;
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Re,sparse->ndata,matvar->data_type);
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Im,sparse->ndata,matvar->data_type);
+            } else {
+                byteswritten += WriteCompressedData(mat,z,
+                    sparse->data,sparse->ndata,matvar->data_type);
+            }
+            break;
+        }
+    }
+    return byteswritten;
+}
+#endif
+
+/** @brief Writes the header and data for a field of a struct array
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @retval 0 on success
+ */
+int
+WriteStructField(mat_t *mat,matvar_t *matvar)
+{
+    mat_uint32_t array_flags = 0x0; 
+    mat_int16_t  fieldname_type = MAT_T_INT32,fieldname_data_size=4;
+    mat_int32_t  array_name_type = MAT_T_INT8;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
+    mat_int8_t   pad1 = 0;
+    int      nBytes, i, nmemb = 1, nzmax = 0;
+    long     start = 0, end = 0;
+
+    if ( (matvar == NULL) || ( mat == NULL ))
+        return 1;
+
+    fwrite(&matrix_type,4,1,mat->fp);
+    fwrite(&pad4,4,1,mat->fp);
+    start = ftell(mat->fp);
+
+    /* Array Flags */
+    array_flags = matvar->class_type & MAT_F_CLASS_T;
+    if ( matvar->isComplex )
+        array_flags |= MAT_F_COMPLEX;
+    if ( matvar->isGlobal )
+        array_flags |= MAT_F_GLOBAL;
+    if ( matvar->isLogical )
+        array_flags |= MAT_F_LOGICAL;
+    if ( matvar->class_type == MAT_C_SPARSE )
+        nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+    if ( mat->byteswap )
+        array_flags = Mat_int32Swap((mat_int32_t*)&array_flags);
+    fwrite(&array_flags_type,4,1,mat->fp);
+    fwrite(&array_flags_size,4,1,mat->fp);
+    fwrite(&array_flags,4,1,mat->fp);
+    fwrite(&nzmax,4,1,mat->fp);
+    /* Rank and Dimension */
+    nBytes = matvar->rank * 4;
+    fwrite(&dims_array_type,4,1,mat->fp);
+    fwrite(&nBytes,4,1,mat->fp);
+    for ( i = 0; i < matvar->rank; i++ ) {
+        mat_int32_t dim;
+        dim = matvar->dims[i];
+        nmemb *= dim;
+        fwrite(&dim,4,1,mat->fp);
+    }
+    if ( matvar->rank % 2 != 0 )
+        fwrite(&pad4,4,1,mat->fp);
+
+    /* Name of variable */
+    fwrite(&array_name_type,4,1,mat->fp);
+    fwrite(&pad4,4,1,mat->fp);
+
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+        case MAT_C_SINGLE:
+        case MAT_C_INT64:
+        case MAT_C_UINT64:
+        case MAT_C_INT32:
+        case MAT_C_UINT32:
+        case MAT_C_INT16:
+        case MAT_C_UINT16:
+        case MAT_C_INT8:
+        case MAT_C_UINT8:
+        {
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = matvar->data;
+
+
+                nBytes=WriteData(mat,complex_data->Re,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                nBytes=WriteData(mat,complex_data->Im,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+            } else {
+                nBytes=WriteData(mat,matvar->data,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+            }
+            break;
+        }
+        case MAT_C_CHAR:
+            nBytes=WriteCharData(mat,matvar->data,nmemb,matvar->data_type);
+            break;
+        case MAT_C_CELL:
+        {
+            int nfields = matvar->nbytes / matvar->data_size;
+            matvar_t **fields = (matvar_t **)matvar->data;
+
+            for ( i = 0; i < nfields; i++ )
+                WriteCellArrayField(mat,fields[i]);
+            break;
+        }
+        case MAT_C_STRUCT:
+        {
+            char **fieldnames, *padzero;
+            int    fieldname_size, nfields;
+            size_t maxlen = 0;
+            matvar_t **fields = (matvar_t **)matvar->data;
+            unsigned fieldname;
+
+            nfields = matvar->nbytes / (nmemb*matvar->data_size);
+            fieldnames = malloc(nfields*sizeof(char *));
+            for ( i = 0; i < nfields; i++ ) {
+                fieldnames[i] = fields[i]->name;
+                if ( strlen(fieldnames[i]) > maxlen )
+                    maxlen = strlen(fieldnames[i]);
+            }
+            maxlen++;
+            fieldname_size = maxlen;
+            while ( nfields*fieldname_size % 8 != 0 )
+                fieldname_size++;
+#if 0
+            fwrite(&fieldname_type,2,1,mat->fp);
+            fwrite(&fieldname_data_size,2,1,mat->fp);
+#else
+            fieldname = (fieldname_data_size<<16) | fieldname_type;
+            fwrite(&fieldname,4,1,mat->fp);
+#endif
+            fwrite(&fieldname_size,4,1,mat->fp);
+            fwrite(&array_name_type,4,1,mat->fp);
+            nBytes = nfields*fieldname_size;
+            fwrite(&nBytes,4,1,mat->fp);
+            padzero = calloc(fieldname_size,1);
+            for ( i = 0; i < nfields; i++ ) {
+                fwrite(fieldnames[i],1,strlen(fieldnames[i]),mat->fp);
+                fwrite(padzero,1,fieldname_size-strlen(fieldnames[i]),
+                       mat->fp);
+            }
+            free(fieldnames);
+            free(padzero);
+            for ( i = 0; i < nmemb*nfields; i++ )
+                WriteStructField(mat,fields[i]);
+            break;
+        }
+        case MAT_C_SPARSE:
+        {
+            sparse_t *sparse = matvar->data;
+
+            nBytes = WriteData(mat,sparse->ir,sparse->nir,MAT_T_INT32);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            nBytes = WriteData(mat,sparse->jc,sparse->njc,MAT_T_INT32);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            nBytes = WriteData(mat,sparse->data,sparse->ndata,
+                       matvar->data_type);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+        }
+    }
+    end = ftell(mat->fp);
+    nBytes = (int)(end-start);
+    fseek(mat->fp,(long)-(nBytes+4),SEEK_CUR);
+    fwrite(&nBytes,4,1,mat->fp);
+    fseek(mat->fp,end,SEEK_SET);
+    return 0;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Writes the header and data for a field of a compressed struct array
+ *
+ * @ingroup mat_internal
+ * @fixme Currently does not work for cell arrays or sparse data
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @return number of bytes written to the MAT file
+ */
+size_t
+WriteCompressedStructField(mat_t *mat,matvar_t *matvar,z_stream *z)
+{
+    mat_uint32_t array_flags = 0x0; 
+    mat_int16_t  array_name_type     = MAT_T_INT8;
+    mat_int16_t  fieldname_type      = MAT_T_INT32;
+    mat_int16_t  fieldname_data_size = 4;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0;
+    mat_int8_t   pad1 = 0;
+    int      nBytes, i, nmemb = 1, nzmax = 0;
+    long     start = 0;
+
+    mat_uint32_t comp_buf[512];
+    mat_uint32_t uncomp_buf[512] = {0,};
+    int buf_size = 512, err;
+    size_t byteswritten = 0;
+
+    if ( NULL == matvar || NULL == mat || NULL == z)
+        return 1;
+
+    start = ftell(mat->fp);
+
+    /* Array Flags */
+    array_flags = matvar->class_type & MAT_F_CLASS_T;
+    if ( matvar->isComplex )
+        array_flags |= MAT_F_COMPLEX;
+    if ( matvar->isGlobal )
+        array_flags |= MAT_F_GLOBAL;
+    if ( matvar->isLogical )
+        array_flags |= MAT_F_LOGICAL;
+    if ( matvar->class_type == MAT_C_SPARSE )
+        nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+    uncomp_buf[0] = MAT_T_MATRIX;
+    uncomp_buf[1] = (int)GetMatrixMaxBufSize(matvar);
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = 8;
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+    uncomp_buf[0] = array_flags_type;
+    uncomp_buf[1] = array_flags_size;
+    uncomp_buf[2] = array_flags;
+    uncomp_buf[3] = nzmax;
+    /* Rank and Dimension */
+    nBytes = matvar->rank * 4;
+    uncomp_buf[4] = dims_array_type;
+    uncomp_buf[5] = nBytes;
+    for ( i = 0; i < matvar->rank; i++ ) {
+        mat_int32_t dim;
+        dim = matvar->dims[i];
+        nmemb *= dim;
+        uncomp_buf[6+i] = dim;
+    }
+    if ( matvar->rank % 2 != 0 ) {
+        uncomp_buf[6+i] = pad4;
+        i++;
+    }
+
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = (6+i)*sizeof(*uncomp_buf);
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+    /* Name of variable */
+    uncomp_buf[0] = array_name_type;
+    uncomp_buf[1] = 0;
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = 8;
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+
+    matvar->datapos = ftell(mat->fp);
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+        case MAT_C_SINGLE:
+        case MAT_C_INT64:
+        case MAT_C_UINT64:
+        case MAT_C_INT32:
+        case MAT_C_UINT32:
+        case MAT_C_INT16:
+        case MAT_C_UINT16:
+        case MAT_C_INT8:
+        case MAT_C_UINT8:
+        {
+            /* WriteCompressedData makes sure uncomressed data is aligned
+             * on an 8-byte boundary */
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = matvar->data;
+
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Re,nmemb,matvar->data_type);
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Im,nmemb,matvar->data_type);
+            } else {
+                byteswritten += WriteCompressedData(mat,z,
+                    matvar->data,nmemb,matvar->data_type);
+            }
+            break;
+        }
+        case MAT_C_CHAR:
+        {
+            /* Check for a NULL character array */
+            if ( matvar->data != NULL && nmemb > 0 )
+                byteswritten += WriteCompressedCharData(mat,z,matvar->data,
+                    nmemb,matvar->data_type);
+            break;
+        }
+        case MAT_C_CELL:
+        {
+            int        ncells;
+            matvar_t **cells = (matvar_t **)matvar->data;
+
+            /* Check for an empty cell array */
+            if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                 matvar->data   == NULL )
+                break;
+            ncells  = matvar->nbytes / matvar->data_size;
+            for ( i = 0; i < ncells; i++ )
+                WriteCompressedCellArrayField(mat,cells[i],z);
+            break;
+        }
+        case MAT_C_STRUCT:
+        {
+            char     **fieldnames;
+            unsigned char *padzero;
+            int        fieldname_size, nfields;
+            size_t     maxlen = 0;
+            mat_int32_t array_name_type = MAT_T_INT8;
+            matvar_t **fields = (matvar_t **)matvar->data;
+
+            /* Check for a structure with no fields */
+            if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                 matvar->data   == NULL ) {
+                fieldname_size = 1;
+                uncomp_buf[0] = (fieldname_data_size << 16) | 
+                                 fieldname_type;
+                uncomp_buf[1] = 1;
+                uncomp_buf[2] = array_name_type;
+                uncomp_buf[3] = 0;
+                z->next_out  = comp_buf;
+                z->next_in   = uncomp_buf;
+                z->avail_out = buf_size*sizeof(*comp_buf);
+                z->avail_in  = 32;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,1,buf_size*
+                    sizeof(*comp_buf)-z->avail_out,mat->fp);
+                break;
+            }
+            nfields = matvar->nbytes / (nmemb*matvar->data_size);
+            fieldnames = malloc(nfields*sizeof(char *));
+            for ( i = 0; i < nfields; i++ ) {
+                fieldnames[i] = fields[i]->name;
+                if ( strlen(fieldnames[i]) > maxlen )
+                    maxlen = strlen(fieldnames[i]);
+            }
+            maxlen++;
+            fieldname_size = maxlen;
+            while ( nfields*fieldname_size % 8 != 0 )
+                fieldname_size++;
+            uncomp_buf[0] = (fieldname_data_size << 16) | fieldname_type;
+            uncomp_buf[1] = fieldname_size;
+            uncomp_buf[2] = array_name_type;
+            uncomp_buf[3] = nfields*fieldname_size;
+
+            padzero = calloc(fieldname_size,1);
+            z->next_out  = comp_buf;
+            z->next_in   = uncomp_buf;
+            z->avail_out = buf_size*sizeof(*comp_buf);
+            z->avail_in  = 16;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,
+                    buf_size*sizeof(*comp_buf)-z->avail_out,mat->fp);
+            for ( i = 0; i < nfields; i++ ) {
+                memset(padzero,'\0',fieldname_size);
+                memcpy(padzero,fieldnames[i],strlen(fieldnames[i]));
+                z->next_out  = comp_buf;
+                z->next_in   = padzero;
+                z->avail_out = buf_size*sizeof(*comp_buf);
+                z->avail_in  = fieldname_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,1,
+                        buf_size*sizeof(*comp_buf)-z->avail_out,mat->fp);
+            }
+            free(fieldnames);
+            free(padzero);
+            for ( i = 0; i < nmemb*nfields; i++ )
+                byteswritten +=
+                    WriteCompressedStructField(mat,fields[i],z);
+            break;
+        }
+        case MAT_C_SPARSE:
+        {
+            sparse_t *sparse = matvar->data;
+
+            byteswritten += WriteCompressedData(mat,z,sparse->ir,
+                sparse->nir,MAT_T_INT32);
+            byteswritten += WriteCompressedData(mat,z,sparse->jc,
+                sparse->njc,MAT_T_INT32);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = sparse->data;
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Re,sparse->ndata,matvar->data_type);
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Im,sparse->ndata,matvar->data_type);
+            } else {
+                byteswritten += WriteCompressedData(mat,z,
+                    sparse->data,sparse->ndata,matvar->data_type);
+            }
+            break;
+        }
+    }
+    return byteswritten;
+}
+#endif
+
+/** @brief Reads the data of a version 5 MAT variable
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar MAT variable pointer to read the data
+ */
+void
+Read5(mat_t *mat, matvar_t *matvar)
+{
+    int nBytes, len = 0, i, byteswap, packed_type, data_in_tag = 0;
+    long fpos;
+    mat_uint32_t tag[2];
+
+    if ( matvar == NULL )
+        return;
+    else if ( matvar->rank == 0 )        /* An empty data set */
+        return;
+
+    fpos = ftell(mat->fp);
+    len = 1;
+    byteswap = mat->byteswap;
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(double);
+            matvar->data_type = MAT_T_DOUBLE;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadDoubleData(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadDoubleData(mat,complex_data->Im,packed_type,
+                                            len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else { /* if ( isComplex ) */
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadDoubleData(mat,(double*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                 (double*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_SINGLE:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(float);
+            matvar->data_type = MAT_T_SINGLE;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadSingleData(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadSingleData(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadSingleData(mat,(float*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                 (float*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+#ifdef HAVE_MAT_INT64_T
+        case MAT_C_INT64:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_int64_t);
+            matvar->data_type = MAT_T_INT64;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt64Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt64Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt64Data(mat,(mat_int64_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 (mat_int64_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+#endif /* HAVE_MAT_INT64_T */
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_C_UINT64:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_uint64_t);
+            matvar->data_type = MAT_T_UINT64;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt64Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt64Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt64Data(mat,(mat_int64_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 (mat_int64_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+#endif /* HAVE_MAT_UINT64_T */
+        case MAT_C_INT32:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_int32_t);
+            matvar->data_type = MAT_T_INT32;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt32Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,(mat_int32_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 (mat_int32_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_UINT32:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_uint32_t);
+            matvar->data_type = MAT_T_UINT32;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt32Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,(mat_int32_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 (mat_int32_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_INT16:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_int16_t);
+            matvar->data_type = MAT_T_INT16;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt16Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt16Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt16Data(mat,(mat_int16_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 (mat_int16_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_UINT16:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_uint16_t);
+            matvar->data_type = MAT_T_UINT16;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt16Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt16Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt16Data(mat,(mat_int16_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 (mat_int16_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_INT8:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_int8_t);
+            matvar->data_type = MAT_T_INT8;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt8Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt8Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt8Data(mat,(mat_int8_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 (mat_int8_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_UINT8:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_uint8_t);
+            matvar->data_type = MAT_T_UINT8;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt8Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt8Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt8Data(mat,(mat_int8_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 (mat_int8_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+            break;
+        case MAT_C_CHAR:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(char);
+            /* FIXME: */
+            matvar->data_type = MAT_T_UINT8;
+            matvar->nbytes = len*matvar->data_size;
+            matvar->data   = calloc(matvar->nbytes+1,1);
+            if ( !matvar->data ) {
+                Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                break;
+            }
+            if ( matvar->compression == COMPRESSION_NONE) {
+                nBytes = ReadCharData(mat,(char*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                if ( (nBytes % 8) != 0 )
+                    fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+            } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                nBytes = ReadCompressedCharData(mat,matvar->z,
+                             (char*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                if ( (nBytes % 8) != 0 )
+                    InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+            }
+            break;
+        case MAT_C_STRUCT:
+        {
+            matvar_t **fields;
+            int nfields = 0;
+
+            if ( !matvar->nbytes || !matvar->data_size || NULL == matvar->data )
+                break;
+            nfields = matvar->nbytes / matvar->data_size;
+            fields = (matvar_t **)matvar->data;
+            for ( i = 0; i < nfields; i++ ) {
+                fields[i]->fp = mat;
+                Read5(mat,fields[i]);
+            }
+            /* FIXME: */
+            matvar->data_type = MAT_T_STRUCT;
+            break;
+        }
+        case MAT_C_CELL:
+        {
+            matvar_t **cells;
+
+            if ( !matvar->data ) {
+                Mat_Critical("Data is NULL for Cell Array %s",matvar->name);
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            cells = (matvar_t **)matvar->data;
+            for ( i = 0; i < len; i++ ) {
+                cells[i]->fp = mat;
+                Read5(mat,cells[i]);
+            }
+            /* FIXME: */
+            matvar->data_type = MAT_T_CELL;
+            break;
+        }
+        case MAT_C_SPARSE:
+        {
+            int N;
+            sparse_t *data;
+
+            matvar->data_size = sizeof(sparse_t);
+            matvar->data      = malloc(matvar->data_size);
+            if ( matvar->data == NULL ) {
+                Mat_Critical("ReadData: Allocation of data pointer failed");
+                break;
+            }
+            data = matvar->data;
+            data->nzmax  = matvar->nbytes;
+            fseek(mat->fp,matvar->datapos,SEEK_SET);
+            /*  Read ir    */
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( mat->byteswap )
+                    (void)Mat_uint32Swap(tag);
+
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    (void)ReadCompressedInt32Data(mat,matvar->z,
+                             (mat_int32_t*)&N,MAT_T_INT32,1);
+                }
+#endif
+            } else {
+                fread(tag,4,1,mat->fp);
+                if ( mat->byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(&N,4,1,mat->fp);
+                    if ( mat->byteswap )
+                        Mat_int32Swap(&N);
+                }
+            }
+            data->nir = N / 4;
+            data->ir = malloc(data->nir*sizeof(mat_int32_t));
+            if ( data->ir != NULL ) {
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,data->ir,packed_type,data->nir);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 data->ir,packed_type,data->nir);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            } else {
+                Mat_Critical("ReadData: Allocation of ir pointer failed");
+                break;
+            }
+            /*  Read jc    */
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( mat->byteswap )
+                    Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    (void)ReadCompressedInt32Data(mat,matvar->z,
+                             (mat_int32_t*)&N,MAT_T_INT32,1);
+                }
+#endif
+            } else {
+                fread(tag,4,1,mat->fp);
+                if ( mat->byteswap )
+                    Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(&N,4,1,mat->fp);
+                    if ( mat->byteswap )
+                        Mat_int32Swap(&N);
+                }
+            }
+            data->njc = N / 4;
+            data->jc = malloc(data->njc*sizeof(mat_int32_t));
+            if ( data->jc != NULL ) {
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,data->jc,packed_type,data->njc);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 data->jc,packed_type,data->njc);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            } else {
+                Mat_Critical("ReadData: Allocation of jc pointer failed");
+                break;
+            }
+            /*  Read data    */
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( mat->byteswap )
+                    Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    (void)ReadCompressedInt32Data(mat,matvar->z,
+                             (mat_int32_t*)&N,MAT_T_INT32,1);
+                }
+#endif
+            } else {
+                fread(tag,4,1,mat->fp);
+                if ( mat->byteswap )
+                    Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(&N,4,1,mat->fp);
+                    if ( mat->byteswap )
+                        Mat_int32Swap(&N);
+                }
+            }
+#if defined(EXTENDED_SPARSE)
+            matvar->data_type = packed_type;
+#else
+            matvar->data_type = MAT_T_DOUBLE;
+#endif
+            data->ndata = N / Mat_SizeOf(packed_type);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(data->ndata*
+                                          Mat_SizeOf(matvar->data_type));
+                complex_data->Im = malloc(data->ndata*
+                                          Mat_SizeOf(matvar->data_type));
+                if ( NULL != complex_data && NULL != complex_data->Re &&
+                     NULL != complex_data->Im ) {
+                    if ( matvar->compression == COMPRESSION_NONE) {
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadDoubleData(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadSingleData(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadInt32Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadInt32Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadInt16Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadInt16Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadInt8Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadInt8Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                        }
+#else
+                        nBytes = ReadDoubleData(mat,complex_data->Re,
+                                     packed_type,data->ndata);
+#endif
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                        /* Complex Data Tag */
+                        fread(tag,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag);
+                        packed_type = tag[0] & 0x000000ff;
+                        if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                            data_in_tag = 1;
+                            nBytes = (tag[0] & 0xffff0000) >> 16;
+                        } else {
+                            data_in_tag = 0;
+                            fread(tag+1,4,1,mat->fp);
+                            if ( byteswap )
+                                (void)Mat_uint32Swap(tag+1);
+                            nBytes = tag[1];
+                        }
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadDoubleData(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadSingleData(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadInt32Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadUInt32Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadInt16Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadUInt16Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadInt8Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadUInt8Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                        }
+#else /* EXTENDED_SPARSE */
+                        nBytes = ReadDoubleData(mat,complex_data->Im,
+                                     packed_type,data->ndata);
+#endif /* EXTENDED_SPARSE */
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                    } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                        }
+#else    /* EXTENDED_SPARSE */
+                        nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+#endif    /* EXTENDED_SPARSE */
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                        /* Complex Data Tag */
+                        InflateDataType(mat,matvar->z,tag);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag);
+
+                        packed_type = tag[0] & 0x000000ff;
+                        if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                            data_in_tag = 1;
+                            nBytes = (tag[0] & 0xffff0000) >> 16;
+                        } else {
+                            data_in_tag = 0;
+                            InflateDataType(mat,matvar->z,tag+1);
+                            if ( byteswap )
+                                (void)Mat_uint32Swap(tag+1);
+                            nBytes = tag[1];
+                        }
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadCompressedUInt32Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadCompressedUInt16Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadCompressedUInt8Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                        }
+#else    /* EXTENDED_SPARSE */
+                        nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+#endif    /* EXTENDED_SPARSE */
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif    /* HAVE_ZLIB */
+                    }
+                } else {
+                    Mat_Critical("ReadData: Allocation of data pointer failed");
+                    break;
+                }
+                data->data = complex_data;
+            } else { /* isComplex */
+                data->data = malloc(data->ndata*Mat_SizeOf(MAT_T_DOUBLE));
+                if ( data->data != NULL ) {
+                    if ( matvar->compression == COMPRESSION_NONE) {
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadDoubleData(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadSingleData(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadInt32Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadInt32Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadInt16Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadInt16Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadInt8Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadInt8Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                        }
+#else
+                        nBytes = ReadDoubleData(mat,data->data,packed_type,
+                                     data->ndata);
+#endif
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                    } else if ( matvar->compression == COMPRESSION_ZLIB) {
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                        }
+#else   /* EXTENDED_SPARSE */
+                        nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+#endif   /* EXTENDED_SPARSE */
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif   /* HAVE_ZLIB */
+                    }
+                } else {
+                    Mat_Critical("ReadData: Allocation of data pointer failed");
+                    break;
+                }
+            }
+            break;
+        }
+        case MAT_C_FUNCTION:
+        {
+            matvar_t **functions;
+            int nfunctions = 0;
+
+            if ( !matvar->nbytes || !matvar->data_size )
+                break;
+            nfunctions = matvar->nbytes / matvar->data_size;
+            functions = (matvar_t **)matvar->data;
+            for ( i = 0; i < nfunctions; i++ ) {
+                functions[i]->fp = mat;
+                Read5(mat,functions[i]);
+            }
+            /* FIXME: */
+            matvar->data_type = MAT_T_FUNCTION;
+            break;
+        }
+        default:
+            Mat_Critical("Read5: %d is not a supported Class", matvar->class_type);
+    }
+    fseek(mat->fp,fpos,SEEK_SET);
+
+    return;
+}
+
+/** @brief Reads a slab of data from the mat variable @c matvar
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @param data pointer to store the read data in (must be of size
+ *             edge[0]*...edge[rank-1]*Mat_SizeOfClass(matvar->class_type))
+ * @param start index to start reading data in each dimension
+ * @param stride write data every @c stride elements in each dimension
+ * @param edge number of elements to read in each dimension
+ * @retval 0 on success
+ */
+int 
+ReadData5(mat_t *mat,matvar_t *matvar,void *data, 
+    int *start,int *stride,int *edge)
+{               
+    int err = 0,real_bytes;
+    mat_int32_t tag[2];
+#if defined(HAVE_ZLIB)
+    z_stream z;
+
+    err = inflateCopy(&z,matvar->z);
+#endif
+
+    fseek(mat->fp,matvar->datapos,SEEK_SET);
+    if ( matvar->compression == COMPRESSION_NONE ) {
+        fread(tag,4,2,mat->fp);
+        if ( mat->byteswap ) {
+            Mat_int32Swap(tag);
+            Mat_int32Swap(tag+1);
+        }
+        matvar->data_type = tag[0] & 0x000000ff;
+        if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
+            fseek(mat->fp,-4,SEEK_CUR);
+            real_bytes = 4+(tag[0] >> 16);
+        } else {
+            real_bytes = 8+tag[1];
+        }
+#if defined(HAVE_ZLIB)
+    } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+        z.avail_in = 0;
+        InflateDataType(mat,&z,tag);
+        if ( mat->byteswap ) {
+            Mat_int32Swap(tag);
+        }
+        matvar->data_type = tag[0] & 0x000000ff;
+        if ( !(tag[0] & 0xffff0000) ) {/* Data is NOT packed in the tag */
+            /* We're cheating, but InflateDataType just inflates 4 bytes */
+            InflateDataType(mat,&z,tag+1);
+            if ( mat->byteswap ) {
+                Mat_int32Swap(tag+1);
+            }
+            real_bytes = 8+tag[1];
+        } else {
+            real_bytes = 4+(tag[0] >> 16);
+        }
+#endif
+    }
+    if ( real_bytes % 8 )
+        real_bytes += (8-(real_bytes % 8));
+
+    if ( matvar->rank == 2 ) {
+        if ( stride[0]*(edge[0]-1)+start[0]+1 > matvar->dims[0] )
+            err = 1;
+        else if ( stride[1]*(edge[1]-1)+start[1]+1 > matvar->dims[1] )
+            err = 1;
+        else if ( matvar->compression == COMPRESSION_NONE ) {
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = data;
+
+                ReadDataSlab2(mat,complex_data->Re,matvar->class_type,
+                    matvar->data_type,matvar->dims,start,stride,edge);
+                fseek(mat->fp,matvar->datapos+real_bytes,SEEK_SET);
+                fread(tag,4,2,mat->fp);
+                if ( mat->byteswap ) {
+                    Mat_int32Swap(tag);
+                    Mat_int32Swap(tag+1);
+                }
+                matvar->data_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
+                    fseek(mat->fp,-4,SEEK_CUR);
+                }
+                ReadDataSlab2(mat,complex_data->Im,matvar->class_type,
+                              matvar->data_type,matvar->dims,start,stride,edge);
+            } else {
+                ReadDataSlab2(mat,data,matvar->class_type,
+                    matvar->data_type,matvar->dims,start,stride,edge);
+            }
+        }
+#if defined(HAVE_ZLIB)
+        else if ( matvar->compression == COMPRESSION_ZLIB ) {
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = data;
+
+                ReadCompressedDataSlab2(mat,&z,complex_data->Re,
+                    matvar->class_type,matvar->data_type,matvar->dims,
+                    start,stride,edge);
+
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                /* Reset zlib knowledge to before reading real tag */
+                inflateEnd(&z);
+                err = inflateCopy(&z,matvar->z);
+                InflateSkip(mat,&z,real_bytes);
+                z.avail_in = 0;
+                InflateDataType(mat,&z,tag);
+                if ( mat->byteswap ) {
+                    Mat_int32Swap(tag);
+                }
+                matvar->data_type = tag[0] & 0x000000ff;
+                if ( !(tag[0] & 0xffff0000) ) {/*Data is NOT packed in the tag*/
+                    InflateSkip(mat,&z,4);
+                }
+                ReadCompressedDataSlab2(mat,&z,complex_data->Im,
+                    matvar->class_type,matvar->data_type,matvar->dims,
+                    start,stride,edge);
+                inflateEnd(&z);
+            } else {
+                ReadCompressedDataSlab2(mat,&z,data,matvar->class_type,
+                    matvar->data_type,matvar->dims,start,stride,edge);
+            }
+        }
+#endif
+    } else {
+        if ( matvar->compression == COMPRESSION_NONE ) {
+            if ( matvar->isComplex ) {
+                int i;
+                struct ComplexSplit *complex_data = data;
+
+                ReadDataSlabN(mat,complex_data->Re,matvar->class_type,
+                    matvar->data_type,matvar->rank,matvar->dims,
+                    start,stride,edge);
+
+                fseek(mat->fp,matvar->datapos+real_bytes,SEEK_SET);
+                fread(tag,4,2,mat->fp);
+                if ( mat->byteswap ) {
+                    Mat_int32Swap(tag);
+                    Mat_int32Swap(tag+1);
+                }
+                matvar->data_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
+                    fseek(mat->fp,-4,SEEK_CUR);
+                }
+                ReadDataSlabN(mat,complex_data->Im,matvar->class_type,
+                    matvar->data_type,matvar->rank,matvar->dims,
+                    start,stride,edge);
+            } else {
+                ReadDataSlabN(mat,data,matvar->class_type,matvar->data_type,
+                    matvar->rank,matvar->dims,start,stride,edge);
+            }
+        }
+#if defined(HAVE_ZLIB)
+        else if ( matvar->compression == COMPRESSION_ZLIB ) {
+            if ( matvar->isComplex ) {
+                int i;
+                struct ComplexSplit *complex_data = data;
+
+                ReadCompressedDataSlabN(mat,&z,complex_data->Re,
+                    matvar->class_type,matvar->data_type,matvar->rank,
+                    matvar->dims,start,stride,edge);
+
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                /* Reset zlib knowledge to before reading real tag */
+                inflateEnd(&z);
+                err = inflateCopy(&z,matvar->z);
+                InflateSkip(mat,&z,real_bytes);
+                z.avail_in = 0;
+                InflateDataType(mat,&z,tag);
+                if ( mat->byteswap ) {
+                    Mat_int32Swap(tag);
+                }
+                matvar->data_type = tag[0] & 0x000000ff;
+                if ( !(tag[0] & 0xffff0000) ) {/*Data is NOT packed in the tag*/
+                    InflateSkip(mat,&z,4);
+                }
+                ReadCompressedDataSlabN(mat,&z,complex_data->Im,
+                    matvar->class_type,matvar->data_type,matvar->rank,
+                    matvar->dims,start,stride,edge);
+                inflateEnd(&z);
+            } else {
+                ReadCompressedDataSlabN(mat,&z,data,matvar->class_type,
+                    matvar->data_type,matvar->rank,matvar->dims,
+                    start,stride,edge);
+            }
+        }
+#endif
+    }
+    if ( err )
+        return err;
+
+    switch(matvar->class_type) {
+        case MAT_C_DOUBLE:
+            matvar->data_type = MAT_T_DOUBLE;
+            matvar->data_size = sizeof(double);
+            break;
+        case MAT_C_SINGLE:
+            matvar->data_type = MAT_T_SINGLE;
+            matvar->data_size = sizeof(float);
+            break;
+#ifdef HAVE_MAT_INT64_T
+        case MAT_C_INT64:
+            matvar->data_type = MAT_T_INT64;
+            matvar->data_size = sizeof(mat_int64_t);
+            break;
+#endif /* HAVE_MAT_INT64_T */
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_C_UINT64:
+            matvar->data_type = MAT_T_UINT64;
+            matvar->data_size = sizeof(mat_uint64_t);
+            break;
+#endif /* HAVE_MAT_UINT64_T */
+        case MAT_C_INT32:
+            matvar->data_type = MAT_T_INT32;
+            matvar->data_size = sizeof(mat_int32_t);
+            break;
+        case MAT_C_UINT32:
+            matvar->data_type = MAT_T_UINT32;
+            matvar->data_size = sizeof(mat_uint32_t);
+            break;
+        case MAT_C_INT16:
+            matvar->data_type = MAT_T_INT16;
+            matvar->data_size = sizeof(mat_int16_t);
+            break;
+        case MAT_C_UINT16:
+            matvar->data_type = MAT_T_UINT16;
+            matvar->data_size = sizeof(mat_uint16_t);
+            break;
+        case MAT_C_INT8:
+            matvar->data_type = MAT_T_INT8;
+            matvar->data_size = sizeof(mat_int8_t);
+            break;
+        case MAT_C_UINT8:
+            matvar->data_type = MAT_T_UINT8;
+            matvar->data_size = sizeof(mat_uint8_t);
+            break;
+    }
+
+    return err;
+}
+
+/** @brief Writes a matlab variable to a version 5 matlab file
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @param compress option to compress the variable
+ *                 (only works for numeric types)
+ * @retval 0 on success
+ */
+int
+Write5(mat_t *mat,matvar_t *matvar,int compress)
+{
+    mat_uint32_t array_flags = 0x0;
+    mat_int16_t  fieldname_type = MAT_T_INT32,fieldname_data_size=4;
+    mat_int8_t  pad1 = 0;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
+    int      nBytes, i, nmemb = 1,nzmax = 0;
+    long     start = 0, end = 0;
+
+    /* FIXME: SEEK_END is not Guaranteed by the C standard */
+    fseek(mat->fp,0,SEEK_END);         /* Always write at end of file */
+
+
+    if ( compress == COMPRESSION_NONE ) {
+        fwrite(&matrix_type,4,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+        start = ftell(mat->fp);
+
+        /* Array Flags */
+
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+        if ( matvar->isComplex )
+            array_flags |= MAT_F_COMPLEX;
+        if ( matvar->isGlobal )
+            array_flags |= MAT_F_GLOBAL;
+        if ( matvar->isLogical )
+            array_flags |= MAT_F_LOGICAL;
+        if ( matvar->class_type == MAT_C_SPARSE )
+            nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+        fwrite(&array_flags_type,4,1,mat->fp);
+        fwrite(&array_flags_size,4,1,mat->fp);
+        fwrite(&array_flags,4,1,mat->fp);
+        fwrite(&nzmax,4,1,mat->fp);
+        /* Rank and Dimension */
+        nBytes = matvar->rank * 4;
+        fwrite(&dims_array_type,4,1,mat->fp);
+        fwrite(&nBytes,4,1,mat->fp);
+        for ( i = 0; i < matvar->rank; i++ ) {
+            mat_int32_t dim;
+            dim = matvar->dims[i];
+            nmemb *= dim;
+            fwrite(&dim,4,1,mat->fp);
+        }
+        if ( matvar->rank % 2 != 0 )
+            fwrite(&pad4,4,1,mat->fp);
+        /* Name of variable */
+        if ( strlen(matvar->name) <= 4 ) {
+            mat_int32_t  array_name_type = MAT_T_INT8;
+            mat_int32_t array_name_len   = strlen(matvar->name);
+            mat_int8_t  pad1 = 0;
+#if 0
+            fwrite(&array_name_type,2,1,mat->fp);
+            fwrite(&array_name_len,2,1,mat->fp);
+#else
+            array_name_type = (array_name_len << 16) | array_name_type;
+            fwrite(&array_name_type,4,1,mat->fp);
+#endif
+            fwrite(matvar->name,1,array_name_len,mat->fp);
+            for ( i = array_name_len; i < 4; i++ )
+                fwrite(&pad1,1,1,mat->fp);
+        } else {
+            mat_int32_t array_name_type = MAT_T_INT8;
+            mat_int32_t array_name_len  = (mat_int32_t)strlen(matvar->name);
+            mat_int8_t  pad1 = 0;
+
+            fwrite(&array_name_type,4,1,mat->fp);
+            fwrite(&array_name_len,4,1,mat->fp);
+            fwrite(matvar->name,1,array_name_len,mat->fp);
+            if ( array_name_len % 8 )
+                for ( i = array_name_len % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+        }
+
+        matvar->datapos = ftell(mat->fp);
+        switch ( matvar->class_type ) {
+            case MAT_C_DOUBLE:
+            case MAT_C_SINGLE:
+            case MAT_C_INT64:
+            case MAT_C_UINT64:
+            case MAT_C_INT32:
+            case MAT_C_UINT32:
+            case MAT_C_INT16:
+            case MAT_C_UINT16:
+            case MAT_C_INT8:
+            case MAT_C_UINT8:
+            {
+                if ( matvar->isComplex ) {
+                    struct ComplexSplit *complex_data = matvar->data;
+                    nBytes = WriteData(mat,complex_data->Re,nmemb,
+                        matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                    nBytes = WriteData(mat,complex_data->Im,nmemb,
+                        matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                } else {
+                    nBytes=WriteData(mat,matvar->data,nmemb,matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                }
+                break;
+            }
+            case MAT_C_CHAR:
+            {
+                /* Check for a NULL character array */
+                if ( matvar->data != NULL && nmemb > 0 )
+                    WriteCharData(mat,matvar->data,nmemb,matvar->data_type);
+                break;
+            }
+            case MAT_C_CELL:
+            {
+                int        ncells;
+                matvar_t **cells = (matvar_t **)matvar->data;
+
+                /* Check for an empty cell array */
+                if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                     matvar->data   == NULL )
+                    break;
+                ncells  = matvar->nbytes / matvar->data_size;
+                for ( i = 0; i < ncells; i++ )
+                    WriteCellArrayField(mat,cells[i]);
+                break;
+            }
+            case MAT_C_STRUCT:
+            {
+                char     **fieldnames, *padzero;
+                int        fieldname_size, nfields;
+                size_t     maxlen = 0;
+                matvar_t **fields = (matvar_t **)matvar->data;
+                mat_int32_t array_name_type = MAT_T_INT8;
+                unsigned   fieldname;
+
+                /* Check for a structure with no fields */
+                if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                     matvar->data   == NULL ) {
+#if 0
+                    fwrite(&fieldname_type,2,1,mat->fp);
+                    fwrite(&fieldname_data_size,2,1,mat->fp);
+#else
+                    fieldname = (fieldname_data_size<<16) | fieldname_type;
+                    fwrite(&fieldname,4,1,mat->fp);
+#endif
+                    fieldname_size = 1;
+                    fwrite(&fieldname_size,4,1,mat->fp);
+                    fwrite(&array_name_type,4,1,mat->fp);
+                    nBytes = 0;
+                    fwrite(&nBytes,4,1,mat->fp);
+                    break;
+                }
+                nfields = matvar->nbytes / (nmemb*matvar->data_size);
+                fieldnames = malloc(nfields*sizeof(char *));
+                for ( i = 0; i < nfields; i++ ) {
+                    fieldnames[i] = fields[i]->name;
+                    if ( strlen(fieldnames[i]) > maxlen )
+                        maxlen = strlen(fieldnames[i]);
+                }
+                maxlen++;
+                fieldname_size = maxlen;
+                while ( nfields*fieldname_size % 8 != 0 )
+                    fieldname_size++;
+#if 0
+                fwrite(&fieldname_type,2,1,mat->fp);
+                fwrite(&fieldname_data_size,2,1,mat->fp);
+#else
+                fieldname = (fieldname_data_size<<16) | fieldname_type;
+                fwrite(&fieldname,4,1,mat->fp);
+#endif
+                fwrite(&fieldname_size,4,1,mat->fp);
+                fwrite(&array_name_type,4,1,mat->fp);
+                nBytes = nfields*fieldname_size;
+                fwrite(&nBytes,4,1,mat->fp);
+                padzero = calloc(fieldname_size,1);
+                for ( i = 0; i < nfields; i++ ) {
+                    fwrite(fieldnames[i],1,strlen(fieldnames[i]),mat->fp);
+                    fwrite(padzero,1,fieldname_size-strlen(fieldnames[i]),mat->fp);
+                }
+                free(fieldnames);
+                free(padzero);
+                for ( i = 0; i < nmemb*nfields; i++ )
+                    WriteStructField(mat,fields[i]);
+                break;
+            }
+            case MAT_C_SPARSE:
+            {
+                sparse_t *sparse = matvar->data;
+
+                nBytes = WriteData(mat,sparse->ir,sparse->nir,MAT_T_INT32);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                nBytes = WriteData(mat,sparse->jc,sparse->njc,MAT_T_INT32);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                if ( matvar->isComplex ) {
+                    struct ComplexSplit *complex_data = sparse->data;
+                    nBytes = WriteData(mat,complex_data->Re,sparse->ndata,
+                        matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                    nBytes = WriteData(mat,complex_data->Im,sparse->ndata,
+                        matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                } else {
+                    nBytes = WriteData(mat,sparse->data,sparse->ndata,matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                }
+            }
+        }
+#if defined(HAVE_ZLIB)
+    } else if ( compress == COMPRESSION_ZLIB ) {
+        mat_uint32_t comp_buf[512];
+        mat_uint32_t uncomp_buf[512] = {0,};
+        int buf_size = 512, err;
+        size_t byteswritten = 0;
+
+        matvar->z         = calloc(1,sizeof(*matvar->z));
+        matvar->z->zalloc = Z_NULL;
+        matvar->z->zfree  = Z_NULL;
+        err = deflateInit(matvar->z,Z_DEFAULT_COMPRESSION);
+
+        matrix_type = MAT_T_COMPRESSED;
+        fwrite(&matrix_type,4,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+        start = ftell(mat->fp);
+
+        /* Array Flags */
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+        if ( matvar->isComplex )
+            array_flags |= MAT_F_COMPLEX;
+        if ( matvar->isGlobal )
+            array_flags |= MAT_F_GLOBAL;
+        if ( matvar->isLogical )
+            array_flags |= MAT_F_LOGICAL;
+        if ( matvar->class_type == MAT_C_SPARSE )
+            nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+        uncomp_buf[0] = MAT_T_MATRIX;
+        uncomp_buf[1] = (int)GetMatrixMaxBufSize(matvar);
+        matvar->z->next_out  = comp_buf;
+        matvar->z->next_in   = uncomp_buf;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+        matvar->z->avail_in  = 8;
+        err = deflate(matvar->z,Z_NO_FLUSH);
+        byteswritten += fwrite(comp_buf,1,
+            buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        uncomp_buf[0] = array_flags_type;
+        uncomp_buf[1] = array_flags_size;
+        uncomp_buf[2] = array_flags;
+        uncomp_buf[3] = nzmax;
+        /* Rank and Dimension */
+        nBytes = matvar->rank * 4;
+        uncomp_buf[4] = dims_array_type;
+        uncomp_buf[5] = nBytes;
+        for ( i = 0; i < matvar->rank; i++ ) {
+            mat_int32_t dim;
+            dim = matvar->dims[i];
+            nmemb *= dim;
+            uncomp_buf[6+i] = dim;
+        }
+        if ( matvar->rank % 2 != 0 ) {
+            uncomp_buf[6+i] = pad4;
+            i++;
+        }
+
+        matvar->z->next_out  = comp_buf;
+        matvar->z->next_in   = uncomp_buf;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+        matvar->z->avail_in  = (6+i)*sizeof(*uncomp_buf);
+        err = deflate(matvar->z,Z_NO_FLUSH);
+        byteswritten += fwrite(comp_buf,1,
+                buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        /* Name of variable */
+        if ( strlen(matvar->name) <= 4 ) {
+            mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
+            mat_int16_t array_name_type = MAT_T_INT8;
+
+            memset(uncomp_buf,0,8);
+            uncomp_buf[0] = (array_name_len << 16) | array_name_type;
+            memcpy(uncomp_buf+1,matvar->name,array_name_len);
+            if ( array_name_len % 4 )
+                array_name_len += 4-(array_name_len % 4);
+
+            matvar->z->next_out  = comp_buf;
+            matvar->z->next_in   = uncomp_buf;
+            matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+            matvar->z->avail_in  = 8;
+            err = deflate(matvar->z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,
+                    buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        } else {
+            mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
+            mat_int32_t array_name_type = MAT_T_INT8;
+
+            memset(uncomp_buf,0,buf_size*sizeof(*uncomp_buf));
+            uncomp_buf[0] = array_name_type;
+            uncomp_buf[1] = array_name_len;
+            memcpy(uncomp_buf+2,matvar->name,array_name_len);
+            if ( array_name_len % 8 )
+                array_name_len += 8-(array_name_len % 8);
+            matvar->z->next_out  = comp_buf;
+            matvar->z->next_in   = uncomp_buf;
+            matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+            matvar->z->avail_in  = 8+array_name_len;
+            err = deflate(matvar->z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,
+                    buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        }
+        matvar->datapos = ftell(mat->fp);
+        switch ( matvar->class_type ) {
+            case MAT_C_DOUBLE:
+            case MAT_C_SINGLE:
+            case MAT_C_INT64:
+            case MAT_C_UINT64:
+            case MAT_C_INT32:
+            case MAT_C_UINT32:
+            case MAT_C_INT16:
+            case MAT_C_UINT16:
+            case MAT_C_INT8:
+            case MAT_C_UINT8:
+            {
+                /* WriteCompressedData makes sure uncomressed data is aligned
+                 * on an 8-byte boundary */
+                if ( matvar->isComplex ) {
+                    struct ComplexSplit *complex_data = matvar->data;
+
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        complex_data->Re,nmemb,matvar->data_type);
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        complex_data->Im,nmemb,matvar->data_type);
+                } else {
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        matvar->data,nmemb,matvar->data_type);
+                }
+                break;
+            }
+            case MAT_C_CHAR:
+            {
+                /* Check for a NULL character array */
+                if ( matvar->data != NULL && nmemb > 0 )
+                    byteswritten += WriteCompressedCharData(mat,matvar->z,
+                        matvar->data,nmemb,matvar->data_type);
+                break;
+            }
+            case MAT_C_CELL:
+            {
+                int        ncells;
+                matvar_t **cells = (matvar_t **)matvar->data;
+
+                /* Check for an empty cell array */
+                if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                     matvar->data   == NULL )
+                    break;
+                ncells  = matvar->nbytes / matvar->data_size;
+                for ( i = 0; i < ncells; i++ )
+                    WriteCompressedCellArrayField(mat,cells[i],matvar->z);
+                break;
+            }
+            case MAT_C_STRUCT:
+            {
+                char     **fieldnames;
+                unsigned char *padzero;
+                int        fieldname_size, nfields;
+                size_t     maxlen = 0;
+                mat_int32_t array_name_type = MAT_T_INT8;
+                matvar_t **fields = (matvar_t **)matvar->data;
+
+                /* Check for a structure with no fields */
+                if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                     matvar->data   == NULL ) {
+                    fieldname_size = 1;
+                    uncomp_buf[0] = (fieldname_data_size << 16) | 
+                                     fieldname_type;
+                    uncomp_buf[1] = 1;
+                    uncomp_buf[2] = array_name_type;
+                    uncomp_buf[3] = 0;
+                    matvar->z->next_out  = comp_buf;
+                    matvar->z->next_in   = uncomp_buf;
+                    matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+                    matvar->z->avail_in  = 32;
+                    err = deflate(matvar->z,Z_NO_FLUSH);
+                    byteswritten += fwrite(comp_buf,1,buf_size*
+                        sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+                    break;
+                }
+                nfields = matvar->nbytes / (nmemb*matvar->data_size);
+                fieldnames = malloc(nfields*sizeof(char *));
+                for ( i = 0; i < nfields; i++ ) {
+                    fieldnames[i] = fields[i]->name;
+                    if ( strlen(fieldnames[i]) > maxlen )
+                        maxlen = strlen(fieldnames[i]);
+                }
+                maxlen++;
+                fieldname_size = maxlen;
+                while ( nfields*fieldname_size % 8 != 0 )
+                    fieldname_size++;
+                uncomp_buf[0] = (fieldname_data_size << 16) | fieldname_type;
+                uncomp_buf[1] = fieldname_size;
+                uncomp_buf[2] = array_name_type;
+                uncomp_buf[3] = nfields*fieldname_size;
+
+                padzero = calloc(fieldname_size,1);
+                matvar->z->next_out  = comp_buf;
+                matvar->z->next_in   = uncomp_buf;
+                matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+                matvar->z->avail_in  = 16;
+                err = deflate(matvar->z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,1,
+                        buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+                for ( i = 0; i < nfields; i++ ) {
+                    memset(padzero,'\0',fieldname_size);
+                    memcpy(padzero,fieldnames[i],strlen(fieldnames[i]));
+                    matvar->z->next_out  = comp_buf;
+                    matvar->z->next_in   = padzero;
+                    matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+                    matvar->z->avail_in  = fieldname_size;
+                    err = deflate(matvar->z,Z_NO_FLUSH);
+                    byteswritten += fwrite(comp_buf,1,
+                            buf_size*sizeof(*comp_buf)-matvar->z->avail_out,
+                            mat->fp);
+                }
+                free(fieldnames);
+                free(padzero);
+                for ( i = 0; i < nmemb*nfields; i++ )
+                    byteswritten +=
+                        WriteCompressedStructField(mat,fields[i],matvar->z);
+                break;
+            }
+            case MAT_C_SPARSE:
+            {
+                sparse_t *sparse = matvar->data;
+
+                byteswritten += WriteCompressedData(mat,matvar->z,sparse->ir,
+                    sparse->nir,MAT_T_INT32);
+                byteswritten += WriteCompressedData(mat,matvar->z,sparse->jc,
+                    sparse->njc,MAT_T_INT32);
+                if ( matvar->isComplex ) {
+                    struct ComplexSplit *complex_data = sparse->data;
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        complex_data->Re,sparse->ndata,matvar->data_type);
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        complex_data->Im,sparse->ndata,matvar->data_type);
+                } else {
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        sparse->data,sparse->ndata,matvar->data_type);
+                }
+                break;
+            }
+        }
+        matvar->z->avail_in  = 0;
+        matvar->z->next_in   = NULL;
+        matvar->z->next_out  = comp_buf;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+
+        err = deflate(matvar->z,Z_FINISH);
+        byteswritten += fwrite(comp_buf,1,
+            buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        while ( err != Z_STREAM_END && !matvar->z->avail_out ) {
+            matvar->z->next_out  = comp_buf;
+            matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+
+            err = deflate(matvar->z,Z_FINISH);
+            byteswritten += fwrite(comp_buf,1,
+                buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        }
+        /* End the compression and set to NULL so Mat_VarFree doesn't try
+         * to free matvar->z with inflateEnd
+         */
+#if 0
+        if ( byteswritten % 8 )
+            for ( i = 0; i < 8-(byteswritten % 8); i++ )
+                fwrite(&pad1,1,1,mat->fp);
+#endif
+        err = deflateEnd(matvar->z);
+        free(matvar->z);
+        matvar->z = NULL;
+#endif
+    }
+    end = ftell(mat->fp);
+    nBytes = (int)(end-start);
+    fseek(mat->fp,(long)-(nBytes+4),SEEK_CUR);
+    fwrite(&nBytes,4,1,mat->fp);
+    fseek(mat->fp,end,SEEK_SET);
+
+    return 0;
+}
+
+/** @brief Writes the variable information and empty data
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ */
+void
+WriteInfo5(mat_t *mat, matvar_t *matvar)
+{
+    mat_uint32_t array_flags = 0x0;
+    mat_int16_t  fieldname_type = MAT_T_INT32,fieldname_data_size=4;
+    mat_int8_t  pad1 = 0;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
+    int      nBytes, i, nmemb = 1,nzmax;
+    long     start = 0, end = 0;
+
+    /* FIXME: SEEK_END is not Guaranteed by the C standard */
+    fseek(mat->fp,0,SEEK_END);         /* Always write at end of file */
+
+
+    if ( matvar->compression == COMPRESSION_NONE ) {
+        fwrite(&matrix_type,4,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+        start = ftell(mat->fp);
+
+        /* Array Flags */
+
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+        if ( matvar->isComplex )
+            array_flags |= MAT_F_COMPLEX;
+        if ( matvar->isGlobal )
+            array_flags |= MAT_F_GLOBAL;
+        if ( matvar->isLogical )
+            array_flags |= MAT_F_LOGICAL;
+        if ( matvar->class_type == MAT_C_SPARSE )
+            nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+        fwrite(&array_flags_type,4,1,mat->fp);
+        fwrite(&array_flags_size,4,1,mat->fp);
+        fwrite(&array_flags,4,1,mat->fp);
+        fwrite(&nzmax,4,1,mat->fp);
+        /* Rank and Dimension */
+        nBytes = matvar->rank * 4;
+        fwrite(&dims_array_type,4,1,mat->fp);
+        fwrite(&nBytes,4,1,mat->fp);
+        for ( i = 0; i < matvar->rank; i++ ) {
+            mat_int32_t dim;
+            dim = matvar->dims[i];
+            nmemb *= dim;
+            fwrite(&dim,4,1,mat->fp);
+        }
+        if ( matvar->rank % 2 != 0 )
+            fwrite(&pad4,4,1,mat->fp);
+        /* Name of variable */
+        if ( strlen(matvar->name) <= 4 ) {
+            mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
+            mat_int8_t  pad1 = 0;
+            mat_int16_t array_name_type = MAT_T_INT8;
+            fwrite(&array_name_type,2,1,mat->fp);
+            fwrite(&array_name_len,2,1,mat->fp);
+            fwrite(matvar->name,1,array_name_len,mat->fp);
+            for ( i = array_name_len; i < 4; i++ )
+                fwrite(&pad1,1,1,mat->fp);
+        } else {
+            mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
+            mat_int8_t  pad1 = 0;
+            mat_int32_t  array_name_type = MAT_T_INT8;
+
+            fwrite(&array_name_type,4,1,mat->fp);
+            fwrite(&array_name_len,4,1,mat->fp);
+            fwrite(matvar->name,1,array_name_len,mat->fp);
+            if ( array_name_len % 8 )
+                for ( i = array_name_len % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+        }
+
+        matvar->datapos = ftell(mat->fp);
+        switch ( matvar->class_type ) {
+            case MAT_C_DOUBLE:
+            case MAT_C_SINGLE:
+            case MAT_C_INT64:
+            case MAT_C_UINT64:
+            case MAT_C_INT32:
+            case MAT_C_UINT32:
+            case MAT_C_INT16:
+            case MAT_C_UINT16:
+            case MAT_C_INT8:
+            case MAT_C_UINT8:
+                nBytes = WriteEmptyData(mat,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                if ( matvar->isComplex ) {
+                    nBytes = WriteEmptyData(mat,nmemb,matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                }
+                break;
+            case MAT_C_CHAR:
+            {
+                WriteEmptyCharData(mat,nmemb,matvar->data_type);
+                break;
+            }
+            case MAT_C_CELL:
+            {
+                int nfields = matvar->nbytes / matvar->data_size;
+                matvar_t **fields = (matvar_t **)matvar->data;
+
+                for ( i = 0; i < nfields; i++ )
+                    WriteCellArrayFieldInfo(mat,fields[i]);
+                break;
+            }
+            case MAT_C_STRUCT:
+            {
+                char **fieldnames, *padzero;
+                int maxlen = 0, fieldname_size;
+                int nfields = matvar->nbytes / matvar->data_size;
+                matvar_t **fields = (matvar_t **)matvar->data;
+                mat_int32_t  array_name_type = MAT_T_INT8;
+                unsigned fieldname;
+
+                fieldnames = malloc(nfields*sizeof(char *));
+                for ( i = 0; i < nfields; i++ ) {
+                    fieldnames[i] = fields[i]->name;
+                    if ( strlen(fieldnames[i]) > maxlen )
+                        maxlen = strlen(fieldnames[i]);
+                }
+                maxlen++;
+                fieldname_size = maxlen;
+                while ( nfields*fieldname_size % 8 != 0 )
+                    fieldname_size++;
+#if 0
+                fwrite(&fieldname_type,2,1,mat->fp);
+                fwrite(&fieldname_data_size,2,1,mat->fp);
+#else
+                fieldname = (fieldname_data_size<<16) | fieldname_type;
+                fwrite(&fieldname,4,1,mat->fp);
+#endif
+                fwrite(&fieldname_size,4,1,mat->fp);
+                fwrite(&array_name_type,4,1,mat->fp);
+                nBytes = nfields*fieldname_size;
+                fwrite(&nBytes,4,1,mat->fp);
+                padzero = calloc(fieldname_size,1);
+                for ( i = 0; i < nfields; i++ ) {
+                    fwrite(fieldnames[i],1,strlen(fieldnames[i]),mat->fp);
+                    fwrite(padzero,1,fieldname_size-strlen(fieldnames[i]),mat->fp);
+                }
+                free(fieldnames);
+                free(padzero);
+                for ( i = 0; i < nfields; i++ )
+                    WriteInfo5(mat,fields[i]);
+                break;
+            }
+        }
+    /* Does not work.
+     * Can write empty data, but how to go back and add the real data?
+     */
+#if 0
+    } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+#if defined(HAVE_ZLIB)
+        mat_uint32_t comp_buf[512];
+        mat_uint32_t uncomp_buf[512] = {0,};
+        int buf_size = 512, err;
+        size_t byteswritten = 0;
+
+        matvar->z         = malloc(sizeof(*matvar->z));
+        matvar->z->zalloc = Z_NULL;
+        matvar->z->zfree  = Z_NULL;
+        err = deflateInit(matvar->z,Z_DEFAULT_COMPRESSION);
+
+        matrix_type = MAT_T_COMPRESSED;
+        fwrite(&matrix_type,4,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+        start = ftell(mat->fp);
+
+        /* Array Flags */
+
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+        if ( matvar->isComplex )
+            array_flags |= MAT_F_COMPLEX;
+        if ( matvar->isGlobal )
+            array_flags |= MAT_F_GLOBAL;
+        if ( matvar->isLogical )
+            array_flags |= MAT_F_LOGICAL;
+
+        uncomp_buf[0] = MAT_T_MATRIX;
+        uncomp_buf[1] = 448;
+        matvar->z->next_out  = comp_buf;
+        matvar->z->next_in   = uncomp_buf;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+        matvar->z->avail_in  = 8;
+        err = deflate(matvar->z,Z_SYNC_FLUSH);
+        byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        uncomp_buf[0] = array_flags_type;
+        uncomp_buf[1] = array_flags_size;
+        uncomp_buf[2] = array_flags;
+        uncomp_buf[3] = 0;
+        /* Rank and Dimension */
+        nBytes = matvar->rank * 4;
+        uncomp_buf[4] = dims_array_type;
+        uncomp_buf[5] = nBytes;
+        for ( i = 0; i < matvar->rank; i++ ) {
+            mat_int32_t dim;
+            dim = matvar->dims[i];
+            nmemb *= dim;
+            uncomp_buf[6+i] = dim;
+        }
+        if ( matvar->rank % 2 != 0 )
+            uncomp_buf[6+i] = pad4;
+
+        matvar->z->next_out  = comp_buf;
+        matvar->z->next_in   = uncomp_buf;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+        matvar->z->avail_in  = (6+i)*sizeof(*uncomp_buf);
+        err = deflate(matvar->z,Z_NO_FLUSH);
+        byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        /* Name of variable */
+        if ( strlen(matvar->name) <= 4 ) {
+#if 0
+            mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
+            mat_int8_t  pad1 = 0;
+
+            uncomp_buf[0] = (array_name_type << 16) | array_name_len;
+            memcpy(uncomp_buf+1,matvar->name,array_name_len);
+
+            matvar->z->next_out  = comp_buf;
+            matvar->z->next_in   = uncomp_buf;
+            matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+            matvar->z->avail_in  = 8;
+            err = deflate(matvar->z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        } else {
+#endif
+            mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
+
+            memset(uncomp_buf,0,buf_size*sizeof(*uncomp_buf));
+            uncomp_buf[0] = array_name_type;
+            uncomp_buf[1] = array_name_len;
+            memcpy(uncomp_buf+2,matvar->name,array_name_len);
+            if ( array_name_len % 8 )
+                array_name_len += array_name_len % 8;
+            matvar->z->next_out  = comp_buf;
+            matvar->z->next_in   = uncomp_buf;
+            matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+            matvar->z->avail_in  = 8+array_name_len;
+            err = deflate(matvar->z,Z_FULL_FLUSH);
+            byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        }
+        matvar->datapos = ftell(mat->fp);
+        deflateCopy(&z_save,matvar->z);
+        switch ( matvar->class_type ) {
+            case MAT_C_DOUBLE:
+            case MAT_C_SINGLE:
+            case MAT_C_INT32:
+            case MAT_C_UINT32:
+            case MAT_C_INT16:
+            case MAT_C_UINT16:
+            case MAT_C_INT8:
+            case MAT_C_UINT8:
+                byteswritten += WriteCompressedEmptyData(mat,matvar->z,nmemb,matvar->data_type);
+#if 0
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                if ( matvar->isComplex ) {
+                    nBytes = WriteEmptyData(mat,nmemb,matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                }
+#endif
+                break;
+        }
+        matvar->z->next_out  = comp_buf;
+        matvar->z->next_in   = NULL;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+        matvar->z->avail_in  = 0;
+
+        err = deflate(matvar->z,Z_FINISH);
+        byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+                if ( byteswritten % 8 )
+                    for ( i = byteswritten % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+        fprintf(stderr,"deflate Z_FINISH: err = %d,byteswritten = %u\n",err,byteswritten);
+
+        err = deflateEnd(matvar->z);
+        fprintf(stderr,"deflateEnd: err = %d\n",err);
+#if 1
+        err = deflateEnd(matvar->z);
+        free(matvar->z);
+        matvar->z = NULL;
+#else
+        memcpy(matvar->z,&z_save,sizeof(*matvar->z));
+#endif
+#endif
+#endif
+    }
+    end = ftell(mat->fp);
+    nBytes = (int)(end-start);
+    fseek(mat->fp,(long)-(nBytes+4),SEEK_CUR);
+    fwrite(&nBytes,4,1,mat->fp);
+    fseek(mat->fp,end,SEEK_SET);
+}
+
+/** @brief Prints the mat variable
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ */
+void
+Mat_VarPrint5( matvar_t *matvar, int printdata )
+{
+    int i, j;
+
+    if ( matvar == NULL )
+        return;
+    if ( matvar->name )
+        Mat_Message("      Name: %s", matvar->name);
+    Mat_Message("      Rank: %d", matvar->rank);
+    if ( matvar->rank == 0 )
+        return;
+    if ( matvar->isComplex )
+        Mat_Message("Class Type: %s (complex)",class_type_desc[matvar->class_type]);
+    else
+        Mat_Message("Class Type: %s",class_type_desc[matvar->class_type]);
+    if ( matvar->data_type )
+        Mat_Message(" Data Type: %s", data_type_desc[matvar->data_type]);
+    if ( matvar->data != NULL && matvar->data_size > 0 ) {
+        switch( matvar->class_type ) {
+            case MAT_C_DOUBLE:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%f ", ((double*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%f ", ((double*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%f\n", ((double*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_SINGLE:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%f ", ((float*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%f ", ((float*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%f\n", ((float*)matvar->data)[i]);
+                }
+                break;
+#ifdef HAVE_MAT_INT64_T
+            case MAT_C_INT64:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%d ", ((mat_int64_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%d ", ((mat_uint64_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%d\n", ((mat_int64_t*)matvar->data)[i]);
+                }
+                break;
+#endif
+#ifdef HAVE_MAT_UINT64_T
+            case MAT_C_UINT64:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%u ", ((mat_uint64_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%u ", ((mat_uint64_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%u\n", ((mat_int64_t*)matvar->data)[i]);
+                }
+                break;
+#endif /* HAVE_MAT_UINT64_T */
+            case MAT_C_INT32:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%d ", ((mat_int32_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%d ", ((mat_uint32_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%d\n", ((mat_int32_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_UINT32:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%u ", ((mat_uint32_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%u ", ((mat_uint32_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%u\n", ((mat_int32_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_INT16:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hd ", ((mat_int16_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hd ", ((mat_uint16_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%hd\n", ((mat_int16_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_UINT16:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hu ", ((mat_uint16_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hu ", ((mat_uint16_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%hu\n", ((mat_int32_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_INT8:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hd ", ((mat_int8_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hd ", ((mat_int8_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%hd\n", ((mat_int8_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_UINT8:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hu ", ((mat_uint8_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hu ", ((mat_uint8_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%hu\n", ((mat_uint8_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_CHAR:
+                if ( !printdata )
+                    break;
+                if ( matvar->dims[0] == 1 ) {
+                    printf("%s\n",(char *)matvar->data);
+                } else {
+                    int ndx = 0;
+                    for ( i = 0; i < matvar->dims[1]; i++ ) {
+                        ndx = i;
+                        j = 0;
+                        while ( j++ < matvar->dims[0] &&
+                                *((char *)matvar->data+ndx) != '\0' ) {
+                            printf("%c", *((char *)matvar->data+ndx));
+                            ndx += matvar->dims[0];
+                        }
+                        printf("\n");
+                    }
+                }
+                break;
+            case MAT_C_STRUCT:
+            {
+                matvar_t **fields = (matvar_t **)matvar->data;
+                int nfields = matvar->nbytes / matvar->data_size;
+                Mat_Message("Fields[%d] {", nfields);
+                for ( i = 0; i < nfields; i++ )
+                    Mat_VarPrint(fields[i],printdata);
+                Mat_Message("}");
+                break;
+            }
+            case MAT_C_CELL:
+            {
+                matvar_t **fields = (matvar_t **)matvar->data;
+                int nfields = matvar->nbytes / matvar->data_size;
+                for ( i = 0; i < nfields; i++ )
+                    Mat_VarPrint(fields[i],printdata);
+                break;
+            }
+            case MAT_C_SPARSE:
+            {
+                sparse_t *sparse;
+/* FIXME: ComplexSplit */
+#if defined(EXTENDED_SPARSE)
+                sparse = matvar->data;
+                switch ( matvar->data_type ) {
+                    case MAT_T_DOUBLE:
+                    {
+                        if ( matvar->isComplex ) {
+                            struct ComplexSplit *complex_data = sparse->data;
+                            double *re,*im;
+                            re = complex_data->Re;
+                            im = complex_data->Im;
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %f + %fi",
+                                        sparse->ir[j]+1,i+1,re[j],im[j]);
+                            }
+                        } else {
+                            double *data;
+                            data = sparse->data;
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %f",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_SINGLE:
+                    {
+                        float *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %f + %fi",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %f",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+#ifdef HAVE_MAT_INT64_T
+                    case MAT_T_INT64:
+                    {
+                        mat_int64_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %d + %di",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %d",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+#endif
+#ifdef HAVE_MAT_UINT64_T
+                    case MAT_T_UINT64:
+                    {
+                        mat_uint64_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %u + %ui",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %u",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+#endif
+                    case MAT_T_INT32:
+                    {
+                        mat_int32_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %d + %di",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %d",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_UINT32:
+                    {
+                        mat_uint32_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %u + %ui",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %u",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_INT16:
+                    {
+                        mat_int16_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hd + %hdi",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hd",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_UINT16:
+                    {
+                        mat_uint16_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hu + %hui",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hu",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_INT8:
+                    {
+                        mat_int8_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hd + %hdi",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hd",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_UINT8:
+                    {
+                        mat_uint8_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hu + %hui",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        (mat_uint16_t)data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hu",
+                                        sparse->ir[j]+1,i+1,
+                                        (mat_uint16_t)data[j]);
+                            }
+                        }
+                        break;
+                    }
+                }
+#else
+                double *data;
+
+                sparse = matvar->data;
+                data = sparse->data;
+                if ( matvar->isComplex ) {
+                    for ( i = 0; i < sparse->njc-1; i++ ) {
+                        for ( j = sparse->jc[i];
+                              j < sparse->jc[i+1] && j < sparse->ndata; j++ )
+                            Mat_Message("    (%d,%d)  %f + %fi",
+                                sparse->ir[j]+1,i+1,data[j],
+                                data[sparse->ndata+j]);
+                    }
+                } else {
+                    for ( i = 0; i < sparse->njc-1; i++ ) {
+                        for ( j = sparse->jc[i];
+                              j < sparse->jc[i+1] && j < sparse->ndata; j++ )
+                            Mat_Message("    (%d,%d)  %f", sparse->ir[j]+1,i+1,
+                                data[j]);
+                    }
+                }
+#endif
+                break;
+            }
+            default:
+                printf("I can't print this class\n");
+        }
+    } else {
+        if ( printdata && !matvar->data  )
+            Mat_Warning("Data is NULL");
+        if ( printdata && matvar->data_size < 1 )
+            Mat_Warning("data-size is %d",matvar->data_size);
+    }
+    Mat_Message("\n");
+    return;
+}
+
+/** @brief Reads the header information for the next MAT variable
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @retuen pointer to the MAT variable or NULL
+ */
+matvar_t *
+Mat_VarReadNextInfo5( mat_t *mat )
+{
+    int err, data_type, nBytes, i;
+    long  fpos;
+    matvar_t *matvar = NULL; 
+    mat_uint32_t array_flags;
+    long     bytesread = 0;
+
+    if( mat == NULL )
+        return NULL; 
+
+    fpos = ftell(mat->fp);
+    err = fread(&data_type,4,1,mat->fp);
+    if ( !err )
+        return NULL;
+    err = fread(&nBytes,4,1,mat->fp);
+    if ( mat->byteswap ) {
+        Mat_int32Swap(&data_type);
+        Mat_int32Swap(&nBytes);
+    }
+    switch ( data_type ) {
+#if defined(HAVE_ZLIB)
+        case MAT_T_COMPRESSED:
+        {
+            mat_uint32_t uncomp_buf[16] = {0,};
+            int      nbytes;
+
+            matvar               = malloc(sizeof(*matvar));
+            matvar->name         = NULL;
+            matvar->data         = NULL;
+            matvar->dims         = NULL;
+            matvar->nbytes       = 0;
+            matvar->data_type    = 0;
+            matvar->class_type   = 0;
+            matvar->data_size    = 0;
+            matvar->mem_conserve = 0;
+            matvar->compression  = 1;
+            matvar->fpos         = fpos;
+            matvar->fp           = mat;
+
+            matvar->z = calloc(1,sizeof(z_stream));
+            matvar->z->zalloc    = NULL;
+            matvar->z->zfree     = NULL;
+            matvar->z->opaque    = NULL;
+            matvar->z->next_in   = NULL;
+            matvar->z->next_out  = NULL;
+            matvar->z->avail_in  = 0;
+            matvar->z->avail_out = 0;
+            err = inflateInit(matvar->z);
+            if ( err != Z_OK ) {
+                Mat_Critical("inflateInit2 returned %d",err);
+                Mat_VarFree(matvar);
+                break;
+            }
+
+            /* Read Variable tag */
+            bytesread += InflateVarTag(mat,matvar,uncomp_buf);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            nbytes = uncomp_buf[1];
+            if ( uncomp_buf[0] != MAT_T_MATRIX ) {
+                Mat_Critical("Uncompressed type not MAT_T_MATRIX");
+                fseek(mat->fp,nBytes-bytesread,SEEK_CUR);
+                Mat_VarFree(matvar);
+                matvar = NULL;
+                break;
+            }
+            /* Inflate Array Flags */
+            bytesread += InflateArrayFlags(mat,matvar,uncomp_buf);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+2);
+                (void)Mat_uint32Swap(uncomp_buf+3);
+            }
+            /* Array Flags */
+            if ( uncomp_buf[0] == MAT_T_UINT32 ) {
+               array_flags = uncomp_buf[2];
+               matvar->class_type  = (array_flags & MAT_F_CLASS_T);
+               matvar->isComplex   = (array_flags & MAT_F_COMPLEX);
+               matvar->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               matvar->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( matvar->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   matvar->nbytes      = uncomp_buf[3];
+               }
+            }
+            /* Inflate Dimensions */
+            bytesread += InflateDimensions(mat,matvar,uncomp_buf);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            /* Rank and Dimension */
+            if ( uncomp_buf[0] == MAT_T_INT32 ) {
+                nbytes = uncomp_buf[1];
+                matvar->rank = nbytes / 4;
+                matvar->dims = malloc(matvar->rank*sizeof(int));
+                if ( mat->byteswap ) {
+                    for ( i = 0; i < matvar->rank; i++ )
+                        matvar->dims[i] = Mat_uint32Swap(&(uncomp_buf[2+i]));
+                } else {
+                    for ( i = 0; i < matvar->rank; i++ )
+                        matvar->dims[i] = uncomp_buf[2+i];
+                }
+            }
+            /* Inflate variable name tag */
+            bytesread += InflateVarNameTag(mat,matvar,uncomp_buf);
+            if ( mat->byteswap )
+                (void)Mat_uint32Swap(uncomp_buf);
+            /* Name of variable */
+            if ( uncomp_buf[0] == MAT_T_INT8 ) {    /* Name not in tag */
+                int len;
+                if ( mat->byteswap )
+                    len = Mat_uint32Swap(uncomp_buf+1);
+                else
+                    len = uncomp_buf[1];
+
+                if ( len % 8 == 0 )
+                    i = len;
+                else
+                    i = len+(8-(len % 8));
+                matvar->name = malloc(i+1);
+                /* Inflate variable name */
+                bytesread += InflateVarName(mat,matvar,matvar->name,i);
+                matvar->name[len] = '\0';
+            } else if ( ((uncomp_buf[0] & 0x0000ffff) == MAT_T_INT8) &&
+                        ((uncomp_buf[0] & 0xffff0000) != 0x00) ) {
+                /* Name packed in tag */
+                int len;
+                len = (uncomp_buf[0] & 0xffff0000) >> 16;
+                matvar->name = malloc(len+1);
+                memcpy(matvar->name,uncomp_buf+1,len);
+                matvar->name[len] = '\0';
+            }
+            if ( matvar->class_type == MAT_C_STRUCT )
+                ReadNextStructField(mat,matvar);
+            else if ( matvar->class_type == MAT_C_CELL ) {
+              if (ReadNextCell(mat,matvar) == -1) {
+                Mat_VarFree(matvar);
+                matvar = NULL;
+                return NULL;
+              }
+            }
+            fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+            matvar->datapos = ftell(mat->fp);
+            fseek(mat->fp,nBytes+8+fpos,SEEK_SET);
+            break;
+        }
+#endif
+        case MAT_T_MATRIX:
+        {
+            int      nbytes;
+            mat_uint32_t buf[32];
+            size_t   bytesread = 0;
+
+            matvar = Mat_VarCalloc();
+            matvar->fpos         = fpos;
+            matvar->fp           = mat;
+
+            /* Read Array Flags and The Dimensions Tag */
+            bytesread  += fread(buf,4,6,mat->fp);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(buf);
+                (void)Mat_uint32Swap(buf+1);
+                (void)Mat_uint32Swap(buf+2);
+                (void)Mat_uint32Swap(buf+3);
+                (void)Mat_uint32Swap(buf+4);
+                (void)Mat_uint32Swap(buf+5);
+            }
+            /* Array Flags */
+            if ( buf[0] == MAT_T_UINT32 ) {
+               array_flags = buf[2];
+               matvar->class_type  = (array_flags & MAT_F_CLASS_T);
+               matvar->isComplex   = (array_flags & MAT_F_COMPLEX);
+               matvar->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               matvar->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( matvar->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   matvar->nbytes      = buf[3];
+               }
+            }
+            /* Rank and Dimension */
+            if ( buf[4] == MAT_T_INT32 ) {
+                nbytes = buf[5];
+
+                matvar->rank = nbytes / 4;
+                matvar->dims = malloc(matvar->rank*sizeof(int));
+
+                /* Assumes rank <= 16 */
+                if ( matvar->rank % 2 != 0 )
+                    bytesread+=fread(buf,4,matvar->rank+1,mat->fp);
+                else
+                    bytesread+=fread(buf,4,matvar->rank,mat->fp);
+
+                if ( mat->byteswap ) {
+                    for ( i = 0; i < matvar->rank; i++ )
+                        matvar->dims[i] = Mat_uint32Swap(buf+i);
+                } else {
+                    for ( i = 0; i < matvar->rank; i++ )
+                        matvar->dims[i] = buf[i];
+                }
+            }
+            /* Variable Name Tag */
+            bytesread+=fread(buf,4,2,mat->fp);
+            if ( mat->byteswap )
+                (void)Mat_uint32Swap(buf);
+            /* Name of variable */
+            if ( buf[0] == MAT_T_INT8 ) {    /* Name not in tag */
+                int len;
+
+                if ( mat->byteswap )
+                    len = Mat_uint32Swap(buf+1);
+                else
+                    len = buf[1];
+                if ( len % 8 == 0 )
+                    i = len;
+                else
+                    i = len+(8-(len % 8));
+                bytesread+=fread(buf,1,i,mat->fp);
+
+                matvar->name = malloc(len+1);
+                memcpy(matvar->name,buf,len);
+                matvar->name[len] = '\0';
+            } else if ( ((buf[0] & 0x0000ffff) == MAT_T_INT8) &&
+                        ((buf[0] & 0xffff0000) != 0x00) ) {
+                /* Name packed in the tag */
+                int len;
+
+                len = (buf[0] & 0xffff0000) >> 16;
+                matvar->name = malloc(len+1);
+                memcpy(matvar->name,buf+1,len);
+                matvar->name[len] = '\0';
+            }
+            if ( matvar->class_type == MAT_C_STRUCT )
+                (void)ReadNextStructField(mat,matvar);
+            else if ( matvar->class_type == MAT_C_CELL )
+                (void)ReadNextCell(mat,matvar);
+            else if ( matvar->class_type == MAT_C_FUNCTION )
+                (void)ReadNextFunctionHandle(mat,matvar);
+            matvar->datapos = ftell(mat->fp);
+            fseek(mat->fp,nBytes+8+fpos,SEEK_SET);
+            break;
+        }
+        default:
+            Mat_Message("%d is not valid (MAT_T_MATRIX or MAT_T_COMPRESSED", data_type);
+            return NULL;
+    }
+
+    return matvar;
+}

+ 7103 - 0
matlabAccess/matio/src/mat5.c.orig

@@ -0,0 +1,7103 @@
+/** @file mat5.c
+ * Matlab MAT version 5 file functions
+ * @ingroup MAT
+ */
+/*
+ * Copyright (C) 2005-2006   Christopher C. Hulbert
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* FIXME: Implement Unicode support */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+#include "matio.h"
+#include "mat5.h"
+#include "matio_private.h"
+
+static const char *class_type_desc[16] = {"Undefined","Cell Array","Structure",
+       "Object","Character Array","Sparse Array","Double Precision Array",
+       "Single Precision Array", "8-bit, signed Integer Array",
+       "8-bit, Unsigned Integer Array","16-bit, signed Integer Array",
+       "16-bit, unsigned Integer Array","32-bit, signed Integer Array",
+       "32-bit, unsigned Integer Array","Matlab Array","Compressed Data"};
+static const char *data_type_desc[23] = {"Unknown","8-bit, signed integer",
+       "8-bit, unsigned integer","16-bit, signed integer",
+       "16-bit, unsigned integer","32-bit, signed integer",
+       "32-bit, unsigned integer","IEEE 754 single-precision","RESERVED",
+       "IEEE 754 double-precision","RESERVED","RESERVED",
+       "64-bit, signed integer","64-bit, unsigned integer", "Matlab Array",
+       "Compressed Data","Unicode UTF-8 Encoded Character Data",
+       "Unicode UTF-16 Encoded Character Data",
+       "Unicode UTF-32 Encoded Character Data","","String","Cell Array",
+       "Structure"};
+
+/*
+ * -------------------------------------------------------------
+ *   Private Functions
+ * -------------------------------------------------------------
+ */
+
+static size_t GetMatrixMaxBufSize(matvar_t *matvar);
+static size_t GetStructFieldBufSize(matvar_t *matvar);
+static size_t GetCellArrayFieldBufSize(matvar_t *matvar);
+
+/** @brief determines the number of bytes needed to store the given struct field
+ *
+ * @ingroup mat_internal
+ * @param matvar field of a structure
+ * @return the number of bytes needed to store the struct field
+ */
+static size_t
+GetStructFieldBufSize(matvar_t *matvar)
+{
+    size_t nBytes = 0,len;
+    size_t tag_size = 8, array_flags_size = 8;
+    int    nmemb = 1, i;
+
+    if ( matvar == NULL )
+        return nBytes;
+
+    /* Have to account for the matrix tag in a struct field */
+    nBytes += tag_size;
+
+    /* Add the Array Flags tag and space to the number of bytes */
+    nBytes += tag_size + array_flags_size;
+
+    /* In a struct field, the name is just a tag with 0 bytes */
+    nBytes += tag_size;
+
+    /* Add rank and dimensions, padded to an 8 byte block */
+    for ( i = 0, len = 0; i < matvar->rank; i++ )
+        nmemb *= matvar->dims[i];
+    if ( matvar->rank % 2 )
+        nBytes += tag_size + matvar->rank*4 + 4;
+    else
+        nBytes += tag_size + matvar->rank*4;
+
+    if ( matvar->class_type == MAT_C_STRUCT ) {
+        matvar_t **fields = matvar->data;
+        int i, nfields;
+        size_t maxlen = 0;
+
+        nfields = matvar->nbytes / (nmemb*matvar->data_size);
+        for ( i = 0; i < nfields; i++ ) {
+            if ( NULL != fields[i]->name && strlen(fields[i]->name) > maxlen )
+                maxlen = strlen(fields[i]->name);
+        }
+        maxlen++;
+        while ( nfields*maxlen % 8 != 0 )
+            maxlen++;
+
+        nBytes += tag_size + tag_size + maxlen*nfields;
+
+        /* FIXME: Add bytes for the fieldnames */
+        if ( NULL != fields && nfields > 0 ) {
+            for ( i = 0; i < nfields*nmemb; i++ )
+                nBytes += GetStructFieldBufSize(fields[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_CELL ) {
+        matvar_t **cells = matvar->data;
+        int i, ncells = matvar->nbytes / matvar->data_size;
+
+        if ( NULL != cells && ncells > 0 ) {
+            for ( i = 0; i < ncells; i++ )
+                nBytes += GetCellArrayFieldBufSize(cells[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_SPARSE ) {
+        sparse_t *sparse = matvar->data;
+
+        nBytes += tag_size + sparse->njc*sizeof(mat_int32_t) +
+                  tag_size + sparse->nir*sizeof(mat_int32_t) +
+                  tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+        if ( matvar->isComplex )
+            nBytes += tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+    } else {
+        nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+        if (nmemb*Mat_SizeOf(matvar->data_type) % 8) {
+            nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+          }
+        if ( matvar->isComplex ) {
+            nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+            if (nmemb*Mat_SizeOf(matvar->data_type) % 8) {
+                nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+              }
+          }
+    }
+    
+    return nBytes;
+}
+
+/** @brief determines the number of bytes needed to store the cell array element
+ *
+ * @ingroup mat_internal
+ * @param matvar MAT variable
+ * @return the number of bytes needed to store the variable
+ */
+static size_t
+GetCellArrayFieldBufSize(matvar_t *matvar)
+{
+    size_t nBytes = 0,len;
+    size_t tag_size = 8, array_flags_size = 8;
+    int    nmemb = 1, i;
+
+    if ( matvar == NULL )
+        return nBytes;
+
+    /* Have to account for the matrix tag in a struct field */
+    nBytes += tag_size;
+
+    /* Add the Array Flags tag and space to the number of bytes */
+    nBytes += tag_size + array_flags_size;
+
+    /* Get size of variable name, pad it to an 8 byte block, and add it to nBytes */
+    if ( NULL != matvar->name )
+        len = strlen(matvar->name);
+    else
+        len=4;
+
+    if ( len <= 4 ) {
+        nBytes += tag_size;
+    } else {
+        if ( len % 8 )
+            len = len + (8 - len % 8);
+        nBytes += tag_size + len;
+    }
+
+    /* Add rank and dimensions, padded to an 8 byte block */
+    for ( i = 0, len = 0; i < matvar->rank; i++ )
+        nmemb *= matvar->dims[i];
+    if ( matvar->rank % 2 )
+        nBytes += tag_size + matvar->rank*4 + 4;
+    else
+        nBytes += tag_size + matvar->rank*4;
+
+    if ( matvar->class_type == MAT_C_STRUCT ) {
+        matvar_t **fields = matvar->data;
+        int i, nfields;
+        size_t maxlen = 0;
+
+        nfields = matvar->nbytes / (nmemb*matvar->data_size);
+        for ( i = 0; i < nfields; i++ ) {
+            if ( NULL != fields[i]->name && strlen(fields[i]->name) > maxlen )
+                maxlen = strlen(fields[i]->name);
+        }
+        maxlen++;
+        while ( nfields*maxlen % 8 != 0 )
+            maxlen++;
+
+        nBytes += tag_size + tag_size + maxlen*nfields;
+
+        if ( NULL != fields && nfields > 0 ) {
+            for ( i = 0; i < nfields*nmemb; i++ )
+                nBytes += GetStructFieldBufSize(fields[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_CELL ) {
+        matvar_t **cells = matvar->data;
+        int i, ncells = matvar->nbytes / matvar->data_size;
+
+        if ( NULL != cells && ncells > 0 ) {
+            for ( i = 0; i < ncells; i++ )
+                nBytes += GetCellArrayFieldBufSize(cells[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_SPARSE ) {
+        sparse_t *sparse = matvar->data;
+
+        nBytes += tag_size + sparse->njc*sizeof(mat_int32_t) +
+                  tag_size + sparse->nir*sizeof(mat_int32_t) +
+                  tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+        if ( matvar->isComplex )
+            nBytes += tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+    } else {
+        nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+        if ( nmemb*Mat_SizeOf(matvar->data_type) % 8 ) {
+            nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+          }
+        if ( matvar->isComplex ) {
+            nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+            if ( nmemb*Mat_SizeOf(matvar->data_type) % 8 ) {
+                nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+              }
+          }
+    }
+    
+    return nBytes;
+}
+
+/** @brief determines the number of bytes needed to store the given variable
+ *
+ * @ingroup mat_internal
+ * @param matvar MAT variable
+ * @return the number of bytes needed to store the variable
+ */
+static size_t
+GetMatrixMaxBufSize(matvar_t *matvar)
+{
+    size_t nBytes = 0,len;
+    size_t tag_size = 8, array_flags_size = 8;
+    int    nmemb = 1, i;
+
+    if ( matvar == NULL )
+        return nBytes;
+
+    /* Add the Array Flags tag and space to the number of bytes */
+    nBytes += tag_size + array_flags_size;
+
+    /* Get size of variable name, pad it to an 8 byte block, and add it to nBytes */
+    if ( NULL != matvar->name )
+        len = strlen(matvar->name);
+    else
+        len=8;
+
+    if ( len <= 4 ) {
+        nBytes += tag_size;
+    } else {
+        if ( len % 8 )
+            len = len + (8 - len % 8);
+        nBytes += tag_size + len;
+    }
+
+    /* Add rank and dimensions, padded to an 8 byte block */
+    for ( i = 0, len = 0; i < matvar->rank; i++ )
+        nmemb *= matvar->dims[i];
+    if ( matvar->rank % 2 )
+        nBytes += tag_size + matvar->rank*4 + 4;
+    else
+        nBytes += tag_size + matvar->rank*4;
+
+    if ( matvar->class_type == MAT_C_STRUCT ) {
+        matvar_t **fields = matvar->data;
+        int i, nfields;
+        size_t maxlen = 0;
+
+        nfields = matvar->nbytes / (nmemb*matvar->data_size);
+        for ( i = 0; i < nfields; i++ ) {
+            if ( NULL != fields[i]->name && strlen(fields[i]->name) > maxlen )
+                maxlen = strlen(fields[i]->name);
+        }
+        maxlen++;
+        while ( nfields*maxlen % 8 != 0 )
+            maxlen++;
+
+        nBytes += tag_size + tag_size + maxlen*nfields;
+
+        /* FIXME: Add bytes for the fieldnames */
+        if ( NULL != fields && nfields > 0 ) {
+            for ( i = 0; i < nfields*nmemb; i++ )
+                nBytes += GetStructFieldBufSize(fields[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_CELL ) {
+        matvar_t **cells = matvar->data;
+        int i, ncells = matvar->nbytes / matvar->data_size;
+
+        if ( NULL != cells && ncells > 0 ) {
+            for ( i = 0; i < ncells; i++ )
+                nBytes += GetCellArrayFieldBufSize(cells[i]);
+        }
+    } else if ( matvar->class_type == MAT_C_SPARSE ) {
+        sparse_t *sparse = matvar->data;
+
+        nBytes += tag_size + sparse->njc*sizeof(mat_int32_t) +
+                  tag_size + sparse->nir*sizeof(mat_int32_t) +
+                  tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+        if ( matvar->isComplex )
+            nBytes += tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
+    } else {
+        nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+        if ( nmemb*Mat_SizeOf(matvar->data_type) % 8 ) {
+            nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+          }
+        if ( matvar->isComplex ) {
+            nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
+            if ( nmemb*Mat_SizeOf(matvar->data_type) % 8 ) {
+                nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
+              }
+          }
+    }
+    
+    return nBytes;
+}
+
+/** @brief Writes @c data as character data
+ *
+ * This function uses the knowledge that the data is part of a character class
+ * to avoid some pitfalls with Matlab listed below.
+ *   @li Matlab character data cannot be unsigned 8-bit integers, it needs at
+ *       least unsigned 16-bit integers
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data character data to write
+ * @param N Number of elements to write
+ * @param data_type character data type (enum matio_types)
+ * @return number of bytes written
+ */ 
+int
+WriteCharData(mat_t *mat, void *data, int N,int data_type)
+{
+    int nBytes = 0, bytesread = 0, i;
+    mat_int8_t pad1 = 0;
+
+    switch ( data_type ) {
+        case MAT_T_UINT16:
+        {
+            nBytes = N*2;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            fwrite(data,2,N,mat->fp);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT8:
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t *ptr;
+            mat_uint16_t c;
+
+            /* Matlab can't read MAT_C_CHAR as uint8, needs uint16 */
+            nBytes = N*2;
+            data_type = MAT_T_UINT16;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            ptr = data;
+            for ( i = 0; i < N; i++ ) {
+                c = (mat_uint16_t)*(char *)ptr;
+                fwrite(&c,2,1,mat->fp);
+                ptr++;
+            }
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            break;
+        }
+        case MAT_T_UTF8:
+        {
+            mat_uint8_t *ptr;
+
+            nBytes = N;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            ptr = data;
+            fwrite(ptr,1,nBytes,mat->fp);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            break;
+        }
+    }
+    bytesread+=nBytes;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Writes @c data as compressed character data
+ *
+ * This function uses the knowledge that the data is part of a character class
+ * to avoid some pitfalls with Matlab listed below.
+ *   @li Matlab character data cannot be unsigned 8-bit integers, it needs at
+ *       least unsigned 16-bit integers
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z pointer to the zlib compression stream
+ * @param data character data to write
+ * @param N Number of elements to write
+ * @param data_type character data type (enum matio_types)
+ * @return number of bytes written
+ */ 
+size_t
+WriteCompressedCharData(mat_t *mat,z_stream *z,void *data,int N,int data_type)
+{
+    int nBytes = 0, data_size, data_tag[2], err, byteswritten = 0;
+    int buf_size = 1024, i;
+    mat_uint8_t   buf[1024], pad[8] = {0,};
+
+    if ((mat == NULL) || (data == NULL) || (mat->fp == NULL))
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_UINT16:
+        {
+            data_size = 2;
+            data_tag[0]  = MAT_T_UINT16;
+            data_tag[1]  = N*data_size;
+            z->next_in   = data_tag;
+            z->avail_in  = 8;
+            z->next_out  = buf;
+            z->avail_out = buf_size;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            z->next_in   = data;
+            z->avail_in  = data_size*N;
+            do {
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            } while ( z->avail_out == 0 );
+            /* Add/Compress padding to pad to 8-byte boundary */
+            if ( N*data_size % 8 ) {
+                z->next_in   = pad;
+                z->avail_in  = 8 - (N*data_size % 8);
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t *ptr;
+            mat_uint16_t c;
+
+            /* Matlab can't read MAT_C_CHAR as uint8, needs uint16 */
+            data_size    = 2;
+            data_tag[0]  = MAT_T_UINT16;
+            data_tag[1]  = N*data_size;
+            z->next_in   = data_tag;
+            z->avail_in  = 8;
+            z->next_out  = buf;
+            z->avail_out = buf_size;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            z->next_in   = data;
+            z->avail_in  = data_size*N;
+            ptr = data;
+            for ( i = 0; i < N; i++ ) {
+                c = (mat_uint16_t)*(char *)ptr;
+                z->next_in   = &c;
+                z->avail_in  = 2;
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+                ptr++;
+            }
+            /* Add/Compress padding to pad to 8-byte boundary */
+            if ( N*data_size % 8 ) {
+                z->next_in   = pad;
+                z->avail_in  = 8 - (N*data_size % 8);
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            }
+            break;
+        }
+        case MAT_T_UTF8:
+        {
+            data_size = 1;
+            data_tag[0]  = MAT_T_UTF8;
+            data_tag[1]  = N*data_size;
+            z->next_in   = data_tag;
+            z->avail_in  = 8;
+            z->next_out  = buf;
+            z->avail_out = buf_size;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            z->next_in   = data;
+            z->avail_in  = data_size*N;
+            do {
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            } while ( z->avail_out == 0 );
+            /* Add/Compress padding to pad to 8-byte boundary */
+            if ( N*data_size % 8 ) {
+                z->next_in   = pad;
+                z->avail_in  = 8 - (N*data_size % 8);
+                z->next_out  = buf;
+                z->avail_out = buf_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+            }
+            break;
+        }
+    }
+    return byteswritten;
+}
+#endif
+
+/** @brief Writes empty characters to the MAT file
+ *
+ * This function uses the knowledge that the data is part of a character class
+ * to avoid some pitfalls with Matlab listed below.
+ *   @li Matlab character data cannot be unsigned 8-bit integers, it needs at
+ *       least unsigned 16-bit integers
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data character data to write
+ * @param N Number of elements to write
+ * @param data_type character data type (enum matio_types)
+ * @return number of bytes written
+ */ 
+int
+WriteEmptyCharData(mat_t *mat, int N, int data_type)
+{
+    int nBytes = 0, bytesread = 0, i;
+    mat_int8_t pad1 = 0;
+
+    switch ( data_type ) {
+        case MAT_T_UINT8: /* Matlab MAT_C_CHAR needs uint16 */
+        case MAT_T_INT8:  /* Matlab MAT_C_CHAR needs uint16 */
+            data_type = MAT_T_UINT16;
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t u16 = 0;
+            nBytes = N*sizeof(mat_uint16_t);
+            fwrite(&data_type,sizeof(mat_int32_t),1,mat->fp);
+            fwrite(&nBytes,sizeof(mat_int32_t),1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&u16,sizeof(mat_uint16_t),1,mat->fp);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            break;
+        }
+        case MAT_T_UTF8:
+        {
+            mat_uint8_t u8 = 0;
+            nBytes = N;
+            fwrite(&data_type,sizeof(mat_int32_t),1,mat->fp);
+            fwrite(&nBytes,sizeof(mat_int32_t),1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&u8,sizeof(mat_uint8_t),1,mat->fp);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            break;
+        }
+    }
+    bytesread+=nBytes;
+    return bytesread;
+}
+
+/* @brief Writes the data tags and empty data to the file
+ *
+ * Writes the data tags and empty data to the file to save space for the
+ * variable when the actual data is written
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param N number of elements to write
+ * @param data_type data type to write
+ * @return Number of bytes written
+ */
+int
+WriteEmptyData(mat_t *mat,int N,int data_type)
+{
+    int nBytes = 0, data_size, i;
+
+    if ( (mat == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d = 0.0;
+
+            data_size = sizeof(double);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&d,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f = 0.0;
+
+            data_size = sizeof(float);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&f,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8 = 0;
+
+            data_size = sizeof(mat_int8_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i8,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8 = 0;
+
+            data_size = sizeof(mat_uint8_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui8,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16 = 0;
+
+            data_size = sizeof(mat_int16_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i16,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16 = 0;
+
+            data_size = sizeof(mat_uint16_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui16,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32 = 0;
+
+            data_size = sizeof(mat_int32_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i32,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32 = 0;
+
+            data_size = sizeof(mat_uint32_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui32,data_size,1,mat->fp);
+            break;
+        }
+#ifdef HAVE_MAT_INT64_T
+        case MAT_T_INT64:
+        {
+            mat_int64_t i64 = 0;
+
+            data_size = sizeof(mat_int64_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i64,data_size,1,mat->fp);
+            break;
+        }
+#endif
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_T_UINT64:
+        {
+            mat_uint64_t ui64 = 0;
+
+            data_size = sizeof(mat_uint64_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui64,data_size,1,mat->fp);
+            break;
+        }
+#endif
+        default:
+            nBytes = 0;
+    }
+    return nBytes;
+}
+
+#if defined(HAVE_ZLIB)
+int
+WriteCompressedEmptyData(mat_t *mat,z_stream *z,int N,int data_type)
+{
+    int nBytes = 0, data_size, i, err, byteswritten = 0;
+
+    if ( (mat == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            mat_uint32_t uncomp_buf[32] = {0,};
+            mat_uint32_t comp_buf[32] = {0,};
+            double data_uncomp_buf[4] = {0.0,};
+
+            data_size = sizeof(double);
+            nBytes = N*data_size;
+            uncomp_buf[0] = data_type;
+            uncomp_buf[1] = 0;
+            z->next_out  = comp_buf;
+            z->next_in   = uncomp_buf;
+            z->avail_out = 32*sizeof(*comp_buf);
+            z->avail_in  = 8;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,32*sizeof(*comp_buf)-z->avail_out,mat->fp);
+            for ( i = 0; i < N; i++ ) {
+                z->next_out  = comp_buf;
+                z->next_in   = data_uncomp_buf;
+                z->avail_out = 32*sizeof(*comp_buf);
+                z->avail_in  = 8;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,32*sizeof(*comp_buf)-z->avail_out,1,mat->fp);
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f = 0.0;
+
+            data_size = sizeof(float);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&f,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8 = 0;
+
+            data_size = sizeof(mat_int8_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i8,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8 = 0;
+
+            data_size = sizeof(mat_uint8_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui8,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16 = 0;
+
+            data_size = sizeof(mat_int16_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i16,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16 = 0;
+
+            data_size = sizeof(mat_uint16_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui16,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32 = 0;
+
+            data_size = sizeof(mat_int32_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i32,data_size,1,mat->fp);
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32 = 0;
+
+            data_size = sizeof(mat_uint32_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui32,data_size,1,mat->fp);
+            break;
+        }
+#ifdef HAVE_MAT_INT64_T
+        case MAT_T_INT64:
+        {
+            mat_int64_t i64 = 0;
+
+            data_size = sizeof(mat_int64_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&i64,data_size,1,mat->fp);
+            break;
+        }
+#endif
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_T_UINT64:
+        {
+            mat_uint64_t ui64 = 0;
+
+            data_size = sizeof(mat_uint64_t);
+            nBytes = N*data_size;
+            fwrite(&data_type,4,1,mat->fp);
+            fwrite(&nBytes,4,1,mat->fp);
+            for ( i = 0; i < N; i++ )
+                fwrite(&ui64,data_size,1,mat->fp);
+            break;
+        }
+#endif
+        default:
+            nBytes = 0;
+    }
+    return byteswritten;
+}
+#endif
+
+/** @param Writes a 2-D slab of data to the MAT file
+ *
+ * @ingroup mat_internal
+ * @fixme should return the number of bytes written, but currently returns 0
+ * @param mat MAT file pointer
+ * @param data pointer to the slab of data
+ * @param data_type data type of the data (enum matio_types)
+ * @param dims dimensions of the dataset
+ * @param start index to start writing the data in each dimension
+ * @param stride write data every @c stride elements
+ * @param edge number of elements to write in each dimension
+ * @return number of byteswritten
+ */
+int
+WriteDataSlab2(mat_t *mat,void *data,int data_type,int *dims,int *start,
+              int *stride,int *edge)
+{
+    int nBytes = 0, data_size, i, j;
+    long pos, row_stride, col_stride;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
+         (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
+        return 0;
+    }
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double *ptr;
+
+            data_size = sizeof(double);
+            ptr = (double *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float *ptr;
+
+            data_size = sizeof(float);
+            ptr = (float *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+#ifdef HAVE_MAT_INT64_T
+        case MAT_T_INT64:
+        {
+            mat_int64_t *ptr;
+
+            data_size = sizeof(mat_int64_t);
+            ptr = (mat_int64_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+#endif
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_T_UINT64:
+        {
+            mat_uint64_t *ptr;
+
+            data_size = sizeof(mat_uint64_t);
+            ptr = (mat_uint64_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+#endif
+        case MAT_T_INT32:
+        {
+            mat_int32_t *ptr;
+
+            data_size = sizeof(mat_int32_t);
+            ptr = (mat_int32_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t *ptr;
+
+            data_size = sizeof(mat_uint32_t);
+            ptr = (mat_uint32_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t *ptr;
+
+            data_size = sizeof(mat_int16_t);
+            ptr = (mat_int16_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t *ptr;
+
+            data_size = sizeof(mat_uint16_t);
+            ptr = (mat_uint16_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t *ptr;
+
+            data_size = sizeof(mat_int8_t);
+            ptr = (mat_int8_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t *ptr;
+
+            data_size = sizeof(mat_uint8_t);
+            ptr = (mat_uint8_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        default:
+            nBytes = 0;
+    }
+    return nBytes;
+}
+
+/** @param Writes a 2-D slab of character data to the MAT file
+ *
+ * This function uses the knowledge that the data is part of a character class
+ * to avoid some pitfalls with Matlab listed below.
+ *   @li Matlab character data cannot be unsigned 8-bit integers, it needs at
+ *       least unsigned 16-bit integers
+ * @ingroup mat_internal
+ * @fixme should return the number of bytes written, but currently returns 0
+ * @param mat MAT file pointer
+ * @param data pointer to the slab of data
+ * @param data_type data type of the data (enum matio_types)
+ * @param dims dimensions of the dataset
+ * @param start index to start writing the data in each dimension
+ * @param stride write data every @c stride elements
+ * @param edge number of elements to write in each dimension
+ * @return number of byteswritten
+ */
+int
+WriteCharDataSlab2(mat_t *mat,void *data,int data_type,int *dims,int *start,
+              int *stride,int *edge)
+{
+    int nBytes = 0, data_size, i, j;
+    long pos, row_stride, col_stride;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
+         (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
+        return 0;
+    }
+
+    switch ( data_type ) {
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t *ptr;
+
+            data_size = sizeof(mat_uint16_t);
+            ptr = data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    fwrite(ptr++,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        case MAT_T_UINT8:
+        {
+            /* Matlab can't read MAT_C_CHAR as uint8, needs uint16 */
+            mat_uint8_t *ptr;
+            mat_uint16_t c;
+
+            data_size = sizeof(mat_uint16_t);
+            ptr = data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++,ptr++ ) {
+                    c = *ptr;
+                    fwrite(&c,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_T_UTF8:
+        {
+            mat_uint8_t *ptr;
+
+            data_size = sizeof(mat_uint8_t);
+            ptr = data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++,ptr++ ) {
+                    fwrite(ptr,data_size,1,mat->fp);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        default:
+            nBytes = 0;
+    }
+    return nBytes;
+}
+
+/** @brief Writes the data buffer to the file
+ *
+ * @param mat MAT file pointer
+ * @param data pointer to the data to write
+ * @param N number of elements to write
+ * @param data_type data type of the data
+ * @return number of bytes written
+ */
+int
+WriteData(mat_t *mat,void *data,int N,int data_type)
+{
+    int nBytes = 0, data_size;
+
+    if ((mat == NULL) || (mat->fp == NULL) || (data == NULL && N > 0))
+        return 0;
+
+    data_size = Mat_SizeOf(data_type);
+    nBytes    = N*data_size;
+    fwrite(&data_type,4,1,mat->fp);
+    fwrite(&nBytes,4,1,mat->fp);
+    fwrite(data,data_size,N,mat->fp);
+
+    return nBytes;
+}
+
+#if defined(HAVE_ZLIB)
+/* Compresses the data buffer and writes it to the file */
+size_t
+WriteCompressedData(mat_t *mat,z_stream *z,void *data,int N,int data_type)
+{
+    int nBytes = 0, data_size, data_tag[2], err, byteswritten = 0;
+    int buf_size = 1024;
+    mat_uint8_t   buf[1024], pad[8] = {0,};
+
+    if ((mat == NULL) || (data == NULL) || (mat->fp == NULL))
+        return 0;
+
+    data_size = Mat_SizeOf(data_type);
+
+    data_tag[0]  = data_type;
+    data_tag[1]  = data_size*N;
+    z->next_in   = data_tag;
+    z->avail_in  = 8;
+    z->next_out  = buf;
+    z->avail_out = buf_size;
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+    z->next_in   = data;
+    z->avail_in  = N*data_size;
+    do {
+        z->next_out  = buf;
+        z->avail_out = buf_size;
+        err = deflate(z,Z_NO_FLUSH);
+        byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+    } while ( z->avail_out == 0 );
+    /* Add/Compress padding to pad to 8-byte boundary */
+    if ( N*data_size % 8 ) {
+        z->next_in   = pad;
+        z->avail_in  = 8 - (N*data_size % 8);
+        z->next_out  = buf;
+        z->avail_out = buf_size;
+        err = deflate(z,Z_NO_FLUSH);
+        byteswritten += fwrite(buf,1,buf_size-z->avail_out,mat->fp);
+    }
+    nBytes = byteswritten;
+    return nBytes;
+}
+#endif
+
+/** @brief Reads the next cell of the cell array in @c matvar
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar MAT variable pointer
+ * @return Number of bytes read
+ */
+int
+ReadNextCell( mat_t *mat, matvar_t *matvar )
+{
+    int ncells, bytesread = 0, i, err;
+    matvar_t **cells = NULL;
+
+    if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+        mat_uint32_t uncomp_buf[16] = {0,};
+        int      nbytes;
+        mat_uint32_t array_flags; 
+
+        ncells = 1;
+        for ( i = 0; i < matvar->rank; i++ )
+            ncells *= matvar->dims[i];
+        matvar->data_size = sizeof(matvar_t *);
+        matvar->nbytes    = ncells*matvar->data_size;
+        matvar->data = malloc(matvar->nbytes);
+        if ( !matvar->data )
+            return bytesread;
+        cells = matvar->data;
+        for ( i = 0; i < ncells; i++ ) {
+            cells[i] = Mat_VarCalloc();
+            if ( NULL == cells[i] ) {
+                Mat_Critical("Couldn't allocate memory for cell %d", i);
+                continue;
+            }
+
+            cells[i]->fpos = ftell(mat->fp)-matvar->z->avail_in;
+
+            /* Read variable tag for cell */
+            bytesread += InflateVarTag(mat,matvar,uncomp_buf);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            nbytes = uncomp_buf[1];
+            if ( uncomp_buf[0] != MAT_T_MATRIX ) {
+                Mat_Critical("cells[%d], Uncompressed type not MAT_T_MATRIX",i);
+                Mat_VarFree(cells[i]);
+                cells[i] = NULL;
+                return -1;
+            }
+            cells[i]->compression = 1;
+            bytesread += InflateArrayFlags(mat,matvar,uncomp_buf);
+            nbytes -= 16;
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+                (void)Mat_uint32Swap(uncomp_buf+2);
+                (void)Mat_uint32Swap(uncomp_buf+3);
+            }
+            /* Array Flags */
+            if ( uncomp_buf[0] == MAT_T_UINT32 ) {
+               array_flags = uncomp_buf[2];
+               cells[i]->class_type  = (array_flags & MAT_F_CLASS_T);
+               cells[i]->isComplex   = (array_flags & MAT_F_COMPLEX);
+               cells[i]->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               cells[i]->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( cells[i]->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   cells[i]->nbytes      = uncomp_buf[3];
+               }
+            } else {
+                Mat_Critical("Expected MAT_T_UINT32 for Array Tags, got %d",
+                               uncomp_buf[0]);
+                bytesread+=InflateSkip(mat,matvar->z,nbytes);
+            }
+            bytesread += InflateDimensions(mat,matvar,uncomp_buf);
+            nbytes -= 8;
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            /* Rank and Dimension */
+            if ( uncomp_buf[0] == MAT_T_INT32 ) {
+                int j = 0;
+
+                cells[i]->rank = uncomp_buf[1];
+                nbytes -= cells[i]->rank;
+                cells[i]->rank /= 4;
+                cells[i]->dims = malloc(cells[i]->rank*sizeof(int));
+                if ( mat->byteswap ) {
+                    for ( j = 0; j < cells[i]->rank; j++ )
+                        cells[i]->dims[j] = Mat_uint32Swap(uncomp_buf+2+j);
+                } else {
+                    for ( j = 0; j < cells[i]->rank; j++ )
+                        cells[i]->dims[j] = uncomp_buf[2+j];
+                }
+                if ( cells[i]->rank % 2 != 0 )
+                    nbytes -= 4;
+            }
+            bytesread += InflateVarNameTag(mat,matvar,uncomp_buf);
+            nbytes -= 8;
+            cells[i]->z = calloc(1,sizeof(z_stream));
+            err = inflateCopy(cells[i]->z,matvar->z);
+            if ( err != Z_OK )
+                Mat_Critical("inflateCopy returned error %d",err);
+            cells[i]->datapos = ftell(mat->fp)-matvar->z->avail_in;
+            if ( cells[i]->class_type == MAT_C_STRUCT )
+                bytesread+=ReadNextStructField(mat,cells[i]);
+            else if ( cells[i]->class_type == MAT_C_CELL )
+                bytesread+=ReadNextCell(mat,cells[i]);
+            fseek(mat->fp,cells[i]->datapos,SEEK_SET);
+            bytesread+=InflateSkip(mat,matvar->z,nbytes);
+        }
+#else
+        Mat_Critical("Not compiled with zlib support");
+#endif
+
+    } else {
+        int ncells;
+        mat_uint32_t buf[16];
+        int      nbytes,nBytes;
+        mat_uint32_t array_flags; 
+
+        ncells = 1;
+        for ( i = 0; i < matvar->rank; i++ )
+            ncells *= matvar->dims[i];
+        matvar->data_size = sizeof(matvar_t *);
+        matvar->nbytes    = ncells*matvar->data_size;
+        matvar->data = malloc(matvar->nbytes);
+        if ( !matvar->data ) {
+            Mat_Critical("Couldn't allocate memory for %s->data",matvar->name);
+            return bytesread;
+        }
+        cells = (matvar_t **)matvar->data;
+        for ( i = 0; i < ncells; i++ ) {
+            cells[i] = Mat_VarCalloc();
+            if ( !cells[i] ) {
+                Mat_Critical("Couldn't allocate memory for cell %d", i);
+                continue;
+            }
+
+            cells[i]->fpos = ftell(mat->fp);
+
+            /* Read variable tag for cell */
+            bytesread += fread(buf,4,2,mat->fp);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(buf);
+                (void)Mat_uint32Swap(buf+1);
+            }
+            nBytes = buf[1];
+            if ( buf[0] != MAT_T_MATRIX ) {
+                Mat_Critical("cells[%d] not MAT_T_MATRIX, fpos = %ld",i,ftell(mat->fp));
+                Mat_VarFree(cells[i]);
+                cells[i] = NULL;
+                continue;
+            }
+            cells[i]->compression = 0;
+#if defined(HAVE_ZLIB)
+            cells[i]->z = NULL;
+#endif
+
+            /* Read Array Flags and The Dimensions Tag */
+            bytesread  += fread(buf,4,6,mat->fp);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(buf);
+                (void)Mat_uint32Swap(buf+1);
+                (void)Mat_uint32Swap(buf+2);
+                (void)Mat_uint32Swap(buf+3);
+                (void)Mat_uint32Swap(buf+4);
+                (void)Mat_uint32Swap(buf+5);
+            }
+            nBytes-=24;
+            /* Array Flags */
+            if ( buf[0] == MAT_T_UINT32 ) {
+               array_flags = buf[2];
+               cells[i]->class_type  = (array_flags & MAT_F_CLASS_T);
+               cells[i]->isComplex   = (array_flags & MAT_F_COMPLEX);
+               cells[i]->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               cells[i]->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( cells[i]->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   cells[i]->nbytes      = buf[3];
+               }
+            }
+            /* Rank and Dimension */
+            if ( buf[4] == MAT_T_INT32 ) {
+                int j;
+                nbytes = buf[5];
+                nBytes-=nbytes;
+
+                cells[i]->rank = nbytes / 4;
+                cells[i]->dims = malloc(cells[i]->rank*sizeof(int));
+
+                /* Assumes rank <= 16 */
+                if ( cells[i]->rank % 2 != 0 ) {
+                    bytesread+=fread(buf,4,cells[i]->rank+1,mat->fp);
+                    nBytes-=4;
+                } else
+                    bytesread+=fread(buf,4,cells[i]->rank,mat->fp);
+
+                if ( mat->byteswap ) {
+                    for ( j = 0; j < cells[i]->rank; j++ )
+                        cells[i]->dims[j] = Mat_uint32Swap(buf+j);
+                } else {
+                    for ( j = 0; j < cells[i]->rank; j++ )
+                        cells[i]->dims[j] = buf[j];
+                }
+            }
+            /* Variable Name Tag */
+            bytesread+=fread(buf,1,8,mat->fp);
+            nBytes-=8;
+            cells[i]->datapos = ftell(mat->fp);
+            if ( cells[i]->class_type == MAT_C_STRUCT )
+                bytesread+=ReadNextStructField(mat,cells[i]);
+            if ( cells[i]->class_type == MAT_C_CELL )
+                bytesread+=ReadNextCell(mat,cells[i]);
+            fseek(mat->fp,cells[i]->datapos+nBytes,SEEK_SET);
+        }
+    }
+
+    return bytesread;
+}
+
+/** @brief Reads the next struct field of the structure in @c matvar
+ *
+ * Reads the next struct fields (fieldname length,names,data headers for all
+ * the fields
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar MAT variable pointer
+ * @return Number of bytes read
+ */
+int
+ReadNextStructField( mat_t *mat, matvar_t *matvar )
+{
+    int fieldname_size,nfields, bytesread = 0, i, err;
+    matvar_t **fields = NULL;
+
+    if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+        char    *ptr;
+        mat_uint32_t uncomp_buf[16] = {0,};
+        int      nbytes, j, nmemb = 1;
+        mat_uint32_t array_flags; 
+
+        for ( i = 0; i < matvar->rank; i++ )
+            nmemb *= matvar->dims[i];
+
+        /* Inflate Field name length */
+        bytesread += InflateFieldNameLength(mat,matvar,uncomp_buf);
+        if ( mat->byteswap ) {
+            (void)Mat_uint32Swap(uncomp_buf);
+            (void)Mat_uint32Swap(uncomp_buf+1);
+        }
+        if ( (uncomp_buf[0] & 0x0000ffff) == MAT_T_INT32 ) {
+            fieldname_size = uncomp_buf[1];
+        } else {
+            Mat_Warning("Error getting fieldname size");
+            return bytesread;
+        }
+
+        bytesread += InflateFieldNamesTag(mat,matvar,uncomp_buf);
+        if ( mat->byteswap ) {
+            (void)Mat_uint32Swap(uncomp_buf);
+            (void)Mat_uint32Swap(uncomp_buf+1);
+        }
+        nfields = uncomp_buf[1];
+        nfields = nfields / fieldname_size;
+        matvar->data_size = sizeof(matvar_t *);
+        matvar->nbytes    = nmemb*nfields*matvar->data_size;
+        matvar->data      = malloc(matvar->nbytes);
+        if ( !matvar->data )
+            return 1;
+        fields = matvar->data;
+        if ( nfields*fieldname_size % 8 != 0 )
+            i = 8-(nfields*fieldname_size % 8);
+        else
+            i = 0;
+        ptr = malloc(nfields*fieldname_size+i);
+        bytesread += InflateFieldNames(mat,matvar,ptr,nfields,fieldname_size,i);
+        for ( i = 0; i < nfields; i++ ) {
+            fields[i]       = calloc(1,sizeof(matvar_t));
+            fields[i]->name = malloc(fieldname_size);
+            memcpy(fields[i]->name,ptr+i*fieldname_size,fieldname_size);
+            fields[i]->name[fieldname_size-1] = '\0';
+        }
+        for ( i = 1; i < nmemb; i++ ) {
+            for ( j = 0; j < nfields; j++ ) {
+                fields[i*nfields+j] = calloc(1,sizeof(matvar_t));
+                fields[i*nfields+j]->name = strdup_printf("%s",fields[j]->name);
+            }
+        }
+
+        for ( i = 0; i < nmemb*nfields; i++ ) {
+            fields[i]->fpos = ftell(mat->fp)-matvar->z->avail_in;
+            /* Read variable tag for struct field */
+            bytesread += InflateVarTag(mat,matvar,uncomp_buf);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            nbytes = uncomp_buf[1];
+            if ( uncomp_buf[0] != MAT_T_MATRIX ) {
+                Mat_Critical("fields[%d], Uncompressed type not MAT_T_MATRIX",i);
+                Mat_VarFree(fields[i]);
+                fields[i] = NULL;
+                continue;
+            } else if ( nbytes == 0 ) {
+                fields[i]->rank = 0;
+                continue;
+            }
+            fields[i]->compression = COMPRESSION_ZLIB;
+            bytesread += InflateArrayFlags(mat,matvar,uncomp_buf);
+            nbytes -= 16;
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+                (void)Mat_uint32Swap(uncomp_buf+2);
+                (void)Mat_uint32Swap(uncomp_buf+3);
+            }
+            /* Array Flags */
+            if ( uncomp_buf[0] == MAT_T_UINT32 ) {
+               array_flags = uncomp_buf[2];
+               fields[i]->class_type  = (array_flags & MAT_F_CLASS_T);
+               fields[i]->isComplex   = (array_flags & MAT_F_COMPLEX);
+               fields[i]->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               fields[i]->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( fields[i]->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   fields[i]->nbytes      = uncomp_buf[3];
+               }
+            } else {
+                Mat_Critical("Expected MAT_T_UINT32 for Array Tags, got %d",
+                    uncomp_buf[0]);
+                bytesread+=InflateSkip(mat,matvar->z,nbytes);
+            }
+            bytesread += InflateDimensions(mat,matvar,uncomp_buf);
+            nbytes -= 8;
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            /* Rank and Dimension */
+            if ( uncomp_buf[0] == MAT_T_INT32 ) {
+                int j = 0;
+
+                fields[i]->rank = uncomp_buf[1];
+                nbytes -= fields[i]->rank;
+                fields[i]->rank /= 4;
+                fields[i]->dims = malloc(fields[i]->rank*sizeof(int));
+                if ( mat->byteswap ) {
+                    for ( j = 0; j < fields[i]->rank; j++ )
+                        fields[i]->dims[j] = Mat_uint32Swap(uncomp_buf+2+j);
+                } else {
+                    for ( j = 0; j < fields[i]->rank; j++ )
+                        fields[i]->dims[j] = uncomp_buf[2+j];
+                }
+                if ( fields[i]->rank % 2 != 0 )
+                    nbytes -= 4;
+            }
+            bytesread += InflateVarNameTag(mat,matvar,uncomp_buf);
+            nbytes -= 8;
+            fields[i]->z = calloc(1,sizeof(z_stream));
+            err = inflateCopy(fields[i]->z,matvar->z);
+            if ( err != Z_OK ) {
+                Mat_Critical("inflateCopy returned error %d",err);
+            }
+            fields[i]->datapos = ftell(mat->fp)-matvar->z->avail_in;
+            if ( fields[i]->class_type == MAT_C_STRUCT )
+                bytesread+=ReadNextStructField(mat,fields[i]);
+            else if ( fields[i]->class_type == MAT_C_CELL )
+                bytesread+=ReadNextCell(mat,fields[i]);
+            fseek(mat->fp,fields[i]->datapos,SEEK_SET);
+            bytesread+=InflateSkip(mat,matvar->z,nbytes);
+        }
+        free(ptr);
+#else
+        Mat_Critical("Not compiled with zlib support");
+#endif
+    } else {
+        int fieldname_size,nfields;
+        mat_uint32_t buf[16] = {0,};
+        int      nbytes,nBytes,nmemb=1,j;
+        mat_uint32_t array_flags; 
+
+        for ( i = 0; i < matvar->rank; i++ )
+            nmemb *= matvar->dims[i];
+
+        bytesread+=fread(buf,4,2,mat->fp);
+        if ( mat->byteswap ) {
+            (void)Mat_uint32Swap(buf);
+            (void)Mat_uint32Swap(buf+1);
+        }
+        if ( (buf[0] & 0x0000ffff) == MAT_T_INT32 ) {
+            fieldname_size = buf[1];
+        } else {
+            Mat_Warning("Error getting fieldname size");
+            return bytesread;
+        }
+        bytesread+=fread(buf,4,2,mat->fp);
+        if ( mat->byteswap ) {
+            (void)Mat_uint32Swap(buf);
+            (void)Mat_uint32Swap(buf+1);
+        }
+        nfields = buf[1];
+        nfields = nfields / fieldname_size;
+        matvar->data_size = sizeof(matvar_t *);
+        matvar->nbytes    = nmemb*nfields*matvar->data_size;
+        matvar->data = malloc(matvar->nbytes);
+        if ( !matvar->data )
+            return bytesread;
+        fields = (matvar_t **)matvar->data;
+        for ( i = 0; i < nfields; i++ ) {
+            fields[i] = calloc(1,sizeof(matvar_t));
+            fields[i]->name = malloc(fieldname_size);
+            bytesread+=fread(fields[i]->name,1,fieldname_size,mat->fp);
+            fields[i]->name[fieldname_size-1] = '\0';
+        }
+        for ( i = 1; i < nmemb; i++ ) {
+            for ( j = 0; j < nfields; j++ ) {
+                fields[i*nfields+j] = calloc(1,sizeof(matvar_t));
+                fields[i*nfields+j]->name = strdup_printf("%s",fields[j]->name);
+            }
+        }
+        if ( (nfields*fieldname_size) % 8 ) {
+            fseek(mat->fp,8-((nfields*fieldname_size) % 8),SEEK_CUR);
+            bytesread+=8-((nfields*fieldname_size) % 8);
+        }
+        for ( i = 0; i < nmemb*nfields; i++ ) {
+
+            fields[i]->fpos = ftell(mat->fp);
+
+            /* Read variable tag for struct field */
+            bytesread += fread(buf,4,2,mat->fp);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(buf);
+                (void)Mat_uint32Swap(buf+1);
+            }
+            nBytes = buf[1];
+            if ( buf[0] != MAT_T_MATRIX ) {
+                Mat_Critical("fields[%d] not MAT_T_MATRIX, fpos = %ld",i,ftell(mat->fp));
+                Mat_VarFree(fields[i]);
+                fields[i] = NULL;
+                return bytesread;
+            } else if ( nBytes == 0 ) {
+                fields[i]->rank = 0;
+                continue;
+            }
+            fields[i]->compression = 0;
+#if defined(HAVE_ZLIB)
+            fields[i]->z = NULL;
+#endif
+
+            /* Read Array Flags and The Dimensions Tag */
+            bytesread  += fread(buf,4,6,mat->fp);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(buf);
+                (void)Mat_uint32Swap(buf+1);
+                (void)Mat_uint32Swap(buf+2);
+                (void)Mat_uint32Swap(buf+3);
+                (void)Mat_uint32Swap(buf+4);
+                (void)Mat_uint32Swap(buf+5);
+            }
+            nBytes-=24;
+            /* Array Flags */
+            if ( buf[0] == MAT_T_UINT32 ) {
+               array_flags = buf[2];
+               fields[i]->class_type  = (array_flags & MAT_F_CLASS_T);
+               fields[i]->isComplex   = (array_flags & MAT_F_COMPLEX);
+               fields[i]->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               fields[i]->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( fields[i]->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   fields[i]->nbytes      = buf[3];
+               }
+            }
+            /* Rank and Dimension */
+            if ( buf[4] == MAT_T_INT32 ) {
+                int j;
+
+                nbytes = buf[5];
+                nBytes-=nbytes;
+
+                fields[i]->rank = nbytes / 4;
+                fields[i]->dims = malloc(fields[i]->rank*sizeof(int));
+
+                /* Assumes rank <= 16 */
+                if ( fields[i]->rank % 2 != 0 ) {
+                    bytesread+=fread(buf,4,fields[i]->rank+1,mat->fp);
+                    nBytes-=4;
+                } else
+                    bytesread+=fread(buf,4,fields[i]->rank,mat->fp);
+
+                if ( mat->byteswap ) {
+                    for ( j = 0; j < fields[i]->rank; j++ )
+                        fields[i]->dims[j] = Mat_uint32Swap(buf+j);
+                } else {
+                    for ( j = 0; j < fields[i]->rank; j++ )
+                        fields[i]->dims[j] = buf[j];
+                }
+            }
+            /* Variable Name Tag */
+            bytesread+=fread(buf,1,8,mat->fp);
+            nBytes-=8;
+            fields[i]->datapos = ftell(mat->fp);
+            if ( fields[i]->class_type == MAT_C_STRUCT )
+                bytesread+=ReadNextStructField(mat,fields[i]);
+            else if ( fields[i]->class_type == MAT_C_CELL )
+                bytesread+=ReadNextCell(mat,fields[i]);
+            fseek(mat->fp,fields[i]->datapos+nBytes,SEEK_SET);
+        }
+    }
+
+    return bytesread;
+}
+
+/** @brief Reads the function handle data of the function handle in @c matvar
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar MAT variable pointer
+ * @return Number of bytes read
+ */
+int
+ReadNextFunctionHandle(mat_t *mat, matvar_t *matvar)
+{
+    int nfunctions = 1, bytesread = 0, i;
+    matvar_t **functions = NULL;
+
+    for ( i = 0; i < matvar->rank; i++ )
+        nfunctions *= matvar->dims[i];
+
+    matvar->data = malloc(nfunctions*sizeof(matvar_t *));
+    if ( matvar->data != NULL ) {
+        matvar->data_size = sizeof(matvar_t *);
+        matvar->nbytes    = nfunctions*matvar->data_size;
+        functions = matvar->data;
+        for ( i = 0 ; i < nfunctions; i++ )
+            functions[i] = Mat_VarReadNextInfo(mat);
+    } else {
+        bytesread = 0;
+        matvar->data_size = 0;
+        matvar->nbytes    = 0;
+    }
+
+    return bytesread;
+}
+
+/** @brief Writes the header and blank data for a cell array
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @return number of bytes written
+ */
+int
+WriteCellArrayFieldInfo(mat_t *mat,matvar_t *matvar)
+{
+    mat_uint32_t array_flags = 0x0; 
+    mat_int16_t  array_name_type = MAT_T_INT8;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
+    mat_int8_t   pad1 = 0;
+    int      nBytes, i, nmemb = 1;
+    long     start = 0, end = 0;
+
+    if ((matvar == NULL) || (mat == NULL))
+        return 0;
+
+#if 0
+    nBytes = GetMatrixMaxBufSize(matvar);
+#endif
+
+    fwrite(&matrix_type,4,1,mat->fp);
+    fwrite(&pad4,4,1,mat->fp);
+    start = ftell(mat->fp);
+
+    /* Array Flags */
+    if ( matvar->rank > 1 && ( matvar->dims[0] > 1 || matvar->dims[1] > 1 ) &&
+         matvar->class_type == MAT_C_INT32 ) {
+        array_flags = MAT_C_DOUBLE & MAT_F_CLASS_T;
+    } else {
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+    }
+    if ( matvar->isComplex )
+        array_flags |= MAT_F_COMPLEX;
+    if ( matvar->isGlobal )
+        array_flags |= MAT_F_GLOBAL;
+    if ( matvar->isLogical )
+        array_flags |= MAT_F_LOGICAL;
+
+    if ( mat->byteswap )
+        array_flags = Mat_int32Swap((mat_int32_t*)&array_flags);
+    fwrite(&array_flags_type,4,1,mat->fp);
+    fwrite(&array_flags_size,4,1,mat->fp);
+    fwrite(&array_flags,4,1,mat->fp);
+    fwrite(&pad4,4,1,mat->fp);
+    /* Rank and Dimension */
+    nBytes = matvar->rank * 4;
+    fwrite(&dims_array_type,4,1,mat->fp);
+    fwrite(&nBytes,4,1,mat->fp);
+    for ( i = 0; i < matvar->rank; i++ ) {
+        mat_int32_t dim;
+        dim = matvar->dims[i];
+        nmemb *= dim;
+        fwrite(&dim,4,1,mat->fp);
+    }
+    if ( matvar->rank % 2 != 0 )
+        fwrite(&pad4,4,1,mat->fp);
+    /* Name of variable */
+    if ( !matvar->name ) {
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+    } else if ( strlen(matvar->name) <= 4 ) {
+        mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
+        mat_int8_t  pad1 = 0;
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&array_name_len,2,1,mat->fp);
+        fwrite(matvar->name,1,array_name_len,mat->fp);
+        for ( i = array_name_len; i < 4; i++ )
+            fwrite(&pad1,1,1,mat->fp);
+    } else {
+        mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
+        mat_int8_t  pad1 = 0;
+
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&array_name_len,4,1,mat->fp);
+        fwrite(matvar->name,1,array_name_len,mat->fp);
+        if ( array_name_len % 8 )
+            for ( i = array_name_len % 8; i < 8; i++ )
+                fwrite(&pad1,1,1,mat->fp);
+    }
+
+    matvar->datapos = ftell(mat->fp);
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+        case MAT_C_SINGLE:
+        case MAT_C_INT64:
+        case MAT_C_UINT64:
+        case MAT_C_INT32:
+        case MAT_C_UINT32:
+        case MAT_C_INT16:
+        case MAT_C_UINT16:
+        case MAT_C_INT8:
+        case MAT_C_UINT8:
+            nBytes = WriteEmptyData(mat,nmemb,matvar->data_type);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            if ( matvar->isComplex ) {
+                nBytes = WriteEmptyData(mat,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+            }
+            break;
+        case MAT_C_CHAR:
+        {
+            WriteEmptyCharData(mat,nmemb,matvar->data_type);
+            break;
+        }
+        case MAT_C_CELL:
+        {
+            int nfields = matvar->nbytes / matvar->data_size;
+            matvar_t **fields = (matvar_t **)matvar->data;
+
+            for ( i = 0; i < nfields; i++ )
+                WriteCellArrayFieldInfo(mat,fields[i]);
+            break;
+        }
+        /* FIXME: Structures */
+    }
+    end = ftell(mat->fp);
+    nBytes = (int)(end-start);
+    fseek(mat->fp,(long)-(nBytes+4),SEEK_CUR);
+    fwrite(&nBytes,4,1,mat->fp);
+    fseek(mat->fp,end,SEEK_SET);
+    return 0;
+}
+
+/** @brief Writes the header and data for an element of a cell array
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @retval 0 on success
+ */
+int
+WriteCellArrayField(mat_t *mat,matvar_t *matvar )
+{
+    mat_uint32_t array_flags = 0x0; 
+    mat_int16_t  array_name_type = MAT_T_INT8,fieldname_type = MAT_T_INT32,fieldname_data_size=4;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
+    mat_int8_t   pad1 = 0;
+    int      nBytes, i, nmemb = 1, nzmax = 0;
+    long     start = 0, end = 0;
+
+    if ((matvar == NULL) || (mat == NULL))
+        return 1;
+
+#if 0
+    nBytes = GetMatrixMaxBufSize(matvar);
+#endif
+
+    fwrite(&matrix_type,4,1,mat->fp);
+    fwrite(&pad4,4,1,mat->fp);
+    start = ftell(mat->fp);
+
+    /* Array Flags */
+    if ( matvar->rank > 1 && ( matvar->dims[0] > 1 || matvar->dims[1] > 1 ) &&
+         matvar->class_type == MAT_C_INT32 ) {
+        array_flags = MAT_C_DOUBLE & MAT_F_CLASS_T;
+    } else {
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+    }
+    if ( matvar->isComplex )
+        array_flags |= MAT_F_COMPLEX;
+    if ( matvar->isGlobal )
+        array_flags |= MAT_F_GLOBAL;
+    if ( matvar->isLogical )
+        array_flags |= MAT_F_LOGICAL;
+    if ( matvar->class_type == MAT_C_SPARSE )
+        nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+    if ( mat->byteswap )
+        array_flags = Mat_int32Swap((mat_int32_t*)&array_flags);
+    fwrite(&array_flags_type,4,1,mat->fp);
+    fwrite(&array_flags_size,4,1,mat->fp);
+    fwrite(&array_flags,4,1,mat->fp);
+    fwrite(&nzmax,4,1,mat->fp);
+    /* Rank and Dimension */
+    nBytes = matvar->rank * 4;
+    fwrite(&dims_array_type,4,1,mat->fp);
+    fwrite(&nBytes,4,1,mat->fp);
+    for ( i = 0; i < matvar->rank; i++ ) {
+        mat_int32_t dim;
+        dim = matvar->dims[i];
+        nmemb *= dim;
+        fwrite(&dim,4,1,mat->fp);
+    }
+    if ( matvar->rank % 2 != 0 )
+        fwrite(&pad4,4,1,mat->fp);
+    /* Name of variable */
+    if ( !matvar->name ) {
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+    } else if ( strlen(matvar->name) <= 4 ) {
+        mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
+        mat_int8_t  pad1 = 0;
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&array_name_len,2,1,mat->fp);
+        fwrite(matvar->name,1,array_name_len,mat->fp);
+        for ( i = array_name_len; i < 4; i++ )
+            fwrite(&pad1,1,1,mat->fp);
+    } else {
+        mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
+        mat_int8_t  pad1 = 0;
+
+        fwrite(&array_name_type,2,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&pad1,1,1,mat->fp);
+        fwrite(&array_name_len,4,1,mat->fp);
+        fwrite(matvar->name,1,array_name_len,mat->fp);
+        if ( array_name_len % 8 )
+            for ( i = array_name_len % 8; i < 8; i++ )
+                fwrite(&pad1,1,1,mat->fp);
+    }
+
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+        case MAT_C_SINGLE:
+        case MAT_C_INT64:
+        case MAT_C_UINT64:
+        case MAT_C_INT32:
+        case MAT_C_UINT32:
+        case MAT_C_INT16:
+        case MAT_C_UINT16:
+        case MAT_C_INT8:
+        case MAT_C_UINT8:
+        {
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = matvar->data;
+
+
+                nBytes=WriteData(mat,complex_data->Re,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                nBytes=WriteData(mat,complex_data->Im,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+            } else {
+                nBytes = WriteData(mat,matvar->data,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+            }
+            break;
+        }
+        case MAT_C_CHAR:
+            WriteCharData(mat,matvar->data,nmemb,matvar->data_type);
+            break;
+        case MAT_C_CELL:
+        {
+            int nfields = matvar->nbytes / matvar->data_size;
+            matvar_t **fields = (matvar_t **)matvar->data;
+
+            for ( i = 0; i < nfields; i++ )
+                WriteCellArrayField(mat,fields[i]);
+            break;
+        }
+        case MAT_C_STRUCT:
+        {
+            char **fieldnames, *padzero;
+            int    fieldname_size, nfields;
+            size_t maxlen = 0;
+            matvar_t **fields = (matvar_t **)matvar->data;
+            unsigned fieldname;
+
+            nfields = matvar->nbytes / (nmemb*matvar->data_size);
+            fieldnames = malloc(nfields*sizeof(char *));
+            for ( i = 0; i < nfields; i++ ) {
+                fieldnames[i] = fields[i]->name;
+                if ( strlen(fieldnames[i]) > maxlen )
+                    maxlen = strlen(fieldnames[i]);
+            }
+            maxlen++;
+            fieldname_size = maxlen;
+            while ( nfields*fieldname_size % 8 != 0 )
+                fieldname_size++;
+#if 0
+            fwrite(&fieldname_type,2,1,mat->fp);
+            fwrite(&fieldname_data_size,2,1,mat->fp);
+#else
+            fieldname = (fieldname_data_size<<16) | fieldname_type;
+            fwrite(&fieldname,4,1,mat->fp);
+#endif
+            fwrite(&fieldname_size,4,1,mat->fp);
+            fwrite(&array_name_type,2,1,mat->fp);
+            fwrite(&pad1,1,1,mat->fp);
+            fwrite(&pad1,1,1,mat->fp);
+            nBytes = nfields*fieldname_size;
+            fwrite(&nBytes,4,1,mat->fp);
+            padzero = calloc(fieldname_size,1);
+            for ( i = 0; i < nfields; i++ ) {
+                fwrite(fieldnames[i],1,strlen(fieldnames[i]),mat->fp);
+                fwrite(padzero,1,fieldname_size-strlen(fieldnames[i]),mat->fp);
+            }
+            free(fieldnames);
+            free(padzero);
+            for ( i = 0; i < nmemb*nfields; i++ )
+                WriteStructField(mat,fields[i]);
+            break;
+        }
+        case MAT_C_SPARSE:
+        {
+            sparse_t *sparse = matvar->data;
+
+            nBytes = WriteData(mat,sparse->ir,sparse->nir,MAT_T_INT32);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            nBytes = WriteData(mat,sparse->jc,sparse->njc,MAT_T_INT32);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            nBytes = WriteData(mat,sparse->data,sparse->ndata,matvar->data_type);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+        }
+    }
+    end = ftell(mat->fp);
+    nBytes = (int)(end-start);
+    fseek(mat->fp,(long)-(nBytes+4),SEEK_CUR);
+    fwrite(&nBytes,4,1,mat->fp);
+    fseek(mat->fp,end,SEEK_SET);
+    return 0;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Writes the header and data for a field of a compressed cell array
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @return number of bytes written to the MAT file
+ */
+size_t
+WriteCompressedCellArrayField(mat_t *mat,matvar_t *matvar,z_stream *z)
+{
+    mat_uint32_t array_flags = 0x0; 
+    mat_int16_t  array_name_type     = MAT_T_INT8;
+    mat_int16_t  fieldname_type      = MAT_T_INT32;
+    mat_int16_t  fieldname_data_size = 4;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0;
+    mat_int8_t   pad1 = 0;
+    int      nBytes, i, nmemb = 1, nzmax = 0;
+    long     start = 0;
+
+    mat_uint32_t comp_buf[512];
+    mat_uint32_t uncomp_buf[512] = {0,};
+    int buf_size = 512, err;
+    size_t byteswritten = 0;
+
+    if ( NULL == matvar || NULL == mat || NULL == z)
+        return 0;
+
+    start = ftell(mat->fp);
+
+    /* Array Flags */
+    array_flags = matvar->class_type & MAT_F_CLASS_T;
+    if ( matvar->isComplex )
+        array_flags |= MAT_F_COMPLEX;
+    if ( matvar->isGlobal )
+        array_flags |= MAT_F_GLOBAL;
+    if ( matvar->isLogical )
+        array_flags |= MAT_F_LOGICAL;
+    if ( matvar->class_type == MAT_C_SPARSE )
+        nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+    uncomp_buf[0] = MAT_T_MATRIX;
+    uncomp_buf[1] = (int)GetMatrixMaxBufSize(matvar);
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = 8;
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+    uncomp_buf[0] = array_flags_type;
+    uncomp_buf[1] = array_flags_size;
+    uncomp_buf[2] = array_flags;
+    uncomp_buf[3] = nzmax;
+    /* Rank and Dimension */
+    nBytes = matvar->rank * 4;
+    uncomp_buf[4] = dims_array_type;
+    uncomp_buf[5] = nBytes;
+    for ( i = 0; i < matvar->rank; i++ ) {
+        mat_int32_t dim;
+        dim = matvar->dims[i];
+        nmemb *= dim;
+        uncomp_buf[6+i] = dim;
+    }
+    if ( matvar->rank % 2 != 0 ) {
+        uncomp_buf[6+i] = pad4;
+        i++;
+    }
+
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = (6+i)*sizeof(*uncomp_buf);
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+    /* Name of variable */
+    uncomp_buf[0] = array_name_type;
+    uncomp_buf[1] = 0;
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = 8;
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+
+    matvar->datapos = ftell(mat->fp);
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+        case MAT_C_SINGLE:
+        case MAT_C_INT64:
+        case MAT_C_UINT64:
+        case MAT_C_INT32:
+        case MAT_C_UINT32:
+        case MAT_C_INT16:
+        case MAT_C_UINT16:
+        case MAT_C_INT8:
+        case MAT_C_UINT8:
+        {
+            /* WriteCompressedData makes sure uncomressed data is aligned
+             * on an 8-byte boundary */
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = matvar->data;
+
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Re,nmemb,matvar->data_type);
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Im,nmemb,matvar->data_type);
+            } else {
+                byteswritten += WriteCompressedData(mat,z,
+                    matvar->data,nmemb,matvar->data_type);
+            }
+            break;
+        }
+        case MAT_C_CHAR:
+        {
+            /* Check for a NULL character array */
+            if ( matvar->data != NULL && nmemb > 0 )
+                byteswritten += WriteCompressedCharData(mat,z,matvar->data,
+                    nmemb,matvar->data_type);
+            break;
+        }
+        case MAT_C_CELL:
+        {
+            int        ncells;
+            matvar_t **cells = (matvar_t **)matvar->data;
+
+            /* Check for an empty cell array */
+            if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                 matvar->data   == NULL )
+                break;
+            ncells  = matvar->nbytes / matvar->data_size;
+            for ( i = 0; i < ncells; i++ )
+                WriteCompressedCellArrayField(mat,cells[i],z);
+            break;
+        }
+        case MAT_C_STRUCT:
+        {
+            char     **fieldnames;
+            unsigned char *padzero;
+            int        fieldname_size, nfields;
+            size_t     maxlen = 0;
+            mat_int32_t array_name_type = MAT_T_INT8;
+            matvar_t **fields = (matvar_t **)matvar->data;
+
+            /* Check for a structure with no fields */
+            if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                 matvar->data   == NULL ) {
+                fieldname_size = 1;
+                uncomp_buf[0] = (fieldname_data_size << 16) | 
+                                 fieldname_type;
+                uncomp_buf[1] = 1;
+                uncomp_buf[2] = array_name_type;
+                uncomp_buf[3] = 0;
+                z->next_out  = comp_buf;
+                z->next_in   = uncomp_buf;
+                z->avail_out = buf_size*sizeof(*comp_buf);
+                z->avail_in  = 32;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,1,buf_size*
+                    sizeof(*comp_buf)-z->avail_out,mat->fp);
+                break;
+            }
+            nfields = matvar->nbytes / (nmemb*matvar->data_size);
+            fieldnames = malloc(nfields*sizeof(char *));
+            for ( i = 0; i < nfields; i++ ) {
+                fieldnames[i] = fields[i]->name;
+                if ( strlen(fieldnames[i]) > maxlen )
+                    maxlen = strlen(fieldnames[i]);
+            }
+            maxlen++;
+            fieldname_size = maxlen;
+            while ( nfields*fieldname_size % 8 != 0 )
+                fieldname_size++;
+            uncomp_buf[0] = (fieldname_data_size << 16) | fieldname_type;
+            uncomp_buf[1] = fieldname_size;
+            uncomp_buf[2] = array_name_type;
+            uncomp_buf[3] = nfields*fieldname_size;
+
+            padzero = calloc(fieldname_size,1);
+            z->next_out  = comp_buf;
+            z->next_in   = uncomp_buf;
+            z->avail_out = buf_size*sizeof(*comp_buf);
+            z->avail_in  = 16;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,
+                    buf_size*sizeof(*comp_buf)-z->avail_out,mat->fp);
+            for ( i = 0; i < nfields; i++ ) {
+                memset(padzero,'\0',fieldname_size);
+                memcpy(padzero,fieldnames[i],strlen(fieldnames[i]));
+                z->next_out  = comp_buf;
+                z->next_in   = padzero;
+                z->avail_out = buf_size*sizeof(*comp_buf);
+                z->avail_in  = fieldname_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,1,
+                        buf_size*sizeof(*comp_buf)-z->avail_out,mat->fp);
+            }
+            free(fieldnames);
+            free(padzero);
+            for ( i = 0; i < nmemb*nfields; i++ )
+                byteswritten +=
+                    WriteCompressedStructField(mat,fields[i],z);
+            break;
+        }
+        case MAT_C_SPARSE:
+        {
+            sparse_t *sparse = matvar->data;
+
+            byteswritten += WriteCompressedData(mat,z,sparse->ir,
+                sparse->nir,MAT_T_INT32);
+            byteswritten += WriteCompressedData(mat,z,sparse->jc,
+                sparse->njc,MAT_T_INT32);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = sparse->data;
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Re,sparse->ndata,matvar->data_type);
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Im,sparse->ndata,matvar->data_type);
+            } else {
+                byteswritten += WriteCompressedData(mat,z,
+                    sparse->data,sparse->ndata,matvar->data_type);
+            }
+            break;
+        }
+    }
+    return byteswritten;
+}
+#endif
+
+/** @brief Writes the header and data for a field of a struct array
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @retval 0 on success
+ */
+int
+WriteStructField(mat_t *mat,matvar_t *matvar)
+{
+    mat_uint32_t array_flags = 0x0; 
+    mat_int16_t  fieldname_type = MAT_T_INT32,fieldname_data_size=4;
+    mat_int32_t  array_name_type = MAT_T_INT8;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
+    mat_int8_t   pad1 = 0;
+    int      nBytes, i, nmemb = 1, nzmax = 0;
+    long     start = 0, end = 0;
+
+    if ( (matvar == NULL) || ( mat == NULL ))
+        return 1;
+
+    fwrite(&matrix_type,4,1,mat->fp);
+    fwrite(&pad4,4,1,mat->fp);
+    start = ftell(mat->fp);
+
+    /* Array Flags */
+    array_flags = matvar->class_type & MAT_F_CLASS_T;
+    if ( matvar->isComplex )
+        array_flags |= MAT_F_COMPLEX;
+    if ( matvar->isGlobal )
+        array_flags |= MAT_F_GLOBAL;
+    if ( matvar->isLogical )
+        array_flags |= MAT_F_LOGICAL;
+    if ( matvar->class_type == MAT_C_SPARSE )
+        nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+    if ( mat->byteswap )
+        array_flags = Mat_int32Swap((mat_int32_t*)&array_flags);
+    fwrite(&array_flags_type,4,1,mat->fp);
+    fwrite(&array_flags_size,4,1,mat->fp);
+    fwrite(&array_flags,4,1,mat->fp);
+    fwrite(&nzmax,4,1,mat->fp);
+    /* Rank and Dimension */
+    nBytes = matvar->rank * 4;
+    fwrite(&dims_array_type,4,1,mat->fp);
+    fwrite(&nBytes,4,1,mat->fp);
+    for ( i = 0; i < matvar->rank; i++ ) {
+        mat_int32_t dim;
+        dim = matvar->dims[i];
+        nmemb *= dim;
+        fwrite(&dim,4,1,mat->fp);
+    }
+    if ( matvar->rank % 2 != 0 )
+        fwrite(&pad4,4,1,mat->fp);
+
+    /* Name of variable */
+    fwrite(&array_name_type,4,1,mat->fp);
+    fwrite(&pad4,4,1,mat->fp);
+
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+        case MAT_C_SINGLE:
+        case MAT_C_INT64:
+        case MAT_C_UINT64:
+        case MAT_C_INT32:
+        case MAT_C_UINT32:
+        case MAT_C_INT16:
+        case MAT_C_UINT16:
+        case MAT_C_INT8:
+        case MAT_C_UINT8:
+        {
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = matvar->data;
+
+
+                nBytes=WriteData(mat,complex_data->Re,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                nBytes=WriteData(mat,complex_data->Im,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+            } else {
+                nBytes=WriteData(mat,matvar->data,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+            }
+            break;
+        }
+        case MAT_C_CHAR:
+            nBytes=WriteCharData(mat,matvar->data,nmemb,matvar->data_type);
+            break;
+        case MAT_C_CELL:
+        {
+            int nfields = matvar->nbytes / matvar->data_size;
+            matvar_t **fields = (matvar_t **)matvar->data;
+
+            for ( i = 0; i < nfields; i++ )
+                WriteCellArrayField(mat,fields[i]);
+            break;
+        }
+        case MAT_C_STRUCT:
+        {
+            char **fieldnames, *padzero;
+            int    fieldname_size, nfields;
+            size_t maxlen = 0;
+            matvar_t **fields = (matvar_t **)matvar->data;
+            unsigned fieldname;
+
+            nfields = matvar->nbytes / (nmemb*matvar->data_size);
+            fieldnames = malloc(nfields*sizeof(char *));
+            for ( i = 0; i < nfields; i++ ) {
+                fieldnames[i] = fields[i]->name;
+                if ( strlen(fieldnames[i]) > maxlen )
+                    maxlen = strlen(fieldnames[i]);
+            }
+            maxlen++;
+            fieldname_size = maxlen;
+            while ( nfields*fieldname_size % 8 != 0 )
+                fieldname_size++;
+#if 0
+            fwrite(&fieldname_type,2,1,mat->fp);
+            fwrite(&fieldname_data_size,2,1,mat->fp);
+#else
+            fieldname = (fieldname_data_size<<16) | fieldname_type;
+            fwrite(&fieldname,4,1,mat->fp);
+#endif
+            fwrite(&fieldname_size,4,1,mat->fp);
+            fwrite(&array_name_type,4,1,mat->fp);
+            nBytes = nfields*fieldname_size;
+            fwrite(&nBytes,4,1,mat->fp);
+            padzero = calloc(fieldname_size,1);
+            for ( i = 0; i < nfields; i++ ) {
+                fwrite(fieldnames[i],1,strlen(fieldnames[i]),mat->fp);
+                fwrite(padzero,1,fieldname_size-strlen(fieldnames[i]),
+                       mat->fp);
+            }
+            free(fieldnames);
+            free(padzero);
+            for ( i = 0; i < nmemb*nfields; i++ )
+                WriteStructField(mat,fields[i]);
+            break;
+        }
+        case MAT_C_SPARSE:
+        {
+            sparse_t *sparse = matvar->data;
+
+            nBytes = WriteData(mat,sparse->ir,sparse->nir,MAT_T_INT32);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            nBytes = WriteData(mat,sparse->jc,sparse->njc,MAT_T_INT32);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+            nBytes = WriteData(mat,sparse->data,sparse->ndata,
+                       matvar->data_type);
+            if ( nBytes % 8 )
+                for ( i = nBytes % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+        }
+    }
+    end = ftell(mat->fp);
+    nBytes = (int)(end-start);
+    fseek(mat->fp,(long)-(nBytes+4),SEEK_CUR);
+    fwrite(&nBytes,4,1,mat->fp);
+    fseek(mat->fp,end,SEEK_SET);
+    return 0;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Writes the header and data for a field of a compressed struct array
+ *
+ * @ingroup mat_internal
+ * @fixme Currently does not work for cell arrays or sparse data
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @return number of bytes written to the MAT file
+ */
+size_t
+WriteCompressedStructField(mat_t *mat,matvar_t *matvar,z_stream *z)
+{
+    mat_uint32_t array_flags = 0x0; 
+    mat_int16_t  array_name_type     = MAT_T_INT8;
+    mat_int16_t  fieldname_type      = MAT_T_INT32;
+    mat_int16_t  fieldname_data_size = 4;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0;
+    mat_int8_t   pad1 = 0;
+    int      nBytes, i, nmemb = 1, nzmax = 0;
+    long     start = 0;
+
+    mat_uint32_t comp_buf[512];
+    mat_uint32_t uncomp_buf[512] = {0,};
+    int buf_size = 512, err;
+    size_t byteswritten = 0;
+
+    if ( NULL == matvar || NULL == mat || NULL == z)
+        return 1;
+
+    start = ftell(mat->fp);
+
+    /* Array Flags */
+    array_flags = matvar->class_type & MAT_F_CLASS_T;
+    if ( matvar->isComplex )
+        array_flags |= MAT_F_COMPLEX;
+    if ( matvar->isGlobal )
+        array_flags |= MAT_F_GLOBAL;
+    if ( matvar->isLogical )
+        array_flags |= MAT_F_LOGICAL;
+    if ( matvar->class_type == MAT_C_SPARSE )
+        nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+    uncomp_buf[0] = MAT_T_MATRIX;
+    uncomp_buf[1] = (int)GetMatrixMaxBufSize(matvar);
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = 8;
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+    uncomp_buf[0] = array_flags_type;
+    uncomp_buf[1] = array_flags_size;
+    uncomp_buf[2] = array_flags;
+    uncomp_buf[3] = nzmax;
+    /* Rank and Dimension */
+    nBytes = matvar->rank * 4;
+    uncomp_buf[4] = dims_array_type;
+    uncomp_buf[5] = nBytes;
+    for ( i = 0; i < matvar->rank; i++ ) {
+        mat_int32_t dim;
+        dim = matvar->dims[i];
+        nmemb *= dim;
+        uncomp_buf[6+i] = dim;
+    }
+    if ( matvar->rank % 2 != 0 ) {
+        uncomp_buf[6+i] = pad4;
+        i++;
+    }
+
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = (6+i)*sizeof(*uncomp_buf);
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+    /* Name of variable */
+    uncomp_buf[0] = array_name_type;
+    uncomp_buf[1] = 0;
+    z->next_out  = comp_buf;
+    z->next_in   = uncomp_buf;
+    z->avail_out = buf_size*sizeof(*comp_buf);
+    z->avail_in  = 8;
+    err = deflate(z,Z_NO_FLUSH);
+    byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
+        mat->fp);
+
+    matvar->datapos = ftell(mat->fp);
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+        case MAT_C_SINGLE:
+        case MAT_C_INT64:
+        case MAT_C_UINT64:
+        case MAT_C_INT32:
+        case MAT_C_UINT32:
+        case MAT_C_INT16:
+        case MAT_C_UINT16:
+        case MAT_C_INT8:
+        case MAT_C_UINT8:
+        {
+            /* WriteCompressedData makes sure uncomressed data is aligned
+             * on an 8-byte boundary */
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = matvar->data;
+
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Re,nmemb,matvar->data_type);
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Im,nmemb,matvar->data_type);
+            } else {
+                byteswritten += WriteCompressedData(mat,z,
+                    matvar->data,nmemb,matvar->data_type);
+            }
+            break;
+        }
+        case MAT_C_CHAR:
+        {
+            /* Check for a NULL character array */
+            if ( matvar->data != NULL && nmemb > 0 )
+                byteswritten += WriteCompressedCharData(mat,z,matvar->data,
+                    nmemb,matvar->data_type);
+            break;
+        }
+        case MAT_C_CELL:
+        {
+            int        ncells;
+            matvar_t **cells = (matvar_t **)matvar->data;
+
+            /* Check for an empty cell array */
+            if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                 matvar->data   == NULL )
+                break;
+            ncells  = matvar->nbytes / matvar->data_size;
+            for ( i = 0; i < ncells; i++ )
+                WriteCompressedCellArrayField(mat,cells[i],z);
+            break;
+        }
+        case MAT_C_STRUCT:
+        {
+            char     **fieldnames;
+            unsigned char *padzero;
+            int        fieldname_size, nfields;
+            size_t     maxlen = 0;
+            mat_int32_t array_name_type = MAT_T_INT8;
+            matvar_t **fields = (matvar_t **)matvar->data;
+
+            /* Check for a structure with no fields */
+            if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                 matvar->data   == NULL ) {
+                fieldname_size = 1;
+                uncomp_buf[0] = (fieldname_data_size << 16) | 
+                                 fieldname_type;
+                uncomp_buf[1] = 1;
+                uncomp_buf[2] = array_name_type;
+                uncomp_buf[3] = 0;
+                z->next_out  = comp_buf;
+                z->next_in   = uncomp_buf;
+                z->avail_out = buf_size*sizeof(*comp_buf);
+                z->avail_in  = 32;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,1,buf_size*
+                    sizeof(*comp_buf)-z->avail_out,mat->fp);
+                break;
+            }
+            nfields = matvar->nbytes / (nmemb*matvar->data_size);
+            fieldnames = malloc(nfields*sizeof(char *));
+            for ( i = 0; i < nfields; i++ ) {
+                fieldnames[i] = fields[i]->name;
+                if ( strlen(fieldnames[i]) > maxlen )
+                    maxlen = strlen(fieldnames[i]);
+            }
+            maxlen++;
+            fieldname_size = maxlen;
+            while ( nfields*fieldname_size % 8 != 0 )
+                fieldname_size++;
+            uncomp_buf[0] = (fieldname_data_size << 16) | fieldname_type;
+            uncomp_buf[1] = fieldname_size;
+            uncomp_buf[2] = array_name_type;
+            uncomp_buf[3] = nfields*fieldname_size;
+
+            padzero = calloc(fieldname_size,1);
+            z->next_out  = comp_buf;
+            z->next_in   = uncomp_buf;
+            z->avail_out = buf_size*sizeof(*comp_buf);
+            z->avail_in  = 16;
+            err = deflate(z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,
+                    buf_size*sizeof(*comp_buf)-z->avail_out,mat->fp);
+            for ( i = 0; i < nfields; i++ ) {
+                memset(padzero,'\0',fieldname_size);
+                memcpy(padzero,fieldnames[i],strlen(fieldnames[i]));
+                z->next_out  = comp_buf;
+                z->next_in   = padzero;
+                z->avail_out = buf_size*sizeof(*comp_buf);
+                z->avail_in  = fieldname_size;
+                err = deflate(z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,1,
+                        buf_size*sizeof(*comp_buf)-z->avail_out,mat->fp);
+            }
+            free(fieldnames);
+            free(padzero);
+            for ( i = 0; i < nmemb*nfields; i++ )
+                byteswritten +=
+                    WriteCompressedStructField(mat,fields[i],z);
+            break;
+        }
+        case MAT_C_SPARSE:
+        {
+            sparse_t *sparse = matvar->data;
+
+            byteswritten += WriteCompressedData(mat,z,sparse->ir,
+                sparse->nir,MAT_T_INT32);
+            byteswritten += WriteCompressedData(mat,z,sparse->jc,
+                sparse->njc,MAT_T_INT32);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = sparse->data;
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Re,sparse->ndata,matvar->data_type);
+                byteswritten += WriteCompressedData(mat,z,
+                    complex_data->Im,sparse->ndata,matvar->data_type);
+            } else {
+                byteswritten += WriteCompressedData(mat,z,
+                    sparse->data,sparse->ndata,matvar->data_type);
+            }
+            break;
+        }
+    }
+    return byteswritten;
+}
+#endif
+
+/** @brief Reads the data of a version 5 MAT variable
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar MAT variable pointer to read the data
+ */
+void
+Read5(mat_t *mat, matvar_t *matvar)
+{
+    int nBytes, len = 0, i, byteswap, packed_type, data_in_tag = 0;
+    long fpos;
+    mat_uint32_t tag[2];
+
+    if ( matvar == NULL )
+        return;
+    else if ( matvar->rank == 0 )        /* An empty data set */
+        return;
+
+    fpos = ftell(mat->fp);
+    len = 1;
+    byteswap = mat->byteswap;
+    switch ( matvar->class_type ) {
+        case MAT_C_DOUBLE:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(double);
+            matvar->data_type = MAT_T_DOUBLE;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadDoubleData(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadDoubleData(mat,complex_data->Im,packed_type,
+                                            len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else { /* if ( isComplex ) */
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadDoubleData(mat,(double*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                 (double*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_SINGLE:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(float);
+            matvar->data_type = MAT_T_SINGLE;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadSingleData(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadSingleData(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadSingleData(mat,(float*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                 (float*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+#ifdef HAVE_MAT_INT64_T
+        case MAT_C_INT64:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_int64_t);
+            matvar->data_type = MAT_T_INT64;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt64Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt64Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt64Data(mat,(mat_int64_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 (mat_int64_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+#endif /* HAVE_MAT_INT64_T */
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_C_UINT64:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_uint64_t);
+            matvar->data_type = MAT_T_UINT64;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt64Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt64Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt64Data(mat,(mat_int64_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt64Data(mat,matvar->z,
+                                 (mat_int64_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+#endif /* HAVE_MAT_UINT64_T */
+        case MAT_C_INT32:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_int32_t);
+            matvar->data_type = MAT_T_INT32;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt32Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,(mat_int32_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 (mat_int32_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_UINT32:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_uint32_t);
+            matvar->data_type = MAT_T_UINT32;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt32Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,(mat_int32_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 (mat_int32_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_INT16:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_int16_t);
+            matvar->data_type = MAT_T_INT16;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt16Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt16Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt16Data(mat,(mat_int16_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 (mat_int16_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_UINT16:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_uint16_t);
+            matvar->data_type = MAT_T_UINT16;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt16Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt16Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt16Data(mat,(mat_int16_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                 (mat_int16_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_INT8:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_int8_t);
+            matvar->data_type = MAT_T_INT8;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt8Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt8Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt8Data(mat,(mat_int8_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 (mat_int8_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+        case MAT_C_UINT8:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(mat_uint8_t);
+            matvar->data_type = MAT_T_UINT8;
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                matvar->nbytes = len*matvar->data_size;
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(matvar->nbytes);
+                complex_data->Im = malloc(matvar->nbytes);
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    Mat_Critical("Failed to allocate %d bytes",2*matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt8Data(mat,complex_data->Re,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                    /* Complex Data Tag */
+                    fread(tag,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        fread(tag+1,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadInt8Data(mat,complex_data->Im,
+                               packed_type,len);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 complex_data->Re,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                    /* Complex Data Tag */
+                    InflateDataType(mat,matvar->z,tag);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag);
+
+                    packed_type = tag[0] & 0x000000ff;
+                    if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                        data_in_tag = 1;
+                        nBytes = (tag[0] & 0xffff0000) >> 16;
+                    } else {
+                        data_in_tag = 0;
+                        InflateDataType(mat,matvar->z,tag+1);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag+1);
+                        nBytes = tag[1];
+                    }
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 complex_data->Im,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+                matvar->data = complex_data;
+            } else {
+                matvar->nbytes = len*matvar->data_size;
+                matvar->data   = malloc(matvar->nbytes);
+                if ( !matvar->data ) {
+                    Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                    break;
+                }
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt8Data(mat,(mat_int8_t*)matvar->data,
+                                 packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                 (mat_int8_t*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            }
+            break;
+            break;
+        case MAT_C_CHAR:
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    InflateDataType(mat,matvar->z,tag+1);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+#endif
+            } else {
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                fread(tag,4,1,mat->fp);
+                if ( byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    nBytes = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(tag+1,4,1,mat->fp);
+                    if ( byteswap )
+                        (void)Mat_uint32Swap(tag+1);
+                    nBytes = tag[1];
+                }
+            }
+            if ( nBytes == 0 ) {
+                matvar->nbytes = 0;
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            matvar->data_size = sizeof(char);
+            /* FIXME: */
+            matvar->data_type = MAT_T_UINT8;
+            matvar->nbytes = len*matvar->data_size;
+            matvar->data   = calloc(matvar->nbytes+1,1);
+            if ( !matvar->data ) {
+                Mat_Critical("Failed to allocate %d bytes",matvar->nbytes);
+                break;
+            }
+            if ( matvar->compression == COMPRESSION_NONE) {
+                nBytes = ReadCharData(mat,(char*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                if ( (nBytes % 8) != 0 )
+                    fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+            } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                nBytes = ReadCompressedCharData(mat,matvar->z,
+                             (char*)matvar->data,packed_type,len);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                if ( (nBytes % 8) != 0 )
+                    InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+            }
+            break;
+        case MAT_C_STRUCT:
+        {
+            matvar_t **fields;
+            int nfields = 0;
+
+            if ( !matvar->nbytes || !matvar->data_size || NULL == matvar->data )
+                break;
+            nfields = matvar->nbytes / matvar->data_size;
+            fields = (matvar_t **)matvar->data;
+            for ( i = 0; i < nfields; i++ ) {
+                fields[i]->fp = mat;
+                Read5(mat,fields[i]);
+            }
+            /* FIXME: */
+            matvar->data_type = MAT_T_STRUCT;
+            break;
+        }
+        case MAT_C_CELL:
+        {
+            matvar_t **cells;
+
+            if ( !matvar->data ) {
+                Mat_Critical("Data is NULL for Cell Array %s",matvar->name);
+                break;
+            }
+            for ( i = 0; i < matvar->rank; i++ )
+                len *= matvar->dims[i];
+            cells = (matvar_t **)matvar->data;
+            for ( i = 0; i < len; i++ ) {
+                cells[i]->fp = mat;
+                Read5(mat,cells[i]);
+            }
+            /* FIXME: */
+            matvar->data_type = MAT_T_CELL;
+            break;
+        }
+        case MAT_C_SPARSE:
+        {
+            int N;
+            sparse_t *data;
+
+            matvar->data_size = sizeof(sparse_t);
+            matvar->data      = malloc(matvar->data_size);
+            if ( matvar->data == NULL ) {
+                Mat_Critical("ReadData: Allocation of data pointer failed");
+                break;
+            }
+            data = matvar->data;
+            data->nzmax  = matvar->nbytes;
+            fseek(mat->fp,matvar->datapos,SEEK_SET);
+            /*  Read ir    */
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( mat->byteswap )
+                    (void)Mat_uint32Swap(tag);
+
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    (void)ReadCompressedInt32Data(mat,matvar->z,
+                             (mat_int32_t*)&N,MAT_T_INT32,1);
+                }
+#endif
+            } else {
+                fread(tag,4,1,mat->fp);
+                if ( mat->byteswap )
+                    (void)Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(&N,4,1,mat->fp);
+                    if ( mat->byteswap )
+                        Mat_int32Swap(&N);
+                }
+            }
+            data->nir = N / 4;
+            data->ir = malloc(data->nir*sizeof(mat_int32_t));
+            if ( data->ir != NULL ) {
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,data->ir,packed_type,data->nir);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 data->ir,packed_type,data->nir);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            } else {
+                Mat_Critical("ReadData: Allocation of ir pointer failed");
+                break;
+            }
+            /*  Read jc    */
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( mat->byteswap )
+                    Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    (void)ReadCompressedInt32Data(mat,matvar->z,
+                             (mat_int32_t*)&N,MAT_T_INT32,1);
+                }
+#endif
+            } else {
+                fread(tag,4,1,mat->fp);
+                if ( mat->byteswap )
+                    Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(&N,4,1,mat->fp);
+                    if ( mat->byteswap )
+                        Mat_int32Swap(&N);
+                }
+            }
+            data->njc = N / 4;
+            data->jc = malloc(data->njc*sizeof(mat_int32_t));
+            if ( data->jc != NULL ) {
+                if ( matvar->compression == COMPRESSION_NONE) {
+                    nBytes = ReadInt32Data(mat,data->jc,packed_type,data->njc);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                } else if ( matvar->compression == COMPRESSION_ZLIB) {
+                    nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                 data->jc,packed_type,data->njc);
+                    /*
+                     * If the data was in the tag we started on a 4-byte
+                     * boundary so add 4 to make it an 8-byte
+                     */
+                    if ( data_in_tag )
+                        nBytes+=4;
+                    if ( (nBytes % 8) != 0 )
+                        InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif
+                }
+            } else {
+                Mat_Critical("ReadData: Allocation of jc pointer failed");
+                break;
+            }
+            /*  Read data    */
+            if ( matvar->compression ) {
+#if defined(HAVE_ZLIB)
+                matvar->z->avail_in = 0;
+                InflateDataType(mat,matvar->z,tag);
+                if ( mat->byteswap )
+                    Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    (void)ReadCompressedInt32Data(mat,matvar->z,
+                             (mat_int32_t*)&N,MAT_T_INT32,1);
+                }
+#endif
+            } else {
+                fread(tag,4,1,mat->fp);
+                if ( mat->byteswap )
+                    Mat_uint32Swap(tag);
+                packed_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                    data_in_tag = 1;
+                    N = (tag[0] & 0xffff0000) >> 16;
+                } else {
+                    data_in_tag = 0;
+                    fread(&N,4,1,mat->fp);
+                    if ( mat->byteswap )
+                        Mat_int32Swap(&N);
+                }
+            }
+#if defined(EXTENDED_SPARSE)
+            matvar->data_type = packed_type;
+#else
+            matvar->data_type = MAT_T_DOUBLE;
+#endif
+            data->ndata = N / Mat_SizeOf(packed_type);
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data;
+
+                complex_data = malloc(sizeof(*complex_data));
+                complex_data->Re = malloc(data->ndata*
+                                          Mat_SizeOf(matvar->data_type));
+                complex_data->Im = malloc(data->ndata*
+                                          Mat_SizeOf(matvar->data_type));
+                if ( NULL == complex_data || NULL == complex_data->Re ||
+                     NULL == complex_data->Im ) {
+                    if ( matvar->compression == COMPRESSION_NONE) {
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadDoubleData(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadSingleData(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadInt32Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadInt32Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadInt16Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadInt16Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadInt8Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadInt8Data(mat,complex_data->Re,
+                                    packed_type,data->ndata);
+                                break;
+                        }
+#else
+                        nBytes = ReadDoubleData(mat,complex_data->Re,
+                                     packed_type,data->ndata);
+#endif
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+
+                        /* Complex Data Tag */
+                        fread(tag,4,1,mat->fp);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag);
+                        packed_type = tag[0] & 0x000000ff;
+                        if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                            data_in_tag = 1;
+                            nBytes = (tag[0] & 0xffff0000) >> 16;
+                        } else {
+                            data_in_tag = 0;
+                            fread(tag+1,4,1,mat->fp);
+                            if ( byteswap )
+                                (void)Mat_uint32Swap(tag+1);
+                            nBytes = tag[1];
+                        }
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadDoubleData(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadSingleData(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadInt32Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadUInt32Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadInt16Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadUInt16Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadInt8Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadUInt8Data(mat,complex_data->Im,
+                                    packed_type,data->ndata);
+                                break;
+                        }
+#else /* EXTENDED_SPARSE */
+                        nBytes = ReadDoubleData(mat,complex_data->Im,
+                                     packed_type,data->ndata);
+#endif /* EXTENDED_SPARSE */
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                    } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+                                break;
+                        }
+#else    /* EXTENDED_SPARSE */
+                        nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     complex_data->Re,packed_type,data->ndata);
+#endif    /* EXTENDED_SPARSE */
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            InflateSkip(mat,matvar->z,8-(nBytes % 8));
+
+                        /* Complex Data Tag */
+                        InflateDataType(mat,matvar->z,tag);
+                        if ( byteswap )
+                            (void)Mat_uint32Swap(tag);
+
+                        packed_type = tag[0] & 0x000000ff;
+                        if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
+                            data_in_tag = 1;
+                            nBytes = (tag[0] & 0xffff0000) >> 16;
+                        } else {
+                            data_in_tag = 0;
+                            InflateDataType(mat,matvar->z,tag+1);
+                            if ( byteswap )
+                                (void)Mat_uint32Swap(tag+1);
+                            nBytes = tag[1];
+                        }
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadCompressedUInt32Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadCompressedUInt16Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadCompressedUInt8Data(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+                                break;
+                        }
+#else    /* EXTENDED_SPARSE */
+                        nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     complex_data->Im,packed_type,data->ndata);
+#endif    /* EXTENDED_SPARSE */
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif    /* HAVE_ZLIB */
+                    }
+                } else {
+                    Mat_Critical("ReadData: Allocation of data pointer failed");
+                    break;
+                }
+                data->data = complex_data;
+            } else { /* isComplex */
+                data->data = malloc(data->ndata*Mat_SizeOf(MAT_T_DOUBLE));
+                if ( data->data != NULL ) {
+                    if ( matvar->compression == COMPRESSION_NONE) {
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadDoubleData(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadSingleData(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadInt32Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadInt32Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadInt16Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadInt16Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadInt8Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadInt8Data(mat,data->data,
+                                    packed_type,data->ndata);
+                                break;
+                        }
+#else
+                        nBytes = ReadDoubleData(mat,data->data,packed_type,
+                                     data->ndata);
+#endif
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            fseek(mat->fp,8-(nBytes % 8),SEEK_CUR);
+#if defined(HAVE_ZLIB)
+                    } else if ( matvar->compression == COMPRESSION_ZLIB) {
+#if defined(EXTENDED_SPARSE)
+                        switch ( matvar->data_type ) {
+                            case MAT_T_DOUBLE:
+                                nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_SINGLE:
+                                nBytes = ReadCompressedSingleData(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT32:
+                                nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT32:
+                                nBytes = ReadCompressedInt32Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT16:
+                                nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT16:
+                                nBytes = ReadCompressedInt16Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_INT8:
+                                nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                            case MAT_T_UINT8:
+                                nBytes = ReadCompressedInt8Data(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+                                break;
+                        }
+#else   /* EXTENDED_SPARSE */
+                        nBytes = ReadCompressedDoubleData(mat,matvar->z,
+                                     data->data,packed_type,data->ndata);
+#endif   /* EXTENDED_SPARSE */
+                        if ( data_in_tag )
+                            nBytes+=4;
+                        if ( (nBytes % 8) != 0 )
+                            InflateSkip(mat,matvar->z,8-(nBytes % 8));
+#endif   /* HAVE_ZLIB */
+                    }
+                } else {
+                    Mat_Critical("ReadData: Allocation of data pointer failed");
+                    break;
+                }
+            }
+            break;
+        }
+        case MAT_C_FUNCTION:
+        {
+            matvar_t **functions;
+            int nfunctions = 0;
+
+            if ( !matvar->nbytes || !matvar->data_size )
+                break;
+            nfunctions = matvar->nbytes / matvar->data_size;
+            functions = (matvar_t **)matvar->data;
+            for ( i = 0; i < nfunctions; i++ ) {
+                functions[i]->fp = mat;
+                Read5(mat,functions[i]);
+            }
+            /* FIXME: */
+            matvar->data_type = MAT_T_FUNCTION;
+            break;
+        }
+        default:
+            Mat_Critical("Read5: %d is not a supported Class", matvar->class_type);
+    }
+    fseek(mat->fp,fpos,SEEK_SET);
+
+    return;
+}
+
+/** @brief Reads a slab of data from the mat variable @c matvar
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @param data pointer to store the read data in (must be of size
+ *             edge[0]*...edge[rank-1]*Mat_SizeOfClass(matvar->class_type))
+ * @param start index to start reading data in each dimension
+ * @param stride write data every @c stride elements in each dimension
+ * @param edge number of elements to read in each dimension
+ * @retval 0 on success
+ */
+int 
+ReadData5(mat_t *mat,matvar_t *matvar,void *data, 
+    int *start,int *stride,int *edge)
+{               
+    int err = 0,real_bytes;
+    mat_int32_t tag[2];
+#if defined(HAVE_ZLIB)
+    z_stream z;
+
+    err = inflateCopy(&z,matvar->z);
+#endif
+
+    fseek(mat->fp,matvar->datapos,SEEK_SET);
+    if ( matvar->compression == COMPRESSION_NONE ) {
+        fread(tag,4,2,mat->fp);
+        if ( mat->byteswap ) {
+            Mat_int32Swap(tag);
+            Mat_int32Swap(tag+1);
+        }
+        matvar->data_type = tag[0] & 0x000000ff;
+        if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
+            fseek(mat->fp,-4,SEEK_CUR);
+            real_bytes = 4+(tag[0] >> 16);
+        } else {
+            real_bytes = 8+tag[1];
+        }
+#if defined(HAVE_ZLIB)
+    } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+        z.avail_in = 0;
+        InflateDataType(mat,&z,tag);
+        if ( mat->byteswap ) {
+            Mat_int32Swap(tag);
+        }
+        matvar->data_type = tag[0] & 0x000000ff;
+        if ( !(tag[0] & 0xffff0000) ) {/* Data is NOT packed in the tag */
+            /* We're cheating, but InflateDataType just inflates 4 bytes */
+            InflateDataType(mat,&z,tag+1);
+            if ( mat->byteswap ) {
+                Mat_int32Swap(tag+1);
+            }
+            real_bytes = 8+tag[1];
+        } else {
+            real_bytes = 4+(tag[0] >> 16);
+        }
+#endif
+    }
+    if ( real_bytes % 8 )
+        real_bytes += (8-(real_bytes % 8));
+
+    if ( matvar->rank == 2 ) {
+        if ( stride[0]*(edge[0]-1)+start[0]+1 > matvar->dims[0] )
+            err = 1;
+        else if ( stride[1]*(edge[1]-1)+start[1]+1 > matvar->dims[1] )
+            err = 1;
+        else if ( matvar->compression == COMPRESSION_NONE ) {
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = data;
+
+                ReadDataSlab2(mat,complex_data->Re,matvar->class_type,
+                    matvar->data_type,matvar->dims,start,stride,edge);
+                fseek(mat->fp,matvar->datapos+real_bytes,SEEK_SET);
+                fread(tag,4,2,mat->fp);
+                if ( mat->byteswap ) {
+                    Mat_int32Swap(tag);
+                    Mat_int32Swap(tag+1);
+                }
+                matvar->data_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
+                    fseek(mat->fp,-4,SEEK_CUR);
+                }
+                ReadDataSlab2(mat,complex_data->Im,matvar->class_type,
+                              matvar->data_type,matvar->dims,start,stride,edge);
+            } else {
+                ReadDataSlab2(mat,data,matvar->class_type,
+                    matvar->data_type,matvar->dims,start,stride,edge);
+            }
+        }
+#if defined(HAVE_ZLIB)
+        else if ( matvar->compression == COMPRESSION_ZLIB ) {
+            if ( matvar->isComplex ) {
+                struct ComplexSplit *complex_data = data;
+
+                ReadCompressedDataSlab2(mat,&z,complex_data->Re,
+                    matvar->class_type,matvar->data_type,matvar->dims,
+                    start,stride,edge);
+
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+
+                /* Reset zlib knowledge to before reading real tag */
+                inflateEnd(&z);
+                err = inflateCopy(&z,matvar->z);
+                InflateSkip(mat,&z,real_bytes);
+                z.avail_in = 0;
+                InflateDataType(mat,&z,tag);
+                if ( mat->byteswap ) {
+                    Mat_int32Swap(tag);
+                }
+                matvar->data_type = tag[0] & 0x000000ff;
+                if ( !(tag[0] & 0xffff0000) ) {/*Data is NOT packed in the tag*/
+                    InflateSkip(mat,&z,4);
+                }
+                ReadCompressedDataSlab2(mat,&z,complex_data->Im,
+                    matvar->class_type,matvar->data_type,matvar->dims,
+                    start,stride,edge);
+                inflateEnd(&z);
+            } else {
+                ReadCompressedDataSlab2(mat,&z,data,matvar->class_type,
+                    matvar->data_type,matvar->dims,start,stride,edge);
+            }
+        }
+#endif
+    } else {
+        if ( matvar->compression == COMPRESSION_NONE ) {
+            if ( matvar->isComplex ) {
+                int i;
+                struct ComplexSplit *complex_data = data;
+
+                ReadDataSlabN(mat,complex_data->Re,matvar->class_type,
+                    matvar->data_type,matvar->rank,matvar->dims,
+                    start,stride,edge);
+
+                fseek(mat->fp,matvar->datapos+real_bytes,SEEK_SET);
+                fread(tag,4,2,mat->fp);
+                if ( mat->byteswap ) {
+                    Mat_int32Swap(tag);
+                    Mat_int32Swap(tag+1);
+                }
+                matvar->data_type = tag[0] & 0x000000ff;
+                if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
+                    fseek(mat->fp,-4,SEEK_CUR);
+                }
+                ReadDataSlabN(mat,complex_data->Im,matvar->class_type,
+                    matvar->data_type,matvar->rank,matvar->dims,
+                    start,stride,edge);
+            } else {
+                ReadDataSlabN(mat,data,matvar->class_type,matvar->data_type,
+                    matvar->rank,matvar->dims,start,stride,edge);
+            }
+        }
+#if defined(HAVE_ZLIB)
+        else if ( matvar->compression == COMPRESSION_ZLIB ) {
+            if ( matvar->isComplex ) {
+                int i;
+                struct ComplexSplit *complex_data = data;
+
+                ReadCompressedDataSlabN(mat,&z,complex_data->Re,
+                    matvar->class_type,matvar->data_type,matvar->rank,
+                    matvar->dims,start,stride,edge);
+
+                fseek(mat->fp,matvar->datapos,SEEK_SET);
+                /* Reset zlib knowledge to before reading real tag */
+                inflateEnd(&z);
+                err = inflateCopy(&z,matvar->z);
+                InflateSkip(mat,&z,real_bytes);
+                z.avail_in = 0;
+                InflateDataType(mat,&z,tag);
+                if ( mat->byteswap ) {
+                    Mat_int32Swap(tag);
+                }
+                matvar->data_type = tag[0] & 0x000000ff;
+                if ( !(tag[0] & 0xffff0000) ) {/*Data is NOT packed in the tag*/
+                    InflateSkip(mat,&z,4);
+                }
+                ReadCompressedDataSlabN(mat,&z,complex_data->Im,
+                    matvar->class_type,matvar->data_type,matvar->rank,
+                    matvar->dims,start,stride,edge);
+                inflateEnd(&z);
+            } else {
+                ReadCompressedDataSlabN(mat,&z,data,matvar->class_type,
+                    matvar->data_type,matvar->rank,matvar->dims,
+                    start,stride,edge);
+            }
+        }
+#endif
+    }
+    if ( err )
+        return err;
+
+    switch(matvar->class_type) {
+        case MAT_C_DOUBLE:
+            matvar->data_type = MAT_T_DOUBLE;
+            matvar->data_size = sizeof(double);
+            break;
+        case MAT_C_SINGLE:
+            matvar->data_type = MAT_T_SINGLE;
+            matvar->data_size = sizeof(float);
+            break;
+#ifdef HAVE_MAT_INT64_T
+        case MAT_C_INT64:
+            matvar->data_type = MAT_T_INT64;
+            matvar->data_size = sizeof(mat_int64_t);
+            break;
+#endif /* HAVE_MAT_INT64_T */
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_C_UINT64:
+            matvar->data_type = MAT_T_UINT64;
+            matvar->data_size = sizeof(mat_uint64_t);
+            break;
+#endif /* HAVE_MAT_UINT64_T */
+        case MAT_C_INT32:
+            matvar->data_type = MAT_T_INT32;
+            matvar->data_size = sizeof(mat_int32_t);
+            break;
+        case MAT_C_UINT32:
+            matvar->data_type = MAT_T_UINT32;
+            matvar->data_size = sizeof(mat_uint32_t);
+            break;
+        case MAT_C_INT16:
+            matvar->data_type = MAT_T_INT16;
+            matvar->data_size = sizeof(mat_int16_t);
+            break;
+        case MAT_C_UINT16:
+            matvar->data_type = MAT_T_UINT16;
+            matvar->data_size = sizeof(mat_uint16_t);
+            break;
+        case MAT_C_INT8:
+            matvar->data_type = MAT_T_INT8;
+            matvar->data_size = sizeof(mat_int8_t);
+            break;
+        case MAT_C_UINT8:
+            matvar->data_type = MAT_T_UINT8;
+            matvar->data_size = sizeof(mat_uint8_t);
+            break;
+    }
+
+    return err;
+}
+
+/** @brief Writes a matlab variable to a version 5 matlab file
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ * @param compress option to compress the variable
+ *                 (only works for numeric types)
+ * @retval 0 on success
+ */
+int
+Write5(mat_t *mat,matvar_t *matvar,int compress)
+{
+    mat_uint32_t array_flags = 0x0;
+    mat_int16_t  fieldname_type = MAT_T_INT32,fieldname_data_size=4;
+    mat_int8_t  pad1 = 0;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
+    int      nBytes, i, nmemb = 1,nzmax = 0;
+    long     start = 0, end = 0;
+
+    /* FIXME: SEEK_END is not Guaranteed by the C standard */
+    fseek(mat->fp,0,SEEK_END);         /* Always write at end of file */
+
+
+    if ( compress == COMPRESSION_NONE ) {
+        fwrite(&matrix_type,4,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+        start = ftell(mat->fp);
+
+        /* Array Flags */
+
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+        if ( matvar->isComplex )
+            array_flags |= MAT_F_COMPLEX;
+        if ( matvar->isGlobal )
+            array_flags |= MAT_F_GLOBAL;
+        if ( matvar->isLogical )
+            array_flags |= MAT_F_LOGICAL;
+        if ( matvar->class_type == MAT_C_SPARSE )
+            nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+        fwrite(&array_flags_type,4,1,mat->fp);
+        fwrite(&array_flags_size,4,1,mat->fp);
+        fwrite(&array_flags,4,1,mat->fp);
+        fwrite(&nzmax,4,1,mat->fp);
+        /* Rank and Dimension */
+        nBytes = matvar->rank * 4;
+        fwrite(&dims_array_type,4,1,mat->fp);
+        fwrite(&nBytes,4,1,mat->fp);
+        for ( i = 0; i < matvar->rank; i++ ) {
+            mat_int32_t dim;
+            dim = matvar->dims[i];
+            nmemb *= dim;
+            fwrite(&dim,4,1,mat->fp);
+        }
+        if ( matvar->rank % 2 != 0 )
+            fwrite(&pad4,4,1,mat->fp);
+        /* Name of variable */
+        if ( strlen(matvar->name) <= 4 ) {
+            mat_int32_t  array_name_type = MAT_T_INT8;
+            mat_int32_t array_name_len   = strlen(matvar->name);
+            mat_int8_t  pad1 = 0;
+#if 0
+            fwrite(&array_name_type,2,1,mat->fp);
+            fwrite(&array_name_len,2,1,mat->fp);
+#else
+            array_name_type = (array_name_len << 16) | array_name_type;
+            fwrite(&array_name_type,4,1,mat->fp);
+#endif
+            fwrite(matvar->name,1,array_name_len,mat->fp);
+            for ( i = array_name_len; i < 4; i++ )
+                fwrite(&pad1,1,1,mat->fp);
+        } else {
+            mat_int32_t array_name_type = MAT_T_INT8;
+            mat_int32_t array_name_len  = (mat_int32_t)strlen(matvar->name);
+            mat_int8_t  pad1 = 0;
+
+            fwrite(&array_name_type,4,1,mat->fp);
+            fwrite(&array_name_len,4,1,mat->fp);
+            fwrite(matvar->name,1,array_name_len,mat->fp);
+            if ( array_name_len % 8 )
+                for ( i = array_name_len % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+        }
+
+        matvar->datapos = ftell(mat->fp);
+        switch ( matvar->class_type ) {
+            case MAT_C_DOUBLE:
+            case MAT_C_SINGLE:
+            case MAT_C_INT64:
+            case MAT_C_UINT64:
+            case MAT_C_INT32:
+            case MAT_C_UINT32:
+            case MAT_C_INT16:
+            case MAT_C_UINT16:
+            case MAT_C_INT8:
+            case MAT_C_UINT8:
+            {
+                if ( matvar->isComplex ) {
+                    struct ComplexSplit *complex_data = matvar->data;
+                    nBytes = WriteData(mat,complex_data->Re,nmemb,
+                        matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                    nBytes = WriteData(mat,complex_data->Im,nmemb,
+                        matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                } else {
+                    nBytes=WriteData(mat,matvar->data,nmemb,matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                }
+                break;
+            }
+            case MAT_C_CHAR:
+            {
+                /* Check for a NULL character array */
+                if ( matvar->data != NULL && nmemb > 0 )
+                    WriteCharData(mat,matvar->data,nmemb,matvar->data_type);
+                break;
+            }
+            case MAT_C_CELL:
+            {
+                int        ncells;
+                matvar_t **cells = (matvar_t **)matvar->data;
+
+                /* Check for an empty cell array */
+                if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                     matvar->data   == NULL )
+                    break;
+                ncells  = matvar->nbytes / matvar->data_size;
+                for ( i = 0; i < ncells; i++ )
+                    WriteCellArrayField(mat,cells[i]);
+                break;
+            }
+            case MAT_C_STRUCT:
+            {
+                char     **fieldnames, *padzero;
+                int        fieldname_size, nfields;
+                size_t     maxlen = 0;
+                matvar_t **fields = (matvar_t **)matvar->data;
+                mat_int32_t array_name_type = MAT_T_INT8;
+                unsigned   fieldname;
+
+                /* Check for a structure with no fields */
+                if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                     matvar->data   == NULL ) {
+#if 0
+                    fwrite(&fieldname_type,2,1,mat->fp);
+                    fwrite(&fieldname_data_size,2,1,mat->fp);
+#else
+                    fieldname = (fieldname_data_size<<16) | fieldname_type;
+                    fwrite(&fieldname,4,1,mat->fp);
+#endif
+                    fieldname_size = 1;
+                    fwrite(&fieldname_size,4,1,mat->fp);
+                    fwrite(&array_name_type,4,1,mat->fp);
+                    nBytes = 0;
+                    fwrite(&nBytes,4,1,mat->fp);
+                    break;
+                }
+                nfields = matvar->nbytes / (nmemb*matvar->data_size);
+                fieldnames = malloc(nfields*sizeof(char *));
+                for ( i = 0; i < nfields; i++ ) {
+                    fieldnames[i] = fields[i]->name;
+                    if ( strlen(fieldnames[i]) > maxlen )
+                        maxlen = strlen(fieldnames[i]);
+                }
+                maxlen++;
+                fieldname_size = maxlen;
+                while ( nfields*fieldname_size % 8 != 0 )
+                    fieldname_size++;
+#if 0
+                fwrite(&fieldname_type,2,1,mat->fp);
+                fwrite(&fieldname_data_size,2,1,mat->fp);
+#else
+                fieldname = (fieldname_data_size<<16) | fieldname_type;
+                fwrite(&fieldname,4,1,mat->fp);
+#endif
+                fwrite(&fieldname_size,4,1,mat->fp);
+                fwrite(&array_name_type,4,1,mat->fp);
+                nBytes = nfields*fieldname_size;
+                fwrite(&nBytes,4,1,mat->fp);
+                padzero = calloc(fieldname_size,1);
+                for ( i = 0; i < nfields; i++ ) {
+                    fwrite(fieldnames[i],1,strlen(fieldnames[i]),mat->fp);
+                    fwrite(padzero,1,fieldname_size-strlen(fieldnames[i]),mat->fp);
+                }
+                free(fieldnames);
+                free(padzero);
+                for ( i = 0; i < nmemb*nfields; i++ )
+                    WriteStructField(mat,fields[i]);
+                break;
+            }
+            case MAT_C_SPARSE:
+            {
+                sparse_t *sparse = matvar->data;
+
+                nBytes = WriteData(mat,sparse->ir,sparse->nir,MAT_T_INT32);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                nBytes = WriteData(mat,sparse->jc,sparse->njc,MAT_T_INT32);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                if ( matvar->isComplex ) {
+                    struct ComplexSplit *complex_data = sparse->data;
+                    nBytes = WriteData(mat,complex_data->Re,sparse->ndata,
+                        matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                    nBytes = WriteData(mat,complex_data->Im,sparse->ndata,
+                        matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                } else {
+                    nBytes = WriteData(mat,sparse->data,sparse->ndata,matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                }
+            }
+        }
+#if defined(HAVE_ZLIB)
+    } else if ( compress == COMPRESSION_ZLIB ) {
+        mat_uint32_t comp_buf[512];
+        mat_uint32_t uncomp_buf[512] = {0,};
+        int buf_size = 512, err;
+        size_t byteswritten = 0;
+
+        matvar->z         = calloc(1,sizeof(*matvar->z));
+        matvar->z->zalloc = Z_NULL;
+        matvar->z->zfree  = Z_NULL;
+        err = deflateInit(matvar->z,Z_DEFAULT_COMPRESSION);
+
+        matrix_type = MAT_T_COMPRESSED;
+        fwrite(&matrix_type,4,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+        start = ftell(mat->fp);
+
+        /* Array Flags */
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+        if ( matvar->isComplex )
+            array_flags |= MAT_F_COMPLEX;
+        if ( matvar->isGlobal )
+            array_flags |= MAT_F_GLOBAL;
+        if ( matvar->isLogical )
+            array_flags |= MAT_F_LOGICAL;
+        if ( matvar->class_type == MAT_C_SPARSE )
+            nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+        uncomp_buf[0] = MAT_T_MATRIX;
+        uncomp_buf[1] = (int)GetMatrixMaxBufSize(matvar);
+        matvar->z->next_out  = comp_buf;
+        matvar->z->next_in   = uncomp_buf;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+        matvar->z->avail_in  = 8;
+        err = deflate(matvar->z,Z_NO_FLUSH);
+        byteswritten += fwrite(comp_buf,1,
+            buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        uncomp_buf[0] = array_flags_type;
+        uncomp_buf[1] = array_flags_size;
+        uncomp_buf[2] = array_flags;
+        uncomp_buf[3] = nzmax;
+        /* Rank and Dimension */
+        nBytes = matvar->rank * 4;
+        uncomp_buf[4] = dims_array_type;
+        uncomp_buf[5] = nBytes;
+        for ( i = 0; i < matvar->rank; i++ ) {
+            mat_int32_t dim;
+            dim = matvar->dims[i];
+            nmemb *= dim;
+            uncomp_buf[6+i] = dim;
+        }
+        if ( matvar->rank % 2 != 0 ) {
+            uncomp_buf[6+i] = pad4;
+            i++;
+        }
+
+        matvar->z->next_out  = comp_buf;
+        matvar->z->next_in   = uncomp_buf;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+        matvar->z->avail_in  = (6+i)*sizeof(*uncomp_buf);
+        err = deflate(matvar->z,Z_NO_FLUSH);
+        byteswritten += fwrite(comp_buf,1,
+                buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        /* Name of variable */
+        if ( strlen(matvar->name) <= 4 ) {
+            mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
+            mat_int16_t array_name_type = MAT_T_INT8;
+
+            memset(uncomp_buf,0,8);
+            uncomp_buf[0] = (array_name_len << 16) | array_name_type;
+            memcpy(uncomp_buf+1,matvar->name,array_name_len);
+            if ( array_name_len % 4 )
+                array_name_len += 4-(array_name_len % 4);
+
+            matvar->z->next_out  = comp_buf;
+            matvar->z->next_in   = uncomp_buf;
+            matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+            matvar->z->avail_in  = 8;
+            err = deflate(matvar->z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,
+                    buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        } else {
+            mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
+            mat_int32_t array_name_type = MAT_T_INT8;
+
+            memset(uncomp_buf,0,buf_size*sizeof(*uncomp_buf));
+            uncomp_buf[0] = array_name_type;
+            uncomp_buf[1] = array_name_len;
+            memcpy(uncomp_buf+2,matvar->name,array_name_len);
+            if ( array_name_len % 8 )
+                array_name_len += 8-(array_name_len % 8);
+            matvar->z->next_out  = comp_buf;
+            matvar->z->next_in   = uncomp_buf;
+            matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+            matvar->z->avail_in  = 8+array_name_len;
+            err = deflate(matvar->z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,
+                    buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        }
+        matvar->datapos = ftell(mat->fp);
+        switch ( matvar->class_type ) {
+            case MAT_C_DOUBLE:
+            case MAT_C_SINGLE:
+            case MAT_C_INT64:
+            case MAT_C_UINT64:
+            case MAT_C_INT32:
+            case MAT_C_UINT32:
+            case MAT_C_INT16:
+            case MAT_C_UINT16:
+            case MAT_C_INT8:
+            case MAT_C_UINT8:
+            {
+                /* WriteCompressedData makes sure uncomressed data is aligned
+                 * on an 8-byte boundary */
+                if ( matvar->isComplex ) {
+                    struct ComplexSplit *complex_data = matvar->data;
+
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        complex_data->Re,nmemb,matvar->data_type);
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        complex_data->Im,nmemb,matvar->data_type);
+                } else {
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        matvar->data,nmemb,matvar->data_type);
+                }
+                break;
+            }
+            case MAT_C_CHAR:
+            {
+                /* Check for a NULL character array */
+                if ( matvar->data != NULL && nmemb > 0 )
+                    byteswritten += WriteCompressedCharData(mat,matvar->z,
+                        matvar->data,nmemb,matvar->data_type);
+                break;
+            }
+            case MAT_C_CELL:
+            {
+                int        ncells;
+                matvar_t **cells = (matvar_t **)matvar->data;
+
+                /* Check for an empty cell array */
+                if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                     matvar->data   == NULL )
+                    break;
+                ncells  = matvar->nbytes / matvar->data_size;
+                for ( i = 0; i < ncells; i++ )
+                    WriteCompressedCellArrayField(mat,cells[i],matvar->z);
+                break;
+            }
+            case MAT_C_STRUCT:
+            {
+                char     **fieldnames;
+                unsigned char *padzero;
+                int        fieldname_size, nfields;
+                size_t     maxlen = 0;
+                mat_int32_t array_name_type = MAT_T_INT8;
+                matvar_t **fields = (matvar_t **)matvar->data;
+
+                /* Check for a structure with no fields */
+                if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
+                     matvar->data   == NULL ) {
+                    fieldname_size = 1;
+                    uncomp_buf[0] = (fieldname_data_size << 16) | 
+                                     fieldname_type;
+                    uncomp_buf[1] = 1;
+                    uncomp_buf[2] = array_name_type;
+                    uncomp_buf[3] = 0;
+                    matvar->z->next_out  = comp_buf;
+                    matvar->z->next_in   = uncomp_buf;
+                    matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+                    matvar->z->avail_in  = 32;
+                    err = deflate(matvar->z,Z_NO_FLUSH);
+                    byteswritten += fwrite(comp_buf,1,buf_size*
+                        sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+                    break;
+                }
+                nfields = matvar->nbytes / (nmemb*matvar->data_size);
+                fieldnames = malloc(nfields*sizeof(char *));
+                for ( i = 0; i < nfields; i++ ) {
+                    fieldnames[i] = fields[i]->name;
+                    if ( strlen(fieldnames[i]) > maxlen )
+                        maxlen = strlen(fieldnames[i]);
+                }
+                maxlen++;
+                fieldname_size = maxlen;
+                while ( nfields*fieldname_size % 8 != 0 )
+                    fieldname_size++;
+                uncomp_buf[0] = (fieldname_data_size << 16) | fieldname_type;
+                uncomp_buf[1] = fieldname_size;
+                uncomp_buf[2] = array_name_type;
+                uncomp_buf[3] = nfields*fieldname_size;
+
+                padzero = calloc(fieldname_size,1);
+                matvar->z->next_out  = comp_buf;
+                matvar->z->next_in   = uncomp_buf;
+                matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+                matvar->z->avail_in  = 16;
+                err = deflate(matvar->z,Z_NO_FLUSH);
+                byteswritten += fwrite(comp_buf,1,
+                        buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+                for ( i = 0; i < nfields; i++ ) {
+                    memset(padzero,'\0',fieldname_size);
+                    memcpy(padzero,fieldnames[i],strlen(fieldnames[i]));
+                    matvar->z->next_out  = comp_buf;
+                    matvar->z->next_in   = padzero;
+                    matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+                    matvar->z->avail_in  = fieldname_size;
+                    err = deflate(matvar->z,Z_NO_FLUSH);
+                    byteswritten += fwrite(comp_buf,1,
+                            buf_size*sizeof(*comp_buf)-matvar->z->avail_out,
+                            mat->fp);
+                }
+                free(fieldnames);
+                free(padzero);
+                for ( i = 0; i < nmemb*nfields; i++ )
+                    byteswritten +=
+                        WriteCompressedStructField(mat,fields[i],matvar->z);
+                break;
+            }
+            case MAT_C_SPARSE:
+            {
+                sparse_t *sparse = matvar->data;
+
+                byteswritten += WriteCompressedData(mat,matvar->z,sparse->ir,
+                    sparse->nir,MAT_T_INT32);
+                byteswritten += WriteCompressedData(mat,matvar->z,sparse->jc,
+                    sparse->njc,MAT_T_INT32);
+                if ( matvar->isComplex ) {
+                    struct ComplexSplit *complex_data = sparse->data;
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        complex_data->Re,sparse->ndata,matvar->data_type);
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        complex_data->Im,sparse->ndata,matvar->data_type);
+                } else {
+                    byteswritten += WriteCompressedData(mat,matvar->z,
+                        sparse->data,sparse->ndata,matvar->data_type);
+                }
+                break;
+            }
+        }
+        matvar->z->avail_in  = 0;
+        matvar->z->next_in   = NULL;
+        matvar->z->next_out  = comp_buf;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+
+        err = deflate(matvar->z,Z_FINISH);
+        byteswritten += fwrite(comp_buf,1,
+            buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        while ( err != Z_STREAM_END && !matvar->z->avail_out ) {
+            matvar->z->next_out  = comp_buf;
+            matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+
+            err = deflate(matvar->z,Z_FINISH);
+            byteswritten += fwrite(comp_buf,1,
+                buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        }
+        /* End the compression and set to NULL so Mat_VarFree doesn't try
+         * to free matvar->z with inflateEnd
+         */
+#if 0
+        if ( byteswritten % 8 )
+            for ( i = 0; i < 8-(byteswritten % 8); i++ )
+                fwrite(&pad1,1,1,mat->fp);
+#endif
+        err = deflateEnd(matvar->z);
+        free(matvar->z);
+        matvar->z = NULL;
+#endif
+    }
+    end = ftell(mat->fp);
+    nBytes = (int)(end-start);
+    fseek(mat->fp,(long)-(nBytes+4),SEEK_CUR);
+    fwrite(&nBytes,4,1,mat->fp);
+    fseek(mat->fp,end,SEEK_SET);
+
+    return 0;
+}
+
+/** @brief Writes the variable information and empty data
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ */
+void
+WriteInfo5(mat_t *mat, matvar_t *matvar)
+{
+    mat_uint32_t array_flags = 0x0;
+    mat_int16_t  fieldname_type = MAT_T_INT32,fieldname_data_size=4;
+    mat_int8_t  pad1 = 0;
+    int      array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
+    int      array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
+    int      nBytes, i, nmemb = 1,nzmax;
+    long     start = 0, end = 0;
+
+    /* FIXME: SEEK_END is not Guaranteed by the C standard */
+    fseek(mat->fp,0,SEEK_END);         /* Always write at end of file */
+
+
+    if ( matvar->compression == COMPRESSION_NONE ) {
+        fwrite(&matrix_type,4,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+        start = ftell(mat->fp);
+
+        /* Array Flags */
+
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+        if ( matvar->isComplex )
+            array_flags |= MAT_F_COMPLEX;
+        if ( matvar->isGlobal )
+            array_flags |= MAT_F_GLOBAL;
+        if ( matvar->isLogical )
+            array_flags |= MAT_F_LOGICAL;
+        if ( matvar->class_type == MAT_C_SPARSE )
+            nzmax = ((sparse_t *)matvar->data)->nzmax;
+
+        fwrite(&array_flags_type,4,1,mat->fp);
+        fwrite(&array_flags_size,4,1,mat->fp);
+        fwrite(&array_flags,4,1,mat->fp);
+        fwrite(&nzmax,4,1,mat->fp);
+        /* Rank and Dimension */
+        nBytes = matvar->rank * 4;
+        fwrite(&dims_array_type,4,1,mat->fp);
+        fwrite(&nBytes,4,1,mat->fp);
+        for ( i = 0; i < matvar->rank; i++ ) {
+            mat_int32_t dim;
+            dim = matvar->dims[i];
+            nmemb *= dim;
+            fwrite(&dim,4,1,mat->fp);
+        }
+        if ( matvar->rank % 2 != 0 )
+            fwrite(&pad4,4,1,mat->fp);
+        /* Name of variable */
+        if ( strlen(matvar->name) <= 4 ) {
+            mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
+            mat_int8_t  pad1 = 0;
+            mat_int16_t array_name_type = MAT_T_INT8;
+            fwrite(&array_name_type,2,1,mat->fp);
+            fwrite(&array_name_len,2,1,mat->fp);
+            fwrite(matvar->name,1,array_name_len,mat->fp);
+            for ( i = array_name_len; i < 4; i++ )
+                fwrite(&pad1,1,1,mat->fp);
+        } else {
+            mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
+            mat_int8_t  pad1 = 0;
+            mat_int32_t  array_name_type = MAT_T_INT8;
+
+            fwrite(&array_name_type,4,1,mat->fp);
+            fwrite(&array_name_len,4,1,mat->fp);
+            fwrite(matvar->name,1,array_name_len,mat->fp);
+            if ( array_name_len % 8 )
+                for ( i = array_name_len % 8; i < 8; i++ )
+                    fwrite(&pad1,1,1,mat->fp);
+        }
+
+        matvar->datapos = ftell(mat->fp);
+        switch ( matvar->class_type ) {
+            case MAT_C_DOUBLE:
+            case MAT_C_SINGLE:
+            case MAT_C_INT64:
+            case MAT_C_UINT64:
+            case MAT_C_INT32:
+            case MAT_C_UINT32:
+            case MAT_C_INT16:
+            case MAT_C_UINT16:
+            case MAT_C_INT8:
+            case MAT_C_UINT8:
+                nBytes = WriteEmptyData(mat,nmemb,matvar->data_type);
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                if ( matvar->isComplex ) {
+                    nBytes = WriteEmptyData(mat,nmemb,matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                }
+                break;
+            case MAT_C_CHAR:
+            {
+                WriteEmptyCharData(mat,nmemb,matvar->data_type);
+                break;
+            }
+            case MAT_C_CELL:
+            {
+                int nfields = matvar->nbytes / matvar->data_size;
+                matvar_t **fields = (matvar_t **)matvar->data;
+
+                for ( i = 0; i < nfields; i++ )
+                    WriteCellArrayFieldInfo(mat,fields[i]);
+                break;
+            }
+            case MAT_C_STRUCT:
+            {
+                char **fieldnames, *padzero;
+                int maxlen = 0, fieldname_size;
+                int nfields = matvar->nbytes / matvar->data_size;
+                matvar_t **fields = (matvar_t **)matvar->data;
+                mat_int32_t  array_name_type = MAT_T_INT8;
+                unsigned fieldname;
+
+                fieldnames = malloc(nfields*sizeof(char *));
+                for ( i = 0; i < nfields; i++ ) {
+                    fieldnames[i] = fields[i]->name;
+                    if ( strlen(fieldnames[i]) > maxlen )
+                        maxlen = strlen(fieldnames[i]);
+                }
+                maxlen++;
+                fieldname_size = maxlen;
+                while ( nfields*fieldname_size % 8 != 0 )
+                    fieldname_size++;
+#if 0
+                fwrite(&fieldname_type,2,1,mat->fp);
+                fwrite(&fieldname_data_size,2,1,mat->fp);
+#else
+                fieldname = (fieldname_data_size<<16) | fieldname_type;
+                fwrite(&fieldname,4,1,mat->fp);
+#endif
+                fwrite(&fieldname_size,4,1,mat->fp);
+                fwrite(&array_name_type,4,1,mat->fp);
+                nBytes = nfields*fieldname_size;
+                fwrite(&nBytes,4,1,mat->fp);
+                padzero = calloc(fieldname_size,1);
+                for ( i = 0; i < nfields; i++ ) {
+                    fwrite(fieldnames[i],1,strlen(fieldnames[i]),mat->fp);
+                    fwrite(padzero,1,fieldname_size-strlen(fieldnames[i]),mat->fp);
+                }
+                free(fieldnames);
+                free(padzero);
+                for ( i = 0; i < nfields; i++ )
+                    WriteInfo5(mat,fields[i]);
+                break;
+            }
+        }
+    /* Does not work.
+     * Can write empty data, but how to go back and add the real data?
+     */
+#if 0
+    } else if ( matvar->compression == COMPRESSION_ZLIB ) {
+#if defined(HAVE_ZLIB)
+        mat_uint32_t comp_buf[512];
+        mat_uint32_t uncomp_buf[512] = {0,};
+        int buf_size = 512, err;
+        size_t byteswritten = 0;
+
+        matvar->z         = malloc(sizeof(*matvar->z));
+        matvar->z->zalloc = Z_NULL;
+        matvar->z->zfree  = Z_NULL;
+        err = deflateInit(matvar->z,Z_DEFAULT_COMPRESSION);
+
+        matrix_type = MAT_T_COMPRESSED;
+        fwrite(&matrix_type,4,1,mat->fp);
+        fwrite(&pad4,4,1,mat->fp);
+        start = ftell(mat->fp);
+
+        /* Array Flags */
+
+        array_flags = matvar->class_type & MAT_F_CLASS_T;
+        if ( matvar->isComplex )
+            array_flags |= MAT_F_COMPLEX;
+        if ( matvar->isGlobal )
+            array_flags |= MAT_F_GLOBAL;
+        if ( matvar->isLogical )
+            array_flags |= MAT_F_LOGICAL;
+
+        uncomp_buf[0] = MAT_T_MATRIX;
+        uncomp_buf[1] = 448;
+        matvar->z->next_out  = comp_buf;
+        matvar->z->next_in   = uncomp_buf;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+        matvar->z->avail_in  = 8;
+        err = deflate(matvar->z,Z_SYNC_FLUSH);
+        byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        uncomp_buf[0] = array_flags_type;
+        uncomp_buf[1] = array_flags_size;
+        uncomp_buf[2] = array_flags;
+        uncomp_buf[3] = 0;
+        /* Rank and Dimension */
+        nBytes = matvar->rank * 4;
+        uncomp_buf[4] = dims_array_type;
+        uncomp_buf[5] = nBytes;
+        for ( i = 0; i < matvar->rank; i++ ) {
+            mat_int32_t dim;
+            dim = matvar->dims[i];
+            nmemb *= dim;
+            uncomp_buf[6+i] = dim;
+        }
+        if ( matvar->rank % 2 != 0 )
+            uncomp_buf[6+i] = pad4;
+
+        matvar->z->next_out  = comp_buf;
+        matvar->z->next_in   = uncomp_buf;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+        matvar->z->avail_in  = (6+i)*sizeof(*uncomp_buf);
+        err = deflate(matvar->z,Z_NO_FLUSH);
+        byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        /* Name of variable */
+        if ( strlen(matvar->name) <= 4 ) {
+#if 0
+            mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
+            mat_int8_t  pad1 = 0;
+
+            uncomp_buf[0] = (array_name_type << 16) | array_name_len;
+            memcpy(uncomp_buf+1,matvar->name,array_name_len);
+
+            matvar->z->next_out  = comp_buf;
+            matvar->z->next_in   = uncomp_buf;
+            matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+            matvar->z->avail_in  = 8;
+            err = deflate(matvar->z,Z_NO_FLUSH);
+            byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        } else {
+#endif
+            mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
+
+            memset(uncomp_buf,0,buf_size*sizeof(*uncomp_buf));
+            uncomp_buf[0] = array_name_type;
+            uncomp_buf[1] = array_name_len;
+            memcpy(uncomp_buf+2,matvar->name,array_name_len);
+            if ( array_name_len % 8 )
+                array_name_len += array_name_len % 8;
+            matvar->z->next_out  = comp_buf;
+            matvar->z->next_in   = uncomp_buf;
+            matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+            matvar->z->avail_in  = 8+array_name_len;
+            err = deflate(matvar->z,Z_FULL_FLUSH);
+            byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+        }
+        matvar->datapos = ftell(mat->fp);
+        deflateCopy(&z_save,matvar->z);
+        switch ( matvar->class_type ) {
+            case MAT_C_DOUBLE:
+            case MAT_C_SINGLE:
+            case MAT_C_INT32:
+            case MAT_C_UINT32:
+            case MAT_C_INT16:
+            case MAT_C_UINT16:
+            case MAT_C_INT8:
+            case MAT_C_UINT8:
+                byteswritten += WriteCompressedEmptyData(mat,matvar->z,nmemb,matvar->data_type);
+#if 0
+                if ( nBytes % 8 )
+                    for ( i = nBytes % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+                if ( matvar->isComplex ) {
+                    nBytes = WriteEmptyData(mat,nmemb,matvar->data_type);
+                    if ( nBytes % 8 )
+                        for ( i = nBytes % 8; i < 8; i++ )
+                            fwrite(&pad1,1,1,mat->fp);
+                }
+#endif
+                break;
+        }
+        matvar->z->next_out  = comp_buf;
+        matvar->z->next_in   = NULL;
+        matvar->z->avail_out = buf_size*sizeof(*comp_buf);
+        matvar->z->avail_in  = 0;
+
+        err = deflate(matvar->z,Z_FINISH);
+        byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-matvar->z->avail_out,mat->fp);
+                if ( byteswritten % 8 )
+                    for ( i = byteswritten % 8; i < 8; i++ )
+                        fwrite(&pad1,1,1,mat->fp);
+        fprintf(stderr,"deflate Z_FINISH: err = %d,byteswritten = %u\n",err,byteswritten);
+
+        err = deflateEnd(matvar->z);
+        fprintf(stderr,"deflateEnd: err = %d\n",err);
+#if 1
+        err = deflateEnd(matvar->z);
+        free(matvar->z);
+        matvar->z = NULL;
+#else
+        memcpy(matvar->z,&z_save,sizeof(*matvar->z));
+#endif
+#endif
+#endif
+    }
+    end = ftell(mat->fp);
+    nBytes = (int)(end-start);
+    fseek(mat->fp,(long)-(nBytes+4),SEEK_CUR);
+    fwrite(&nBytes,4,1,mat->fp);
+    fseek(mat->fp,end,SEEK_SET);
+}
+
+/** @brief Prints the mat variable
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param matvar pointer to the mat variable
+ */
+void
+Mat_VarPrint5( matvar_t *matvar, int printdata )
+{
+    int i, j;
+
+    if ( matvar == NULL )
+        return;
+    if ( matvar->name )
+        Mat_Message("      Name: %s", matvar->name);
+    Mat_Message("      Rank: %d", matvar->rank);
+    if ( matvar->rank == 0 )
+        return;
+    if ( matvar->isComplex )
+        Mat_Message("Class Type: %s (complex)",class_type_desc[matvar->class_type]);
+    else
+        Mat_Message("Class Type: %s",class_type_desc[matvar->class_type]);
+    if ( matvar->data_type )
+        Mat_Message(" Data Type: %s", data_type_desc[matvar->data_type]);
+    if ( matvar->data != NULL && matvar->data_size > 0 ) {
+        switch( matvar->class_type ) {
+            case MAT_C_DOUBLE:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%f ", ((double*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%f ", ((double*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%f\n", ((double*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_SINGLE:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%f ", ((float*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%f ", ((float*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%f\n", ((float*)matvar->data)[i]);
+                }
+                break;
+#ifdef HAVE_MAT_INT64_T
+            case MAT_C_INT64:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%d ", ((mat_int64_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%d ", ((mat_uint64_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%d\n", ((mat_int64_t*)matvar->data)[i]);
+                }
+                break;
+#endif
+#ifdef HAVE_MAT_UINT64_T
+            case MAT_C_UINT64:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%u ", ((mat_uint64_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%u ", ((mat_uint64_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%u\n", ((mat_int64_t*)matvar->data)[i]);
+                }
+                break;
+#endif /* HAVE_MAT_UINT64_T */
+            case MAT_C_INT32:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%d ", ((mat_int32_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%d ", ((mat_uint32_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%d\n", ((mat_int32_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_UINT32:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%u ", ((mat_uint32_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%u ", ((mat_uint32_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%u\n", ((mat_int32_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_INT16:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hd ", ((mat_int16_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hd ", ((mat_uint16_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%hd\n", ((mat_int16_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_UINT16:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hu ", ((mat_uint16_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hu ", ((mat_uint16_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%hu\n", ((mat_int32_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_INT8:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hd ", ((mat_int8_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hd ", ((mat_int8_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%hd\n", ((mat_int8_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_UINT8:
+                if ( !printdata )
+                    break;
+                if ( matvar->rank > 2 ) {
+                    printf("I can't print more than 2 dimensions\n");
+                } else if ( matvar->rank == 1 && matvar->dims[0] > 15 ) {
+                    printf("I won't print more than 15 elements in a vector\n");
+                } else if ( matvar->rank == 2 &&
+                         (matvar->dims[0] > 15 || matvar->dims[1] > 15) ) {
+                    for ( i = 0; i < matvar->dims[0] && i < 15; i++ ) {
+                        for ( j = 0; j < matvar->dims[1] && j < 15; j++ )
+                            printf("%hu ", ((mat_uint8_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        if ( j < matvar->dims[1] )
+                            printf("...");
+                        printf("\n");
+                    }
+                    if ( i < matvar->dims[0] )
+                        printf(".\n.\n.\n");
+                } else if ( matvar->rank == 2 ) {
+                    for ( i = 0; i < matvar->dims[0]; i++ ) {
+                        for ( j = 0; j < matvar->dims[1]; j++ )
+                            printf("%hu ", ((mat_uint8_t*)matvar->data)[matvar->dims[0]*j+i]);
+                        printf("\n");
+                    }
+                } else {
+                    for ( i = 0; i < matvar->nbytes/matvar->data_size; i++ )
+                        printf("%hu\n", ((mat_uint8_t*)matvar->data)[i]);
+                }
+                break;
+            case MAT_C_CHAR:
+                if ( !printdata )
+                    break;
+                if ( matvar->dims[0] == 1 ) {
+                    printf("%s\n",(char *)matvar->data);
+                } else {
+                    int ndx = 0;
+                    for ( i = 0; i < matvar->dims[1]; i++ ) {
+                        ndx = i;
+                        j = 0;
+                        while ( j++ < matvar->dims[0] &&
+                                *((char *)matvar->data+ndx) != '\0' ) {
+                            printf("%c", *((char *)matvar->data+ndx));
+                            ndx += matvar->dims[0];
+                        }
+                        printf("\n");
+                    }
+                }
+                break;
+            case MAT_C_STRUCT:
+            {
+                matvar_t **fields = (matvar_t **)matvar->data;
+                int nfields = matvar->nbytes / matvar->data_size;
+                Mat_Message("Fields[%d] {", nfields);
+                for ( i = 0; i < nfields; i++ )
+                    Mat_VarPrint(fields[i],printdata);
+                Mat_Message("}");
+                break;
+            }
+            case MAT_C_CELL:
+            {
+                matvar_t **fields = (matvar_t **)matvar->data;
+                int nfields = matvar->nbytes / matvar->data_size;
+                for ( i = 0; i < nfields; i++ )
+                    Mat_VarPrint(fields[i],printdata);
+                break;
+            }
+            case MAT_C_SPARSE:
+            {
+                sparse_t *sparse;
+/* FIXME: ComplexSplit */
+#if defined(EXTENDED_SPARSE)
+                sparse = matvar->data;
+                switch ( matvar->data_type ) {
+                    case MAT_T_DOUBLE:
+                    {
+                        if ( matvar->isComplex ) {
+                            struct ComplexSplit *complex_data = sparse->data;
+                            double *re,*im;
+                            re = complex_data->Re;
+                            im = complex_data->Im;
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %f + %fi",
+                                        sparse->ir[j]+1,i+1,re[j],im[j]);
+                            }
+                        } else {
+                            double *data;
+                            data = sparse->data;
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %f",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_SINGLE:
+                    {
+                        float *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %f + %fi",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %f",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+#ifdef HAVE_MAT_INT64_T
+                    case MAT_T_INT64:
+                    {
+                        mat_int64_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %d + %di",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %d",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+#endif
+#ifdef HAVE_MAT_UINT64_T
+                    case MAT_T_UINT64:
+                    {
+                        mat_uint64_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %u + %ui",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %u",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+#endif
+                    case MAT_T_INT32:
+                    {
+                        mat_int32_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %d + %di",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %d",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_UINT32:
+                    {
+                        mat_uint32_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %u + %ui",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %u",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_INT16:
+                    {
+                        mat_int16_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hd + %hdi",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hd",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_UINT16:
+                    {
+                        mat_uint16_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hu + %hui",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hu",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_INT8:
+                    {
+                        mat_int8_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hd + %hdi",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hd",
+                                        sparse->ir[j]+1,i+1,data[j]);
+                            }
+                        }
+                        break;
+                    }
+                    case MAT_T_UINT8:
+                    {
+                        mat_uint8_t *data;
+                        data = sparse->data;
+                        if ( matvar->isComplex ) {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hu + %hui",
+                                        sparse->ir[j]+1,i+1,data[j],
+                                        (mat_uint16_t)data[sparse->ndata+j]);
+                            }
+                        } else {
+                            for ( i = 0; i < sparse->njc-1; i++ ) {
+                                for (j = sparse->jc[i];
+                                     j<sparse->jc[i+1] && j<sparse->ndata;j++ )
+                                    Mat_Message("    (%d,%d)  %hu",
+                                        sparse->ir[j]+1,i+1,
+                                        (mat_uint16_t)data[j]);
+                            }
+                        }
+                        break;
+                    }
+                }
+#else
+                double *data;
+
+                sparse = matvar->data;
+                data = sparse->data;
+                if ( matvar->isComplex ) {
+                    for ( i = 0; i < sparse->njc-1; i++ ) {
+                        for ( j = sparse->jc[i];
+                              j < sparse->jc[i+1] && j < sparse->ndata; j++ )
+                            Mat_Message("    (%d,%d)  %f + %fi",
+                                sparse->ir[j]+1,i+1,data[j],
+                                data[sparse->ndata+j]);
+                    }
+                } else {
+                    for ( i = 0; i < sparse->njc-1; i++ ) {
+                        for ( j = sparse->jc[i];
+                              j < sparse->jc[i+1] && j < sparse->ndata; j++ )
+                            Mat_Message("    (%d,%d)  %f", sparse->ir[j]+1,i+1,
+                                data[j]);
+                    }
+                }
+#endif
+                break;
+            }
+            default:
+                printf("I can't print this class\n");
+        }
+    } else {
+        if ( printdata && !matvar->data  )
+            Mat_Warning("Data is NULL");
+        if ( printdata && matvar->data_size < 1 )
+            Mat_Warning("data-size is %d",matvar->data_size);
+    }
+    Mat_Message("\n");
+    return;
+}
+
+/** @brief Reads the header information for the next MAT variable
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @retuen pointer to the MAT variable or NULL
+ */
+matvar_t *
+Mat_VarReadNextInfo5( mat_t *mat )
+{
+    int err, data_type, nBytes, i;
+    long  fpos;
+    matvar_t *matvar = NULL; 
+    mat_uint32_t array_flags;
+    long     bytesread = 0;
+
+    if( mat == NULL )
+        return NULL; 
+
+    fpos = ftell(mat->fp);
+    err = fread(&data_type,4,1,mat->fp);
+    if ( !err )
+        return NULL;
+    err = fread(&nBytes,4,1,mat->fp);
+    if ( mat->byteswap ) {
+        Mat_int32Swap(&data_type);
+        Mat_int32Swap(&nBytes);
+    }
+    switch ( data_type ) {
+#if defined(HAVE_ZLIB)
+        case MAT_T_COMPRESSED:
+        {
+            mat_uint32_t uncomp_buf[16] = {0,};
+            int      nbytes;
+
+            matvar               = malloc(sizeof(*matvar));
+            matvar->name         = NULL;
+            matvar->data         = NULL;
+            matvar->dims         = NULL;
+            matvar->nbytes       = 0;
+            matvar->data_type    = 0;
+            matvar->class_type   = 0;
+            matvar->data_size    = 0;
+            matvar->mem_conserve = 0;
+            matvar->compression  = 1;
+            matvar->fpos         = fpos;
+            matvar->fp           = mat;
+
+            matvar->z = calloc(1,sizeof(z_stream));
+            matvar->z->zalloc    = NULL;
+            matvar->z->zfree     = NULL;
+            matvar->z->opaque    = NULL;
+            matvar->z->next_in   = NULL;
+            matvar->z->next_out  = NULL;
+            matvar->z->avail_in  = 0;
+            matvar->z->avail_out = 0;
+            err = inflateInit(matvar->z);
+            if ( err != Z_OK ) {
+                Mat_Critical("inflateInit2 returned %d",err);
+                Mat_VarFree(matvar);
+                break;
+            }
+
+            /* Read Variable tag */
+            bytesread += InflateVarTag(mat,matvar,uncomp_buf);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            nbytes = uncomp_buf[1];
+            if ( uncomp_buf[0] != MAT_T_MATRIX ) {
+                Mat_Critical("Uncompressed type not MAT_T_MATRIX");
+                fseek(mat->fp,nBytes-bytesread,SEEK_CUR);
+                Mat_VarFree(matvar);
+                matvar = NULL;
+                break;
+            }
+            /* Inflate Array Flags */
+            bytesread += InflateArrayFlags(mat,matvar,uncomp_buf);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+2);
+                (void)Mat_uint32Swap(uncomp_buf+3);
+            }
+            /* Array Flags */
+            if ( uncomp_buf[0] == MAT_T_UINT32 ) {
+               array_flags = uncomp_buf[2];
+               matvar->class_type  = (array_flags & MAT_F_CLASS_T);
+               matvar->isComplex   = (array_flags & MAT_F_COMPLEX);
+               matvar->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               matvar->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( matvar->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   matvar->nbytes      = uncomp_buf[3];
+               }
+            }
+            /* Inflate Dimensions */
+            bytesread += InflateDimensions(mat,matvar,uncomp_buf);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(uncomp_buf);
+                (void)Mat_uint32Swap(uncomp_buf+1);
+            }
+            /* Rank and Dimension */
+            if ( uncomp_buf[0] == MAT_T_INT32 ) {
+                nbytes = uncomp_buf[1];
+                matvar->rank = nbytes / 4;
+                matvar->dims = malloc(matvar->rank*sizeof(int));
+                if ( mat->byteswap ) {
+                    for ( i = 0; i < matvar->rank; i++ )
+                        matvar->dims[i] = Mat_uint32Swap(&(uncomp_buf[2+i]));
+                } else {
+                    for ( i = 0; i < matvar->rank; i++ )
+                        matvar->dims[i] = uncomp_buf[2+i];
+                }
+            }
+            /* Inflate variable name tag */
+            bytesread += InflateVarNameTag(mat,matvar,uncomp_buf);
+            if ( mat->byteswap )
+                (void)Mat_uint32Swap(uncomp_buf);
+            /* Name of variable */
+            if ( uncomp_buf[0] == MAT_T_INT8 ) {    /* Name not in tag */
+                int len;
+                if ( mat->byteswap )
+                    len = Mat_uint32Swap(uncomp_buf+1);
+                else
+                    len = uncomp_buf[1];
+
+                if ( len % 8 == 0 )
+                    i = len;
+                else
+                    i = len+(8-(len % 8));
+                matvar->name = malloc(i+1);
+                /* Inflate variable name */
+                bytesread += InflateVarName(mat,matvar,matvar->name,i);
+                matvar->name[len] = '\0';
+            } else if ( ((uncomp_buf[0] & 0x0000ffff) == MAT_T_INT8) &&
+                        ((uncomp_buf[0] & 0xffff0000) != 0x00) ) {
+                /* Name packed in tag */
+                int len;
+                len = (uncomp_buf[0] & 0xffff0000) >> 16;
+                matvar->name = malloc(len+1);
+                memcpy(matvar->name,uncomp_buf+1,len);
+                matvar->name[len] = '\0';
+            }
+            if ( matvar->class_type == MAT_C_STRUCT )
+                ReadNextStructField(mat,matvar);
+            else if ( matvar->class_type == MAT_C_CELL ) {
+              if (ReadNextCell(mat,matvar) == -1) {
+                Mat_VarFree(matvar);
+                matvar = NULL;
+                return NULL;
+              }
+            }
+            fseek(mat->fp,-(int)matvar->z->avail_in,SEEK_CUR);
+            matvar->datapos = ftell(mat->fp);
+            fseek(mat->fp,nBytes+8+fpos,SEEK_SET);
+            break;
+        }
+#endif
+        case MAT_T_MATRIX:
+        {
+            int      nbytes;
+            mat_uint32_t buf[32];
+            size_t   bytesread = 0;
+
+            matvar = Mat_VarCalloc();
+            matvar->fpos         = fpos;
+            matvar->fp           = mat;
+
+            /* Read Array Flags and The Dimensions Tag */
+            bytesread  += fread(buf,4,6,mat->fp);
+            if ( mat->byteswap ) {
+                (void)Mat_uint32Swap(buf);
+                (void)Mat_uint32Swap(buf+1);
+                (void)Mat_uint32Swap(buf+2);
+                (void)Mat_uint32Swap(buf+3);
+                (void)Mat_uint32Swap(buf+4);
+                (void)Mat_uint32Swap(buf+5);
+            }
+            /* Array Flags */
+            if ( buf[0] == MAT_T_UINT32 ) {
+               array_flags = buf[2];
+               matvar->class_type  = (array_flags & MAT_F_CLASS_T);
+               matvar->isComplex   = (array_flags & MAT_F_COMPLEX);
+               matvar->isGlobal    = (array_flags & MAT_F_GLOBAL);
+               matvar->isLogical   = (array_flags & MAT_F_LOGICAL);
+               if ( matvar->class_type == MAT_C_SPARSE ) {
+                   /* Need to find a more appropriate place to store nzmax */
+                   matvar->nbytes      = buf[3];
+               }
+            }
+            /* Rank and Dimension */
+            if ( buf[4] == MAT_T_INT32 ) {
+                nbytes = buf[5];
+
+                matvar->rank = nbytes / 4;
+                matvar->dims = malloc(matvar->rank*sizeof(int));
+
+                /* Assumes rank <= 16 */
+                if ( matvar->rank % 2 != 0 )
+                    bytesread+=fread(buf,4,matvar->rank+1,mat->fp);
+                else
+                    bytesread+=fread(buf,4,matvar->rank,mat->fp);
+
+                if ( mat->byteswap ) {
+                    for ( i = 0; i < matvar->rank; i++ )
+                        matvar->dims[i] = Mat_uint32Swap(buf+i);
+                } else {
+                    for ( i = 0; i < matvar->rank; i++ )
+                        matvar->dims[i] = buf[i];
+                }
+            }
+            /* Variable Name Tag */
+            bytesread+=fread(buf,4,2,mat->fp);
+            if ( mat->byteswap )
+                (void)Mat_uint32Swap(buf);
+            /* Name of variable */
+            if ( buf[0] == MAT_T_INT8 ) {    /* Name not in tag */
+                int len;
+
+                if ( mat->byteswap )
+                    len = Mat_uint32Swap(buf+1);
+                else
+                    len = buf[1];
+                if ( len % 8 == 0 )
+                    i = len;
+                else
+                    i = len+(8-(len % 8));
+                bytesread+=fread(buf,1,i,mat->fp);
+
+                matvar->name = malloc(len+1);
+                memcpy(matvar->name,buf,len);
+                matvar->name[len] = '\0';
+            } else if ( ((buf[0] & 0x0000ffff) == MAT_T_INT8) &&
+                        ((buf[0] & 0xffff0000) != 0x00) ) {
+                /* Name packed in the tag */
+                int len;
+
+                len = (buf[0] & 0xffff0000) >> 16;
+                matvar->name = malloc(len+1);
+                memcpy(matvar->name,buf+1,len);
+                matvar->name[len] = '\0';
+            }
+            if ( matvar->class_type == MAT_C_STRUCT )
+                (void)ReadNextStructField(mat,matvar);
+            else if ( matvar->class_type == MAT_C_CELL )
+                (void)ReadNextCell(mat,matvar);
+            else if ( matvar->class_type == MAT_C_FUNCTION )
+                (void)ReadNextFunctionHandle(mat,matvar);
+            matvar->datapos = ftell(mat->fp);
+            fseek(mat->fp,nBytes+8+fpos,SEEK_SET);
+            break;
+        }
+        default:
+            Mat_Message("%d is not valid (MAT_T_MATRIX or MAT_T_COMPRESSED", data_type);
+            return NULL;
+    }
+
+    return matvar;
+}

+ 62 - 0
matlabAccess/matio/src/mat5.h

@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2008   Christopher C. Hulbert
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef MAT5_H
+#define MAT5_H
+
+#include "matio.h"
+
+#ifdef __cplusplus
+#   define EXTERN extern "C"
+#else
+#   define EXTERN extern
+#endif
+
+EXTERN int WriteCellArrayField(mat_t *mat,matvar_t *matvar );
+EXTERN int WriteCellArrayFieldInfo(mat_t *mat,matvar_t *matvar);
+EXTERN int WriteStructField(mat_t *mat,matvar_t *matvar);
+#if defined(HAVE_ZLIB)
+EXTERN size_t WriteCompressedCellArrayField(mat_t *mat,matvar_t *matvar,
+                                            z_stream *z);
+EXTERN size_t WriteCompressedStructField(mat_t *mat,matvar_t *matvar,
+                                         z_stream *z);
+#endif
+EXTERN int ReadNextStructField( mat_t *mat, matvar_t *matvar );
+EXTERN int ReadNextCell( mat_t *mat, matvar_t *matvar );
+EXTERN int WriteEmptyCharData(mat_t *mat, int N, int data_type);
+
+/*   mat5.c    */
+void      Mat_VarPrint5( matvar_t *matvar, int printdata );
+matvar_t *Mat_VarReadNextInfo5( mat_t *mat );
+void      Read5(mat_t *mat, matvar_t *matvar);
+int       ReadData5(mat_t *mat,matvar_t *matvar,void *data, 
+              int *start,int *stride,int *edge);
+int       Write5(mat_t *mat,matvar_t *matvar,int compress);
+int       WriteCharDataSlab2(mat_t *mat,void *data,int data_type,int *dims,
+              int *start,int *stride,int *edge);
+#if defined(HAVE_ZLIB)
+size_t    WriteCompressedData(mat_t *mat,z_stream *z,void *data,int N,
+              int data_type);
+size_t    WriteCompressedCharData(mat_t *mat,z_stream *z,void *data,int N,
+              int data_type);
+#endif
+int       WriteData(mat_t *mat,void *data,int N,int data_type);
+int       WriteDataSlab2(mat_t *mat,void *data,int data_type,int *dims,
+              int *start,int *stride,int *edge);
+void      WriteInfo5(mat_t *mat, matvar_t *matvar);
+
+#endif

+ 323 - 0
matlabAccess/matio/src/matio.h

@@ -0,0 +1,323 @@
+/** @file matio.h
+ * LIBMATIO Header
+ * @ingroup MAT
+ */
+/*
+ * Copyright (C) 2005-2006   Christopher C. Hulbert
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef MATIO_H
+#define MATIO_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "matioConfig.h"
+#if defined(HAVE_INTTYPES_H)
+#   include <inttypes.h>
+#endif
+#if defined(HAVE_STDINT_H)
+#   include <stdint.h>
+#endif
+
+#include <stdarg.h>
+#if defined(HAVE_ZLIB)
+#   include <zlib.h>
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+#   define EXTERN extern "C"
+#else
+#   define EXTERN extern
+#endif
+
+#ifdef _mat_int64_t
+    typedef _mat_int64_t mat_int64_t;
+#endif
+#ifdef _mat_uint64_t
+    typedef _mat_uint64_t mat_uint64_t;
+#endif
+#ifdef _mat_int32_t
+    typedef _mat_int32_t mat_int32_t;
+#endif
+#ifdef _mat_uint32_t
+    typedef _mat_uint32_t mat_uint32_t;
+#endif
+#ifdef _mat_int16_t
+    typedef _mat_int16_t mat_int16_t;
+#endif
+#ifdef _mat_uint16_t
+    typedef _mat_uint16_t mat_uint16_t;
+#endif
+#ifdef _mat_int8_t
+    typedef _mat_int8_t mat_int8_t;
+#endif
+#ifdef _mat_uint8_t
+    typedef _mat_uint8_t mat_uint8_t;
+#endif
+
+/** @defgroup MAT Matlab MAT File I/O Library */
+/** @defgroup mat_internal Internal Functions */
+
+/** @brief MAT file access types
+ *
+ * @ingroup MAT
+ * MAT file access types
+ */
+enum mat_acc {
+    MAT_ACC_RDONLY = 1,  /**< @brief Read only file access                */
+    MAT_ACC_RDWR   = 2   /**< @brief Read/Write file access               */
+};
+
+/** @brief MAT file versions
+ *
+ * @ingroup MAT
+ * MAT file versions
+ */
+enum mat_ft {
+    MAT_FT_MAT5  = 1,        /**< @brief Matlab level-5 file                  */
+    MAT_FT_MAT4  = 1 << 16   /**< @brief Version 4 file                       */
+};
+
+
+/** @brief Matlab data types
+ *
+ * @ingroup MAT
+ * Matlab data types
+ */
+enum matio_types {
+    MAT_T_UNKNOWN    =  0,    /**< @brief UNKOWN data type                    */
+    MAT_T_INT8       =  1,    /**< @brief 8-bit signed integer data type      */
+    MAT_T_UINT8      =  2,    /**< @brief 8-bit unsigned integer data type    */
+    MAT_T_INT16      =  3,    /**< @brief 16-bit signed integer data type     */
+    MAT_T_UINT16     =  4,    /**< @brief 16-bit unsigned integer data type   */
+    MAT_T_INT32      =  5,    /**< @brief 32-bit signed integer data type     */
+    MAT_T_UINT32     =  6,    /**< @brief 32-bit unsigned integer data type   */
+    MAT_T_SINGLE     =  7,    /**< @brief IEEE 754 single precision data type */
+    MAT_T_DOUBLE     =  9,    /**< @brief IEEE 754 double precision data type */
+    MAT_T_INT64      = 12,    /**< @brief 64-bit signed integer data type     */
+    MAT_T_UINT64     = 13,    /**< @brief 64-bit unsigned integer data type   */
+    MAT_T_MATRIX     = 14,    /**< @brief matrix data type                    */
+    MAT_T_COMPRESSED = 15,    /**< @brief compressed data type                */
+    MAT_T_UTF8       = 16,    /**< @brief 8-bit unicode text data type        */
+    MAT_T_UTF16      = 17,    /**< @brief 16-bit unicode text data type       */
+    MAT_T_UTF32      = 18,    /**< @brief 32-bit unicode text data type       */
+
+    MAT_T_STRING     = 20,    /**< @brief String data type                    */
+    MAT_T_CELL       = 21,    /**< @brief Cell array data type                */
+    MAT_T_STRUCT     = 22,    /**< @brief Structure data type                 */
+    MAT_T_ARRAY      = 23,    /**< @brief Array data type                     */
+    MAT_T_FUNCTION   = 24     /**< @brief Function data type                  */
+};
+
+/** @brief Matlab variable classes
+ *
+ * @ingroup MAT
+ * Matlab variable classes
+ */
+enum matio_classes {
+    MAT_C_CELL     =  1, /**< @brief Matlab cell array class               */
+    MAT_C_STRUCT   =  2, /**< @brief Matlab structure class                */
+    MAT_C_OBJECT   =  3, /**< @brief Matlab object class                   */
+    MAT_C_CHAR     =  4, /**< @brief Matlab character array class          */
+    MAT_C_SPARSE   =  5, /**< @brief Matlab sparse array class             */
+    MAT_C_DOUBLE   =  6, /**< @brief Matlab double-precision class         */
+    MAT_C_SINGLE   =  7, /**< @brief Matlab single-precision class         */
+    MAT_C_INT8     =  8, /**< @brief Matlab signed 8-bit integer class     */
+    MAT_C_UINT8    =  9, /**< @brief Matlab unsigned 8-bit integer class   */
+    MAT_C_INT16    = 10, /**< @brief Matlab signed 16-bit integer class    */
+    MAT_C_UINT16   = 11, /**< @brief Matlab unsigned 16-bit integer class  */
+    MAT_C_INT32    = 12, /**< @brief Matlab signed 32-bit integer class    */
+    MAT_C_UINT32   = 13, /**< @brief Matlab unsigned 32-bit integer class  */
+    MAT_C_INT64    = 14, /**< @brief Matlab unsigned 32-bit integer class  */
+    MAT_C_UINT64   = 15, /**< @brief Matlab unsigned 32-bit integer class  */
+    MAT_C_FUNCTION = 16 /**< @brief Matlab unsigned 32-bit integer class  */
+};
+
+/** @brief Matlab array flags
+ *
+ * @ingroup MAT
+ * Matlab array flags
+ */
+enum matio_flags {
+    MAT_F_COMPLEX = 0x0800,    /**< @brief Complex bit flag */
+    MAT_F_GLOBAL  = 0x0400,    /**< @brief Global bit flag */
+    MAT_F_LOGICAL = 0x0200,    /**< @brief Logical bit flag */
+    MAT_F_CLASS_T = 0x00ff     /**< @brief Class-Type bits flag */
+};
+
+#define MEM_CONSERVE 1       /**< @brief Conserve memory */
+
+/** @brief Matlab compression options
+ *
+ * @ingroup MAT
+ * Matlab compression options
+ */
+enum matio_compression {
+    COMPRESSION_NONE = 0,   /**< @brief No compression */
+    COMPRESSION_ZLIB = 1    /**< @brief zlib compression */
+};
+
+/** @brief matio lookup type
+ *
+ * @ingroup MAT
+ * matio lookup type
+ */
+enum {
+    BY_NAME  = 1, /**< Lookup by name */
+    BY_INDEX = 2  /**< Lookup by index */
+};
+
+/** @brief Complex data type using split storage
+ *
+ * Complex data type using split real/imaginary pointers
+ * @ingroup MAT
+ */
+struct ComplexSplit {
+    void *Re; /**< Pointer to the real part */
+    void *Im; /**< Pointer to the imaginary part */
+};
+
+/** @brief Matlab MAT File information
+ *
+ * Contains information about a Matlab MAT file
+ * @ingroup MAT
+ */
+typedef struct mat_t {
+    FILE *fp;               /**< Pointer to the MAT file */
+    char *header;           /**< MAT File header string */
+    char *subsys_offset;    /**< offset */
+    char *filename;         /**< Name of the file that fp points to */
+    int   version;          /**< MAT File version */
+    int   byteswap;         /**< 1 if byte swapping is required, 0 else */
+    int   mode;             /**< Access mode */
+    long  bof;              /**< Beginning of file not including header */
+} mat_t;
+
+/** @brief Matlab variable information
+ *
+ * Contains information about a Matlab variable
+ * @ingroup MAT
+ */
+typedef struct matvar_t {
+    int   nbytes;       /**< Number of bytes for the MAT variable */
+    int   rank;         /**< Rank (Number of dimensions) of the data */
+    int   data_type;    /**< Data type(MAT_T_*) */
+    int   data_size;    /**< Bytes / element for the data */
+    int   class_type;   /**< Class type in Matlab(mxDOUBLE_CLASS, etc) */
+    int   isComplex;    /**< non-zero if the data is complex, 0 if real */
+    int   isGlobal;     /**< non-zero if the variable is global */
+    int   isLogical;    /**< non-zero if the variable is logical */
+    int  *dims;         /**< Array of lengths for each dimension */
+    char *name;         /**< Name of the variable */
+    void *data;         /**< Pointer to the data */
+    int   mem_conserve; /**< 1 if Memory was conserved with data */
+    int   compression;  /**< Compression (0=>None,1=>ZLIB) */
+    long  fpos;         /**< Offset from the beginning of the MAT file to the variable */
+    long  datapos;      /**< Offset from the beginning of the MAT file to the data */
+    mat_t    *fp;       /**< Pointer to the MAT file structure (mat_t) */
+#if defined(HAVE_ZLIB)
+    z_stream *z;        /**< zlib compression state */
+#endif
+} matvar_t;
+
+/** @brief sparse data information
+ *
+ * Contains information and data for a sparse matrix
+ * @ingroup MAT
+ */
+typedef struct sparse_t {
+    int nzmax;               /**< Maximum number of non-zero elements */
+    int *ir;                 /**< Array of size nzmax where ir[k] is the row of
+                               *  data[k].  0 <= k <= nzmax
+                               */
+    int nir;                 /**< number of elements in ir */
+    int *jc;                 /**< Array size N+1 (N is number of columsn) with
+                               *  jc[k] being the index into ir/data of the
+                               *  first non-zero element for row k.
+                               */
+    int   njc;               /**< Number of elements in jc */
+    int   ndata;             /**< Number of complex/real data values */
+    void *data;              /**< Array of data elements */
+} sparse_t;
+
+/*     io.c         */
+EXTERN char  *strdup_vprintf(const char *format, va_list ap);
+EXTERN char  *strdup_printf(const char *format, ...);
+EXTERN int    Mat_SetVerbose( int verb, int s );
+EXTERN int    Mat_SetDebug( int d );
+EXTERN void   Mat_Critical( const char *format, ... );
+EXTERN void   Mat_Error( const char *format, ... );
+EXTERN void   Mat_Help( const char *helpstr[] );
+EXTERN int    Mat_LogInit( char *progname );
+EXTERN int    Mat_LogClose(void);
+EXTERN int    Mat_LogInitFunc(char *prog_name,
+                    void (*log_func)(int log_level, char *message) );
+EXTERN int    Mat_Message( const char *format, ... );
+EXTERN int    Mat_DebugMessage( int level, const char *format, ... );
+EXTERN int    Mat_VerbMessage( int level, const char *format, ... );
+EXTERN void   Mat_Warning( const char *format, ... );
+EXTERN size_t Mat_SizeOf(int data_type);
+EXTERN size_t Mat_SizeOfClass(int class_type);
+
+/*   MAT File functions   */
+EXTERN mat_t  *Mat_Create(const char *matname,const char *hdr_str);
+EXTERN int     Mat_Close(mat_t *mat);
+EXTERN mat_t  *Mat_Open(const char *matname,int mode);
+EXTERN int     Mat_Rewind(mat_t *mat);
+
+/* MAT variable functions */
+EXTERN matvar_t  *Mat_VarCalloc(void);
+EXTERN matvar_t  *Mat_VarCreate(const char *name,int class_type,int data_type,
+                      int rank,int *dims,void *data, int opt);
+EXTERN int        Mat_VarDelete(mat_t *mat, char *name);
+EXTERN matvar_t  *Mat_VarDuplicate(const matvar_t *in, int opt);
+EXTERN void       Mat_VarFree(matvar_t *matvar);
+EXTERN matvar_t  *Mat_VarGetCell(matvar_t *matvar,int index);
+EXTERN matvar_t **Mat_VarGetCells(matvar_t *matvar,int *start,int *stride,
+                      int *edge);
+EXTERN matvar_t **Mat_VarGetCellsLinear(matvar_t *matvar,int start,int stride,
+                      int edge);
+EXTERN size_t     Mat_VarGetSize(matvar_t *matvar);
+EXTERN int        Mat_VarGetNumberOfFields(matvar_t *matvar);
+EXTERN int        Mat_VarAddStructField(matvar_t *matvar,matvar_t **fields);
+EXTERN matvar_t  *Mat_VarGetStructField(matvar_t *matvar,void *name_or_index,
+                      int opt,int index);
+EXTERN matvar_t  *Mat_VarGetStructs(matvar_t *matvar,int *start,int *stride,
+                      int *edge,int copy_fields);
+EXTERN matvar_t  *Mat_VarGetStructsLinear(matvar_t *matvar,int start,int stride,
+                      int edge,int copy_fields);
+EXTERN void       Mat_VarPrint( matvar_t *matvar, int printdata );
+EXTERN matvar_t  *Mat_VarRead(mat_t *mat, char *name );
+EXTERN int        Mat_VarReadData(mat_t *mat,matvar_t *matvar,void *data,
+                      int *start,int *stride,int *edge);
+EXTERN int        Mat_VarReadDataAll(mat_t *mat,matvar_t *matvar);
+EXTERN int        Mat_VarReadDataLinear(mat_t *mat,matvar_t *matvar,void *data,
+                      int start,int stride,int edge);
+EXTERN matvar_t  *Mat_VarReadInfo( mat_t *mat, char *name );
+EXTERN matvar_t  *Mat_VarReadNext( mat_t *mat );
+EXTERN matvar_t  *Mat_VarReadNextInfo( mat_t *mat );
+EXTERN int        Mat_VarWrite(mat_t *mat,matvar_t *matvar,int compress );
+EXTERN int        Mat_VarWriteInfo(mat_t *mat,matvar_t *matvar);
+EXTERN int        Mat_VarWriteData(mat_t *mat,matvar_t *matvar,void *data,
+                      int *start,int *stride,int *edge);
+
+/* Other functions */
+EXTERN int       Mat_CalcSingleSubscript(int rank,int *dims,int *subs);
+EXTERN int      *Mat_CalcSubscripts(int rank,int *dims,int index);
+
+#endif

+ 55 - 0
matlabAccess/matio/src/matioConfig.h

@@ -0,0 +1,55 @@
+/* src/matioConfig.h.  Generated from matioConfig.h.in by configure.  */
+#define HAVE_ZLIB 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_STDINT_H 1
+#define STDC_HEADERS 1
+
+#define MATIO_PLATFORM "x86_64-unknown-linux-gnu"
+#define MATIO_MAJOR_VERSION 1
+#define MATIO_MINOR_VERSION 3
+#define MATIO_RELEASE_LEVEL 4
+
+/* #undef FC_FUNC */
+/* #undef FC_FUNC_ */
+
+#define LINUX 1
+/* #undef WINNT */
+/* #undef SUN */
+
+#define SIZEOF_DOUBLE 8
+#define SIZEOF_FLOAT 4
+/* #undef SIZEOF_LONG */
+#define SIZEOF_INT 4
+#define SIZEOF_SHORT 2
+#define SIZEOF_CHAR 1
+/* #undef SIZEOF_VOID_PTR */
+
+#define HAVE_MAT_INT64_T 1
+#define HAVE_MAT_INT32_T 1
+#define HAVE_MAT_INT16_T 1
+#define HAVE_MAT_INT8_T 1
+#define HAVE_MAT_UINT64_T 1
+#define HAVE_MAT_UINT32_T 1
+#define HAVE_MAT_UINT16_T 1
+#define HAVE_MAT_UINT8_T 1
+
+#define _mat_uint8_t uint8_t
+#define _mat_uint16_t uint16_t
+#define _mat_uint32_t uint32_t
+#define _mat_uint64_t uint64_t
+#define _mat_int8_t int8_t
+#define _mat_int16_t int16_t
+#define _mat_int32_t int32_t
+#define _mat_int64_t int64_t
+
+#define HAVE_VA_COPY 1
+/* #undef HAVE___VA_COPY */
+#define HAVE_VSNPRINTF 1
+#define HAVE_SNPRINTF 1
+#define HAVE_VASPRINTF 1
+#define HAVE_ASPRINTF 1
+
+#define EXTENDED_SPARSE 1
+
+/* #undef Z_PREFIX */

+ 92 - 0
matlabAccess/matio/src/matio_private.h

@@ -0,0 +1,92 @@
+#ifndef MATIO_PRIVATE_H
+#define MATIO_PRIVATE_H
+
+#include "matio.h"
+
+#ifndef EXTERN
+#   ifdef __cplusplus
+#       define EXTERN extern "C"
+#   else
+#       define EXTERN extern
+#   endif
+#endif
+
+/*    snprintf.c    */
+EXTERN int mat_snprintf(char *str,size_t count,const char *fmt,...);
+EXTERN int mat_asprintf(char **ptr,const char *format, ...);
+EXTERN int mat_vsnprintf(char *str,size_t count,const char *fmt,va_list args);
+EXTERN int mat_vasprintf(char **ptr,const char *format,va_list ap);
+
+/*   endian.c     */
+EXTERN double        Mat_doubleSwap(double  *a);
+EXTERN float         Mat_floatSwap(float   *a);
+#ifdef HAVE_MAT_INT64_T
+EXTERN mat_int64_t   Mat_int64Swap(mat_int64_t  *a);
+#endif /* HAVE_MAT_INT64_T */
+#ifdef HAVE_MAT_UINT64_T
+EXTERN mat_uint64_t  Mat_uint64Swap(mat_uint64_t *a);
+#endif /* HAVE_MAT_UINT64_T */
+EXTERN mat_int32_t   Mat_int32Swap(mat_int32_t  *a);
+EXTERN mat_uint32_t  Mat_uint32Swap(mat_uint32_t *a);
+EXTERN mat_int16_t   Mat_int16Swap(mat_int16_t  *a);
+EXTERN mat_uint16_t  Mat_uint16Swap(mat_uint16_t *a);
+
+/* read_data.c */
+EXTERN int ReadDoubleData(mat_t *mat,double  *data,int data_type,int len);
+EXTERN int ReadSingleData(mat_t *mat,float   *data,int data_type,int len);
+EXTERN int ReadInt32Data (mat_t *mat,mat_int32_t *data,int data_type,int len);
+EXTERN int ReadUInt32Data(mat_t *mat,mat_uint32_t *data,int data_type,int len);
+EXTERN int ReadInt16Data (mat_t *mat,mat_int16_t *data,int data_type,int len);
+EXTERN int ReadUInt16Data(mat_t *mat,mat_uint16_t *data,int data_type,int len);
+EXTERN int ReadInt8Data  (mat_t *mat,mat_int8_t  *data,int data_type,int len);
+EXTERN int ReadUInt8Data (mat_t *mat,mat_uint8_t  *data,int data_type,int len);
+EXTERN int ReadCharData  (mat_t *mat,char  *data,int data_type,int len);
+EXTERN int ReadDataSlab2(mat_t *mat,void *data,int class_type,int data_type,
+               int *dims,int *start,int *stride,int *edge);
+EXTERN int ReadDataSlabN(mat_t *mat,void *data,int class_type,int data_type,
+               int rank,int *dims,int *start,int *stride,int *edge);
+#if defined(HAVE_ZLIB)
+EXTERN int ReadCompressedDoubleData(mat_t *mat,z_stream *z,double  *data,
+               int data_type,int len);
+EXTERN int ReadCompressedSingleData(mat_t *mat,z_stream *z,float   *data,
+               int data_type,int len);
+EXTERN int ReadCompressedInt32Data(mat_t *mat,z_stream *z,mat_int32_t *data,
+               int data_type,int len);
+EXTERN int ReadCompressedUInt32Data(mat_t *mat,z_stream *z,mat_uint32_t *data,
+               int data_type,int len);
+EXTERN int ReadCompressedInt16Data(mat_t *mat,z_stream *z,mat_int16_t *data,
+               int data_type,int len);
+EXTERN int ReadCompressedUInt16Data(mat_t *mat,z_stream *z,mat_uint16_t *data,
+               int data_type,int len);
+EXTERN int ReadCompressedInt8Data(mat_t *mat,z_stream *z,mat_int8_t  *data,
+               int data_type,int len);
+EXTERN int ReadCompressedUInt8Data(mat_t *mat,z_stream *z,mat_uint8_t  *data,
+               int data_type,int len);
+EXTERN int ReadCompressedCharData(mat_t *mat,z_stream *z,char *data,
+               int data_type,int len);
+EXTERN int ReadCompressedDataSlab2(mat_t *mat,z_stream *z,void *data,
+               int class_type,int data_type,int *dims,int *start,int *stride,
+               int *edge);
+EXTERN int ReadCompressedDataSlabN(mat_t *mat,z_stream *z,void *data,
+               int class_type,int data_type,int rank,int *dims,int *start,
+               int *stride,int *edge);
+
+/*   inflate.c    */
+EXTERN int InflateSkip(mat_t *mat, z_stream *z, int nbytes);
+EXTERN int InflateSkip2(mat_t *mat, matvar_t *matvar, int nbytes);
+EXTERN int InflateSkipData(mat_t *mat,z_stream *z,int data_type,int len);
+EXTERN int InflateVarTag(mat_t *mat, matvar_t *matvar, void *buf);
+EXTERN int InflateArrayFlags(mat_t *mat, matvar_t *matvar, void *buf);
+EXTERN int InflateDimensions(mat_t *mat, matvar_t *matvar, void *buf);
+EXTERN int InflateVarNameTag(mat_t *mat, matvar_t *matvar, void *buf);
+EXTERN int InflateVarName(mat_t *mat,matvar_t *matvar,void *buf,int N);
+EXTERN int InflateDataTag(mat_t *mat, matvar_t *matvar, void *buf);
+EXTERN int InflateDataType(mat_t *mat, z_stream *matvar, void *buf);
+EXTERN int InflateData(mat_t *mat, z_stream *z, void *buf, int nBytes);
+EXTERN int InflateFieldNameLength(mat_t *mat,matvar_t *matvar,void *buf);
+EXTERN int InflateFieldNamesTag(mat_t *mat,matvar_t *matvar,void *buf);
+EXTERN int InflateFieldNames(mat_t *mat,matvar_t *matvar,void *buf,int nfields,
+               int fieldname_length,int padding);
+#endif
+
+#endif

+ 5285 - 0
matlabAccess/matio/src/read_data.c

@@ -0,0 +1,5285 @@
+/** @file read_data.c
+ * Matlab MAT version 5 file functions
+ * @ingroup MAT
+ */
+/*
+ * Copyright (C) 2005-2006   Christopher C. Hulbert
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* FIXME: Implement Unicode support */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+#include "matio.h"
+#include "matio_private.h"
+#if defined(HAVE_ZLIB)
+#   include <zlib.h>
+#endif
+
+/*
+ * --------------------------------------------------------------------------
+ *    Routines to read data of any type into arrays of a specific type
+ * --------------------------------------------------------------------------
+ */
+
+/** @brief Reads data of type @c data_type into a double type
+ *
+ * Reads from the MAT file @c len elements of data type @c data_type storing
+ * them as double's in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output double values (len*sizeof(double))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadDoubleData(mat_t *mat,double *data,int data_type,int len)
+{
+    int bytesread = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                bytesread += fread(data,data_size,len,mat->fp);
+                for ( i = 0; i < len; i++ ) {
+                    (void)Mat_doubleSwap(data+i);
+                }
+            } else {
+                bytesread += fread(data,data_size,len,mat->fp);
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            }
+            break;
+        }
+    }
+    bytesread *= data_size;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type into a double type
+ *
+ * Reads from the MAT file @c len compressed elements of data type @c data_type
+ * storing them as double's in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z Pointer to the zlib stream for inflation
+ * @param data Pointer to store the output double values (len*sizeof(double))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadCompressedDoubleData(mat_t *mat,z_stream *z,double *data,
+    int data_type,int len)
+{
+    int nBytes = 0, data_size = 0, i;
+    union _buf {
+#if SIZEOF_DOUBLE == 8
+        double          d[128];
+#elif SIZEOF_DOUBLE == 16
+        double          d[64];
+#endif
+        float           f[256];
+        mat_int32_t   i32[256];
+        mat_uint32_t ui32[256];
+        mat_int16_t   i16[512];
+        mat_uint16_t ui16[512];
+        mat_int8_t     i8[1024];
+        mat_uint8_t   ui8[1024];
+    } buf;
+
+    
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                InflateData(mat,z,data,len*data_size);
+                for ( i = 0; i < len; i++ )
+                    (void)Mat_doubleSwap(data+i);
+            } else {
+                InflateData(mat,z,data,len*data_size);
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                if ( len <= 256 ){
+                    InflateData(mat,z,buf.i32,len*data_size);
+                    for ( i = 0; i < len; i++ )
+                        data[i] = Mat_int32Swap(buf.i32+i);
+                } else {
+                    int j;
+                    len -= 256;
+                    for ( i = 0; i < len; i+=256 ) {
+                        InflateData(mat,z,buf.i32,256*data_size);
+                        for ( j = 0; j < 256; j++ )
+                            data[i+j] = Mat_int32Swap(buf.i32+j);
+                    }
+                    len = len-(i-256);
+                    InflateData(mat,z,buf.i32,len*data_size);
+                    for ( j = 0; j < len; j++ )
+                        data[i+j] = Mat_int32Swap(buf.i32+j);
+                }
+            } else {
+                if ( len <= 256 ){
+                    InflateData(mat,z,buf.i32,len*data_size);
+                    for ( i = 0; i < len; i++ )
+                        data[i] = buf.i32[i];
+                } else {
+                    int j;
+                    len -= 256;
+                    for ( i = 0; i < len; i+=256 ) {
+                        InflateData(mat,z,buf.i32,256*data_size);
+                        for ( j = 0; j < 256; j++ )
+                            data[i+j] = buf.i32[j];
+                    }
+                    len = len-(i-256);
+                    InflateData(mat,z,buf.i32,len*data_size);
+                    for ( j = 0; j < len; j++ )
+                        data[i+j] = buf.i32[j];
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                if ( len <= 256 ){
+                    InflateData(mat,z,buf.ui32,len*data_size);
+                    for ( i = 0; i < len; i++ )
+                        data[i] = Mat_uint32Swap(buf.ui32+i);
+                } else {
+                    int j;
+                    len -= 256;
+                    for ( i = 0; i < len; i+=256 ) {
+                        InflateData(mat,z,buf.ui32,256*data_size);
+                        for ( j = 0; j < 256; j++ )
+                            data[i+j] = Mat_uint32Swap(buf.ui32+j);
+                    }
+                    len = len-(i-256);
+                    InflateData(mat,z,buf.ui32,len*data_size);
+                    for ( j = 0; j < len; j++ )
+                        data[i+j] = Mat_uint32Swap(buf.ui32+j);
+                }
+            } else {
+                if ( len <= 256 ) {
+                    InflateData(mat,z,buf.ui32,len*data_size);
+                    for ( i = 0; i < len; i++ )
+                        data[i] = buf.ui32[i];
+                } else {
+                    int j;
+                    len -= 256;
+                    for ( i = 0; i < len; i+=256 ) {
+                        InflateData(mat,z,buf.ui32,256*data_size);
+                        for ( j = 0; j < 256; j++ )
+                            data[i+j] = buf.ui32[j];
+                    }
+                    len = len-(i-256);
+                    InflateData(mat,z,buf.ui32,len*data_size);
+                    for ( j = 0; j < len; j++ )
+                        data[i+j] = buf.ui32[j];
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                if ( len <= 512 ){
+                    InflateData(mat,z,buf.i16,len*data_size);
+                    for ( i = 0; i < len; i++ )
+                        data[i] = Mat_int16Swap(buf.i16+i);
+                } else {
+                    int j;
+                    len -= 512;
+                    for ( i = 0; i < len; i+=512 ) {
+                        InflateData(mat,z,buf.i16,512*data_size);
+                        for ( j = 0; j < 512; j++ )
+                            data[i+j] = Mat_int16Swap(buf.i16+j);
+                    }
+                    len = len-(i-512);
+                    InflateData(mat,z,buf.i16,len*data_size);
+                    for ( j = 0; j < len; j++ )
+                        data[i+j] = Mat_int16Swap(buf.i16+j);
+                }
+            } else {
+                if ( len <= 512 ) {
+                    InflateData(mat,z,buf.i16,len*data_size);
+                    for ( i = 0; i < len; i++ )
+                        data[i] = buf.i16[i];
+                } else {
+                    int j;
+                    len -= 512;
+                    for ( i = 0; i < len; i+=512 ) {
+                        InflateData(mat,z,buf.i16,512*data_size);
+                        for ( j = 0; j < 512; j++ )
+                            data[i+j] = buf.i16[j];
+                    }
+                    len = len-(i-512);
+                    InflateData(mat,z,buf.i16,len*data_size);
+                    for ( j = 0; j < len; j++ )
+                        data[i+j] = buf.i16[j];
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                if ( len <= 512 ){
+                    InflateData(mat,z,buf.ui16,len*data_size);
+                    for ( i = 0; i < len; i++ )
+                        data[i] = Mat_uint16Swap(buf.ui16+i);
+                } else {
+                    int j;
+                    len -= 512;
+                    for ( i = 0; i < len; i+=512 ) {
+                        InflateData(mat,z,buf.ui16,512*data_size);
+                        for ( j = 0; j < 512; j++ )
+                            data[i+j] = Mat_uint16Swap(buf.ui16+j);
+                    }
+                    len = len-(i-512);
+                    InflateData(mat,z,buf.ui16,len*data_size);
+                    for ( j = 0; j < len; j++ )
+                        data[i+j] = Mat_uint16Swap(buf.ui16+j);
+                }
+            } else {
+                if ( len <= 512 ) {
+                    InflateData(mat,z,buf.ui16,len*data_size);
+                    for ( i = 0; i < len; i++ )
+                        data[i] = buf.ui16[i];
+                } else {
+                    int j;
+                    len -= 512;
+                    for ( i = 0; i < len; i+=512 ) {
+                        InflateData(mat,z,buf.ui16,512*data_size);
+                        for ( j = 0; j < 512; j++ )
+                            data[i+j] = buf.ui16[j];
+                    }
+                    len = len-(i-512);
+                    InflateData(mat,z,buf.ui16,len*data_size);
+                    for ( j = 0; j < len; j++ )
+                        data[i+j] = buf.ui16[j];
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            data_size = sizeof(mat_uint8_t);
+            if ( len <= 1024 ) {
+                InflateData(mat,z,buf.ui8,len*data_size);
+                for ( i = 0; i < len; i++ )
+                    data[i] = buf.ui8[i];
+            } else {
+                int j;
+                len -= 1024;
+                for ( i = 0; i < len; i+=1024 ) {
+                    InflateData(mat,z,buf.ui8,1024*data_size);
+                    for ( j = 0; j < 1024; j++ )
+                        data[i+j] = buf.ui8[j];
+                }
+                len = len-(i-1024);
+                InflateData(mat,z,buf.ui8,len*data_size);
+                for ( j = 0; j < len; j++ )
+                    data[i+j] = buf.ui8[j];
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            data_size = sizeof(mat_int8_t);
+            if ( len <= 1024 ) {
+                InflateData(mat,z,buf.i8,len*data_size);
+                for ( i = 0; i < len; i++ )
+                    data[i] = buf.i8[i];
+            } else {
+                int j;
+                len -= 1024;
+                for ( i = 0; i < len; i+=1024 ) {
+                    InflateData(mat,z,buf.i8,1024*data_size);
+                    for ( j = 0; j < 1024; j++ )
+                        data[i+j] = buf.i8[j];
+                }
+                len = len-(i-1024);
+                InflateData(mat,z,buf.i8,len*data_size);
+                for ( j = 0; j < len; j++ )
+                    data[i+j] = buf.i8[j];
+            }
+            break;
+        }
+    }
+    nBytes = len*data_size;
+    return nBytes;
+}
+#endif
+
+/** @brief Reads data of type @c data_type into a float type
+ *
+ * Reads from the MAT file @c len elements of data type @c data_type storing
+ * them as float's in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output float values (len*sizeof(float))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadSingleData(mat_t *mat,float *data,int data_type,int len)
+{
+    int bytesread = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            }
+            break;
+        }
+    }
+    bytesread *= data_size;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type into a float type
+ *
+ * Reads from the MAT file @c len compressed elements of data type @c data_type
+ * storing them as float's in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z Pointer to the zlib stream for inflation
+ * @param data Pointer to store the output float values (len*sizeof(float))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadCompressedSingleData(mat_t *mat,z_stream *z,float *data,
+    int data_type,int len)
+{
+    int nBytes = 0, data_size = 0, i;
+
+    if ( (mat == NULL) || (data == NULL) || (z == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,data+i,data_size);
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&ui8,data_size);
+                data[i] = ui8;
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&i8,data_size);
+                data[i] = i8;
+            }
+            break;
+        }
+    }
+    nBytes = len*data_size;
+    return nBytes;
+}
+#endif
+
+#ifdef HAVE_MAT_INT64_T
+/** @brief Reads data of type @c data_type into a signed 64-bit integer type
+ *
+ * Reads from the MAT file @c len elements of data type @c data_type storing
+ * them as signed 64-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output signed 64-bit integer values
+ *             (len*sizeof(mat_int64_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadInt64Data(mat_t *mat,mat_int64_t *data,int data_type,int len)
+{
+    int bytesread = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT64:
+        {
+            mat_int64_t i64;
+
+            data_size = sizeof(mat_int64_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i64,data_size,1,mat->fp);
+                    data[i] = Mat_int64Swap(&i64);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i64,data_size,1,mat->fp);
+                    data[i] = i64;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT64:
+        {
+            mat_uint64_t ui64;
+
+            data_size = sizeof(mat_uint64_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui64,data_size,1,mat->fp);
+                    data[i] = Mat_uint64Swap(&ui64);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui64,data_size,1,mat->fp);
+                    data[i] = ui64;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            }
+            break;
+        }
+    }
+    bytesread *= data_size;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type into a signed 64-bit integer type
+ *
+ * Reads from the MAT file @c len compressed elements of data type @c data_type
+ * storing them as signed 64-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z Pointer to the zlib stream for inflation
+ * @param data Pointer to store the output signed 64-bit integer values
+ *             (len*sizeof(mat_int64_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadCompressedInt64Data(mat_t *mat,z_stream *z,mat_int64_t *data,
+    int data_type,int len)
+{
+    int nBytes = 0, data_size = 0, i;
+
+    if ( (mat == NULL) || (data == NULL) || (z == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT64:
+        {
+            mat_int64_t i64;
+
+            data_size = sizeof(mat_int64_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i64,data_size);
+                    data[i] = Mat_int64Swap(&i64);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i64,data_size);
+                    data[i] = i64;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT64:
+        {
+            mat_uint64_t ui64;
+
+            data_size = sizeof(mat_uint64_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui64,data_size);
+                    data[i] = Mat_uint64Swap(&ui64);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui64,data_size);
+                    data[i] = ui64;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&ui8,data_size);
+                data[i] = ui8;
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&i8,data_size);
+                data[i] = i8;
+            }
+            break;
+        }
+    }
+    nBytes = len*data_size;
+    return nBytes;
+}
+#endif
+#endif /* HAVE_MAT_INT64_T */
+
+#ifdef HAVE_MAT_UINT64_T
+/** @brief Reads data of type @c data_type into an unsigned 64-bit integer type
+ *
+ * Reads from the MAT file @c len elements of data type @c data_type storing
+ * them as unsigned 64-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output unsigned 64-bit integer values
+ *             (len*sizeof(mat_uint64_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadUInt64Data(mat_t *mat,mat_uint64_t *data,int data_type,int len)
+{
+    int bytesread = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT64:
+        {
+            mat_int64_t i64;
+
+            data_size = sizeof(mat_int64_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i64,data_size,1,mat->fp);
+                    data[i] = Mat_int64Swap(&i64);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i64,data_size,1,mat->fp);
+                    data[i] = i64;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT64:
+        {
+            mat_uint64_t ui64;
+
+            data_size = sizeof(mat_uint64_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui64,data_size,1,mat->fp);
+                    data[i] = Mat_uint64Swap(&ui64);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui64,data_size,1,mat->fp);
+                    data[i] = ui64;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            }
+            break;
+        }
+    }
+    bytesread *= data_size;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type into an unsigned 64-bit integer type
+ *
+ * Reads from the MAT file @c len compressed elements of data type @c data_type
+ * storing them as unsigned 64-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z Pointer to the zlib stream for inflation
+ * @param data Pointer to store the output unsigned 64-bit integer values
+ *             (len*sizeof(mat_uint64_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadCompressedUInt64Data(mat_t *mat,z_stream *z,mat_uint64_t *data,
+    int data_type,int len)
+{
+    int nBytes = 0, data_size = 0, i;
+
+    if ( (mat == NULL) || (data == NULL) || (z == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT64:
+        {
+            mat_int64_t i64;
+
+            data_size = sizeof(mat_int64_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i64,data_size);
+                    data[i] = Mat_int64Swap(&i64);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i64,data_size);
+                    data[i] = i64;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT64:
+        {
+            mat_uint64_t ui64;
+
+            data_size = sizeof(mat_uint64_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui64,data_size);
+                    data[i] = Mat_uint64Swap(&ui64);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui64,data_size);
+                    data[i] = ui64;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&ui8,data_size);
+                data[i] = ui8;
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&i8,data_size);
+                data[i] = i8;
+            }
+            break;
+        }
+    }
+    nBytes = len*data_size;
+    return nBytes;
+}
+#endif /* HAVE_ZLIB */
+#endif /* HAVE_MAT_UINT64_T */
+
+/** @brief Reads data of type @c data_type into a signed 32-bit integer type
+ *
+ * Reads from the MAT file @c len elements of data type @c data_type storing
+ * them as signed 32-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output signed 32-bit integer values
+ *             (len*sizeof(mat_int32_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadInt32Data(mat_t *mat,mat_int32_t *data,int data_type,int len)
+{
+    int bytesread = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            }
+            break;
+        }
+    }
+    bytesread *= data_size;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type into a signed 32-bit integer type
+ *
+ * Reads from the MAT file @c len compressed elements of data type @c data_type
+ * storing them as signed 32-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z Pointer to the zlib stream for inflation
+ * @param data Pointer to store the output signed 32-bit integer values
+ *             (len*sizeof(mat_int32_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadCompressedInt32Data(mat_t *mat,z_stream *z,mat_int32_t *data,
+    int data_type,int len)
+{
+    int nBytes = 0, data_size = 0, i;
+
+    if ( (mat == NULL) || (data == NULL) || (z == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&ui8,data_size);
+                data[i] = ui8;
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&i8,data_size);
+                data[i] = i8;
+            }
+            break;
+        }
+    }
+    nBytes = len*data_size;
+    return nBytes;
+}
+#endif
+
+/** @brief Reads data of type @c data_type into an unsigned 32-bit integer type
+ *
+ * Reads from the MAT file @c len elements of data type @c data_type storing
+ * them as unsigned 32-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output unsigned 32-bit integer values
+ *             (len*sizeof(mat_uint32_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadUInt32Data(mat_t *mat,mat_uint32_t *data,int data_type,int len)
+{
+    int bytesread = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            }
+            break;
+        }
+    }
+    bytesread *= data_size;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type into an unsigned 32-bit integer type
+ *
+ * Reads from the MAT file @c len compressed elements of data type @c data_type
+ * storing them as unsigned 32-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z Pointer to the zlib stream for inflation
+ * @param data Pointer to store the output unsigned 32-bit integer values
+ *             (len*sizeof(mat_uint32_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadCompressedUInt32Data(mat_t *mat,z_stream *z,mat_uint32_t *data,
+    int data_type,int len)
+{
+    int nBytes = 0, data_size = 0, i;
+
+    if ( (mat == NULL) || (data == NULL) || (z == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&ui8,data_size);
+                data[i] = ui8;
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&i8,data_size);
+                data[i] = i8;
+            }
+            break;
+        }
+    }
+    nBytes = len*data_size;
+    return nBytes;
+}
+#endif
+
+/** @brief Reads data of type @c data_type into a signed 16-bit integer type
+ *
+ * Reads from the MAT file @c len elements of data type @c data_type storing
+ * them as signed 16-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output signed 16-bit integer values
+ *             (len*sizeof(mat_int16_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadInt16Data(mat_t *mat,mat_int16_t *data,int data_type,int len)
+{
+    int bytesread = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            }
+            break;
+        }
+    }
+    bytesread *= data_size;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type into a signed 16-bit integer type
+ *
+ * Reads from the MAT file @c len compressed elements of data type @c data_type
+ * storing them as signed 16-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z Pointer to the zlib stream for inflation
+ * @param data Pointer to store the output signed 16-bit integer values
+ *             (len*sizeof(mat_int16_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadCompressedInt16Data(mat_t *mat,z_stream *z,mat_int16_t *data,
+    int data_type,int len)
+{
+    int nBytes = 0, data_size = 0, i;
+
+    if ( (mat == NULL) || (data == NULL) || (z == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&ui8,data_size);
+                data[i] = ui8;
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&i8,data_size);
+                data[i] = i8;
+            }
+            break;
+        }
+    }
+    nBytes = len*data_size;
+    return nBytes;
+}
+#endif
+
+/** @brief Reads data of type @c data_type into an unsigned 16-bit integer type
+ *
+ * Reads from the MAT file @c len elements of data type @c data_type storing
+ * them as unsigned 16-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output unsigned 16-bit integer values
+ *             (len*sizeof(mat_uint16_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadUInt16Data(mat_t *mat,mat_uint16_t *data,int data_type,int len)
+{
+    int bytesread = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            }
+            break;
+        }
+    }
+    bytesread *= data_size;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type into an unsigned 16-bit integer type
+ *
+ * Reads from the MAT file @c len compressed elements of data type @c data_type
+ * storing them as unsigned 16-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z Pointer to the zlib stream for inflation
+ * @param data Pointer to store the output n unsigned 16-bit integer values
+ *             (len*sizeof(mat_uint16_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadCompressedUInt16Data(mat_t *mat,z_stream *z,mat_uint16_t *data,
+    int data_type,int len)
+{
+    int nBytes = 0, data_size = 0, i;
+
+    if ( (mat == NULL) || (data == NULL) || (z == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&ui8,data_size);
+                data[i] = ui8;
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&i8,data_size);
+                data[i] = i8;
+            }
+            break;
+        }
+    }
+    nBytes = len*data_size;
+    return nBytes;
+}
+#endif
+
+/** @brief Reads data of type @c data_type into a signed 8-bit integer type
+ *
+ * Reads from the MAT file @c len elements of data type @c data_type storing
+ * them as signed 8-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output signed 8-bit integer values
+ *             (len*sizeof(mat_int8_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadInt8Data(mat_t *mat,mat_int8_t *data,int data_type,int len)
+{
+    int bytesread = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            }
+            break;
+        }
+    }
+    bytesread *= data_size;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type into a signed 8-bit integer type
+ *
+ * Reads from the MAT file @c len compressed elements of data type @c data_type
+ * storing them as signed 8-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z Pointer to the zlib stream for inflation
+ * @param data Pointer to store the output signed 8-bit integer values
+ *             (len*sizeof(mat_int8_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadCompressedInt8Data(mat_t *mat,z_stream *z,mat_int8_t *data,
+    int data_type,int len)
+{
+    int nBytes = 0, data_size = 0, i;
+
+    if ( (mat == NULL) || (data == NULL) || (z == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&ui8,data_size);
+                data[i] = ui8;
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&i8,data_size);
+                data[i] = i8;
+            }
+            break;
+        }
+    }
+    nBytes = len*data_size;
+    return nBytes;
+}
+#endif
+
+/** @brief Reads data of type @c data_type into an unsigned 8-bit integer type
+ *
+ * Reads from the MAT file @c len elements of data type @c data_type storing
+ * them as unsigned 8-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output unsigned 8-bit integer values
+ *             (len*sizeof(mat_uint8_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadUInt8Data(mat_t *mat,mat_uint8_t *data,int data_type,int len)
+{
+    int bytesread = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&d,data_size,1,mat->fp);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&f,data_size,1,mat->fp);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i32,data_size,1,mat->fp);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui32,data_size,1,mat->fp);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,data_size,1,mat->fp);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui16,data_size,1,mat->fp);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i8,data_size,1,mat->fp);
+                    data[i] = i8;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&ui8,data_size,1,mat->fp);
+                    data[i] = ui8;
+                }
+            }
+            break;
+        }
+    }
+    bytesread *= data_size;
+    return bytesread;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type into an unsigned 8-bit integer type
+ *
+ * Reads from the MAT file @c len compressed elements of data type @c data_type
+ * storing them as unsigned 8-bit integers in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z Pointer to the zlib stream for inflation
+ * @param data Pointer to store the output 8-bit integer values
+ *             (len*sizeof(mat_uint8_t))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadCompressedUInt8Data(mat_t *mat,z_stream *z,mat_uint8_t *data,
+    int data_type,int len)
+{
+    int nBytes = 0, data_size = 0, i;
+
+    if ( (mat == NULL) || (data == NULL) || (z == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_DOUBLE:
+        {
+            double d;
+
+            data_size = sizeof(double);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = Mat_doubleSwap(&d);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&d,data_size);
+                    data[i] = d;
+                }
+            }
+            break;
+        }
+        case MAT_T_SINGLE:
+        {
+            float f;
+
+            data_size = sizeof(float);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = Mat_floatSwap(&f);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&f,data_size);
+                    data[i] = f;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT32:
+        {
+            mat_int32_t i32;
+
+            data_size = sizeof(mat_int32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = Mat_int32Swap(&i32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i32,data_size);
+                    data[i] = i32;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT32:
+        {
+            mat_uint32_t ui32;
+
+            data_size = sizeof(mat_uint32_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = Mat_uint32Swap(&ui32);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui32,data_size);
+                    data[i] = ui32;
+                }
+            }
+            break;
+        }
+        case MAT_T_INT16:
+        {
+            mat_int16_t i16;
+
+            data_size = sizeof(mat_int16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = Mat_int16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t ui16;
+
+            data_size = sizeof(mat_uint16_t);
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = Mat_uint16Swap(&ui16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&ui16,data_size);
+                    data[i] = ui16;
+                }
+            }
+            break;
+        }
+        case MAT_T_UINT8:
+        {
+            mat_uint8_t ui8;
+
+            data_size = sizeof(mat_uint8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&ui8,data_size);
+                data[i] = ui8;
+            }
+            break;
+        }
+        case MAT_T_INT8:
+        {
+            mat_int8_t i8;
+
+            data_size = sizeof(mat_int8_t);
+            for ( i = 0; i < len; i++ ) {
+                InflateData(mat,z,&i8,data_size);
+                data[i] = i8;
+            }
+            break;
+        }
+    }
+    nBytes = len*data_size;
+    return nBytes;
+}
+#endif
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type into a char type
+ *
+ * Reads from the MAT file @c len compressed elements of data type @c data_type
+ * storing them as char's in @c data.
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z Pointer to the zlib stream for inflation
+ * @param data Pointer to store the output char values (len*sizeof(char))
+ * @param data_type one of the @c matio_types enumerations which is the source
+ *                  data type in the file
+ * @param len Number of elements of type @c data_type to read from the file
+ * @retval Number of bytes read from the file
+ */
+int
+ReadCompressedCharData(mat_t *mat,z_stream *z,char *data,int data_type,int len)
+{
+    int nBytes = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_UTF8:
+            data_size = 1;
+            for ( i = 0; i < len; i++ )
+                InflateData(mat,z,data+i,data_size);
+            break;
+        case MAT_T_INT8:
+        case MAT_T_UINT8:
+            data_size = 1;
+            for ( i = 0; i < len; i++ )
+                InflateData(mat,z,data+i,data_size);
+            break;
+        case MAT_T_INT16:
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t i16;
+
+            data_size = 2;
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = Mat_uint16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    InflateData(mat,z,&i16,data_size);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        default:
+            printf("Character data not supported type: %d",data_type);
+            break;
+    }
+    nBytes = len*data_size;
+    return nBytes;
+}
+#endif
+
+int
+ReadCharData(mat_t *mat,char *data,int data_type,int len)
+{
+    int bytesread = 0, data_size = 0, i;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) )
+        return 0;
+
+    switch ( data_type ) {
+        case MAT_T_UTF8:
+            for ( i = 0; i < len; i++ )
+                bytesread += fread(data+i,1,1,mat->fp);
+            break;
+        case MAT_T_INT8:
+        case MAT_T_UINT8:
+            for ( i = 0; i < len; i++ )
+                bytesread += fread(data+i,1,1,mat->fp);
+            break;
+        case MAT_T_INT16:
+        case MAT_T_UINT16:
+        {
+            mat_uint16_t i16;
+
+            if ( mat->byteswap ) {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,2,1,mat->fp);
+                    data[i] = Mat_uint16Swap(&i16);
+                }
+            } else {
+                for ( i = 0; i < len; i++ ) {
+                    bytesread += fread(&i16,2,1,mat->fp);
+                    data[i] = i16;
+                }
+            }
+            break;
+        }
+        default:
+            printf("Character data not supported type: %d",data_type);
+            break;
+    }
+    bytesread *= data_size;
+    return bytesread;
+}
+
+/*
+ *-------------------------------------------------------------------
+ *  Routines to read "slabs" of data
+ *-------------------------------------------------------------------
+ */
+
+/** @brief Reads data of type @c data_type by user-defined dimensions
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output data
+ * @param class_type Type of data class (matio_classes enumerations)
+ * @param data_type Datatype of the stored data (matio_types enumerations)
+ * @param rank Number of dimensions in the data
+ * @param dims Dimensions of the data
+ * @param start Index to start reading data in each dimension
+ * @param stride Read every @c stride elements in each dimension
+ * @param edge Number of elements to read in each dimension
+ * @retval Number of bytes read from the file, or -1 on error
+ */
+int
+ReadDataSlabN(mat_t *mat,void *data,int class_type,int data_type,int rank,
+    int *dims,int *start,int *stride,int *edge)
+{
+    int nBytes = 0, i, j, N, I = 0;
+    int inc[10] = {0,}, cnt[10] = {0,}, dimp[10] = {0,};
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
+         (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
+        return -1;
+    } else if ( rank > 10 ) {
+        return -1; 
+    }
+
+    switch ( class_type ) {
+        case MAT_C_DOUBLE:
+        {
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            fseek(mat->fp,I*Mat_SizeOf(data_type),SEEK_CUR);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadDoubleData(mat,(double*)data+i+j,data_type,1);
+                    fseek(mat->fp,Mat_SizeOf(data_type)*(stride[0]-1),SEEK_CUR);
+                    I += stride[0];
+                }
+                I += dims[0]-edge[0]*stride[0]-start[0];
+                fseek(mat->fp,Mat_SizeOf(data_type)*
+                      (dims[0]-edge[0]*stride[0]-start[0]),SEEK_CUR);
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            fseek(mat->fp,Mat_SizeOf(data_type)*
+                                  (dimp[j]-(I % dimp[j])),SEEK_CUR);
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += inc[j];
+                        fseek(mat->fp,Mat_SizeOf(data_type)*inc[j],SEEK_CUR);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_SINGLE:
+        {
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            fseek(mat->fp,I*Mat_SizeOf(data_type),SEEK_CUR);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadSingleData(mat,(float*)data+i+j,data_type,1);
+                    fseek(mat->fp,Mat_SizeOf(data_type)*(stride[0]-1),SEEK_CUR);
+                    I += stride[0];
+                }
+                I += dims[0]-edge[0]*stride[0]-start[0];
+                fseek(mat->fp,Mat_SizeOf(data_type)*
+                      (dims[0]-edge[0]*stride[0]-start[0]),SEEK_CUR);
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            fseek(mat->fp,Mat_SizeOf(data_type)*
+                                  (dimp[j]-(I % dimp[j])),SEEK_CUR);
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += inc[j];
+                        fseek(mat->fp,Mat_SizeOf(data_type)*inc[j],SEEK_CUR);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+#ifdef HAVE_MAT_INT64_T
+        case MAT_C_INT64:
+        {
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            fseek(mat->fp,I*Mat_SizeOf(data_type),SEEK_CUR);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadInt64Data(mat,(mat_int64_t*)data+i+j,data_type,1);
+                    fseek(mat->fp,Mat_SizeOf(data_type)*(stride[0]-1),SEEK_CUR);
+                    I += stride[0];
+                }
+                I += dims[0]-edge[0]*stride[0]-start[0];
+                fseek(mat->fp,Mat_SizeOf(data_type)*
+                      (dims[0]-edge[0]*stride[0]-start[0]),SEEK_CUR);
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            fseek(mat->fp,Mat_SizeOf(data_type)*
+                                  (dimp[j]-(I % dimp[j])),SEEK_CUR);
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += inc[j];
+                        fseek(mat->fp,Mat_SizeOf(data_type)*inc[j],SEEK_CUR);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+#endif /* HAVE_MAT_INT64_T */
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_C_UINT64:
+        {
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            fseek(mat->fp,I*Mat_SizeOf(data_type),SEEK_CUR);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadUInt64Data(mat,(mat_uint64_t*)data+i+j,data_type,1);
+                    fseek(mat->fp,Mat_SizeOf(data_type)*(stride[0]-1),SEEK_CUR);
+                    I += stride[0];
+                }
+                I += dims[0]-edge[0]*stride[0]-start[0];
+                fseek(mat->fp,Mat_SizeOf(data_type)*
+                      (dims[0]-edge[0]*stride[0]-start[0]),SEEK_CUR);
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            fseek(mat->fp,Mat_SizeOf(data_type)*
+                                  (dimp[j]-(I % dimp[j])),SEEK_CUR);
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += inc[j];
+                        fseek(mat->fp,Mat_SizeOf(data_type)*inc[j],SEEK_CUR);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+#endif /* HAVE_MAT_UINT64_T */
+        case MAT_C_INT32:
+        {
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            fseek(mat->fp,I*Mat_SizeOf(data_type),SEEK_CUR);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadInt32Data(mat,(mat_int32_t*)data+i+j,data_type,1);
+                    fseek(mat->fp,Mat_SizeOf(data_type)*(stride[0]-1),SEEK_CUR);
+                    I += stride[0];
+                }
+                I += dims[0]-edge[0]*stride[0]-start[0];
+                fseek(mat->fp,Mat_SizeOf(data_type)*
+                      (dims[0]-edge[0]*stride[0]-start[0]),SEEK_CUR);
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            fseek(mat->fp,Mat_SizeOf(data_type)*
+                                  (dimp[j]-(I % dimp[j])),SEEK_CUR);
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += inc[j];
+                        fseek(mat->fp,Mat_SizeOf(data_type)*inc[j],SEEK_CUR);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_UINT32:
+        {
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            fseek(mat->fp,I*Mat_SizeOf(data_type),SEEK_CUR);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadUInt32Data(mat,(mat_uint32_t*)data+i+j,data_type,1);
+                    fseek(mat->fp,Mat_SizeOf(data_type)*(stride[0]-1),SEEK_CUR);
+                    I += stride[0];
+                }
+                I += dims[0]-edge[0]*stride[0]-start[0];
+                fseek(mat->fp,Mat_SizeOf(data_type)*
+                      (dims[0]-edge[0]*stride[0]-start[0]),SEEK_CUR);
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            fseek(mat->fp,Mat_SizeOf(data_type)*
+                                  (dimp[j]-(I % dimp[j])),SEEK_CUR);
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += inc[j];
+                        fseek(mat->fp,Mat_SizeOf(data_type)*inc[j],SEEK_CUR);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_INT16:
+        {
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            fseek(mat->fp,I*Mat_SizeOf(data_type),SEEK_CUR);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadInt16Data(mat,(mat_int16_t*)data+i+j,data_type,1);
+                    fseek(mat->fp,Mat_SizeOf(data_type)*(stride[0]-1),SEEK_CUR);
+                    I += stride[0];
+                }
+                I += dims[0]-edge[0]*stride[0]-start[0];
+                fseek(mat->fp,Mat_SizeOf(data_type)*
+                      (dims[0]-edge[0]*stride[0]-start[0]),SEEK_CUR);
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            fseek(mat->fp,Mat_SizeOf(data_type)*
+                                  (dimp[j]-(I % dimp[j])),SEEK_CUR);
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += inc[j];
+                        fseek(mat->fp,Mat_SizeOf(data_type)*inc[j],SEEK_CUR);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_UINT16:
+        {
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            fseek(mat->fp,I*Mat_SizeOf(data_type),SEEK_CUR);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadUInt16Data(mat,(mat_uint16_t*)data+i+j,data_type,1);
+                    fseek(mat->fp,Mat_SizeOf(data_type)*(stride[0]-1),SEEK_CUR);
+                    I += stride[0];
+                }
+                I += dims[0]-edge[0]*stride[0]-start[0];
+                fseek(mat->fp,Mat_SizeOf(data_type)*
+                      (dims[0]-edge[0]*stride[0]-start[0]),SEEK_CUR);
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            fseek(mat->fp,Mat_SizeOf(data_type)*
+                                  (dimp[j]-(I % dimp[j])),SEEK_CUR);
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += inc[j];
+                        fseek(mat->fp,Mat_SizeOf(data_type)*inc[j],SEEK_CUR);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_INT8:
+        {
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            fseek(mat->fp,I*Mat_SizeOf(data_type),SEEK_CUR);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadInt8Data(mat,(mat_int8_t*)data+i+j,data_type,1);
+                    fseek(mat->fp,Mat_SizeOf(data_type)*(stride[0]-1),SEEK_CUR);
+                    I += stride[0];
+                }
+                I += dims[0]-edge[0]*stride[0]-start[0];
+                fseek(mat->fp,Mat_SizeOf(data_type)*
+                      (dims[0]-edge[0]*stride[0]-start[0]),SEEK_CUR);
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            fseek(mat->fp,Mat_SizeOf(data_type)*
+                                  (dimp[j]-(I % dimp[j])),SEEK_CUR);
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += inc[j];
+                        fseek(mat->fp,Mat_SizeOf(data_type)*inc[j],SEEK_CUR);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_UINT8:
+        {
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            fseek(mat->fp,I*Mat_SizeOf(data_type),SEEK_CUR);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadUInt8Data(mat,(mat_uint8_t*)data+i+j,data_type,1);
+                    fseek(mat->fp,Mat_SizeOf(data_type)*(stride[0]-1),SEEK_CUR);
+                    I += stride[0];
+                }
+                I += dims[0]-edge[0]*stride[0]-start[0];
+                fseek(mat->fp,Mat_SizeOf(data_type)*
+                      (dims[0]-edge[0]*stride[0]-start[0]),SEEK_CUR);
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            fseek(mat->fp,Mat_SizeOf(data_type)*
+                                  (dimp[j]-(I % dimp[j])),SEEK_CUR);
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += inc[j];
+                        fseek(mat->fp,Mat_SizeOf(data_type)*inc[j],SEEK_CUR);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        default:
+            nBytes = 0;
+    }
+    return nBytes;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type by user-defined dimensions
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z zlib compression stream
+ * @param data Pointer to store the output data
+ * @param class_type Type of data class (matio_classes enumerations)
+ * @param data_type Datatype of the stored data (matio_types enumerations)
+ * @param rank Number of dimensions in the data
+ * @param dims Dimensions of the data
+ * @param start Index to start reading data in each dimension
+ * @param stride Read every @c stride elements in each dimension
+ * @param edge Number of elements to read in each dimension
+ * @retval Number of bytes read from the file, or -1 on error
+ */
+int
+ReadCompressedDataSlabN(mat_t *mat,z_stream *z,void *data,int class_type,
+    int data_type,int rank,int *dims,int *start,int *stride,int *edge)
+{
+    int nBytes = 0, i, j, N, I = 0;
+    int inc[10] = {0,}, cnt[10] = {0,}, dimp[10] = {0,};
+    z_stream z_copy = {0,};
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
+         (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
+        return 1;
+    } else if ( rank > 10 ) {
+        return 1;
+    }
+
+    i = inflateCopy(&z_copy,z);
+    switch ( class_type ) {
+        case MAT_C_DOUBLE:
+        {
+            double *ptr;
+
+            ptr     = data;
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            /* Skip all data to the starting indeces */
+            InflateSkipData(mat,&z_copy,data_type,I);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedDoubleData(mat,&z_copy,ptr+i+j,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,(stride[0]-1));
+                    I += stride[0];
+                }
+                ReadCompressedDoubleData(mat,&z_copy,ptr+i+j,data_type,1);
+                I += stride[0];
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            InflateSkipData(mat,&z_copy,data_type,
+                                  dimp[j]-(I % dimp[j]));
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += dims[0]-edge[0]*stride[0]-start[0];
+                        InflateSkipData(mat,&z_copy,data_type,
+                              dims[0]-edge[0]*stride[0]-start[0]);
+                        I += inc[j];
+                        InflateSkipData(mat,&z_copy,data_type,inc[j]);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_SINGLE:
+        {
+            float *ptr;
+
+            ptr     = data;
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            /* Skip all data to the starting indeces */
+            InflateSkipData(mat,&z_copy,data_type,I);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedSingleData(mat,&z_copy,ptr+i+j,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,(stride[0]-1));
+                    I += stride[0];
+                }
+                ReadCompressedSingleData(mat,&z_copy,ptr+i+j,data_type,1);
+                I += stride[0];
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            InflateSkipData(mat,&z_copy,data_type,
+                                  dimp[j]-(I % dimp[j]));
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += dims[0]-edge[0]*stride[0]-start[0];
+                        InflateSkipData(mat,&z_copy,data_type,
+                              dims[0]-edge[0]*stride[0]-start[0]);
+                        I += inc[j];
+                        InflateSkipData(mat,&z_copy,data_type,inc[j]);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+#ifdef HAVE_MAT_INT64_T
+        case MAT_C_INT64:
+        {
+            mat_int64_t *ptr;
+
+            ptr     = data;
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            /* Skip all data to the starting indeces */
+            InflateSkipData(mat,&z_copy,data_type,I);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedInt64Data(mat,&z_copy,ptr+i+j,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,(stride[0]-1));
+                    I += stride[0];
+                }
+                ReadCompressedInt64Data(mat,&z_copy,ptr+i+j,data_type,1);
+                I += stride[0];
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            InflateSkipData(mat,&z_copy,data_type,
+                                  dimp[j]-(I % dimp[j]));
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += dims[0]-edge[0]*stride[0]-start[0];
+                        InflateSkipData(mat,&z_copy,data_type,
+                              dims[0]-edge[0]*stride[0]-start[0]);
+                        I += inc[j];
+                        InflateSkipData(mat,&z_copy,data_type,inc[j]);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+#endif /* HAVE_MAT_INT64_T */
+#ifdef HAVE_MAT_INT64_T
+        case MAT_C_UINT64:
+        {
+            mat_uint64_t *ptr;
+
+            ptr     = data;
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            /* Skip all data to the starting indeces */
+            InflateSkipData(mat,&z_copy,data_type,I);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedUInt64Data(mat,&z_copy,ptr+i+j,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,(stride[0]-1));
+                    I += stride[0];
+                }
+                ReadCompressedUInt64Data(mat,&z_copy,ptr+i+j,data_type,1);
+                I += stride[0];
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            InflateSkipData(mat,&z_copy,data_type,
+                                  dimp[j]-(I % dimp[j]));
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += dims[0]-edge[0]*stride[0]-start[0];
+                        InflateSkipData(mat,&z_copy,data_type,
+                              dims[0]-edge[0]*stride[0]-start[0]);
+                        I += inc[j];
+                        InflateSkipData(mat,&z_copy,data_type,inc[j]);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+#endif /* HAVE_MAT_UINT64_T */
+        case MAT_C_INT32:
+        {
+            mat_int32_t *ptr;
+
+            ptr     = data;
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            /* Skip all data to the starting indeces */
+            InflateSkipData(mat,&z_copy,data_type,I);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedInt32Data(mat,&z_copy,ptr+i+j,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,(stride[0]-1));
+                    I += stride[0];
+                }
+                ReadCompressedInt32Data(mat,&z_copy,ptr+i+j,data_type,1);
+                I += stride[0];
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            InflateSkipData(mat,&z_copy,data_type,
+                                  dimp[j]-(I % dimp[j]));
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += dims[0]-edge[0]*stride[0]-start[0];
+                        InflateSkipData(mat,&z_copy,data_type,
+                              dims[0]-edge[0]*stride[0]-start[0]);
+                        I += inc[j];
+                        InflateSkipData(mat,&z_copy,data_type,inc[j]);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_UINT32:
+        {
+            mat_uint32_t *ptr;
+
+            ptr     = data;
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            /* Skip all data to the starting indeces */
+            InflateSkipData(mat,&z_copy,data_type,I);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedUInt32Data(mat,&z_copy,ptr+i+j,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,(stride[0]-1));
+                    I += stride[0];
+                }
+                ReadCompressedUInt32Data(mat,&z_copy,ptr+i+j,data_type,1);
+                I += stride[0];
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            InflateSkipData(mat,&z_copy,data_type,
+                                  dimp[j]-(I % dimp[j]));
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += dims[0]-edge[0]*stride[0]-start[0];
+                        InflateSkipData(mat,&z_copy,data_type,
+                              dims[0]-edge[0]*stride[0]-start[0]);
+                        I += inc[j];
+                        InflateSkipData(mat,&z_copy,data_type,inc[j]);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_INT16:
+        {
+            mat_int16_t *ptr;
+
+            ptr     = data;
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            /* Skip all data to the starting indeces */
+            InflateSkipData(mat,&z_copy,data_type,I);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedInt16Data(mat,&z_copy,ptr+i+j,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,(stride[0]-1));
+                    I += stride[0];
+                }
+                ReadCompressedInt16Data(mat,&z_copy,ptr+i+j,data_type,1);
+                I += stride[0];
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            InflateSkipData(mat,&z_copy,data_type,
+                                  dimp[j]-(I % dimp[j]));
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += dims[0]-edge[0]*stride[0]-start[0];
+                        InflateSkipData(mat,&z_copy,data_type,
+                              dims[0]-edge[0]*stride[0]-start[0]);
+                        I += inc[j];
+                        InflateSkipData(mat,&z_copy,data_type,inc[j]);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_UINT16:
+        {
+            mat_uint16_t *ptr;
+
+            ptr     = data;
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            /* Skip all data to the starting indeces */
+            InflateSkipData(mat,&z_copy,data_type,I);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedUInt16Data(mat,&z_copy,ptr+i+j,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,(stride[0]-1));
+                    I += stride[0];
+                }
+                ReadCompressedUInt16Data(mat,&z_copy,ptr+i+j,data_type,1);
+                I += stride[0];
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            InflateSkipData(mat,&z_copy,data_type,
+                                  dimp[j]-(I % dimp[j]));
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += dims[0]-edge[0]*stride[0]-start[0];
+                        InflateSkipData(mat,&z_copy,data_type,
+                              dims[0]-edge[0]*stride[0]-start[0]);
+                        I += inc[j];
+                        InflateSkipData(mat,&z_copy,data_type,inc[j]);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_INT8:
+        {
+            mat_int8_t *ptr;
+
+            ptr     = data;
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            /* Skip all data to the starting indeces */
+            InflateSkipData(mat,&z_copy,data_type,I);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedInt8Data(mat,&z_copy,ptr+i+j,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,(stride[0]-1));
+                    I += stride[0];
+                }
+                ReadCompressedInt8Data(mat,&z_copy,ptr+i+j,data_type,1);
+                I += stride[0];
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            InflateSkipData(mat,&z_copy,data_type,
+                                  dimp[j]-(I % dimp[j]));
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += dims[0]-edge[0]*stride[0]-start[0];
+                        InflateSkipData(mat,&z_copy,data_type,
+                              dims[0]-edge[0]*stride[0]-start[0]);
+                        I += inc[j];
+                        InflateSkipData(mat,&z_copy,data_type,inc[j]);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        case MAT_C_UINT8:
+        {
+            mat_uint8_t *ptr;
+
+            ptr     = data;
+            inc[0]  = stride[0]-1;
+            dimp[0] = dims[0];
+            N       = edge[0];
+            I       = start[0];
+            for ( i = 1; i < rank; i++ ) {
+                inc[i]  = stride[i]-1;
+                dimp[i] = dims[i-1];
+                for ( j = i ; j--; ) {
+                    inc[i]  *= dims[j];
+                    dimp[i] *= dims[j+1];
+                }
+                N *= edge[i];
+                I += dimp[i-1]*start[i];
+            }
+            /* Skip all data to the starting indeces */
+            InflateSkipData(mat,&z_copy,data_type,I);
+            for ( i = 0; i < N; i+=edge[0] ) {
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedUInt8Data(mat,&z_copy,ptr+i+j,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,(stride[0]-1));
+                    I += stride[0];
+                }
+                ReadCompressedUInt8Data(mat,&z_copy,ptr+i+j,data_type,1);
+                I += stride[0];
+                for ( j = 1; j < rank-1; j++ ) {
+                    cnt[j]++;
+                    if ( (cnt[j] % edge[j]) == 0 ) {
+                        cnt[j] = 0;
+                        if ( (I % dimp[j]) != 0 ) {
+                            InflateSkipData(mat,&z_copy,data_type,
+                                  dimp[j]-(I % dimp[j]));
+                            I += dimp[j]-(I % dimp[j]);
+                        }
+                    } else {
+                        I += dims[0]-edge[0]*stride[0]-start[0];
+                        InflateSkipData(mat,&z_copy,data_type,
+                              dims[0]-edge[0]*stride[0]-start[0]);
+                        I += inc[j];
+                        InflateSkipData(mat,&z_copy,data_type,inc[j]);
+                        break;
+                    }
+                }
+            }
+            break;
+        }
+        default:
+            nBytes = 0;
+    }
+    inflateEnd(&z_copy);
+    return nBytes;
+}
+#endif
+
+/** @brief Reads data of type @c data_type by user-defined dimensions for 2-D
+ *         data
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param data Pointer to store the output data
+ * @param class_type Type of data class (matio_classes enumerations)
+ * @param data_type Datatype of the stored data (matio_types enumerations)
+ * @param dims Dimensions of the data
+ * @param start Index to start reading data in each dimension
+ * @param stride Read every @c stride elements in each dimension
+ * @param edge Number of elements to read in each dimension
+ * @retval Number of bytes read from the file, or -1 on error
+ */
+int
+ReadDataSlab2(mat_t *mat,void *data,int class_type,int data_type,
+    int *dims,int *start,int *stride,int *edge)
+{
+    int nBytes = 0, data_size, i, j;
+    long pos, row_stride, col_stride;
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
+         (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
+        return 0;
+    }
+
+    data_size = Mat_SizeOf(data_type);
+
+    switch ( class_type ) {
+        case MAT_C_DOUBLE:
+        {
+            double *ptr;
+
+            ptr = (double *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+            pos = ftell(mat->fp);
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadDoubleData(mat,ptr++,data_type,1);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_C_SINGLE:
+        {
+            float *ptr;
+
+            ptr = (float *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+            pos = ftell(mat->fp);
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadSingleData(mat,ptr++,data_type,1);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+#ifdef HAVE_MAT_INT64_T
+        case MAT_C_INT64:
+        {
+            mat_int64_t *ptr;
+
+            ptr = (mat_int64_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+            pos = ftell(mat->fp);
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadInt64Data(mat,ptr++,data_type,1);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+#endif /* HAVE_MAT_INT64_T */
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_C_UINT64:
+        {
+            mat_uint64_t *ptr;
+
+            ptr = (mat_uint64_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+            pos = ftell(mat->fp);
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadUInt64Data(mat,ptr++,data_type,1);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+#endif /* HAVE_MAT_UINT64_T */
+        case MAT_C_INT32:
+        {
+            mat_int32_t *ptr;
+
+            ptr = (mat_int32_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+            pos = ftell(mat->fp);
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadInt32Data(mat,ptr++,data_type,1);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_C_UINT32:
+        {
+            mat_uint32_t *ptr;
+
+            ptr = (mat_uint32_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+            pos = ftell(mat->fp);
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadUInt32Data(mat,ptr++,data_type,1);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_C_INT16:
+        {
+            mat_int16_t *ptr;
+
+            ptr = (mat_int16_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+            pos = ftell(mat->fp);
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadInt16Data(mat,ptr++,data_type,1);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_C_UINT16:
+        {
+            mat_uint16_t *ptr;
+
+            ptr = (mat_uint16_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+            pos = ftell(mat->fp);
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadUInt16Data(mat,ptr++,data_type,1);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_C_INT8:
+        {
+            mat_int8_t *ptr;
+
+            ptr = (mat_int8_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+            pos = ftell(mat->fp);
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadInt8Data(mat,ptr++,data_type,1);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        case MAT_C_UINT8:
+        {
+            mat_uint8_t *ptr;
+
+            ptr = (mat_uint8_t *)data;
+            row_stride = (stride[0]-1)*data_size;
+            col_stride = stride[1]*dims[0]*data_size;
+            pos = ftell(mat->fp);
+            fseek(mat->fp,start[1]*dims[0]*data_size,SEEK_CUR);
+            for ( i = 0; i < edge[1]; i++ ) {
+                pos = ftell(mat->fp);
+                fseek(mat->fp,start[0]*data_size,SEEK_CUR);
+                for ( j = 0; j < edge[0]; j++ ) {
+                    ReadUInt8Data(mat,ptr++,data_type,1);
+                    fseek(mat->fp,row_stride,SEEK_CUR);
+                }
+                pos = pos+col_stride-ftell(mat->fp);
+                fseek(mat->fp,pos,SEEK_CUR);
+            }
+            break;
+        }
+        default:
+            nBytes = 0;
+    }
+    return nBytes;
+}
+
+#if defined(HAVE_ZLIB)
+/** @brief Reads data of type @c data_type by user-defined dimensions for 2-D
+ *         data
+ *
+ * @ingroup mat_internal
+ * @param mat MAT file pointer
+ * @param z zlib compression stream
+ * @param data Pointer to store the output data
+ * @param class_type Type of data class (matio_classes enumerations)
+ * @param data_type Datatype of the stored data (matio_types enumerations)
+ * @param dims Dimensions of the data
+ * @param start Index to start reading data in each dimension
+ * @param stride Read every @c stride elements in each dimension
+ * @param edge Number of elements to read in each dimension
+ * @retval Number of bytes read from the file, or -1 on error
+ */
+int
+ReadCompressedDataSlab2(mat_t *mat,z_stream *z,void *data,int class_type,
+    int data_type,int *dims,int *start,int *stride,int *edge)
+{
+    int nBytes = 0, data_size, i, j, err;
+    int pos, row_stride, col_stride;
+    z_stream z_copy = {0,};
+
+    if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
+         (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
+        return 0;
+    }
+
+    err = inflateCopy(&z_copy,z);
+    switch ( class_type ) {
+        case MAT_C_DOUBLE:
+        {
+            double *ptr;
+
+            data_size = sizeof(double);
+            ptr = data;
+            row_stride = (stride[0]-1);
+            col_stride = (stride[1]-1)*dims[0];
+            InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]);
+            /* If stride[0] is 1 and stride[1] is 1, we are reading all of the
+             * data so get rid of the loops.  If stride[0] is 1 and stride[1]
+             * is not 0, we are reading whole columns, so get rid of inner loop
+             * to speed up the code
+             */
+#if 0
+            if ( (stride[0] == 1 && edge[0] == dims[0]) && 
+                 (stride[1] == 1) ) {
+                ReadCompressedDoubleData(mat,&z_copy,ptr,data_type,
+                                         edge[0]*edge[1]);
+            } else if ( stride[0] == 1 ) {
+                for ( i = 0; i < edge[1]; i++ ) {
+                    InflateSkipData(mat,&z_copy,data_type,start[0]);
+                    ReadCompressedDoubleData(mat,&z_copy,ptr,data_type,edge[0]);
+                    ptr += edge[0];
+                    pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                    InflateSkipData(mat,&z_copy,data_type,pos);
+                }
+            } else {
+#endif
+            for ( i = 0; i < edge[1]; i++ ) {
+                InflateSkipData(mat,&z_copy,data_type,start[0]);
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedDoubleData(mat,&z_copy,ptr++,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,stride[0]-1);
+                }
+                ReadCompressedDoubleData(mat,&z_copy,ptr++,data_type,1);
+                pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                InflateSkipData(mat,&z_copy,data_type,pos);
+            }
+#if 0
+            }
+#endif
+            break;
+        }
+        case MAT_C_SINGLE:
+        {
+            float *ptr;
+
+            data_size = sizeof(float);
+            ptr = data;
+            row_stride = (stride[0]-1);
+            col_stride = (stride[1]-1)*dims[0];
+            InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]);
+            for ( i = 0; i < edge[1]; i++ ) {
+                InflateSkipData(mat,&z_copy,data_type,start[0]);
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedSingleData(mat,&z_copy,ptr++,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,stride[0]-1);
+                }
+                ReadCompressedSingleData(mat,&z_copy,ptr++,data_type,1);
+                pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                InflateSkipData(mat,&z_copy,data_type,pos);
+            }
+            break;
+        }
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_C_INT64:
+        {
+            mat_int64_t *ptr;
+
+            data_size = sizeof(mat_int64_t);
+            ptr = data;
+            row_stride = (stride[0]-1);
+            col_stride = (stride[1]-1)*dims[0];
+            InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]);
+            for ( i = 0; i < edge[1]; i++ ) {
+                InflateSkipData(mat,&z_copy,data_type,start[0]);
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedInt64Data(mat,&z_copy,ptr++,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,stride[0]-1);
+                }
+                ReadCompressedInt64Data(mat,&z_copy,ptr++,data_type,1);
+                pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                InflateSkipData(mat,&z_copy,data_type,pos);
+            }
+            break;
+        }
+#endif /* HAVE_MAT_INT64_T */
+#ifdef HAVE_MAT_UINT64_T
+        case MAT_C_UINT64:
+        {
+            mat_uint64_t *ptr;
+
+            data_size = sizeof(mat_uint64_t);
+            ptr = data;
+            row_stride = (stride[0]-1);
+            col_stride = (stride[1]-1)*dims[0];
+            InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]);
+            for ( i = 0; i < edge[1]; i++ ) {
+                InflateSkipData(mat,&z_copy,data_type,start[0]);
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedUInt64Data(mat,&z_copy,ptr++,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,stride[0]-1);
+                }
+                ReadCompressedUInt64Data(mat,&z_copy,ptr++,data_type,1);
+                pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                InflateSkipData(mat,&z_copy,data_type,pos);
+            }
+            break;
+        }
+#endif /* HAVE_MAT_UINT64_T */
+        case MAT_C_INT32:
+        {
+            mat_int32_t *ptr;
+
+            data_size = sizeof(mat_int32_t);
+            ptr = data;
+            row_stride = (stride[0]-1);
+            col_stride = (stride[1]-1)*dims[0];
+            InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]);
+            for ( i = 0; i < edge[1]; i++ ) {
+                InflateSkipData(mat,&z_copy,data_type,start[0]);
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedInt32Data(mat,&z_copy,ptr++,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,stride[0]-1);
+                }
+                ReadCompressedInt32Data(mat,&z_copy,ptr++,data_type,1);
+                pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                InflateSkipData(mat,&z_copy,data_type,pos);
+            }
+            break;
+        }
+        case MAT_C_UINT32:
+        {
+            mat_uint32_t *ptr;
+
+            data_size = sizeof(mat_uint32_t);
+            ptr = data;
+            row_stride = (stride[0]-1);
+            col_stride = (stride[1]-1)*dims[0];
+            InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]);
+            for ( i = 0; i < edge[1]; i++ ) {
+                InflateSkipData(mat,&z_copy,data_type,start[0]);
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedUInt32Data(mat,&z_copy,ptr++,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,stride[0]-1);
+                }
+                ReadCompressedUInt32Data(mat,&z_copy,ptr++,data_type,1);
+                pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                InflateSkipData(mat,&z_copy,data_type,pos);
+            }
+            break;
+        }
+        case MAT_C_INT16:
+        {
+            mat_int16_t *ptr;
+
+            data_size = sizeof(mat_int16_t);
+            ptr = data;
+            row_stride = (stride[0]-1);
+            col_stride = (stride[1]-1)*dims[0];
+            InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]);
+            for ( i = 0; i < edge[1]; i++ ) {
+                InflateSkipData(mat,&z_copy,data_type,start[0]);
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedInt16Data(mat,&z_copy,ptr++,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,stride[0]-1);
+                }
+                ReadCompressedInt16Data(mat,&z_copy,ptr++,data_type,1);
+                pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                InflateSkipData(mat,&z_copy,data_type,pos);
+            }
+            break;
+        }
+        case MAT_C_UINT16:
+        {
+            mat_uint16_t *ptr;
+
+            data_size = sizeof(mat_uint16_t);
+            ptr = data;
+            row_stride = (stride[0]-1);
+            col_stride = (stride[1]-1)*dims[0];
+            InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]);
+            for ( i = 0; i < edge[1]; i++ ) {
+                InflateSkipData(mat,&z_copy,data_type,start[0]);
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedUInt16Data(mat,&z_copy,ptr++,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,stride[0]-1);
+                }
+                ReadCompressedUInt16Data(mat,&z_copy,ptr++,data_type,1);
+                pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                InflateSkipData(mat,&z_copy,data_type,pos);
+            }
+            break;
+        }
+        case MAT_C_INT8:
+        {
+            mat_int8_t *ptr;
+
+            data_size = sizeof(mat_int8_t);
+            ptr = data;
+            row_stride = (stride[0]-1);
+            col_stride = (stride[1]-1)*dims[0];
+            InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]);
+            for ( i = 0; i < edge[1]; i++ ) {
+                InflateSkipData(mat,&z_copy,data_type,start[0]);
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedInt8Data(mat,&z_copy,ptr++,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,stride[0]-1);
+                }
+                ReadCompressedInt8Data(mat,&z_copy,ptr++,data_type,1);
+                pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                InflateSkipData(mat,&z_copy,data_type,pos);
+            }
+            break;
+        }
+        case MAT_C_UINT8:
+        {
+            mat_uint8_t *ptr;
+
+            data_size = sizeof(mat_uint8_t);
+            ptr = data;
+            row_stride = (stride[0]-1);
+            col_stride = (stride[1]-1)*dims[0];
+            InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]);
+            for ( i = 0; i < edge[1]; i++ ) {
+                InflateSkipData(mat,&z_copy,data_type,start[0]);
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedUInt8Data(mat,&z_copy,ptr++,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,stride[0]-1);
+                }
+                ReadCompressedUInt8Data(mat,&z_copy,ptr++,data_type,1);
+                pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                InflateSkipData(mat,&z_copy,data_type,pos);
+            }
+            break;
+        }
+        case MAT_C_CHAR:
+        {
+            char *ptr;
+
+            data_size = 1;
+            ptr = data;
+            row_stride = (stride[0]-1);
+            col_stride = (stride[1]-1)*dims[0];
+            InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]);
+            for ( i = 0; i < edge[1]; i++ ) {
+                InflateSkipData(mat,&z_copy,data_type,start[0]);
+                for ( j = 0; j < edge[0]-1; j++ ) {
+                    ReadCompressedCharData(mat,&z_copy,ptr++,data_type,1);
+                    InflateSkipData(mat,&z_copy,data_type,stride[0]-1);
+                }
+                ReadCompressedCharData(mat,&z_copy,ptr++,data_type,1);
+                pos = dims[0]-(edge[0]-1)*stride[0]-1-start[0] + col_stride;
+                InflateSkipData(mat,&z_copy,data_type,pos);
+            }
+            break;
+        }
+        default:
+            nBytes = 0;
+    }
+    inflateEnd(&z_copy);
+    return nBytes;
+}
+#endif

+ 852 - 0
matlabAccess/matio/src/snprintf.c

@@ -0,0 +1,852 @@
+/*
+ * Copyright Patrick Powell 1995
+ * This code is based on code written by Patrick Powell (papowell@astart.com)
+ * It may be used for any purpose as long as this notice remains intact
+ * on all source code distributions
+ */
+
+/*=============================================================
+ * Original:
+ * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
+ * A bombproof version of doprnt (dopr) included.
+ * Sigh.  This sort of thing is always nasty do deal with.  Note that
+ * the version here does not include floating point...
+ *
+ * snprintf() is used instead of sprintf() as it does limit checks
+ * for string length.  This covers a nasty loophole.
+ *
+ * The other functions are there to prevent NULL pointers from
+ * causing nast effects.
+ *
+ * More Recently:
+ *  Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
+ *  This was ugly.  It is still ugly.  I opted out of floating point
+ *  numbers, but the formatter understands just about everything
+ *  from the normal C string format, at least as far as I can tell from
+ *  the Solaris 2.5 printf(3S) man page.
+ *
+ *  Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
+ *    Ok, added some minimal floating point support, which means this
+ *    probably requires libm on most operating systems.  Don't yet
+ *    support the exponent (e,E) and sigfig (g,G).  Also, fmtint()
+ *    was pretty badly broken, it just wasn't being exercised in ways
+ *    which showed it, so that's been fixed.  Also, formated the code
+ *    to mutt conventions, and removed dead code left over from the
+ *    original.  Also, there is now a builtin-test, just compile with:
+ *           gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
+ *    and run snprintf for results.
+ * 
+ *  Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
+ *    The PGP code was using unsigned hexadecimal formats. 
+ *    Unfortunately, unsigned formats simply didn't work.
+ *
+ *  Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
+ *    The original code assumed that both snprintf() and vsnprintf() were
+ *    missing.  Some systems only have snprintf() but not vsnprintf(), so
+ *    the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
+ *
+ *  Andrew Tridgell (tridge@samba.org) Oct 1998
+ *    fixed handling of %.0f
+ *    added test for HAVE_LONG_DOUBLE
+ *
+ * tridge@samba.org, idra@samba.org, April 2001
+ *    got rid of fcvt code (twas buggy and made testing harder)
+ *    added C99 semantics
+ *
+ * date: 2002/12/19 19:56:31;  author: herb;  state: Exp;  lines: +2 -0
+ * actually print args for %g and %e
+ * 
+ * date: 2002/06/03 13:37:52;  author: jmcd;  state: Exp;  lines: +8 -0
+ * Since includes.h isn't included here, VA_COPY has to be defined here.  I don't
+ * see any include file that is guaranteed to be here, so I'm defining it
+ * locally.  Fixes AIX and Solaris builds.
+ * 
+ * date: 2002/06/03 03:07:24;  author: tridge;  state: Exp;  lines: +5 -13
+ * put the ifdef for HAVE_VA_COPY in one place rather than in lots of
+ * functions
+ * 
+ * date: 2002/05/17 14:51:22;  author: jmcd;  state: Exp;  lines: +21 -4
+ * Fix usage of va_list passed as an arg.  Use __va_copy before using it
+ * when it exists.
+ * 
+ * date: 2002/04/16 22:38:04;  author: idra;  state: Exp;  lines: +20 -14
+ * Fix incorrect zpadlen handling in fmtfp.
+ * Thanks to Ollie Oldham <ollie.oldham@metro-optix.com> for spotting it.
+ * few mods to make it easier to compile the tests.
+ * addedd the "Ollie" test to the floating point ones.
+ *
+ * Martin Pool (mbp@samba.org) April 2003
+ *    Remove NO_CONFIG_H so that the test case can be built within a source
+ *    tree with less trouble.
+ *    Remove unnecessary SAFE_FREE() definition.
+ *
+ * Martin Pool (mbp@samba.org) May 2003
+ *    Put in a prototype for dummy_snprintf() to quiet compiler warnings.
+ *
+ *    Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
+ *    if the C library has some snprintf functions already.
+ =============================================================*/
+
+#include "matioConfig.h"
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#include <string.h>
+#endif
+
+#if defined(HAVE_STRINGS_H)
+#include <strings.h>
+#endif
+#if defined(HAVE_CTYPE_H) || defined(STDC_HEADERS)
+#include <ctype.h>
+#endif
+#include <sys/types.h>
+#include <stdarg.h>
+#if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS)
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+
+#ifdef HAVE_LONG_DOUBLE
+#define LDOUBLE long double
+#else
+#define LDOUBLE double
+#endif
+
+#ifdef HAVE_LONG_LONG
+#define LLONG long long
+#else
+#define LLONG long
+#endif
+
+#ifndef VA_COPY
+#ifdef HAVE_VA_COPY
+#define VA_COPY(dest, src) va_copy(dest, src)
+#else
+#ifdef HAVE___VA_COPY
+#define VA_COPY(dest, src) __va_copy(dest, src)
+#else
+#define VA_COPY(dest, src) (dest) = (src)
+#endif
+#endif
+
+/*
+ * dopr(): poor man's version of doprintf
+ */
+
+/* format read states */
+#define DP_S_DEFAULT 0
+#define DP_S_FLAGS   1
+#define DP_S_MIN     2
+#define DP_S_DOT     3
+#define DP_S_MAX     4
+#define DP_S_MOD     5
+#define DP_S_CONV    6
+#define DP_S_DONE    7
+
+/* format flags - Bits */
+#define DP_F_MINUS      (1 << 0)
+#define DP_F_PLUS       (1 << 1)
+#define DP_F_SPACE      (1 << 2)
+#define DP_F_NUM        (1 << 3)
+#define DP_F_ZERO       (1 << 4)
+#define DP_F_UP         (1 << 5)
+#define DP_F_UNSIGNED   (1 << 6)
+
+/* Conversion Flags */
+#define DP_C_SHORT   1
+#define DP_C_LONG    2
+#define DP_C_LDOUBLE 3
+#define DP_C_LLONG   4
+
+#define char_to_int(p) ((p)- '0')
+#ifndef MAX
+#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
+#endif
+
+/* yes this really must be a ||. Don't muck with this (tridge) */
+#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+static size_t dopr(char *buffer, size_t maxlen, const char *format, 
+                   va_list args_in);
+static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
+                    char *value, int flags, int min, int max);
+static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
+                    long value, int base, int min, int max, int flags);
+static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
+                   LDOUBLE fvalue, int min, int max, int flags);
+static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
+
+static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
+{
+        char ch;
+        LLONG value;
+        LDOUBLE fvalue;
+        char *strvalue;
+        int min;
+        int max;
+        int state;
+        int flags;
+        int cflags;
+        size_t currlen;
+        va_list args;
+
+        VA_COPY(args, args_in);
+        
+        state = DP_S_DEFAULT;
+        currlen = flags = cflags = min = 0;
+        max = -1;
+        ch = *format++;
+        
+        while (state != DP_S_DONE) {
+                if (ch == '\0') 
+                        state = DP_S_DONE;
+
+                switch(state) {
+                case DP_S_DEFAULT:
+                        if (ch == '%') 
+                                state = DP_S_FLAGS;
+                        else 
+                                dopr_outch (buffer, &currlen, maxlen, ch);
+                        ch = *format++;
+                        break;
+                case DP_S_FLAGS:
+                        switch (ch) {
+                        case '-':
+                                flags |= DP_F_MINUS;
+                                ch = *format++;
+                                break;
+                        case '+':
+                                flags |= DP_F_PLUS;
+                                ch = *format++;
+                                break;
+                        case ' ':
+                                flags |= DP_F_SPACE;
+                                ch = *format++;
+                                break;
+                        case '#':
+                                flags |= DP_F_NUM;
+                                ch = *format++;
+                                break;
+                        case '0':
+                                flags |= DP_F_ZERO;
+                                ch = *format++;
+                                break;
+                        default:
+                                state = DP_S_MIN;
+                                break;
+                        }
+                        break;
+                case DP_S_MIN:
+                        if (isdigit((unsigned char)ch)) {
+                                min = 10*min + char_to_int (ch);
+                                ch = *format++;
+                        } else if (ch == '*') {
+                                min = va_arg (args, int);
+                                ch = *format++;
+                                state = DP_S_DOT;
+                        } else {
+                                state = DP_S_DOT;
+                        }
+                        break;
+                case DP_S_DOT:
+                        if (ch == '.') {
+                                state = DP_S_MAX;
+                                ch = *format++;
+                        } else { 
+                                state = DP_S_MOD;
+                        }
+                        break;
+                case DP_S_MAX:
+                        if (isdigit((unsigned char)ch)) {
+                                if (max < 0)
+                                        max = 0;
+                                max = 10*max + char_to_int (ch);
+                                ch = *format++;
+                        } else if (ch == '*') {
+                                max = va_arg (args, int);
+                                ch = *format++;
+                                state = DP_S_MOD;
+                        } else {
+                                state = DP_S_MOD;
+                        }
+                        break;
+                case DP_S_MOD:
+                        switch (ch) {
+                        case 'h':
+                                cflags = DP_C_SHORT;
+                                ch = *format++;
+                                break;
+                        case 'l':
+                                cflags = DP_C_LONG;
+                                ch = *format++;
+                                if (ch == 'l') {        /* It's a long long */
+                                        cflags = DP_C_LLONG;
+                                        ch = *format++;
+                                }
+                                break;
+                        case 'L':
+                                cflags = DP_C_LDOUBLE;
+                                ch = *format++;
+                                break;
+                        default:
+                                break;
+                        }
+                        state = DP_S_CONV;
+                        break;
+                case DP_S_CONV:
+                        switch (ch) {
+                        case 'd':
+                        case 'i':
+                                if (cflags == DP_C_SHORT) 
+                                        value = va_arg (args, int);
+                                else if (cflags == DP_C_LONG)
+                                        value = va_arg (args, long int);
+                                else if (cflags == DP_C_LLONG)
+                                        value = va_arg (args, LLONG);
+                                else
+                                        value = va_arg (args, int);
+                                fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+                                break;
+                        case 'o':
+                                flags |= DP_F_UNSIGNED;
+                                if (cflags == DP_C_SHORT)
+                                        value = va_arg (args, unsigned int);
+                                else if (cflags == DP_C_LONG)
+                                        value = (long)va_arg (args, unsigned long int);
+                                else if (cflags == DP_C_LLONG)
+                                        value = (long)va_arg (args, unsigned LLONG);
+                                else
+                                        value = (long)va_arg (args, unsigned int);
+                                fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
+                                break;
+                        case 'u':
+                                flags |= DP_F_UNSIGNED;
+                                if (cflags == DP_C_SHORT)
+                                        value = va_arg (args, unsigned int);
+                                else if (cflags == DP_C_LONG)
+                                        value = (long)va_arg (args, unsigned long int);
+                                else if (cflags == DP_C_LLONG)
+                                        value = (LLONG)va_arg (args, unsigned LLONG);
+                                else
+                                        value = (long)va_arg (args, unsigned int);
+                                fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+                                break;
+                        case 'X':
+                                flags |= DP_F_UP;
+                        case 'x':
+                                flags |= DP_F_UNSIGNED;
+                                if (cflags == DP_C_SHORT)
+                                        value = va_arg (args, unsigned int);
+                                else if (cflags == DP_C_LONG)
+                                        value = (long)va_arg (args, unsigned long int);
+                                else if (cflags == DP_C_LLONG)
+                                        value = (LLONG)va_arg (args, unsigned LLONG);
+                                else
+                                        value = (long)va_arg (args, unsigned int);
+                                fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
+                                break;
+                        case 'f':
+                                if (cflags == DP_C_LDOUBLE)
+                                        fvalue = va_arg (args, LDOUBLE);
+                                else
+                                        fvalue = va_arg (args, double);
+                                /* um, floating point? */
+                                fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
+                                break;
+                        case 'E':
+                                flags |= DP_F_UP;
+                        case 'e':
+                                if (cflags == DP_C_LDOUBLE)
+                                        fvalue = va_arg (args, LDOUBLE);
+                                else
+                                        fvalue = va_arg (args, double);
+                                fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
+                                break;
+                        case 'G':
+                                flags |= DP_F_UP;
+                        case 'g':
+                                if (cflags == DP_C_LDOUBLE)
+                                        fvalue = va_arg (args, LDOUBLE);
+                                else
+                                        fvalue = va_arg (args, double);
+                                fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
+                                break;
+                        case 'c':
+                                dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
+                                break;
+                        case 's':
+                                strvalue = va_arg (args, char *);
+                                if (!strvalue) strvalue = "(NULL)";
+                                if (max == -1) {
+                                        max = strlen(strvalue);
+                                }
+                                if (min > 0 && max >= 0 && min > max) max = min;
+                                fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
+                                break;
+                        case 'p':
+                                strvalue = va_arg (args, void *);
+                                fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
+                                break;
+                        case 'n':
+                                if (cflags == DP_C_SHORT) {
+                                        short int *num;
+                                        num = va_arg (args, short int *);
+                                        *num = currlen;
+                                } else if (cflags == DP_C_LONG) {
+                                        long int *num;
+                                        num = va_arg (args, long int *);
+                                        *num = (long int)currlen;
+                                } else if (cflags == DP_C_LLONG) {
+                                        LLONG *num;
+                                        num = va_arg (args, LLONG *);
+                                        *num = (LLONG)currlen;
+                                } else {
+                                        int *num;
+                                        num = va_arg (args, int *);
+                                        *num = currlen;
+                                }
+                                break;
+                        case '%':
+                                dopr_outch (buffer, &currlen, maxlen, ch);
+                                break;
+                        case 'w':
+                                /* not supported yet, treat as next char */
+                                ch = *format++;
+                                break;
+                        default:
+                                /* Unknown, skip */
+                                break;
+                        }
+                        ch = *format++;
+                        state = DP_S_DEFAULT;
+                        flags = cflags = min = 0;
+                        max = -1;
+                        break;
+                case DP_S_DONE:
+                        break;
+                default:
+                        /* hmm? */
+                        break; /* some picky compilers need this */
+                }
+        }
+        if (maxlen != 0) {
+                if (currlen < maxlen - 1) 
+                        buffer[currlen] = '\0';
+                else if (maxlen > 0) 
+                        buffer[maxlen - 1] = '\0';
+        }
+        
+        return currlen;
+}
+
+static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
+                    char *value, int flags, int min, int max)
+{
+        int padlen, strln;     /* amount to pad */
+        int cnt = 0;
+
+#ifdef DEBUG_SNPRINTF
+        printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
+#endif
+        if (value == 0) {
+                value = "<NULL>";
+        }
+
+        for (strln = 0; value[strln]; ++strln); /* strlen */
+        padlen = min - strln;
+        if (padlen < 0) 
+                padlen = 0;
+        if (flags & DP_F_MINUS) 
+                padlen = -padlen; /* Left Justify */
+        
+        while ((padlen > 0) && (cnt < max)) {
+                dopr_outch (buffer, currlen, maxlen, ' ');
+                --padlen;
+                ++cnt;
+        }
+        while (*value && (cnt < max)) {
+                dopr_outch (buffer, currlen, maxlen, *value++);
+                ++cnt;
+        }
+        while ((padlen < 0) && (cnt < max)) {
+                dopr_outch (buffer, currlen, maxlen, ' ');
+                ++padlen;
+                ++cnt;
+        }
+}
+
+/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
+
+static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
+                    long value, int base, int min, int max, int flags)
+{
+        int signvalue = 0;
+        unsigned long uvalue;
+        char convert[20];
+        int place = 0;
+        int spadlen = 0; /* amount to space pad */
+        int zpadlen = 0; /* amount to zero pad */
+        int caps = 0;
+        
+        if (max < 0)
+                max = 0;
+        
+        uvalue = value;
+        
+        if(!(flags & DP_F_UNSIGNED)) {
+                if( value < 0 ) {
+                        signvalue = '-';
+                        uvalue = -value;
+                } else {
+                        if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
+                                signvalue = '+';
+                        else if (flags & DP_F_SPACE)
+                                signvalue = ' ';
+                }
+        }
+  
+        if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
+
+        do {
+                convert[place++] =
+                        (caps? "0123456789ABCDEF":"0123456789abcdef")
+                        [uvalue % (unsigned)base  ];
+                uvalue = (uvalue / (unsigned)base );
+        } while(uvalue && (place < 20));
+        if (place == 20) place--;
+        convert[place] = 0;
+
+        zpadlen = max - place;
+        spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
+        if (zpadlen < 0) zpadlen = 0;
+        if (spadlen < 0) spadlen = 0;
+        if (flags & DP_F_ZERO) {
+                zpadlen = MAX(zpadlen, spadlen);
+                spadlen = 0;
+        }
+        if (flags & DP_F_MINUS) 
+                spadlen = -spadlen; /* Left Justifty */
+
+#ifdef DEBUG_SNPRINTF
+        printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
+               zpadlen, spadlen, min, max, place);
+#endif
+
+        /* Spaces */
+        while (spadlen > 0) {
+                dopr_outch (buffer, currlen, maxlen, ' ');
+                --spadlen;
+        }
+
+        /* Sign */
+        if (signvalue) 
+                dopr_outch (buffer, currlen, maxlen, signvalue);
+
+        /* Zeros */
+        if (zpadlen > 0) {
+                while (zpadlen > 0) {
+                        dopr_outch (buffer, currlen, maxlen, '0');
+                        --zpadlen;
+                }
+        }
+
+        /* Digits */
+        while (place > 0) 
+                dopr_outch (buffer, currlen, maxlen, convert[--place]);
+  
+        /* Left Justified spaces */
+        while (spadlen < 0) {
+                dopr_outch (buffer, currlen, maxlen, ' ');
+                ++spadlen;
+        }
+}
+
+static LDOUBLE abs_val(LDOUBLE value)
+{
+        LDOUBLE result = value;
+
+        if (value < 0)
+                result = -value;
+        
+        return result;
+}
+
+static LDOUBLE POW10(int exp)
+{
+        LDOUBLE result = 1;
+        
+        while (exp) {
+                result *= 10;
+                exp--;
+        }
+  
+        return result;
+}
+
+static LLONG ROUND(LDOUBLE value)
+{
+        LLONG intpart;
+
+        intpart = (LLONG)value;
+        value = value - intpart;
+        if (value >= 0.5) intpart++;
+        
+        return intpart;
+}
+
+/* a replacement for modf that doesn't need the math library. Should
+   be portable, but slow */
+static double my_modf(double x0, double *iptr)
+{
+        int i;
+        long l;
+        double x = x0;
+        double f = 1.0;
+
+        for (i=0;i<100;i++) {
+                l = (long)x;
+                if (l <= (x+1) && l >= (x-1)) break;
+                x *= 0.1;
+                f *= 10.0;
+        }
+
+        if (i == 100) {
+                /* yikes! the number is beyond what we can handle. What do we do? */
+                (*iptr) = 0;
+                return 0;
+        }
+
+        if (i != 0) {
+                double i2;
+                double ret;
+
+                ret = my_modf(x0-l*f, &i2);
+                (*iptr) = l*f + i2;
+                return ret;
+        } 
+
+        (*iptr) = l;
+        return x - (*iptr);
+}
+
+
+static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
+                   LDOUBLE fvalue, int min, int max, int flags)
+{
+        int signvalue = 0;
+        double ufvalue;
+        char iconvert[311];
+        char fconvert[311];
+        int iplace = 0;
+        int fplace = 0;
+        int padlen = 0; /* amount to pad */
+        int zpadlen = 0; 
+        int caps = 0;
+        int idx;
+        double intpart;
+        double fracpart;
+        double temp;
+  
+        /* 
+         * AIX manpage says the default is 0, but Solaris says the default
+         * is 6, and sprintf on AIX defaults to 6
+         */
+        if (max < 0)
+                max = 6;
+
+        ufvalue = abs_val (fvalue);
+
+        if (fvalue < 0) {
+                signvalue = '-';
+        } else {
+                if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
+                        signvalue = '+';
+                } else {
+                        if (flags & DP_F_SPACE)
+                                signvalue = ' ';
+                }
+        }
+
+#if 0
+        if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
+#endif
+
+#if 0
+         if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
+#endif
+
+        /* 
+         * Sorry, we only support 16 digits past the decimal because of our 
+         * conversion method
+         */
+        if (max > 16)
+                max = 16;
+
+        /* We "cheat" by converting the fractional part to integer by
+         * multiplying by a factor of 10
+         */
+
+        temp = ufvalue;
+        my_modf(temp, &intpart);
+
+        fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
+        
+        if (fracpart >= POW10(max)) {
+                intpart++;
+                fracpart -= POW10(max);
+        }
+
+
+        /* Convert integer part */
+        do {
+                temp = intpart*0.1;
+                my_modf(temp, &intpart);
+                idx = (int) ((temp -intpart +0.05)* 10.0);
+                /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
+                /* printf ("%llf, %f, %x\n", temp, intpart, idx); */
+                iconvert[iplace++] =
+                        (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
+        } while (intpart && (iplace < 311));
+        if (iplace == 311) iplace--;
+        iconvert[iplace] = 0;
+
+        /* Convert fractional part */
+        if (fracpart)
+        {
+                do {
+                        temp = fracpart*0.1;
+                        my_modf(temp, &fracpart);
+                        idx = (int) ((temp -fracpart +0.05)* 10.0);
+                        /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
+                        /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
+                        fconvert[fplace++] =
+                        (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
+                } while(fracpart && (fplace < 311));
+                if (fplace == 311) fplace--;
+        }
+        fconvert[fplace] = 0;
+  
+        /* -1 for decimal point, another -1 if we are printing a sign */
+        padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 
+        zpadlen = max - fplace;
+        if (zpadlen < 0) zpadlen = 0;
+        if (padlen < 0) 
+                padlen = 0;
+        if (flags & DP_F_MINUS) 
+                padlen = -padlen; /* Left Justifty */
+        
+        if ((flags & DP_F_ZERO) && (padlen > 0)) {
+                if (signvalue) {
+                        dopr_outch (buffer, currlen, maxlen, signvalue);
+                        --padlen;
+                        signvalue = 0;
+                }
+                while (padlen > 0) {
+                        dopr_outch (buffer, currlen, maxlen, '0');
+                        --padlen;
+                }
+        }
+        while (padlen > 0) {
+                dopr_outch (buffer, currlen, maxlen, ' ');
+                --padlen;
+        }
+        if (signvalue) 
+                dopr_outch (buffer, currlen, maxlen, signvalue);
+        
+        while (iplace > 0) 
+                dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
+
+#ifdef DEBUG_SNPRINTF
+        printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
+#endif
+
+        /*
+         * Decimal point.  This should probably use locale to find the correct
+         * char to print out.
+         */
+        if (max > 0) {
+                dopr_outch (buffer, currlen, maxlen, '.');
+                
+                while (zpadlen > 0) {
+                        dopr_outch (buffer, currlen, maxlen, '0');
+                        --zpadlen;
+                }
+
+                while (fplace > 0) 
+                        dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
+        }
+
+        while (padlen < 0) {
+                dopr_outch (buffer, currlen, maxlen, ' ');
+                ++padlen;
+        }
+}
+
+static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
+{
+        if (*currlen < maxlen) {
+                buffer[(*currlen)] = c;
+        }
+        (*currlen)++;
+}
+
+int mat_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
+{
+        return dopr(str, count, fmt, args);
+}
+#else
+int mat_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
+{
+        return vsnprintf(str, count, fmt, args);
+}
+#endif
+
+int mat_snprintf(char *str,size_t count,const char *fmt,...)
+{
+        size_t ret;
+        va_list ap;
+    
+        va_start(ap, fmt);
+        ret = mat_vsnprintf(str, count, fmt, ap);
+        va_end(ap);
+        return ret;
+}
+#endif 
+
+#ifndef HAVE_VASPRINTF
+ int mat_vasprintf(char **ptr, const char *format, va_list ap)
+{
+        int ret;
+        va_list ap2;
+
+        VA_COPY(ap2, ap);
+        
+        ret = mat_vsnprintf(NULL, 0, format, ap2);
+        if (ret <= 0) return ret;
+
+        (*ptr) = (char *)malloc(ret+1);
+        if (!*ptr) return -1;
+
+        VA_COPY(ap2, ap);
+
+        ret = mat_vsnprintf(*ptr, ret+1, format, ap2);
+
+        return ret;
+}
+#else
+int mat_vasprintf(char **ptr, const char *format, va_list ap)
+{
+    return vasprintf(ptr,format,ap);
+}
+#endif
+
+int mat_asprintf(char **ptr, const char *format, ...)
+{
+        va_list ap;
+        int ret;
+        
+        *ptr = NULL;
+        va_start(ap, format);
+        ret = mat_vasprintf(ptr, format, ap);
+        va_end(ap);
+
+        return ret;
+}