Browse Source

Merge branch 'master', remote branch 'origin/master'

Alexander Freytag 12 years ago
parent
commit
59cf2573fe
52 changed files with 32352 additions and 1467 deletions
  1. 3 85
      baselib/ICETools.cpp
  2. 3 3
      baselib/ICETools.h
  3. 2 2
      cbaselib/ClassNames.cpp
  4. 1 1
      cbaselib/LabeledFileList.cpp
  5. 262 262
      cbaselib/MultiDataset.cpp
  6. 1 2
      classifier/fpclassifier/logisticregression/FPCSMLR.cpp
  7. 173 0
      classifier/kernelclassifier/KCGPApproxOneClass.cpp
  8. 64 0
      classifier/kernelclassifier/KCGPApproxOneClass.h
  9. 1 3
      classifier/vclassifier/VCDTSVM.cpp
  10. 221 221
      features/localfeatures/LFColorSande.cpp
  11. 49 49
      features/localfeatures/LFColorSande.h
  12. 15 0
      features/localfeatures/LFColorWeijer.cpp
  13. 19 19
      features/localfeatures/progs/testColorWeijer.cpp
  14. 8 48
      math/cluster/SpectralCluster.cpp
  15. 0 4
      math/cluster/SpectralCluster.h
  16. 694 762
      math/kernels/KernelData.cpp
  17. 1 1
      math/kernels/KernelData.h
  18. 143 0
      matlabAccess/ImageNetData.cpp
  19. 110 0
      matlabAccess/ImageNetData.h
  20. 8 0
      matlabAccess/Makefile
  21. 103 0
      matlabAccess/Makefile.inc
  22. 657 0
      matlabAccess/MatFileIO.cpp
  23. 134 0
      matlabAccess/MatFileIO.h
  24. 1 0
      matlabAccess/libdepend.inc
  25. 103 0
      matlabAccess/matio/Makefile.inc
  26. 79 0
      matlabAccess/matio/README
  27. BIN
      matlabAccess/matio/src/.libs/libmatio.a
  28. 1 0
      matlabAccess/matio/src/.libs/libmatio.la
  29. 41 0
      matlabAccess/matio/src/.libs/libmatio.lai
  30. 103 0
      matlabAccess/matio/src/Makefile.inc
  31. 248 0
      matlabAccess/matio/src/endian.c
  32. 840 0
      matlabAccess/matio/src/inflate.c
  33. 423 0
      matlabAccess/matio/src/io.c
  34. 1932 0
      matlabAccess/matio/src/mat.c
  35. 744 0
      matlabAccess/matio/src/mat4.c
  36. 30 0
      matlabAccess/matio/src/mat4.h
  37. 7103 0
      matlabAccess/matio/src/mat5.c
  38. 7103 0
      matlabAccess/matio/src/mat5.c.orig
  39. 62 0
      matlabAccess/matio/src/mat5.h
  40. 323 0
      matlabAccess/matio/src/matio.h
  41. 55 0
      matlabAccess/matio/src/matioConfig.h
  42. 92 0
      matlabAccess/matio/src/matio_private.h
  43. 5285 0
      matlabAccess/matio/src/read_data.c
  44. 852 0
      matlabAccess/matio/src/snprintf.c
  45. 1 1
      optimization/quadprog/QuadProg++.cpp
  46. 46 0
      progs/ImagenetBinary.conf
  47. 1000 0
      progs/approxVarNoise.txt
  48. 1000 0
      progs/approxVarSigma.txt
  49. 9 4
      progs/libdepend.inc
  50. 149 0
      progs/testImageNetBinary.cpp
  51. 1775 0
      progs/testImageNetBinaryBruteForce.cpp
  52. 280 0
      progs/testImageNetBinaryGPBaseline.cpp

+ 3 - 85
baselib/ICETools.cpp

@@ -10,6 +10,7 @@
 #include "core/vector/MatrixT.h"
 #include <core/imagedisplay/ImageDisplay.h>
 #include <core/image/Filter.h>
+#include <core/image/Convert.h>
 
 #include <iostream>
 
@@ -100,97 +101,14 @@ void ICETools::selectPoints ( const NICE::Image & panel, NICE::Image & overlay,
 
 }
 
-void ICETools::toColor ( double x, double & r, double & g, double & b )
-{
-  size_t seg = ( size_t ) ( x * 6.0 );
-  double y   = ( 6 * x - seg );
-
-  switch ( seg ) {
-    case 0:
-      r = 0.0;
-      g = 0.0;
-      b = y;
-      break;
-    case 1:
-      r = 0.0;
-      g =  y;
-      b = 1.0;
-      break;
-    case 2:
-      r = 0.0;
-      g = 1.0;
-      b = 1.0 - y;
-      break;
-    case 3:
-      r =  y;
-      g = 1.0;
-      b = 0.0;
-      break;
-    case 4:
-      r = 1.0;
-      g = 1.0 - y;
-      b = 0.0;
-      break;
-    case 5:
-      r = 1.0;
-      g = y;
-      b = y;
-      break;
-    default:
-      r = 1.0;
-      g = 1.0;
-      b = 1.0;
-      break;
-  }
-}
-
 void ICETools::convertToRGB ( const NICE::Matrix & m, NICE::ColorImage & img )
 {
-  img.resize ( m.cols(), m.rows() );
-  double max = - numeric_limits<double>::max();
-  double min = numeric_limits<double>::max();
-  for ( size_t x = 0 ; x < ( size_t ) m.cols(); x++ )
-    for ( size_t y = 0 ; y < ( size_t ) m.rows() ; y++ )
-    {
-      if ( m ( y, x ) > max ) max = m ( y, x );
-      if ( m ( y, x ) < min ) min = m ( y, x );
-    }
-cout << "max: " << max << " min: " << min << endl;
-  for ( size_t y = 0 ; y < ( size_t ) m.rows() ; y++ )
-    for ( size_t x = 0 ; x < ( size_t ) m.cols(); x++ )
-    {
-      double val = ( m ( y, x ) - min ) / ( max - min );
-      double r, g, b;
-      toColor ( val, r, g, b );
-      img.setPixel ( x, y, 0, ( int ) ( r*255 ) );
-      img.setPixel ( x, y, 1, ( int ) ( g*255 ) );
-      img.setPixel ( x, y, 2, ( int ) ( b*255 ) );
-    }
+  matrixToPseudoColor(m, img);
 }
 
 void ICETools::convertToRGB ( const NICE::FloatImage & m, NICE::ColorImage & img )
 {
-  img.resize ( m.width(), m.height() );
-  double max = - numeric_limits<double>::max();
-  double min = numeric_limits<double>::max();
-  for ( size_t x = 0 ; x < ( size_t ) m.width(); x++ )
-    for ( size_t y = 0 ; y < ( size_t ) m.height() ; y++ )
-    {
-      double v = m.getPixel ( x, y );
-      if ( v > max ) max = v;
-      if ( v < min ) min = v;
-    }
-
-  for ( size_t y = 0 ; y < ( size_t ) m.height() ; y++ )
-    for ( size_t x = 0 ; x < ( size_t ) m.width(); x++ )
-    {
-      double val = ( m.getPixel ( x, y ) - min ) / ( max - min );
-      double r, g, b;
-      toColor ( val, r, g, b );
-      img.setPixel ( x, y, 0, ( int ) ( r*255 ) );
-      img.setPixel ( x, y, 1, ( int ) ( g*255 ) );
-      img.setPixel ( x, y, 2, ( int ) ( b*255 ) );
-    }
+  imageToPseudoColor(m, img);
 }
 
 void ICETools::calcGrayImage ( const NICE::ColorImage & img, NICE::Image & imgg )

+ 3 - 3
baselib/ICETools.h

@@ -49,19 +49,19 @@ class ICETools
     static void selectPoints ( const NICE::Image & panel, NICE::Image & overlay,
                                std::vector<NICE::Vector> & x, int color );
 
-    /** convert a double image to a pseudocolor rgb image
+    /** convert a double image to a pseudocolor rgb image (DEPRECATED)
         @param m input double image
         @param img resulting pseudocolor rgb image
     */
     static void convertToRGB ( const NICE::FloatImage & m, NICE::ColorImage & img );
 
-    /** convert a matrix to a pseudocolor rgb image
+    /** convert a matrix to a pseudocolor rgb image (DEPRECATED)
         @param m input double image
         @param img resulting pseudocolor rgb image
     */
     static void convertToRGB ( const NICE::Matrix & m, NICE::ColorImage & img );
 
-    /** convert a single double value to a pseudocolor
+    /** convert a single double value to a pseudocolor (DEPRECATED)
         @param x input double value
         @param r resulting red value
         @param g resulting green value

+ 2 - 2
cbaselib/ClassNames.cpp

@@ -17,10 +17,10 @@
 
 #include "vislearning/cbaselib/ClassNames.h"
 #include "core/basics/StringTools.h"
+#include "core/image/ImageTools.h"
 #include "vislearning/baselib/ICETools.h"
 
 using namespace OBJREC;
-
 using namespace std;
 using namespace NICE;
 
@@ -374,7 +374,7 @@ void ClassNames::getRGBColor ( int classno, int & r, int & g, int & b ) const
     getchar();
     double x = classno / ( double ) numClasses();
     double rd, gd, bd;
-    ICETools::toColor ( x, rd, gd, bd );
+    convertToPseudoColor ( x, rd, gd, bd );
     r = ( int ) ( 255 * rd );
     g = ( int ) ( 255 * gd );
     b = ( int ) ( 255 * bd );

+ 1 - 1
cbaselib/LabeledFileList.cpp

@@ -24,7 +24,7 @@ using namespace NICE;
 
 LabeledFileList::LabeledFileList()
 {
-  debug_dataset = false;
+  debug_dataset = true;
 }
 
 LabeledFileList::~LabeledFileList()

+ 262 - 262
cbaselib/MultiDataset.cpp

@@ -1,4 +1,4 @@
-/** 
+/**
 * @file MultiDataset.cpp
 * @brief multiple datasets
 * @author Erik Rodner
@@ -25,300 +25,300 @@ using namespace NICE;
 #undef DEBUG_MultiDataset
 
 void MultiDataset::selectExamples ( const std::string & examples_command,
-		      const LabeledSet & base,
-		      LabeledSet & positives,
-		      LabeledSet & negatives,
-		      const ClassNames & cn ) const
+                                    const LabeledSet & base,
+                                    LabeledSet & positives,
+                                    LabeledSet & negatives,
+                                    const ClassNames & cn ) const
 {
-    vector<string> examples;
-    StringTools::split ( examples_command, ';', examples );
-    set<int> processed_classes;
-
-    for ( vector<string>::const_iterator i  = examples.begin();
-					 i != examples.end();
-					 i++ )
+  vector<string> examples;
+  StringTools::split ( examples_command, ';', examples );
+  set<int> processed_classes;
+
+  for ( vector<string>::const_iterator i  = examples.begin();
+        i != examples.end();
+        i++ )
+  {
+    const std::string & cmd = *i;
+    vector<string> parts;
+    StringTools::split ( cmd, ' ', parts );
+
+    if ( (parts.size() != 3) && ((parts.size() != 2) || (parts[0] != "all")) )
+      fthrow( Exception, "Syntax error " << examples_command );
+
+    const std::string & mode = parts[0];
+    const std::string & csel = parts[1];
+    double parameter = (parts.size() == 3 ) ? atof(parts[2].c_str()) : 0.0;
+    map<int, int> fpe;
+
+    set<int> selection;
+    cn.getSelection ( csel, selection );
+    for ( set<int>::const_iterator j  = selection.begin();
+          j != selection.end();
+          j++ )
     {
-		const std::string & cmd = *i;
-		vector<string> parts;
-		StringTools::split ( cmd, ' ', parts );
-		
-		if ( (parts.size() != 3) && ((parts.size() != 2) || (parts[0] != "all")) ) 
-			fthrow( Exception, "Syntax error " << examples_command );
-		
-		const std::string & mode = parts[0];
-		const std::string & csel = parts[1];
-		double parameter = (parts.size() == 3 ) ? atof(parts[2].c_str()) : 0.0;
-		map<int, int> fpe;
-
-		set<int> selection;
-		cn.getSelection ( csel, selection );
-		for ( set<int>::const_iterator j  = selection.begin();
-						   j != selection.end();
-						   j++ )
-		{
-			int classno = *j;
-			if ( processed_classes.find(classno) == processed_classes.end() )
-			{
+      int classno = *j;
+      if ( processed_classes.find(classno) == processed_classes.end() )
+      {
 #ifdef DEBUG_MultiDataset
-				fprintf (stderr, "class %s: %s %d\n", cn.text(classno).c_str(),
-					mode.c_str(), (int)parameter );
+        fprintf (stderr, "class %s: %s %d\n", cn.text(classno).c_str(),
+                 mode.c_str(), (int)parameter );
 #endif
-				fpe[*j] = (int)parameter;
-				processed_classes.insert(classno);
-			} else {
-				if ( csel != "*" ) {
-					fthrow ( Exception, "Example selection method for class %s has multiple specifications" << cn.text(classno) );
-				}
-			}
-		}
-
-		if ( mode == "seq" ) {
-			LabeledSetSelection<LabeledSet>::selectSequential ( 
-			fpe, base, positives, negatives );   
+        fpe[*j] = (int)parameter;
+        processed_classes.insert(classno);
+      } else {
+        if ( csel != "*" ) {
+          fthrow ( Exception, "Example selection method for class %s has multiple specifications" << cn.text(classno) );
+        }
+      }
+    }
+
+    if ( mode == "seq" ) {
+      LabeledSetSelection<LabeledSet>::selectSequential (
+        fpe, base, positives, negatives );
 #ifdef DEBUG_MultiDataset
-			fprintf (stderr, "MultiDataset: after special seq selection: %d\n", positives.count() );
+      fprintf (stderr, "MultiDataset: after special seq selection: %d\n", positives.count() );
 #endif
-		} else if ( mode == "step" ) {
-			LabeledSetSelection<LabeledSet>::selectSequentialStep ( 
-			fpe, base, positives, negatives );   
+    } else if ( mode == "step" ) {
+      LabeledSetSelection<LabeledSet>::selectSequentialStep (
+        fpe, base, positives, negatives );
 #ifdef DEBUG_MultiDataset
-			fprintf (stderr, "MultiDataset: after special step selection: %d\n", positives.count() );
+      fprintf (stderr, "MultiDataset: after special step selection: %d\n", positives.count() );
 #endif
-		} else if ( mode == "random" ) {
-			LabeledSetSelection<LabeledSet>::selectRandom ( 
-			fpe, base, positives, negatives );   
+    } else if ( mode == "random" ) {
+      LabeledSetSelection<LabeledSet>::selectRandom (
+        fpe, base, positives, negatives );
 #ifdef DEBUG_MultiDataset
-			fprintf (stderr, "MultiDataset: after special random selection: %d\n", positives.count() );
+      fprintf (stderr, "MultiDataset: after special random selection: %d\n", positives.count() );
 #endif
-		} else if ( mode == "all" ) {
-			if ( (int)selection.size() == cn.numClasses() ) 
-			{
-				// preserve permutation
-				LabeledSet::Permutation permutation;
-				base.getPermutation ( permutation );
-				for ( LabeledSet::Permutation::iterator i = permutation.begin(); i != permutation.end(); i++ )
-				{
-					int classno = i->first;
-					ImageInfo *element = const_cast< ImageInfo * > ( i->second );
-					positives.add_reference ( classno, element );
-				}
-			} else {
-				LabeledSetSelection<LabeledSet>::selectClasses ( selection, base, positives, negatives );
-			}
+    } else if ( mode == "all" ) {
+      if ( (int)selection.size() == cn.numClasses() )
+      {
+        // preserve permutation
+        LabeledSet::Permutation permutation;
+        base.getPermutation ( permutation );
+        for ( LabeledSet::Permutation::iterator i = permutation.begin(); i != permutation.end(); i++ )
+        {
+          int classno = i->first;
+          ImageInfo *element = const_cast< ImageInfo * > ( i->second );
+          positives.add_reference ( classno, element );
+        }
+      } else {
+        LabeledSetSelection<LabeledSet>::selectClasses ( selection, base, positives, negatives );
+      }
 #ifdef DEBUG_MultiDataset
-			fprintf (stderr, "MultiDataset: after special class selection: %d\n", positives.count() );
+      fprintf (stderr, "MultiDataset: after special class selection: %d\n", positives.count() );
 #endif
-		} else {
-			fthrow ( Exception, "Wrong value for parameter example\n");
-		}
+    } else {
+      fthrow ( Exception, "Wrong value for parameter example\n");
     }
+  }
 
 #ifdef DEBUG_MultiDataset
-    fprintf (stderr, "MultiDataset: after special selection operations: %d\n", positives.count() );
+  fprintf (stderr, "MultiDataset: after special selection operations: %d\n", positives.count() );
 #endif
-    
-    set<int> allclasses;
-    cn.getSelection ( "*", allclasses );
 
-    set<int> allnegative_classes;
+  set<int> allclasses;
+  cn.getSelection ( "*", allclasses );
+
+  set<int> allnegative_classes;
 
-    // add all examples from allclasses \setminus processed_classes
-    set_difference(allclasses.begin(), allclasses.end(), processed_classes.begin(), processed_classes.end(),
-                      inserter(allnegative_classes, allnegative_classes.end()));
+  // add all examples from allclasses \setminus processed_classes
+  set_difference(allclasses.begin(), allclasses.end(), processed_classes.begin(), processed_classes.end(),
+                 inserter(allnegative_classes, allnegative_classes.end()));
 
-    LabeledSet dummy;
-    LabeledSetSelection<LabeledSet>::selectClasses ( allnegative_classes, 
-	base, negatives, dummy );
+  LabeledSet dummy;
+  LabeledSetSelection<LabeledSet>::selectClasses ( allnegative_classes,
+      base, negatives, dummy );
 
 }
 
 /** MultiDataset ------- constructor */
 MultiDataset::MultiDataset( const Config *conf )
 {
-    std::set<string> blocks;
-    conf->getAllBlocks ( blocks );
-
-    map<string, Config> dsconfs;
-    map<string, string> dirs;
-    for ( set<string>::iterator i = blocks.begin();
-	    i != blocks.end();  )
+  std::set<string> blocks;
+  conf->getAllBlocks ( blocks );
+
+  map<string, Config> dsconfs;
+  map<string, string> dirs;
+  for ( set<string>::iterator i = blocks.begin();
+        i != blocks.end();  )
+  {
+    if ( conf->gB(*i, "disable", false) )
     {
-		if ( conf->gB(*i, "disable", false) )
-		{
-			i++;
-			continue;
-		}
-
-		std::string dataset = conf->gS( *i, "dataset", "unknown" );
-		if ( dataset == "unknown" )
-			blocks.erase(i++);
-		else {
+      i++;
+      continue;
+    }
+
+    std::string dataset = conf->gS( *i, "dataset", "unknown" );
+    if ( dataset == "unknown" )
+      blocks.erase(i++);
+    else {
 #ifdef DEBUG_MultiDataset
-			fprintf (stderr, "Reading dataset config for block [%s]\n", i->c_str() );
+      fprintf (stderr, "Reading dataset config for block [%s]\n", i->c_str() );
 #endif
-			Config dsconf ( (dataset + "/dataset.conf").c_str() );
-			
-			dirs[*i] = dataset;
-			dsconfs[*i] = dsconf;
-			i++;
-		}
+      Config dsconf ( (dataset + "/dataset.conf").c_str() );
+
+      dirs[*i] = dataset;
+      dsconfs[*i] = dsconf;
+      i++;
     }
-  
-    if ( blocks.find("traintest") != blocks.end() )
+  }
+
+  if ( blocks.find("traintest") != blocks.end() )
+  {
+    LabeledSet ls_base;
+    LabeledSet ls_train (true);
+    LabeledSet ls_nontrain (true);
+    LabeledSet ls_test (true);
+    LabeledSet dummy (true);
+    LabeledSet temp (true);
+
+    bool localizationInfoDisabled = conf->gB("traintest", "disable_localization_info", false );
+
+    std::string classselection_train = conf->gS("traintest", "classselection_train", "*");
+    std::string classselection_test = conf->gS("traintest", "classselection_test", "*");
+    classnames["traintest"] = ClassNames();
+
+    std::string classNamesTxt = dirs["traintest"] + "/classnames.txt";
+    if ( FileMgt::fileExists ( classNamesTxt ) )
     {
-		LabeledSet ls_base;
-		LabeledSet ls_train (true);
-		LabeledSet ls_nontrain (true);
-		LabeledSet ls_test (true);
-		LabeledSet dummy (true);
-		LabeledSet temp (true);
-
-		bool localizationInfoDisabled = conf->gB("traintest", "disable_localization_info", false );
-
-		std::string classselection_train = conf->gS("traintest", "classselection_train", "*");
-		std::string classselection_test = conf->gS("traintest", "classselection_test", "*");
-		classnames["traintest"] = ClassNames();
-		
-		std::string classNamesTxt = dirs["traintest"] + "/classnames.txt";
-		if ( FileMgt::fileExists ( classNamesTxt ) )
-		{
-			classnames["traintest"].read ( classNamesTxt );
-		} else {
-			classnames["traintest"].readFromConfig ( dsconfs["traintest"], classselection_train );
-		}
-		
-		lfl.get ( dirs["traintest"], dsconfs["traintest"], classnames["traintest"], ls_base,
-			localizationInfoDisabled, conf->gB("traintest", "debug_dataset", false ) ); 
-
-		std::string examples_train =  conf->gS("traintest", "examples_train" );
-		selectExamples ( examples_train, ls_base, ls_train, ls_nontrain, classnames["traintest"] );
-			
-		set<int> selection_test;
-		classnames["traintest"].getSelection ( classselection_test, selection_test );
-
-		std::string examples_test =  conf->gS("traintest", "examples_test" );
-		if ( examples_test == "reclassification" )
-		{
-			LabeledSetSelection<LabeledSet>::selectClasses 
-			( selection_test, ls_train, ls_test, dummy );
-
-		} else {
-			selectExamples ( examples_test, ls_nontrain, temp, dummy, classnames["traintest"] );
-			LabeledSetSelection<LabeledSet>::selectClasses 
-			( selection_test, temp, ls_test, dummy );
-		}
-
-		classnames["train"] = classnames["traintest"];
-		classnames["test"] = ClassNames ( classnames["traintest"], classselection_test );
-		datasets["test"] = ls_test;
-		datasets["train"] = ls_train;
+      classnames["traintest"].read ( classNamesTxt );
+    } else {
+      classnames["traintest"].readFromConfig ( dsconfs["traintest"], classselection_train );
     }
 
-    for ( set<string>::const_iterator i = blocks.begin();
-				      i != blocks.end();
-				      i++ )
+    lfl.get ( dirs["traintest"], dsconfs["traintest"], classnames["traintest"], ls_base,
+              localizationInfoDisabled, conf->gB("traintest", "debug_dataset", false ) );
+
+    std::string examples_train =  conf->gS("traintest", "examples_train" );
+    selectExamples ( examples_train, ls_base, ls_train, ls_nontrain, classnames["traintest"] );
+
+    set<int> selection_test;
+    classnames["traintest"].getSelection ( classselection_test, selection_test );
+
+    std::string examples_test =  conf->gS("traintest", "examples_test" );
+    if ( examples_test == "reclassification" )
     {
-		std::string name = *i;
-		if ( classnames.find(name) != classnames.end() )
-			continue;
+      LabeledSetSelection<LabeledSet>::selectClasses
+      ( selection_test, ls_train, ls_test, dummy );
+
+    } else {
+      selectExamples ( examples_test, ls_nontrain, temp, dummy, classnames["traintest"] );
+      LabeledSetSelection<LabeledSet>::selectClasses
+      ( selection_test, temp, ls_test, dummy );
+    }
+
+    classnames["train"] = classnames["traintest"];
+    classnames["test"] = ClassNames ( classnames["traintest"], classselection_test );
+    datasets["test"] = ls_test;
+    datasets["train"] = ls_train;
+  }
 
-		if ( conf->gB(name, "disable", false) == true )
-			continue;
+  for ( set<string>::const_iterator i = blocks.begin();
+        i != blocks.end();
+        i++ )
+  {
+    std::string name = *i;
+    if ( classnames.find(name) != classnames.end() )
+      continue;
 
-		if ( dsconfs.find(name) == dsconfs.end() )
-			continue;
+    if ( conf->gB(name, "disable", false) == true )
+      continue;
 
-		LabeledSet ls_base;
-		LabeledSet ls (true);
-		LabeledSet dummy (true);
-		LabeledSet temp (true);
+    if ( dsconfs.find(name) == dsconfs.end() )
+      continue;
 
-		bool localizationInfoDisabled = conf->gB(name, "disable_localization_info", false );
+    LabeledSet ls_base;
+    LabeledSet ls (true);
+    LabeledSet dummy (true);
+    LabeledSet temp (true);
 
-		std::string classselection = conf->gS(name, "classselection", "*");
-		classnames[name] = ClassNames();
+    bool localizationInfoDisabled = conf->gB(name, "disable_localization_info", false );
 
-		std::string classNamesTxt = dirs[name] + "/classnames.txt";
-		if ( FileMgt::fileExists ( classNamesTxt ) )
-		{
+    std::string classselection = conf->gS(name, "classselection", "*");
+    classnames[name] = ClassNames();
+
+    std::string classNamesTxt = dirs[name] + "/classnames.txt";
+    if ( FileMgt::fileExists ( classNamesTxt ) )
+    {
 #ifdef DEBUG_MultiDataset
-			fprintf (stderr, "MultiDataset: reading class names from %s\n", classNamesTxt.c_str() );
+      fprintf (stderr, "MultiDataset: reading class names from %s\n", classNamesTxt.c_str() );
 #endif
-			classnames[name].read ( classNamesTxt );
-		} else {
+      classnames[name].read ( classNamesTxt );
+    } else {
 #ifdef DEBUG_MultiDataset
-			fprintf (stderr, "MultiDataset: reading class names from dataset config file\n" );
+      fprintf (stderr, "MultiDataset: reading class names from dataset config file\n" );
 #endif
-			classnames[name].readFromConfig ( dsconfs[name], classselection );
-		}
-		
-		lfl.get ( dirs[name], dsconfs[name], classnames[name], ls_base,
-			localizationInfoDisabled, conf->gB(name, "debug_dataset", false ) ); 
+      classnames[name].readFromConfig ( dsconfs[name], classselection );
+    }
+
+    lfl.get ( dirs[name], dsconfs[name], classnames[name], ls_base,
+              localizationInfoDisabled, conf->gB(name, "debug_dataset", false ) );
 #ifdef DEBUG_MultiDataset
-		fprintf (stderr, "MultiDataset: class names -->\n" );
-		classnames[name].store ( cerr );
-		fprintf (stderr, "MultiDataset: all information about %s set obtained ! (size %d)\n", name.c_str(), ls_base.count() );
+    fprintf (stderr, "MultiDataset: class names -->\n" );
+    classnames[name].store ( cerr );
+    fprintf (stderr, "MultiDataset: all information about %s set obtained ! (size %d)\n", name.c_str(), ls_base.count() );
 #endif
 
-		std::string examples = conf->gS(name, "examples", "all *" );
-		selectExamples ( examples, ls_base, ls, dummy, classnames[name] );
-		
+    std::string examples = conf->gS(name, "examples", "all *" );
+    selectExamples ( examples, ls_base, ls, dummy, classnames[name] );
+
 #ifdef DEBUG_MultiDataset
-		fprintf (stderr, "MultiDataset: size after selection %d\n", ls.count() );
+    fprintf (stderr, "MultiDataset: size after selection %d\n", ls.count() );
 #endif
 
-		datasets[name] = ls;
-    }
+    datasets[name] = ls;
+  }
 
-    bool dumpSelections = conf->gB("datasets", "dump_selection", false);
-    if ( dumpSelections )
+  bool dumpSelections = conf->gB("datasets", "dump_selection", false);
+  if ( dumpSelections )
+  {
+    for ( map<string, LabeledSet>::const_iterator i = datasets.begin();
+          i != datasets.end(); i++ )
     {
-		for ( map<string, LabeledSet>::const_iterator i = datasets.begin();
-			i != datasets.end(); i++ )
-		{
-			const std::string & name = i->first;
-			const LabeledSet & ls = i->second;
-			const ClassNames & classNames = classnames[name];
-
-			mkdir ( name.c_str(), 0755 );
-
-			std::string filelist = name + "/files.txt";
-			ofstream olist ( filelist.c_str(), ios::out );
-			if ( !olist.good() )
-				fthrow (IOException, "Unable to dump selections to " << filelist );
-			
-			LOOP_ALL_S(ls)
-			{
-				EACH_S(classno, file);
-				std::string classtext = classNames.code(classno);
-				olist << classtext << " " << file << endl;
-			}
-			olist.close();
-
-			std::string datasetconf = name + "/dataset.conf";
-			ofstream oconf ( datasetconf.c_str(), ios::out );
-			if ( !oconf.good() )
-				fthrow (IOException, "Unable to dump selections to " << datasetconf );
-
-			set<int> classnos;
-			classNames.getSelection ( "*", classnos);
-
-			oconf << "[main]" << endl;
-			oconf << "filelist = \"files.txt\"" << endl << endl;
-
-			oconf << "[classnames]" << endl;
-			for ( set<int>::const_iterator i = classnos.begin();
-					i != classnos.end(); i++ )
-			{
-				const std::string & code = classNames.code(*i);
-				const std::string & text = classNames.text(*i);
-				oconf << code << "     =     \"" << text << "\"" << endl;
-			}
-			oconf.close();
-			
-			classNames.save ( name + "/classnames.txt" );
-		}
+      const std::string & name = i->first;
+      const LabeledSet & ls = i->second;
+      const ClassNames & classNames = classnames[name];
+
+      mkdir ( name.c_str(), 0755 );
+
+      std::string filelist = name + "/files.txt";
+      ofstream olist ( filelist.c_str(), ios::out );
+      if ( !olist.good() )
+        fthrow (IOException, "Unable to dump selections to " << filelist );
+
+      LOOP_ALL_S(ls)
+      {
+        EACH_S(classno, file);
+        std::string classtext = classNames.code(classno);
+        olist << classtext << " " << file << endl;
+      }
+      olist.close();
+
+      std::string datasetconf = name + "/dataset.conf";
+      ofstream oconf ( datasetconf.c_str(), ios::out );
+      if ( !oconf.good() )
+        fthrow (IOException, "Unable to dump selections to " << datasetconf );
+
+      set<int> classnos;
+      classNames.getSelection ( "*", classnos);
+
+      oconf << "[main]" << endl;
+      oconf << "filelist = \"files.txt\"" << endl << endl;
+
+      oconf << "[classnames]" << endl;
+      for ( set<int>::const_iterator i = classnos.begin();
+            i != classnos.end(); i++ )
+      {
+        const std::string & code = classNames.code(*i);
+        const std::string & text = classNames.text(*i);
+        oconf << code << "     =     \"" << text << "\"" << endl;
+      }
+      oconf.close();
+
+      classNames.save ( name + "/classnames.txt" );
     }
+  }
 
 }
 
@@ -328,32 +328,32 @@ MultiDataset::~MultiDataset()
 
 const ClassNames & MultiDataset::getClassNames ( const std::string & key ) const
 {
-    map<string, ClassNames>::const_iterator i = classnames.find(key);
-    if ( i == classnames.end() )
-    {
-	fprintf (stderr, "MultiDataSet::getClassNames() FATAL ERROR: dataset <%s> not found !\n", key.c_str() );
-	exit(-1);
-    } 
-    return (i->second);
+  map<string, ClassNames>::const_iterator i = classnames.find(key);
+  if ( i == classnames.end() )
+  {
+    fprintf (stderr, "MultiDataSet::getClassNames() FATAL ERROR: dataset <%s> not found !\n", key.c_str() );
+    exit(-1);
+  }
+  return (i->second);
 
 }
 
 const LabeledSet *MultiDataset::operator[] ( const std::string & key ) const
 {
-    map<string, LabeledSet>::const_iterator i = datasets.find(key);
-    if ( i == datasets.end() )
-    {
-	fprintf (stderr, "MultiDataSet: FATAL ERROR: dataset <%s> not found !\n", key.c_str() );
-	exit(-1);
-    } 
-    return &(i->second);
+  map<string, LabeledSet>::const_iterator i = datasets.find(key);
+  if ( i == datasets.end() )
+  {
+    fprintf (stderr, "MultiDataSet: FATAL ERROR: dataset <%s> not found !\n", key.c_str() );
+    exit(-1);
+  }
+  return &(i->second);
 }
 
 const LabeledSet *MultiDataset::at ( const std::string & key ) const
 {
-    map<string, LabeledSet>::const_iterator i = datasets.find(key);
-    if ( i == datasets.end() )
-	return NULL;
-    else
-	return &(i->second);
+  map<string, LabeledSet>::const_iterator i = datasets.find(key);
+  if ( i == datasets.end() )
+    return NULL;
+  else
+    return &(i->second);
 }

+ 1 - 2
classifier/fpclassifier/logisticregression/FPCSMLR.cpp

@@ -28,8 +28,7 @@ FPCSMLR::~FPCSMLR()
 
 ClassificationResult FPCSMLR::classify ( Example & pce )
 {
-  FullVector overall_distribution ( maxClassNo + 1 );
-  overall_distribution[maxClassNo] = 0.0;
+  FullVector overall_distribution ( maxClassNo);
 
   double maxp = -numeric_limits<double>::max();
   int classno = 0;

+ 173 - 0
classifier/kernelclassifier/KCGPApproxOneClass.cpp

@@ -0,0 +1,173 @@
+/** 
+* @file KCGPApproxOneClass.cpp
+* @brief One-Class Gaussian Process Regression for Classification: we approximate the inverse of the regularized kernel matrix using a diagonal matrix
+* @author Alexander Lütz
+* @date 22-05-2012 (dd-mm-yyyy)
+
+*/
+#include <iostream>
+#include <typeinfo>
+#include <cstring>
+
+#include "core/vector/Algorithms.h"
+#include "core/vector/VVector.h"
+
+#include "KCGPApproxOneClass.h"
+
+
+using namespace std;
+using namespace NICE;
+using namespace OBJREC;
+
+
+KCGPApproxOneClass::KCGPApproxOneClass( const Config *conf, Kernel *kernel, const string & section ) : KernelClassifier ( conf, kernel )
+{
+//   this->kernelFunction = kernel;  
+  //overwrite the default optimization options, since we don't want to perform standard loo or marginal likelihood stuff
+  Config config(*conf);
+  string modestr = config.gS(section,"detection_mode"); 
+
+  if(strcmp("mean",modestr.c_str())==0){
+    this->mode=MEAN_DETECTION_MODE;cerr << "One-class classification via GP predictive _mean_ !!!"<<endl;
+  }
+  if(strcmp("variance",modestr.c_str())==0){
+    mode=VARIANCE_DETECTION_MODE;cerr << "One-class classification via GP predictive _variance_ !!!"<<endl;
+  }
+
+  this->staticNoise = conf->gD(section, "static_noise", 0.0);
+}
+
+
+
+KCGPApproxOneClass::KCGPApproxOneClass( const KCGPApproxOneClass & src ) : KernelClassifier ( src )
+{
+  this->matrixDInv = src.matrixDInv;
+  this->InvDY = src.InvDY;
+  this->mode = src.mode;
+  this->staticNoise = src.staticNoise;
+}
+
+KCGPApproxOneClass::~KCGPApproxOneClass()
+{
+}
+
+
+void KCGPApproxOneClass::teach ( KernelData *kernelData, const NICE::Vector & y )
+{
+    fthrow( Exception, "KCGPApproxOneClass::teach: this method is not implemented for this specific type of classifier. Please use the second teach-method." );  
+}
+
+void KCGPApproxOneClass::teach (const LabeledSetVector &teachSet)
+{
+  if ( this->kernelFunction == NULL )
+    fthrow( Exception, "KernelClassifier::teach: To use this function, you have to specify a kernel function using the constructor" );  
+  
+  //we do not have to allocate new storage here since these variables come from the interface KernelClassifier
+//   NICE::VVector vecSet;
+
+  teachSet.getFlatRepresentation (this->vecSet, this->vecSetLabels);
+    
+  if ( (this->vecSetLabels.Min() != 1) || (this->vecSetLabels.Max() != 1) ) {
+    fthrow(Exception, "This classifier is suitable only for one-class classification problems, i.e. max(y) = min(y) = 1");
+  }  
+
+  this->matrixDInv.resize(this->vecSetLabels.size());
+ 
+  //compute D 
+  //start with adding some noise, if necessary
+  if (this->staticNoise != 0.0)
+    this->matrixDInv.set(this->staticNoise);
+  else
+    this->matrixDInv.set(0.0);
+  
+  //now sum up all entries of each row in the original kernel matrix
+  double kernelScore(0.0);
+  for (int i = 0; i < this->vecSetLabels.size(); i++)
+  {
+    for (int j = i; j < this->vecSetLabels.size(); j++)
+    {
+      kernelScore = this->kernelFunction->K(vecSet[i],vecSet[j]);
+      this->matrixDInv[i] += kernelScore;
+      if (i != j)
+        this->matrixDInv[j] += kernelScore; 
+    }
+  }  
+  
+  //compute its inverse
+  for (int i = 0; i < this->vecSetLabels.size(); i++)
+  {
+    this->matrixDInv[i] = 1.0 / this->matrixDInv[i];
+  }
+  
+  //and multiply it from right with the label vector (precalculation for mean computation)
+  if(this->mode==MEAN_DETECTION_MODE)
+  {
+    this->InvDY.resize ( this->vecSetLabels.size() );
+    for (int i = 0; i < this->vecSetLabels.size(); i++)
+    {
+      this->InvDY[i] = this->vecSetLabels[i] * this->matrixDInv[i];
+    }
+  }  
+}
+
+ClassificationResult KCGPApproxOneClass::classifyKernel ( const NICE::Vector & kernelVector, double kernelSelf ) const
+{
+  FullVector scores ( 2 );
+  scores[0] = 0.0;
+
+  if(this->mode==MEAN_DETECTION_MODE)
+  {
+    // kernelSelf is not needed for the regression type of GP
+
+    if ( kernelVector.size() != this->vecSetLabels.size() ) 
+      fthrow(Exception, "KCGPApproxOneClass::classifyKernel: size of kernel value vector " << 
+        kernelVector.size() << " does not match number of training points " << this->vecSetLabels.size() );
+      
+    double yEstimate = kernelVector.scalarProduct ( InvDY );    
+    scores[1] = yEstimate;
+  }
+  if(this->mode==VARIANCE_DETECTION_MODE)
+  {
+    if ( kernelVector.size() != this->vecSetLabels.size() ) 
+      fthrow(Exception, "KCGPApproxOneClass::classifyKernel: size of kernel value vector " << 
+        kernelVector.size() << " does not match number of training points " << this->vecSetLabels.size() );
+      
+    NICE::Vector rightPart (this->vecSetLabels.size());
+    for (int i = 0; i < this->vecSetLabels.size(); i++)
+    {
+      rightPart[i] = kernelVector[i] * this->matrixDInv[i];
+    }
+
+    double uncertainty = kernelSelf - kernelVector.scalarProduct ( rightPart );
+    scores[1] = 1.0 - uncertainty;
+
+  }
+  ClassificationResult r ( scores[1]<0.5 ? 0 : 1, scores );
+
+  return r;
+}
+
+KCGPApproxOneClass *KCGPApproxOneClass::clone() const
+{
+  return new KCGPApproxOneClass ( *this );
+}
+
+void KCGPApproxOneClass::store(std::ostream& ofs, int type) const
+{
+  ofs << this->matrixDInv << std::endl;
+  ofs << this->InvDY << std::endl;
+  ofs << this->mode << std::endl;
+  ofs << this->staticNoise << std::endl;
+}
+
+void KCGPApproxOneClass::restore(std::istream& ifs, int type)
+{
+  ifs >> this->matrixDInv;
+  ifs >> this->InvDY;
+  ifs >> this->mode;
+  ifs >> this->staticNoise;
+} 
+
+void KCGPApproxOneClass::clear()
+{
+}

+ 64 - 0
classifier/kernelclassifier/KCGPApproxOneClass.h

@@ -0,0 +1,64 @@
+/** 
+* @file KCGPApproxOneClass.h
+* @brief One-Class Gaussian Process Regression for Classification: we approximate the inverse of the regularized kernel matrix using a diagonal matrix
+* @author Alexander Lütz
+* @date 22-05-2012 (dd-mm-yyyy)
+
+*/
+#ifndef KCGPAPPROXONECLASSINCLUDE
+#define KCGPAPPROXONECLASSINCLUDE
+
+#include "vislearning/cbaselib/ClassificationResult.h"
+
+#include "vislearning/classifier/classifierbase/KernelClassifier.h"
+
+#include "vislearning/math/kernels/Kernel.h"
+
+
+#define VARIANCE_DETECTION_MODE 1
+#define MEAN_DETECTION_MODE 2
+
+namespace OBJREC {
+ 
+  class KCGPApproxOneClass : public KernelClassifier
+  {
+
+      protected:
+        NICE::Vector matrixDInv;
+        NICE::Vector InvDY;
+        int mode;
+        double staticNoise;
+      
+
+      public:
+    
+        /** simple constructor */
+        KCGPApproxOneClass( const NICE::Config *conf, Kernel *kernel = NULL, const std::string & section = "OneClassGP" );
+
+        /** copy constructor */
+        KCGPApproxOneClass( const KCGPApproxOneClass & src );
+            
+        /** simple destructor */
+        virtual ~KCGPApproxOneClass();
+          
+        /** teach the classifier with a kernel matrix and the corresponding class labels @param y ! */
+        void teach ( KernelData *kernelData, const NICE::Vector & y );
+        
+        void teach (const LabeledSetVector &teachSet);
+          
+        /** classify an example by using its kernel values with the training set,
+          be careful with the order in @param kernelVector */
+        virtual ClassificationResult classifyKernel ( const NICE::Vector & kernelVector, double kernelSelf ) const;
+        
+          /** clone this object */
+        KCGPApproxOneClass *clone() const;
+
+        void restore(std::istream&, int);
+        void store(std::ostream&, int) const;
+        void clear();
+
+  };
+
+}
+
+#endif

+ 1 - 3
classifier/vclassifier/VCDTSVM.cpp

@@ -119,9 +119,7 @@ ClassificationResult VCDTSVM::classify ( const NICE::Vector & x ) const
     }
   }
   return ClassificationResult ( bclass, scores );
-#endif
-
-#ifndef WRITE
+#else
   int c2 = ( *counter ) [0];
   ( *counter ) [0]++;
   FullVector tmp ( results[c2].size() );

+ 221 - 221
features/localfeatures/LFColorSande.cpp

@@ -1,4 +1,4 @@
-/** 
+/**
 * @file LFColorSande.cpp
 * @brief interface to ColorSande implementation
 * @author Erik Rodner
@@ -28,40 +28,40 @@ using namespace NICE;
 
 
 
-LFColorSande::LFColorSande( const Config *conf, std::string section )
+LFColorSande::LFColorSande ( const Config *conf, std::string section )
 {
-    c_binaryExecutable = conf->gS( section, "binaryExecutable", "/home/bachi/libs/van_de_sande/x86_64-linux-gcc/colorDescriptor" );
-    c_params = conf->gS(section, "params", "--descriptor opponentsift");
-	scales = conf->gS(section, "scales", "1+1.5+3.0+4.5+6");
-	
-	descriptor_size = conf->gI(section, "descriptor_size", -1 );
-    
-	usegrid = conf->gB(section, "usegrid", false);
-	
-	int g = conf->gI( section, "grid", 5);
-	std::ostringstream temp;
-	temp << g;
-	gridsize = temp.str();
-	
-    if ( descriptor_size <= 0 ) 
-    {
-		fprintf (stderr, "LFColorSande::LFColorSande: No descriptor size found in config -> self test\n");
-		/** get feature dimension **/
-		NICE::Image testimg (DESCSIZE_DUMMY);
-		VVector features;
-		VVector positions;
-		extractFeatures ( testimg, features, positions );
-		if ( features.size() <= 0 )
-			fthrow( Exception, "No features found in " << DESCSIZE_DUMMY << " picture.");
-		descriptor_size = features[0].size();
-
-		fprintf (stderr, "LFColorSande::LFColorSande Self Test features:%d dimension:%d\n", (int)features.size(), descriptor_size );
-    }
-
-    if ( descriptor_size != conf->gI("features", "descriptor_size", descriptor_size) )
-    {
-		cerr << "Warning: LFColorSande: descriptor sizes do not match !!!" << endl;
-	}
+  c_binaryExecutable = conf->gS ( section, "binaryExecutable", "/home/bachi/libs/van_de_sande/x86_64-linux-gcc/colorDescriptor" );
+  c_params = conf->gS ( section, "params", "--descriptor opponentsift" );
+  scales = conf->gS ( section, "scales", "1+1.5+3.0+4.5+6" );
+
+  descriptor_size = conf->gI ( section, "descriptor_size", -1 );
+
+  usegrid = conf->gB ( section, "usegrid", false );
+
+  int g = conf->gI ( section, "grid", 5 );
+  std::ostringstream temp;
+  temp << g;
+  gridsize = temp.str();
+
+  if ( descriptor_size <= 0 )
+  {
+    fprintf ( stderr, "LFColorSande::LFColorSande: No descriptor size found in config -> self test\n" );
+    /** get feature dimension **/
+    NICE::Image testimg ( DESCSIZE_DUMMY );
+    VVector features;
+    VVector positions;
+    extractFeatures ( testimg, features, positions );
+    if ( features.size() <= 0 )
+      fthrow ( Exception, "No features found in " << DESCSIZE_DUMMY << " picture." );
+    descriptor_size = features[0].size();
+
+    fprintf ( stderr, "LFColorSande::LFColorSande Self Test features:%d dimension:%d\n", ( int ) features.size(), descriptor_size );
+  }
+
+  if ( descriptor_size != conf->gI ( "features", "descriptor_size", descriptor_size ) )
+  {
+    cerr << "Warning: LFColorSande: descriptor sizes do not match !!!" << endl;
+  }
 }
 
 LFColorSande::~LFColorSande()
@@ -70,199 +70,199 @@ LFColorSande::~LFColorSande()
 
 int LFColorSande::getDescSize () const
 {
-    return descriptor_size;
+  return descriptor_size;
 }
 
-int LFColorSande::extractFeatures ( const NICE::Image & img, VVector & features, 
-				     VVector & positions ) const
+int LFColorSande::extractFeatures ( const NICE::Image & img, VVector & features,
+                                    VVector & positions ) const
 {
-	cerr << "Warning: LFColorSande is a color local feature implementation, but you are calling the gray-image version of extractFeatures" << endl;
-	NICE::ColorImage colorimg;
-	NICE::grayToRGB (img, &colorimg);
-	extractFeatures( colorimg, features, positions);
+  cerr << "Warning: LFColorSande is a color local feature implementation, but you are calling the gray-image version of extractFeatures" << endl;
+  NICE::ColorImage colorimg;
+  NICE::grayToRGB ( img, &colorimg );
+  extractFeatures ( colorimg, features, positions );
 
-	return 0;
+  return 0;
 }
 
 int LFColorSande::extractFeatures ( const NICE::ColorImage & img, VVector & features, VVector & positions ) const
 {
-	if(features.size() != positions.size())
-	{
-		positions.clear();
-	}
-	
-	bool delete_imgfile = false;
-	std::string imgfile = Globals::getCurrentImgFN();
-
-	fprintf (stderr, "imgfile: %s\n", imgfile.c_str());
-	if ( (imgfile.size() <= 0) || (( !StringTools::regexMatch ( imgfile, ".[Jj][pP][Gg]$" ) ) 
-		     && ( !StringTools::regexMatch ( imgfile, ".[Pp][Nn][Gg]$" ))))
-	{
-		
-		if ( imgfile.size() <= 0 )
-		{
-			imgfile = FileMgt::createTempFile ( "/tmp/osl_lfColorSande_input_%s.png" );
-			fprintf (stderr, "LFColorSande: write image to %s (write image)\n", imgfile.c_str() );
-			ImageFile imgf ( imgfile );
-			imgf.writer ( &img );
-		} else {
-			std::string tmpfile = FileMgt::createTempFile ( "/tmp/osl_lfColorSande_input_%s.png" );
-			fprintf (stderr, "LFColorSande: write image to %s (convert)\n", tmpfile.c_str() );
-
-			std::string convertcall = "convert " + imgfile + " " + tmpfile;
-			cerr << "convert call: " << convertcall << endl;
-			system ( convertcall.c_str() );
-
-			imgfile = tmpfile;
-		}
-	    
-		delete_imgfile = true;
-	}
-    
-	std::string outputfn  = FileMgt::createTempFile ( "/tmp/osl_lfColorSande_output_%s" ) ;
-
-	std::string gridparams ="";
-	
-	if(usegrid)
-		gridparams = " --detector densesampling --ds_spacing " + gridsize +" --ds_scales "+scales;
-	
-	std::string call = c_binaryExecutable + " " +
-			   imgfile            + " " +   
-			   c_params           +
-			   gridparams         +
-			   " -output "        + outputfn;
-
-	cerr << "LFColorSande: parameters: <" << c_params+gridparams << ">" << endl;
-	clog << "Systemcall: " << call << endl;
-
-	
-	const int buffersize = 65536;
-	char *buffer = new char [buffersize];
-	FILE *f = popen ( call.c_str(), "r" );
-	if ( f == NULL )
-	{
-		fthrow(Exception, "Unable to run the implementation of van de Sande: " << call << endl << strerror(errno) );
-	}
-
-	while ( ! feof(f) ) 
-	{
-		if ( fgets ( buffer, buffersize, f ) <= 0 )
-		{
-			break;
-		} else {
-			fprintf (stderr, "LFColorSande::extractFeatures: [INFO] %s", buffer );
-		}
-	}
- 
-
-	pclose(f);
-
-	f = fopen ( outputfn.c_str(), "r" );
-	if ( f == NULL )
-	{
-		fthrow( Exception, "Unable to read output of van de Sande implementation\n");
-	}
-
-	if ( fgets ( buffer, buffersize, f ) <= 0 )
-	{
-		fprintf (stderr, "LFColorSande::extractFeatures: output is empty !\n");
-		fprintf (stderr, "img %s out %s\n", imgfile.c_str(), outputfn.c_str() );
-		fprintf (stderr, "call %s\n", call.c_str() );
-
-		exit(-1);
-	}
-
-	if ( ! strcmp(buffer, "KOEN1" ) ) 
-	{
-		fprintf (stderr, "LFColorSande::extractFeatures: wrong file format\n");
-		fprintf (stderr, "img %s out %s\n", imgfile.c_str(), outputfn.c_str() );
-		fprintf (stderr, "call %s\n", call.c_str() );
-
-		exit(-1);
-	}
-    
-    
-	fgets ( buffer, buffersize, f );
-	int dimension = atoi (buffer);
-	fprintf (stderr, "LFColorSande: descriptor dimension = %d\n", dimension );
-
-	if ( (descriptor_size > 0) && (dimension != descriptor_size) )
-	{
-		fprintf (stderr, "LFColorSande::extractFeatures: dimensions do not match %d -> %d!\n",
-			 dimension, descriptor_size);
-		fprintf (stderr, "img %s out %s\n", imgfile.c_str(), outputfn.c_str() );
-		fprintf (stderr, "call %s\n", call.c_str() );
-		fprintf (stderr, "dimension std::string buffer: \"%s\"", buffer );
-		exit(-1);
-	}
-
-	fgets ( buffer, buffersize, f );
-	int noDesc = atoi (buffer);
-
-	fprintf (stderr, "LFColorSande::extractFeatures: no. of descriptors = %d\n", noDesc );
- 
-	NICE::Vector x;
-	while ( ! feof(f) ) 
-	{
-	// <CIRCLE 119 307 1.26134 0 0.00014763>; 0 0 6 2 0 6 25 7 9 4 4 0 0 4 20 36 78 4 5 0 0 
-		if ( fgets(buffer, buffersize, f) == NULL )
-			break;
-
-		const char *buffer_data = strchr ( buffer, ';' );
-		if ( strlen(buffer_data) <= 0 )
-		{
-			fprintf (stderr, "LFColorSande::extractFeatures: it seems you forget to specify a descriptor\n");
-			exit(-1);
-		}
-
-		const char *buffer_key_start = strchr ( buffer, ' ' );
-		const char *buffer_key_end = strchr ( buffer, '>' );
-		buffer_key_start++;
-		int keylen = buffer_key_end - buffer_key_start;
-		char *key = new char [keylen+1];
-		strncpy ( key, buffer_key_start, keylen );
-		key[keylen] = '\0';
-
-		buffer_data+=2;
-
-		std::string buffer_data_s (buffer_data);
-
-		//clog << "[log] buffer = " << buffer_data_s << endl;		
-		
-		StringTools::splitVector ( buffer_data_s, ' ', x );
-		if ( (int)x.size() != dimension ) 
-		{
-			cerr << "Line = " << buffer_data_s << endl;
-			cerr << "Vector = " << x << endl;
-			cerr << "dimension = " << dimension << endl;
-			cerr << "x.size() = " << x.size() << endl;
-			fprintf (stderr, "LFColorSande::extractFeatures: error parsing output !!\n");
-			exit(-1);
-		} else {
-			NICE::Vector pos;
-
-			StringTools::splitVector ( key, ' ', pos );
-
-			if ( pos.size() != 5 ) {
-				fprintf (stderr, "LFColorSande::extractFeatures: dimension mismatch (position information)\n");
-				exit(-1);
-			}
-			// Van De Sande verwendet MatLab-Darstellung der Koordinaten. Diese fangen bei 1 an und nicht bei 0.
-			pos[0] --;
-			pos[1] --;
-			positions.push_back( pos );
-			features.push_back ( x );
-		}
-	}
-
-	fclose (f);
-
-	if ( delete_imgfile )
-		FileMgt::deleteTempFile ( imgfile );
-
-	FileMgt::deleteTempFile ( outputfn );
-
-	delete [] buffer;
-
-	return 0;
+  if ( features.size() != positions.size() )
+  {
+    positions.clear();
+  }
+
+  bool delete_imgfile = false;
+  std::string imgfile = Globals::getCurrentImgFN();
+
+  fprintf ( stderr, "imgfile: %s\n", imgfile.c_str() );
+  if ( ( imgfile.size() <= 0 ) || ( ( !StringTools::regexMatch ( imgfile, ".[Jj][pP][Gg]$" ) )
+                                    && ( !StringTools::regexMatch ( imgfile, ".[Pp][Nn][Gg]$" ) ) ) )
+  {
+
+    if ( imgfile.size() <= 0 )
+    {
+      imgfile = FileMgt::createTempFile ( "/tmp/osl_lfColorSande_input_%s.png" );
+      fprintf ( stderr, "LFColorSande: write image to %s (write image)\n", imgfile.c_str() );
+      ImageFile imgf ( imgfile );
+      imgf.writer ( &img );
+    } else {
+      std::string tmpfile = FileMgt::createTempFile ( "/tmp/osl_lfColorSande_input_%s.png" );
+      fprintf ( stderr, "LFColorSande: write image to %s (convert)\n", tmpfile.c_str() );
+
+      std::string convertcall = "convert " + imgfile + " " + tmpfile;
+      cerr << "convert call: " << convertcall << endl;
+      system ( convertcall.c_str() );
+
+      imgfile = tmpfile;
+    }
+
+    delete_imgfile = true;
+  }
+
+  std::string outputfn  = FileMgt::createTempFile ( "/tmp/osl_lfColorSande_output_%s" ) ;
+
+  std::string gridparams = "";
+
+  if ( usegrid )
+    gridparams = " --detector densesampling --ds_spacing " + gridsize + " --ds_scales " + scales;
+
+  std::string call = c_binaryExecutable + " " +
+                     imgfile            + " " +
+                     c_params           +
+                     gridparams         +
+                     " -output "        + outputfn;
+
+  cerr << "LFColorSande: parameters: <" << c_params + gridparams << ">" << endl;
+  clog << "Systemcall: " << call << endl;
+
+
+  const int buffersize = 65536;
+  char *buffer = new char [buffersize];
+  FILE *f = popen ( call.c_str(), "r" );
+  if ( f == NULL )
+  {
+    fthrow ( Exception, "Unable to run the implementation of van de Sande: " << call << endl << strerror ( errno ) );
+  }
+
+  while ( ! feof ( f ) )
+  {
+    if ( fgets ( buffer, buffersize, f ) <= 0 )
+    {
+      break;
+    } else {
+      fprintf ( stderr, "LFColorSande::extractFeatures: [INFO] %s", buffer );
+    }
+  }
+
+
+  pclose ( f );
+
+  f = fopen ( outputfn.c_str(), "r" );
+  if ( f == NULL )
+  {
+    fthrow ( Exception, "Unable to read output of van de Sande implementation\n" );
+  }
+
+  if ( fgets ( buffer, buffersize, f ) <= 0 )
+  {
+    fprintf ( stderr, "LFColorSande::extractFeatures: output is empty !\n" );
+    fprintf ( stderr, "img %s out %s\n", imgfile.c_str(), outputfn.c_str() );
+    fprintf ( stderr, "call %s\n", call.c_str() );
+
+    exit ( -1 );
+  }
+
+  if ( ! strcmp ( buffer, "KOEN1" ) )
+  {
+    fprintf ( stderr, "LFColorSande::extractFeatures: wrong file format\n" );
+    fprintf ( stderr, "img %s out %s\n", imgfile.c_str(), outputfn.c_str() );
+    fprintf ( stderr, "call %s\n", call.c_str() );
+
+    exit ( -1 );
+  }
+
+
+  fgets ( buffer, buffersize, f );
+  int dimension = atoi ( buffer );
+  fprintf ( stderr, "LFColorSande: descriptor dimension = %d\n", dimension );
+
+  if ( ( descriptor_size > 0 ) && ( dimension != descriptor_size ) )
+  {
+    fprintf ( stderr, "LFColorSande::extractFeatures: dimensions do not match %d -> %d!\n",
+              dimension, descriptor_size );
+    fprintf ( stderr, "img %s out %s\n", imgfile.c_str(), outputfn.c_str() );
+    fprintf ( stderr, "call %s\n", call.c_str() );
+    fprintf ( stderr, "dimension std::string buffer: \"%s\"", buffer );
+    exit ( -1 );
+  }
+
+  fgets ( buffer, buffersize, f );
+  int noDesc = atoi ( buffer );
+
+  fprintf ( stderr, "LFColorSande::extractFeatures: no. of descriptors = %d\n", noDesc );
+
+  NICE::Vector x;
+  while ( ! feof ( f ) )
+  {
+    // <CIRCLE 119 307 1.26134 0 0.00014763>; 0 0 6 2 0 6 25 7 9 4 4 0 0 4 20 36 78 4 5 0 0
+    if ( fgets ( buffer, buffersize, f ) == NULL )
+      break;
+
+    const char *buffer_data = strchr ( buffer, ';' );
+    if ( strlen ( buffer_data ) <= 0 )
+    {
+      fprintf ( stderr, "LFColorSande::extractFeatures: it seems you forget to specify a descriptor\n" );
+      exit ( -1 );
+    }
+
+    const char *buffer_key_start = strchr ( buffer, ' ' );
+    const char *buffer_key_end = strchr ( buffer, '>' );
+    buffer_key_start++;
+    int keylen = buffer_key_end - buffer_key_start;
+    char *key = new char [keylen+1];
+    strncpy ( key, buffer_key_start, keylen );
+    key[keylen] = '\0';
+
+    buffer_data += 2;
+
+    std::string buffer_data_s ( buffer_data );
+
+    //clog << "[log] buffer = " << buffer_data_s << endl;
+
+    StringTools::splitVector ( buffer_data_s, ' ', x );
+    if ( ( int ) x.size() != dimension )
+    {
+      cerr << "Line = " << buffer_data_s << endl;
+      cerr << "Vector = " << x << endl;
+      cerr << "dimension = " << dimension << endl;
+      cerr << "x.size() = " << x.size() << endl;
+      fprintf ( stderr, "LFColorSande::extractFeatures: error parsing output !!\n" );
+      exit ( -1 );
+    } else {
+      NICE::Vector pos;
+
+      StringTools::splitVector ( key, ' ', pos );
+
+      if ( pos.size() != 5 ) {
+        fprintf ( stderr, "LFColorSande::extractFeatures: dimension mismatch (position information)\n" );
+        exit ( -1 );
+      }
+      // Van De Sande verwendet MatLab-Darstellung der Koordinaten. Diese fangen bei 1 an und nicht bei 0.
+      pos[0] --;
+      pos[1] --;
+      positions.push_back ( pos );
+      features.push_back ( x );
+    }
+  }
+
+  fclose ( f );
+
+  if ( delete_imgfile )
+    FileMgt::deleteTempFile ( imgfile );
+
+  FileMgt::deleteTempFile ( outputfn );
+
+  delete [] buffer;
+
+  return 0;
 }

+ 49 - 49
features/localfeatures/LFColorSande.h

@@ -1,4 +1,4 @@
-/** 
+/**
 * @file LFColorSande.h
 * @brief interface to ColorSande implementation
 * @author Erik Rodner
@@ -14,7 +14,7 @@
 
 #include "LocalFeatureRepresentation.h"
 #include "core/basics/Config.h"
-  
+
 
 namespace OBJREC {
 
@@ -22,53 +22,53 @@ namespace OBJREC {
 class LFColorSande : public LocalFeatureRepresentation
 {
 
-    protected:
-		std::string c_binaryExecutable;
-		std::string c_params;
-		double c_minScale;
-		
-		//! size of the descriptor
-		int descriptor_size;
-		
-		//! use grid for SIFT Positions
-		bool usegrid;
-	
-		//! size of the grid
-		std::string gridsize;
-	
-		//! used scales
-		std::string scales;
-		
-    public:
-  
-		/** simple constructor */
-		LFColorSande( const NICE::Config *conf, std::string section = "LFColorSande" );
-		  
-		/** simple destructor */
-		virtual ~LFColorSande();
-		
-		int getDescSize () const;
-		
-		/**
-		 * get the colorSIFT features
-		 * @param img grayvalue input image
-		 * @param features features (output)
-		 * @param positions position of the features
-		 * @return 
-		 */
-		int extractFeatures ( const NICE::Image & img, NICE::VVector & features, 
-					  NICE::VVector & positions ) const;
-		
-		/**
-		 * get the colorSIFT features
-		 * @param img color input image
-		 * @param features features (output)
-		 * @param positions position of the features
-		 * @return 
-		 */
-		int extractFeatures ( const NICE::ColorImage & img, NICE::VVector & features, 
-					  NICE::VVector & positions ) const;
-		 
+  protected:
+    std::string c_binaryExecutable;
+    std::string c_params;
+    double c_minScale;
+
+    //! size of the descriptor
+    int descriptor_size;
+
+    //! use grid for SIFT Positions
+    bool usegrid;
+
+    //! size of the grid
+    std::string gridsize;
+
+    //! used scales
+    std::string scales;
+
+  public:
+
+    /** simple constructor */
+    LFColorSande ( const NICE::Config *conf, std::string section = "LFColorSande" );
+
+    /** simple destructor */
+    virtual ~LFColorSande();
+
+    int getDescSize () const;
+
+    /**
+     * get the colorSIFT features
+     * @param img grayvalue input image
+     * @param features features (output)
+     * @param positions position of the features
+     * @return
+     */
+    int extractFeatures ( const NICE::Image & img, NICE::VVector & features,
+                          NICE::VVector & positions ) const;
+
+    /**
+     * get the colorSIFT features
+     * @param img color input image
+     * @param features features (output)
+     * @param positions position of the features
+     * @return
+     */
+    int extractFeatures ( const NICE::ColorImage & img, NICE::VVector & features,
+                          NICE::VVector & positions ) const;
+
 };
 
 

+ 15 - 0
features/localfeatures/LFColorWeijer.cpp

@@ -438,6 +438,21 @@ void LFColorWeijer::visualizeFeatures( const NICE::ColorImage & cimg, NICE::Colo
   }
 
   getDescriptors( cimg, pos, feats );
+  
+  //heatmap for a special class
+  /*ofstream fout("out.txt");
+  
+  int counter = 0;
+  for ( int y = 0; y < cimg.height(); y++ )
+  {
+    for ( int x = 0; x < cimg.width(); x++, counter++ )
+    {
+      fout << feats[counter][8] << " ";
+    }
+  }
+  cout << "counter: " << counter << " feats.size(): " << feats.size() << endl;
+  
+  fout.close();*/
 
   out.resize( cimg.width(), cimg.height() );
   out.set( 0, 0, 0 );

+ 19 - 19
features/localfeatures/progs/testColorWeijer.cpp

@@ -11,24 +11,24 @@ using namespace NICE;
 using namespace OBJREC;
 
 int main(int argc, char **argv)
-{	
-	if(argc < 1)
-	{
-		cerr << "Bitte Bild angeben" << endl;
-		return -1;
-	}
-	
-	Config *conf = new Config();
-	LFColorWeijer lfc(conf);
-		
-	//! testen
-	ColorImage cimg(argv[1]);
-	ColorImage out;
-	lfc.visualizeFeatures (cimg,out);
-	
-	cimg.writePPM("org.ppm");
-	out.writePPM("out.ppm");
-	
-	return 0;
+{
+  if (argc < 1)
+  {
+    cerr << "Bitte Bild angeben" << endl;
+    return -1;
+  }
+
+  Config *conf = new Config();
+  LFColorWeijer lfc(conf);
+
+  //! testen
+  ColorImage cimg(argv[1]);
+  ColorImage out;
+  lfc.visualizeFeatures (cimg, out);
+
+  cimg.writePPM("org.ppm");
+  out.writePPM("out.ppm");
+
+  return 0;
 }
 

+ 8 - 48
math/cluster/SpectralCluster.cpp

@@ -16,8 +16,6 @@
 using namespace OBJREC;
 
 using namespace std;
-// refactor-nice.pl: check this substitution
-// old: using namespace ice;
 using namespace NICE;
 
 SpectralCluster::SpectralCluster ( int _noClasses, double alpha ) : noClasses(_noClasses), kmeans(_noClasses)
@@ -30,13 +28,9 @@ SpectralCluster::~SpectralCluster()
 }
 
 void SpectralCluster::getSimilarityMatrix ( const VVector & features, 
-					    // refactor-nice.pl: check this substitution
-					    // old: Matrix & laplacian,
 					    NICE::Matrix & laplacian,
 					    double alpha )
 {
-    // refactor-nice.pl: check this substitution
-    // old: Matrix distances ( laplacian );
     NICE::Matrix distances ( laplacian );
     double mindist = numeric_limits<double>::max();
     double maxdist = - numeric_limits<double>::max();
@@ -47,18 +41,12 @@ void SpectralCluster::getSimilarityMatrix ( const VVector & features,
 
     for ( int i = 0 ; i < (int)features.size() ; i++ )
     {
-	// refactor-nice.pl: check this substitution
-	// old: const Vector & xi = features[i];
 	const NICE::Vector & xi = features[i];
 	for ( int j = i ; j < (int)features.size() ; j++ )
 	{
-	    // refactor-nice.pl: check this substitution
-	    // old: const Vector & xj = features[j];
 	    const NICE::Vector & xj = features[j];
 	    // double sim = xi * xj;
 	    double dist = distance.calculate ( xi, xj );
-	    // refactor-nice.pl: check this substitution
-	    // old: distances[i][j] = dist;
 	    distances(i, j) = dist;
 
 	    if ( dist < mindist )
@@ -75,9 +63,7 @@ void SpectralCluster::getSimilarityMatrix ( const VVector & features,
     for ( int i = 0 ; i < (int)features.size() ; i++ )
 	for ( int j = i ; j < (int)features.size() ; j++ )
 	{
-	    // refactor-nice.pl: check this substitution
-	    // old: double d = ( mean - distances[i][j] );
-	    double d = ( mean -distances(i, j) );
+	    double d = ( mean - distances(i, j) );
 	    stddev += d*d;
 	}
 
@@ -88,31 +74,19 @@ void SpectralCluster::getSimilarityMatrix ( const VVector & features,
     for ( int i = 0 ; i < (int)features.size() ; i++ )
 	for ( int j = i ; j < (int)features.size() ; j++ )
 	{
-	    // refactor-nice.pl: check this substitution
-	    // old: double sim = exp(- distances[i][j] * norm );
 	    double sim = exp(-distances(i, j) * norm );
 	    
-	    // refactor-nice.pl: check this substitution
-	    // old: laplacian[i][j] = - sim;
 	    laplacian(i, j) = - sim;
-	    // refactor-nice.pl: check this substitution
-	    // old: laplacian[j][i] = - sim;
 	    laplacian(j, i) = - sim;
 	}
 }
 
 void SpectralCluster::computeLaplacian ( const VVector & features,
-					 // refactor-nice.pl: check this substitution
-					 // old: Matrix & laplacian, int method, double alpha )
 					 NICE::Matrix & laplacian, int method, double alpha )
 {
-	//unused:
-    //int n = (int)features.size();
     laplacian.set(0.0);
     getSimilarityMatrix(features, laplacian, alpha);
     
-    // refactor-nice.pl: check this substitution
-    // old: Vector d ( laplacian.rows() );
     NICE::Vector d ( laplacian.rows() );
     d.set(0.0);
     for ( int i = 0 ; i < (int)laplacian.rows(); i++ )
@@ -155,13 +129,9 @@ void SpectralCluster::cluster ( const VVector & features,
 	exit(-1);
     }
 
-    // refactor-nice.pl: check this substitution
-    // old: const Vector & x = features[0];
     const NICE::Vector & x = features[0];
     int dimension = x.size();
 
-    // refactor-nice.pl: check this substitution
-    // old: Matrix laplacian ( features.size(), features.size() );
     NICE::Matrix laplacian ( features.size(), features.size() );
 
     computeLaplacian ( features, laplacian, L_RW_NORMALIZED, alpha );
@@ -169,33 +139,29 @@ void SpectralCluster::cluster ( const VVector & features,
 
     NICE::Matrix eigvect;
     NICE::Vector eigvals;
-    NICE::eigenvectorvalues ( laplacian, eigvect, eigvals );
+    try {
+      NICE::eigenvectorvalues ( laplacian, eigvect, eigvals );
+    } catch (...) {
+      cerr << "You should adjust the alpha parameter, or the features are somehow weird" << endl;
+      cerr << "Laplacian = " << laplacian(0, 0, min((int)laplacian.rows()-1, 5), min((int)laplacian.cols()-1, 5)) << endl;
+      throw Exception ("Laplacian matrix is singular or not well-conditioned!");
+    }
 
-    // refactor-nice.pl: check this substitution
-    // old: Matrix eigvals_sorted ( eigvals.size(), 1 );
     std::map<double, int> eigvals_sorted;
 	for ( int i = 0 ; i < (int)eigvals.size(); i++ ) 
     {
-	// refactor-nice.pl: check this substitution
-	// old: eigvals_sorted[i][0] = i;
 	eigvals_sorted.insert ( make_pair( eigvals[i], i ) );
     }
-    // refactor: eigvals_sorted = eigvals_sorted || eigvals;
-    // refactor: eigvals_sorted.Sort(1);
 
     VVector spectral_features;
 
 	for ( int i = 0 ; i < (int)eigvect.rows() ; i++ )
     {
-	// refactor-nice.pl: check this substitution
-	// old: Vector eigvec_k ( noClasses );
 	NICE::Vector eigvec_k ( noClasses );
 	map<double, int>::const_iterator k = eigvals_sorted.begin();
 	for ( int j = 0 ; j < noClasses ; j++ )
 	{
 	    int eigval_index = k->second;
-	    // refactor-nice.pl: check this substitution
-	    // old: eigvec_k[j] = eigvect[i][ (int)eigvals_sorted[j][0] ] ;
 	    eigvec_k[j] = eigvect(i, eigval_index ) ;
 	    k++;
 	}
@@ -221,11 +187,7 @@ void SpectralCluster::cluster ( const VVector & features,
     {
 	int k = assignment[j];
 	
-	// refactor-nice.pl: check this substitution
-	// old: Vector & p = prototypes[k];
 	NICE::Vector & p = prototypes[k];
-	// refactor-nice.pl: check this substitution
-	// old: const Vector & x = *i;
 	const NICE::Vector & x = *i;
 	p += x;
 	weights[k]++;
@@ -233,8 +195,6 @@ void SpectralCluster::cluster ( const VVector & features,
 
     for ( int k = 0 ; k < noClasses ; k++ )
     {
-	// refactor-nice.pl: check this substitution
-	// old: Vector & p = prototypes[k];
 	NICE::Vector & p = prototypes[k];
 	if ( weights[k] <= 0 ) {
 	    fprintf (stderr, "FATAL ERROR: spectral clustering produced empty cluster !\n");

+ 0 - 4
math/cluster/SpectralCluster.h

@@ -33,15 +33,11 @@ class SpectralCluster : public ClusterAlgorithm
 	};
 
 	virtual void computeLaplacian ( const NICE::VVector & features,
-					 // refactor-nice.pl: check this substitution
-					 // old: Matrix & laplacian,
 					 NICE::Matrix & laplacian,
 					 int method, double alpha );
 
 
 	virtual void getSimilarityMatrix ( const NICE::VVector & features, 
-					    // refactor-nice.pl: check this substitution
-					    // old: Matrix & laplacian, double alpha );
 					    NICE::Matrix & laplacian, double alpha );
     public:
   

+ 694 - 762
math/kernels/KernelData.cpp

@@ -1,4 +1,4 @@
-/** 
+/**
 * @file KernelData.cpp
 * @brief caching some kernel data
 * @author Erik Rodner
@@ -26,873 +26,805 @@ using namespace OBJREC;
 
 KernelData::KernelData()
 {
-	// empty config
-	Config conf;
-	initFromConfig( &conf, "DONTCARE");
+  // empty config
+  Config conf;
+  initFromConfig ( &conf, "DONTCARE" );
 }
 
 KernelData::KernelData ( const KernelData & src )
 {
-	kernelMatrix = src.kernelMatrix;
-	inverseKernelMatrix = src.inverseKernelMatrix;
-	choleskyMatrix = src.choleskyMatrix;
-	for ( map<int, NICE::Matrix *>::const_iterator i = src.cachedMatrices.begin();
-		i != src.cachedMatrices.end(); i++ )
-	{
-		Matrix *M = new Matrix ( *(i->second) );
-		cachedMatrices.insert ( pair<int, NICE::Matrix *> ( i->first, M ) );
-	}
-	logdet = src.logdet;
-	verbose = src.verbose;
-	cr = src.cr->clone();
+  kernelMatrix = src.kernelMatrix;
+  inverseKernelMatrix = src.inverseKernelMatrix;
+  choleskyMatrix = src.choleskyMatrix;
+  for ( map<int, NICE::Matrix *>::const_iterator i = src.cachedMatrices.begin();
+        i != src.cachedMatrices.end(); i++ )
+  {
+    Matrix *M = new Matrix ( * ( i->second ) );
+    cachedMatrices.insert ( pair<int, NICE::Matrix *> ( i->first, M ) );
+  }
+  logdet = src.logdet;
+  verbose = src.verbose;
+  cr = src.cr->clone();
 }
 
-KernelData::KernelData( const Config *conf, const Matrix & kernelMatrix, const string & section )
+KernelData::KernelData ( const Config *conf, const Matrix & kernelMatrix, const string & section, bool updateCholesky )
 {
-	initFromConfig ( conf, section );
-	this->kernelMatrix = kernelMatrix;
-	updateCholeskyFactorization();
+  initFromConfig ( conf, section );
+  this->kernelMatrix = kernelMatrix;
+  if ( updateCholesky ) 
+    updateCholeskyFactorization();
 }
 
-KernelData::KernelData( const Config *conf, const string & section )
+KernelData::KernelData ( const Config *conf, const string & section )
 {
-	initFromConfig ( conf, section );
+  initFromConfig ( conf, section );
 }
 
 void KernelData::initFromConfig ( const Config *conf, const string & section )
 {
-	verbose = conf->gB(section, "verbose", false );
-	string inv_method = conf->gS(section, "robust_cholesky", "auto" );
-
-	double noiseStep = conf->gD(section, "rchol_noise_variance", 1e-7 );
-	double minimumLogDet = conf->gD(section, "rchol_minimum_logdet", - std::numeric_limits<double>::max() );
-	bool useCuda = conf->gB(section, "rchol_cuda", true );
-	if ( verbose && useCuda )
-		std::cerr << "KernelData: using the cuda implementation of cholesky decomposition (might be inaccurate)" << std::endl;
-
-	if ( inv_method == "auto" )
-	{
-		if ( verbose )
-			std::cerr << "KernelData: using the cholesky method with automatic regularization" << std::endl;
-		cr = new CholeskyRobustAuto ( verbose, noiseStep, minimumLogDet, useCuda );
-	} else {
-		if ( verbose )
-			std::cerr << "KernelData: using the cholesky method with static regularization" << std::endl;
-
-		cr = new CholeskyRobust ( verbose, noiseStep, useCuda );
-	}
+  verbose = conf->gB ( section, "verbose", false );
+  string inv_method = conf->gS ( section, "robust_cholesky", "auto" );
+
+  double noiseStep = conf->gD ( section, "rchol_noise_variance", 1e-7 );
+  double minimumLogDet = conf->gD ( section, "rchol_minimum_logdet", - std::numeric_limits<double>::max() );
+  bool useCuda = conf->gB ( section, "rchol_cuda", true );
+  if ( verbose && useCuda )
+    std::cerr << "KernelData: using the cuda implementation of cholesky decomposition (might be inaccurate)" << std::endl;
+
+  if ( inv_method == "auto" )
+  {
+    if ( verbose )
+      std::cerr << "KernelData: using the cholesky method with automatic regularization" << std::endl;
+    cr = new CholeskyRobustAuto ( verbose, noiseStep, minimumLogDet, useCuda );
+  } else {
+    if ( verbose )
+      std::cerr << "KernelData: using the cholesky method with static regularization" << std::endl;
+
+    cr = new CholeskyRobust ( verbose, noiseStep, useCuda );
+  }
 }
 
 KernelData::~KernelData()
 {
-	delete cr;
+  delete cr;
 }
 
 void KernelData::updateCholeskyFactorization ()
 {
-	if ( verbose )
-		std::cerr << "KernelData: kernel: " << kernelMatrix.rows() << " " << kernelMatrix.cols() << std::endl;
-
-	if ( (kernelMatrix.rows() <= 0) || (kernelMatrix.cols() <= 0) )
-		fthrow(Exception, "KernelData: no kernel matrix available !");
-
-	if ( kernelMatrix.containsNaN() ) 
-	{
-		if ( verbose )
-			std::cerr << "KernelData: kernel matrix contains NaNs (setting inverse to identity)" << std::endl;
-
-		logdet = numeric_limits<double>::max();
-
-		choleskyMatrix.resize ( kernelMatrix.rows(), kernelMatrix.cols() );
-		choleskyMatrix.setIdentity();
-	} else {
-		if ( verbose )
-			std::cerr << "KernelData: calculating cholesky decomposition" << std::endl;
-
-		cr->robustChol ( kernelMatrix, choleskyMatrix );
-		logdet = cr->getLastLogDet();
-
-		if ( !finite(logdet) )
-		{
-			choleskyMatrix.resize ( kernelMatrix.rows(), kernelMatrix.cols() );
-			choleskyMatrix.setIdentity();
-			logdet = numeric_limits<double>::max();
-		}
-	}
+  if ( verbose )
+    std::cerr << "KernelData: kernel: " << kernelMatrix.rows() << " " << kernelMatrix.cols() << std::endl;
+
+  if ( ( kernelMatrix.rows() <= 0 ) || ( kernelMatrix.cols() <= 0 ) )
+    fthrow ( Exception, "KernelData: no kernel matrix available !" );
+
+  if ( kernelMatrix.containsNaN() )
+  {
+    if ( verbose )
+      std::cerr << "KernelData: kernel matrix contains NaNs (setting inverse to identity)" << std::endl;
+
+    logdet = numeric_limits<double>::max();
+
+    choleskyMatrix.resize ( kernelMatrix.rows(), kernelMatrix.cols() );
+    choleskyMatrix.setIdentity();
+  } else {
+    if ( verbose )
+      std::cerr << "KernelData: calculating cholesky decomposition" << std::endl;
+
+    cr->robustChol ( kernelMatrix, choleskyMatrix );
+    logdet = cr->getLastLogDet();
+
+    if ( !finite ( logdet ) )
+    {
+      choleskyMatrix.resize ( kernelMatrix.rows(), kernelMatrix.cols() );
+      choleskyMatrix.setIdentity();
+      logdet = numeric_limits<double>::max();
+    }
+  }
 }
 
 void KernelData::updateInverseKernelMatrix ()
 {
-	if ( ! hasCholeskyFactorization() )
-		updateCholeskyFactorization();
-	inverseKernelMatrix.resize ( choleskyMatrix.rows(), choleskyMatrix.cols() );
-	choleskyInvertLargeScale ( choleskyMatrix, inverseKernelMatrix );
+  if ( ! hasCholeskyFactorization() )
+    updateCholeskyFactorization();
+  inverseKernelMatrix.resize ( choleskyMatrix.rows(), choleskyMatrix.cols() );
+  choleskyInvertLargeScale ( choleskyMatrix, inverseKernelMatrix );
 }
 
-		
+
 void KernelData::computeInverseKernelMultiply ( const Vector & x, Vector & result ) const
 {
-	if ( choleskyMatrix.rows() == 0 )
-		fthrow(Exception, "Cholesky factorization was not initialized, use updateCholeskyFactorization() in advance");
-	choleskySolveLargeScale ( choleskyMatrix, x, result );
+  if ( choleskyMatrix.rows() == 0 )
+    fthrow ( Exception, "Cholesky factorization was not initialized, use updateCholeskyFactorization() in advance" );
+  choleskySolveLargeScale ( choleskyMatrix, x, result );
 }
 
-const NICE::Matrix & KernelData::getKernelMatrix() const 
+const NICE::Matrix & KernelData::getKernelMatrix() const
 {
-	return kernelMatrix; 
+  return kernelMatrix;
 }
 
-NICE::Matrix & KernelData::getKernelMatrix() 
-{ 
-	return kernelMatrix; 
+NICE::Matrix & KernelData::getKernelMatrix()
+{
+  return kernelMatrix;
 }
 
-const NICE::Matrix & KernelData::getInverseKernelMatrix() const 
-{ 
-	return inverseKernelMatrix; 
+const NICE::Matrix & KernelData::getInverseKernelMatrix() const
+{
+  return inverseKernelMatrix;
 };
 
 NICE::Matrix & KernelData::getInverseKernelMatrix()
-{ 
-	return inverseKernelMatrix; 
+{
+  return inverseKernelMatrix;
 };
 
 const NICE::Matrix & KernelData::getCholeskyMatrix() const
 {
-	return choleskyMatrix;
+  return choleskyMatrix;
 }
 
-const Matrix & KernelData::getCachedMatrix (int i) const
+const Matrix & KernelData::getCachedMatrix ( int i ) const
 {
-	map<int, NICE::Matrix *>::const_iterator it = cachedMatrices.find(i);
-	if ( it != cachedMatrices.end() )
-		return *(it->second);
-	else
-		fthrow(Exception, "Cached matrix with index " << i << " is not available.");
+  map<int, NICE::Matrix *>::const_iterator it = cachedMatrices.find ( i );
+  if ( it != cachedMatrices.end() )
+    return * ( it->second );
+  else
+    fthrow ( Exception, "Cached matrix with index " << i << " is not available." );
 }
-		
-void KernelData::setCachedMatrix (int i, Matrix *m)
+
+void KernelData::setCachedMatrix ( int i, Matrix *m )
 {
-	cachedMatrices[i] = m; 
+  cachedMatrices[i] = m;
 }
-		
-uint KernelData::getKernelMatrixSize () const { 
-	uint mysize = ( kernelMatrix.rows() == 0 ) ? (choleskyMatrix.rows()) : kernelMatrix.rows(); 
-	return mysize;
+
+uint KernelData::getKernelMatrixSize () const {
+  uint mysize = ( kernelMatrix.rows() == 0 ) ? ( choleskyMatrix.rows() ) : kernelMatrix.rows();
+  return mysize;
 };
-		
+
 void KernelData::getLooEstimates ( const Vector & y, Vector & muLoo, Vector & sigmaLoo ) const
 {
-	if ( inverseKernelMatrix.rows() != getKernelMatrixSize() )  
-		fthrow(Exception, "updateInverseKernelMatrix() has to be called in advance to use this function\n");
-	if ( y.size() != inverseKernelMatrix.rows() )
-		fthrow(Exception, "inverse kernel matrix does not fit to the size of the vector of function values y\n");
-	
-	Vector alpha;
-	computeInverseKernelMultiply ( y, alpha );
-	muLoo.resize ( y.size() );
-	sigmaLoo.resize ( y.size() );
-    for ( uint l = 0 ; l < y.size(); l++ )
-	{
-		 sigmaLoo[l] = 1.0 / inverseKernelMatrix(l,l);
-		 muLoo[l] = y[l] - alpha[l] * sigmaLoo[l];
-	}
+  if ( inverseKernelMatrix.rows() != getKernelMatrixSize() )
+    fthrow ( Exception, "updateInverseKernelMatrix() has to be called in advance to use this function\n" );
+  if ( y.size() != inverseKernelMatrix.rows() )
+    fthrow ( Exception, "inverse kernel matrix does not fit to the size of the vector of function values y\n" );
+
+  Vector alpha;
+  computeInverseKernelMultiply ( y, alpha );
+  muLoo.resize ( y.size() );
+  sigmaLoo.resize ( y.size() );
+  for ( uint l = 0 ; l < y.size(); l++ )
+  {
+    sigmaLoo[l] = 1.0 / inverseKernelMatrix ( l, l );
+    muLoo[l] = y[l] - alpha[l] * sigmaLoo[l];
+  }
 }
-	
-	
-KernelData *KernelData::clone(void) const
+
+
+KernelData *KernelData::clone ( void ) const
 {
-	return new KernelData( *this );
+  return new KernelData ( *this );
 }
 
-/** 
+/**
 * @brief Updates the GP-Likelihood, if only the i-th row and column has changed. Time is O(n^2) instaed O(n^3)
 * @author Alexander Lütz
 * @date 01/12/2010 (dd/mm/yyyy)
 */
-void KernelData::getGPLikelihoodWithOneNewRow(  const NICE::Vector & y, const double & oldLogdetK, const int & rowIndex, const NICE::Vector & newRow, const Vector & oldAlpha , Vector & newAlpha, double & loglike)
+void KernelData::getGPLikelihoodWithOneNewRow ( const NICE::Vector & y, const double & oldLogdetK, const int & rowIndex, const NICE::Vector & newRow, const Vector & oldAlpha , Vector & newAlpha, double & loglike )
 {
-	// oldAlpha = K^{-1} y
-
-	// K' new kernel matrix = exchange the row and column at position rowIndex
-	// with newRow
-	// try to find U and V such that K' = K + U*V with U,V having rank 2
-	
-	// rowIndex'th base vector 
-	Vector ei (y.size(), 0.0);
-	ei[rowIndex] = 1.0;
-
-	// we have to consider the diagonal entry
-	Vector a = newRow - kernelMatrix.getRow(rowIndex) ;
-	a[rowIndex] = a[rowIndex]/2;
-
-	NICE::Matrix U (y.size(),2);
-	NICE::Matrix V (2,y.size());
-	for (uint i = 0; i < y.size(); i++)
-	{
-		U(i,0) = a[i];
-		U(i,1) = ei[i];
-		V(0,i) = ei[i];
-		V(1,i) = a[i];
-	}
-
-	// Sherman Woodbury-Morrison Formula:
-	// alpha_new = (K + UV)^{-1} y = K^{-1} y - K^{-1} U ( I + V
-	// K^{-1} U )^{-1} V K^{-1} y = oldAlpha - B ( I + V B )^{-1} V oldAlpha
-	// = oldAlpha - B F^{-1} V oldAlpha
-	// with B = K^{-1} U and F = (I+VB)
-	
-	// Time complexity: 2 choleskySolve calls: O(n^2)
-
-	NICE::Vector B_1;
-	computeInverseKernelMultiply(U.getColumn(0),B_1);
-
-	NICE::Vector B_2;
-	computeInverseKernelMultiply(U.getColumn(1),B_2);
-
-	NICE::Matrix B(y.size(),2);
-
-	for (uint i = 0; i < y.size(); i++)
-	{
-		B(i,0) = B_1[i];
-		B(i,1) = B_2[i];
-	}
-	
-	NICE::Matrix F (2,2);
-	F.setIdentity();
-	Matrix V_B (2,2);
-	V_B.multiply(V,B);
-	F += V_B;
-
-	// Time complexity: 1 linear equation system with 2 variables
-	// can be computed in O(1) using a fixed implementation
-	NICE::Matrix F_inv = NICE::Matrix(2,2);
-	double denominator = F(0,0)*F(1,1)-F(0,1)*F(1,0);
-	F_inv(0,0) = F(1,1)/denominator;
-	F_inv(0,1) = -F(0,1)/denominator;
-	F_inv(1,0) = - F(1,0)/denominator;
-	F_inv(1,1) = F(0,0)/denominator;
-
-	Matrix M_oldAlpha (y.size(),1);
-	for (uint i = 0; i < y.size(); i++)
-	{
-		M_oldAlpha(i,0) = oldAlpha[i];
-	}
-	NICE::Matrix V_oldAlpha;
-	V_oldAlpha.multiply( V,M_oldAlpha);
-	NICE::Matrix F_inv_V_old_Alpha;
-	F_inv_V_old_Alpha.multiply(F_inv, V_oldAlpha);
-
-	NICE::Matrix M_newAlpha;
-	M_newAlpha.multiply(B, F_inv_V_old_Alpha);
-
-	M_newAlpha *= -1;
-	M_newAlpha += M_oldAlpha;
-
-	newAlpha = NICE::Vector(y.size());
-	for (uint i = 0; i < y.size(); i++)
-	{
-		newAlpha[i] = M_newAlpha(i,0);
-	}
-
-	// Matrix Determinant Lemma
-	// http://en.wikipedia.org/wiki/Matrix_determinant_lemma
-	// det(K + U*V) = det(I + V * K^{-1} * U) * det(K)
-	// logdet(K + U*V) = logdet( F ) + logdet(K)
-	double logdetF = log(F(0,0) * F(1,1) - F(0,1) * F(1,0));
-
-	double newLogdetK = logdetF + oldLogdetK;
-
-	logdet = newLogdetK;
-
-	loglike = newLogdetK + newAlpha.scalarProduct(y);
+  // oldAlpha = K^{-1} y
+
+  // K' new kernel matrix = exchange the row and column at position rowIndex
+  // with newRow
+  // try to find U and V such that K' = K + U*V with U,V having rank 2
+
+  // rowIndex'th base vector
+  Vector ei ( y.size(), 0.0 );
+  ei[rowIndex] = 1.0;
+
+  // we have to consider the diagonal entry
+  Vector a = newRow - kernelMatrix.getRow ( rowIndex ) ;
+  a[rowIndex] = a[rowIndex] / 2;
+
+  NICE::Matrix U ( y.size(), 2 );
+  NICE::Matrix V ( 2, y.size() );
+  for ( uint i = 0; i < y.size(); i++ )
+  {
+    U ( i, 0 ) = a[i];
+    U ( i, 1 ) = ei[i];
+    V ( 0, i ) = ei[i];
+    V ( 1, i ) = a[i];
+  }
+
+  // Sherman Woodbury-Morrison Formula:
+  // alpha_new = (K + UV)^{-1} y = K^{-1} y - K^{-1} U ( I + V
+  // K^{-1} U )^{-1} V K^{-1} y = oldAlpha - B ( I + V B )^{-1} V oldAlpha
+  // = oldAlpha - B F^{-1} V oldAlpha
+  // with B = K^{-1} U and F = (I+VB)
+
+  // Time complexity: 2 choleskySolve calls: O(n^2)
+
+  NICE::Vector B_1;
+  computeInverseKernelMultiply ( U.getColumn ( 0 ), B_1 );
+
+  NICE::Vector B_2;
+  computeInverseKernelMultiply ( U.getColumn ( 1 ), B_2 );
+
+  NICE::Matrix B ( y.size(), 2 );
+
+  for ( uint i = 0; i < y.size(); i++ )
+  {
+    B ( i, 0 ) = B_1[i];
+    B ( i, 1 ) = B_2[i];
+  }
+
+  NICE::Matrix F ( 2, 2 );
+  F.setIdentity();
+  Matrix V_B ( 2, 2 );
+  V_B.multiply ( V, B );
+  F += V_B;
+
+  // Time complexity: 1 linear equation system with 2 variables
+  // can be computed in O(1) using a fixed implementation
+  NICE::Matrix F_inv = NICE::Matrix ( 2, 2 );
+  double denominator = F ( 0, 0 ) * F ( 1, 1 ) - F ( 0, 1 ) * F ( 1, 0 );
+  F_inv ( 0, 0 ) = F ( 1, 1 ) / denominator;
+  F_inv ( 0, 1 ) = -F ( 0, 1 ) / denominator;
+  F_inv ( 1, 0 ) = - F ( 1, 0 ) / denominator;
+  F_inv ( 1, 1 ) = F ( 0, 0 ) / denominator;
+
+  Matrix M_oldAlpha ( y.size(), 1 );
+  for ( uint i = 0; i < y.size(); i++ )
+  {
+    M_oldAlpha ( i, 0 ) = oldAlpha[i];
+  }
+  NICE::Matrix V_oldAlpha;
+  V_oldAlpha.multiply ( V, M_oldAlpha );
+  NICE::Matrix F_inv_V_old_Alpha;
+  F_inv_V_old_Alpha.multiply ( F_inv, V_oldAlpha );
+
+  NICE::Matrix M_newAlpha;
+  M_newAlpha.multiply ( B, F_inv_V_old_Alpha );
+
+  M_newAlpha *= -1;
+  M_newAlpha += M_oldAlpha;
+
+  newAlpha = NICE::Vector ( y.size() );
+  for ( uint i = 0; i < y.size(); i++ )
+  {
+    newAlpha[i] = M_newAlpha ( i, 0 );
+  }
+
+  // Matrix Determinant Lemma
+  // http://en.wikipedia.org/wiki/Matrix_determinant_lemma
+  // det(K + U*V) = det(I + V * K^{-1} * U) * det(K)
+  // logdet(K + U*V) = logdet( F ) + logdet(K)
+  double logdetF = log ( F ( 0, 0 ) * F ( 1, 1 ) - F ( 0, 1 ) * F ( 1, 0 ) );
+
+  double newLogdetK = logdetF + oldLogdetK;
+
+  logdet = newLogdetK;
+
+  loglike = newLogdetK + newAlpha.scalarProduct ( y );
 }
 
-/** 
+/**
 * @brief Updates the GP-Likelihood, if only the i-th row and column has changed. Time is O(n^2) instaed O(n^3). This is only the first part. Usefull for multiclass-problems.
 * @author Alexander Lütz
 * @date 01/12/2010 (dd/mm/yyyy)
 */
-void KernelData::getGPLikelihoodWithOneNewRow_FirstPart(const int & rowIndex, const NICE::Vector & newRow)
+void KernelData::getGPLikelihoodWithOneNewRow_FirstPart ( const int & rowIndex, const NICE::Vector & newRow )
 {
 
-	// oldAlpha = K^{-1} y
-
-	// K' new kernel matrix = exchange the row and column at position rowIndex
-	// with newRow
-	// try to find U and V such that K' = K + U*V with U,V having rank 2
-	
-	// rowIndex'th base vector 
-	Vector ei (newRow.size(), 0.0);
-	ei[rowIndex] = 1.0;
-
-	// we have to consider the diagonal entry
-	Vector a = newRow - kernelMatrix.getRow(rowIndex) ;
-	a[rowIndex] = a[rowIndex]/2;
-
-	U.resize(newRow.size(),2);
-	V.resize(2,newRow.size());
-// 	#pragma omp parallel for
-	for (uint i = 0; i < newRow.size(); i++)
-	{
-		U(i,0) = a[i];
-		U(i,1) = ei[i];
-		V(0,i) = ei[i];
-		V(1,i) = a[i];
-	}
-	
-	if (verbose)
-	{
-		std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- U:"  << std::endl;
-		for ( uint ik = 0; ik < U.rows(); ik++ )
-		{
-			for ( uint jk = 0; jk < U.cols(); jk++)
-			{
-				std::cerr << U(ik,jk) << " ";
-			}
-			std::cerr << std::endl;
-		}
-		std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- V:"  << std::endl;
-		for ( uint ik = 0; ik < V.rows(); ik++ )
-		{
-			for ( uint jk = 0; jk < V.cols(); jk++)
-			{
-				std::cerr << V(ik,jk) << " ";
-			}
-			std::cerr << std::endl;
-		}
-	}
-
-	// Sherman Woodbury-Morrison Formula:
-	// alpha_new = (K + UV)^{-1} y = K^{-1} y - K^{-1} U ( I + V
-	// K^{-1} U )^{-1} V K^{-1} y = oldAlpha - B ( I + V B )^{-1} V oldAlpha
-	// = oldAlpha - B F^{-1} V oldAlpha
-	// with B = K^{-1} U and F = (I+VB)
-	
-	// Time complexity: 2 choleskySolve calls: O(n^2)
-
-
-	NICE::Vector B_1;
-	computeInverseKernelMultiply(U.getColumn(0),B_1);
-
-	NICE::Vector B_2;
-	computeInverseKernelMultiply(U.getColumn(1),B_2);
-
-	B.resize(newRow.size(),2);
-
-	for (uint i = 0; i < newRow.size(); i++)
-	{
-		B(i,0) = B_1[i];
-		B(i,1) = B_2[i];
-	}
-	
-	if (verbose)
-	{
-		std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- B:"  << std::endl;
-		for ( uint ik = 0; ik < B.rows(); ik++ )
-		{
-			for ( uint jk = 0; jk < B.cols(); jk++)
-			{
-				std::cerr << B(ik,jk) << " ";
-			}
-			std::cerr << std::endl;
-		}
-	}
-
-	F.resize(2,2);
-	F.setIdentity();
-	Matrix V_B (2,2);
-	V_B.multiply(V,B);
-	F += V_B;
-	
-	if (verbose)
-	{
-		std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- F:"  << std::endl;
-		for ( uint ik = 0; ik < F.rows(); ik++ )
-		{
-			for ( uint jk = 0; jk < F.cols(); jk++)
-			{
-				std::cerr << F(ik,jk) << " ";
-			}
-			std::cerr << std::endl;
-		}
-	}
-
-	// Time complexity: 1 linear equation system with 2 variables
-	// can be computed in O(1) using a fixed implementation
-	F_inv.resize(2,2);
-	double denominator = F(0,0)*F(1,1)-F(0,1)*F(1,0);
-	F_inv(0,0) = F(1,1)/denominator;
-	F_inv(0,1) = -F(0,1)/denominator;
-	F_inv(1,0) = - F(1,0)/denominator;
-	F_inv(1,1) = F(0,0)/denominator;
-	
-	if (verbose)
-	{
-		std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- F_inv:"  << std::endl;
-		for ( uint ik = 0; ik < F_inv.rows(); ik++ )
-		{
-			for ( uint jk = 0; jk < F_inv.cols(); jk++)
-			{
-				std::cerr << F_inv(ik,jk) << " ";
-			}
-			std::cerr << std::endl;
-		}
-		
-		NICE::Matrix MultiplicationResult( F_inv.cols(), F_inv.cols(), 0.0 );
-		MultiplicationResult.multiply(F,F_inv);
-		std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- F-inversion MultiplicationResult:"  << std::endl;
-		for ( uint ik = 0; ik < MultiplicationResult.rows(); ik++ )
-		{
-			for ( uint jk = 0; jk < MultiplicationResult.cols(); jk++)
-			{
-				std::cerr << MultiplicationResult(ik,jk) << " ";
-			}
-			std::cerr << std::endl;
-		}
-	}
+  // oldAlpha = K^{-1} y
+
+  // K' new kernel matrix = exchange the row and column at position rowIndex
+  // with newRow
+  // try to find U and V such that K' = K + U*V with U,V having rank 2
+
+  // rowIndex'th base vector
+  Vector ei ( newRow.size(), 0.0 );
+  ei[rowIndex] = 1.0;
+
+  // we have to consider the diagonal entry
+  Vector a = newRow - kernelMatrix.getRow ( rowIndex ) ;
+  a[rowIndex] = a[rowIndex] / 2;
+
+  U.resize ( newRow.size(), 2 );
+  V.resize ( 2, newRow.size() );
+//  #pragma omp parallel for
+  for ( uint i = 0; i < newRow.size(); i++ )
+  {
+    U ( i, 0 ) = a[i];
+    U ( i, 1 ) = ei[i];
+    V ( 0, i ) = ei[i];
+    V ( 1, i ) = a[i];
+  }
+
+  if ( verbose )
+  {
+    std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- U:"  << std::endl;
+    for ( uint ik = 0; ik < U.rows(); ik++ )
+    {
+      for ( uint jk = 0; jk < U.cols(); jk++ )
+      {
+        std::cerr << U ( ik, jk ) << " ";
+      }
+      std::cerr << std::endl;
+    }
+    std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- V:"  << std::endl;
+    for ( uint ik = 0; ik < V.rows(); ik++ )
+    {
+      for ( uint jk = 0; jk < V.cols(); jk++ )
+      {
+        std::cerr << V ( ik, jk ) << " ";
+      }
+      std::cerr << std::endl;
+    }
+  }
+
+  // Sherman Woodbury-Morrison Formula:
+  // alpha_new = (K + UV)^{-1} y = K^{-1} y - K^{-1} U ( I + V
+  // K^{-1} U )^{-1} V K^{-1} y = oldAlpha - B ( I + V B )^{-1} V oldAlpha
+  // = oldAlpha - B F^{-1} V oldAlpha
+  // with B = K^{-1} U and F = (I+VB)
+
+  // Time complexity: 2 choleskySolve calls: O(n^2)
+
+
+  NICE::Vector B_1;
+  computeInverseKernelMultiply ( U.getColumn ( 0 ), B_1 );
+
+  NICE::Vector B_2;
+  computeInverseKernelMultiply ( U.getColumn ( 1 ), B_2 );
+
+  B.resize ( newRow.size(), 2 );
+
+  for ( uint i = 0; i < newRow.size(); i++ )
+  {
+    B ( i, 0 ) = B_1[i];
+    B ( i, 1 ) = B_2[i];
+  }
+
+  if ( verbose )
+  {
+    std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- B:"  << std::endl;
+    for ( uint ik = 0; ik < B.rows(); ik++ )
+    {
+      for ( uint jk = 0; jk < B.cols(); jk++ )
+      {
+        std::cerr << B ( ik, jk ) << " ";
+      }
+      std::cerr << std::endl;
+    }
+  }
+
+  F.resize ( 2, 2 );
+  F.setIdentity();
+  Matrix V_B ( 2, 2 );
+  V_B.multiply ( V, B );
+  F += V_B;
+
+  if ( verbose )
+  {
+    std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- F:"  << std::endl;
+    for ( uint ik = 0; ik < F.rows(); ik++ )
+    {
+      for ( uint jk = 0; jk < F.cols(); jk++ )
+      {
+        std::cerr << F ( ik, jk ) << " ";
+      }
+      std::cerr << std::endl;
+    }
+  }
+
+  // Time complexity: 1 linear equation system with 2 variables
+  // can be computed in O(1) using a fixed implementation
+  F_inv.resize ( 2, 2 );
+  double denominator = F ( 0, 0 ) * F ( 1, 1 ) - F ( 0, 1 ) * F ( 1, 0 );
+  F_inv ( 0, 0 ) = F ( 1, 1 ) / denominator;
+  F_inv ( 0, 1 ) = -F ( 0, 1 ) / denominator;
+  F_inv ( 1, 0 ) = - F ( 1, 0 ) / denominator;
+  F_inv ( 1, 1 ) = F ( 0, 0 ) / denominator;
+  
+  if ( verbose )
+  {
+    std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- F_inv:"  << std::endl;
+    for ( uint ik = 0; ik < F_inv.rows(); ik++ )
+    {
+      for ( uint jk = 0; jk < F_inv.cols(); jk++ )
+      {
+        std::cerr << F_inv ( ik, jk ) << " ";
+      }
+      std::cerr << std::endl;
+    }
+
+    NICE::Matrix MultiplicationResult ( F_inv.cols(), F_inv.cols(), 0.0 );
+    MultiplicationResult.multiply ( F, F_inv );
+    std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- F-inversion MultiplicationResult:"  << std::endl;
+    for ( uint ik = 0; ik < MultiplicationResult.rows(); ik++ )
+    {
+      for ( uint jk = 0; jk < MultiplicationResult.cols(); jk++ )
+      {
+        std::cerr << MultiplicationResult ( ik, jk ) << " ";
+      }
+      std::cerr << std::endl;
+    }
+  }
 }
 
-/** 
+/**
 * @brief Updates the GP-Likelihood, if only the i-th row and column has changed. Time is O(n^2) instaed O(n^3). This is only the second part. Usefull for multiclass-problems.
 * @author Alexander Lütz
 * @date 01/12/2010 (dd/mm/yyyy)
 */
-void KernelData::getGPLikelihoodWithOneNewRow_SecondPart(  const NICE::Vector & y, const double & oldLogdetK, const Vector & oldAlpha , Vector & newAlpha, double & loglike)
+void KernelData::getGPLikelihoodWithOneNewRow_SecondPart ( const NICE::Vector & y, const double & oldLogdetK, const Vector & oldAlpha , Vector & newAlpha, double & loglike )
 {
-	Matrix M_oldAlpha (y.size(),1);
-	for (uint i = 0; i < y.size(); i++)
-	{
-		M_oldAlpha(i,0) = oldAlpha[i];
-	}
-	NICE::Matrix V_oldAlpha;
-	V_oldAlpha.multiply( V,M_oldAlpha);
-	NICE::Matrix F_inv_V_old_Alpha;
-	F_inv_V_old_Alpha.multiply(F_inv, V_oldAlpha);
-
-	NICE::Matrix M_newAlpha;
-	M_newAlpha.multiply(B, F_inv_V_old_Alpha);
-
-	M_newAlpha *= -1;
-	M_newAlpha += M_oldAlpha;
-
-	newAlpha = NICE::Vector(y.size());
-	for (uint i = 0; i < y.size(); i++)
-	{
-		newAlpha[i] = M_newAlpha(i,0);
-	}
-
-	// Matrix Determinant Lemma
-	// http://en.wikipedia.org/wiki/Matrix_determinant_lemma
-	// det(K + U*V) = det(I + V * K^{-1} * U) * det(K)
-	// logdet(K + U*V) = logdet( F ) + logdet(K)
-	double logdetF = log(F(0,0) * F(1,1) - F(0,1) * F(1,0));
-
-	double newLogdetK = logdetF + oldLogdetK;
-
-	logdet = newLogdetK;
-
-	loglike = newLogdetK + newAlpha.scalarProduct(y);
+  Matrix M_oldAlpha ( y.size(), 1 );
+  for ( uint i = 0; i < y.size(); i++ )
+  {
+    M_oldAlpha ( i, 0 ) = oldAlpha[i];
+  }
+  NICE::Matrix V_oldAlpha;
+  V_oldAlpha.multiply ( V, M_oldAlpha );
+  NICE::Matrix F_inv_V_old_Alpha;
+  F_inv_V_old_Alpha.multiply ( F_inv, V_oldAlpha );
+
+  NICE::Matrix M_newAlpha;
+  M_newAlpha.multiply ( B, F_inv_V_old_Alpha );
+
+  M_newAlpha *= -1;
+  M_newAlpha += M_oldAlpha;
+
+  newAlpha = NICE::Vector ( y.size() );
+  for ( uint i = 0; i < y.size(); i++ )
+  {
+    newAlpha[i] = M_newAlpha ( i, 0 );
+  }
+
+  // Matrix Determinant Lemma
+  // http://en.wikipedia.org/wiki/Matrix_determinant_lemma
+  // det(K + U*V) = det(I + V * K^{-1} * U) * det(K)
+  // logdet(K + U*V) = logdet( F ) + logdet(K)
+  double logdetF = log ( F ( 0, 0 ) * F ( 1, 1 ) - F ( 0, 1 ) * F ( 1, 0 ) );
+
+  double newLogdetK = logdetF + oldLogdetK;
+
+  logdet = newLogdetK;
+
+  loglike = newLogdetK + newAlpha.scalarProduct ( y );
 }
 
 
-/** 
+/**
 * @brief Updates the GP-Likelihood, if only the i-th row and column has changed. Time is O(n^2) instaed O(n^3).
 * @author Alexander Lütz
 * @date 01/09/2011 (dd/mm/yyyy)
 */
-void KernelData::perform_Rank_2_Update(const int & rowIndex, const NICE::Vector & newRow)
+void KernelData::perform_Rank_2_Update ( const int & rowIndex, const NICE::Vector & newRow )
 {
-	getGPLikelihoodWithOneNewRow_FirstPart(rowIndex,newRow);
-	Matrix prod_1;
-	prod_1.multiply(V,inverseKernelMatrix);
-	
-	if (verbose)
-	{
-		std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- prod_1:"  << std::endl;
-		for ( uint ik = 0; ik < prod_1.rows(); ik++ )
-		{
-			for ( uint jk = 0; jk < prod_1.cols(); jk++)
-			{
-				std::cerr << prod_1(ik,jk) << " ";
-			}
-			std::cerr << std::endl;
-		}
-	}
-	
-	Matrix prod_2;
-	prod_2.multiply(F_inv,prod_1);
-	
-	if (verbose)
-	{
-		std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- prod_2:"  << std::endl;
-		for ( uint ik = 0; ik < prod_2.rows(); ik++ )
-		{
-			for ( uint jk = 0; jk < prod_2.cols(); jk++)
-			{
-				std::cerr << prod_2(ik,jk) << " ";
-			}
-			std::cerr << std::endl;
-		}
-	}
-	
-	Matrix prod_3;
-	prod_3.multiply(B,prod_2);
-	
-	if (verbose)
-	{
-		std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- prod_3:"  << std::endl;
-		for ( uint ik = 0; ik < prod_3.rows(); ik++ )
-		{
-			for ( uint jk = 0; jk < prod_3.cols(); jk++)
-			{
-				std::cerr << prod_3(ik,jk) << " ";
-			}
-			std::cerr << std::endl;
-		}
-	}
-	inverseKernelMatrix = inverseKernelMatrix - prod_3;
-	
-	//correct the stored kernel matrix after our computations
-	for (uint i = 0; i < newRow.size(); i++)
-	{
-		kernelMatrix(i,rowIndex) = newRow[i];
-		kernelMatrix(rowIndex,i) = newRow[i];
-	}
+  getGPLikelihoodWithOneNewRow_FirstPart ( rowIndex, newRow );
+  Matrix prod_1;
+  prod_1.multiply ( V, inverseKernelMatrix );
+
+  if ( verbose )
+  {
+    std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- prod_1:"  << std::endl;
+    for ( uint ik = 0; ik < prod_1.rows(); ik++ )
+    {
+      for ( uint jk = 0; jk < prod_1.cols(); jk++ )
+      {
+        std::cerr << prod_1 ( ik, jk ) << " ";
+      }
+      std::cerr << std::endl;
+    }
+  }
+
+  Matrix prod_2;
+  prod_2.multiply ( F_inv, prod_1 );
+
+  if ( verbose )
+  {
+    std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- prod_2:"  << std::endl;
+    for ( uint ik = 0; ik < prod_2.rows(); ik++ )
+    {
+      for ( uint jk = 0; jk < prod_2.cols(); jk++ )
+      {
+        std::cerr << prod_2 ( ik, jk ) << " ";
+      }
+      std::cerr << std::endl;
+    }
+  }
+
+  Matrix prod_3;
+  prod_3.multiply ( B, prod_2 );
+
+  if ( verbose )
+  {
+    std::cerr << std::endl << "KernelData::perform_Rank_2_Update -- prod_3:"  << std::endl;
+    for ( uint ik = 0; ik < prod_3.rows(); ik++ )
+    {
+      for ( uint jk = 0; jk < prod_3.cols(); jk++ )
+      {
+        std::cerr << prod_3 ( ik, jk ) << " ";
+      }
+      std::cerr << std::endl;
+    }
+  }
+  inverseKernelMatrix = inverseKernelMatrix - prod_3;
+  
+//   std::cerr << "perform rank 2 update: inverseKernelMatrix: " << inverseKernelMatrix << std::endl;
+
+  //correct the stored kernel matrix after our computations
+  for ( uint i = 0; i < newRow.size(); i++ )
+  {
+    kernelMatrix ( i, rowIndex ) = newRow[i];
+    kernelMatrix ( rowIndex, i ) = newRow[i];
+  }
+//   std::cerr << "kernelMatrix: " << kernelMatrix << std::endl << " newRow: " << newRow << std::endl;
 }
 
-/** 
+/**
 * @brief Updates the GP-Likelihood, if only k rows and colums are changed. Time is O(k^3+n^2) instaed O(n^3). Alternatively it could also be done with iteratively change one row, which leads to O(k*n^2).
 * @author Alexander Lütz
 * @date 01/09/2011 (dd/mm/yyyy)
 */
-void KernelData::perform_Rank_2k_Update(const std::vector<int> & rowIndices, const std::vector<NICE::Vector> & newRows)
+void KernelData::perform_Rank_2k_Update ( const std::vector<int> & rowIndices, const std::vector<NICE::Vector> & newRows )
 {
-	if ( (rowIndices.size() != 0) && (rowIndices.size() == newRows.size()) )
-	{
-		std::vector<NICE::Vector> unity_vectors;
-		std::vector<NICE::Vector> diff_vectors;
-		for (uint j = 0; j < rowIndices.size(); j++)
-		{
-			NICE::Vector unity_vector(newRows[0].size(), 0.0);
-			unity_vector[rowIndices[j] ] = 1.0;
-			unity_vectors.push_back(unity_vector);
-			
-			NICE::Vector a = newRows[j] - kernelMatrix.getRow(rowIndices[j]);
-			for (uint x = 0; x < rowIndices.size(); x++)
-			{
-				a[rowIndices[x] ] /= 2.0;
-			}
-			diff_vectors.push_back(a);
-		}
-
-		U.resize(newRows[0].size(),2*rowIndices.size());
-		V.resize(2*rowIndices.size(),newRows[0].size());
-		
-		for (uint i = 0; i < newRows[0].size(); i++)
-		{
-			for (uint j = 0; j < rowIndices.size(); j++)
-			{
-				U(i,rowIndices.size()+j) = (unity_vectors[j])[i];
-				U(i,j) = (diff_vectors[j])[i];
-				
-				V(rowIndices.size()+j,i) = (diff_vectors[j])[i];
-				V(j,i) = (unity_vectors[j])[i];
-			}
-		}
-		
-		if (verbose)
-		{
-			std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- U:"  << std::endl;
-			for ( uint ik = 0; ik < U.rows(); ik++ )
-			{
-				for ( uint jk = 0; jk < U.cols(); jk++)
-				{
-					std::cerr << U(ik,jk) << " ";
-				}
-				std::cerr << std::endl;
-			}
-			std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- V:"  << std::endl;
-			for ( uint ik = 0; ik < V.rows(); ik++ )
-			{
-				for ( uint jk = 0; jk < V.cols(); jk++)
-				{
-					std::cerr << V(ik,jk) << " ";
-				}
-				std::cerr << std::endl;
-			}
-		}
-		
-		NICE::Matrix UV(newRows[0].size(),newRows[0].size());
-		UV.multiply(U,V);
-	
-		if (verbose)
-		{
-			// we have to consider the entries which are added twice
-			for (int x = 0; x < (int)rowIndices.size(); x++)
-			{
-				for (int y = x; y < (int)rowIndices.size(); y++)
-				{
-					UV(rowIndices[x] , rowIndices[y]) /= 2.0;
-					if (x!=y)
-						UV(rowIndices[y] , rowIndices[x]) /= 2.0;
-				}
-			}
-		}
-		
-		if (verbose)
-		{
-			std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- UV:"  << std::endl;
-			for ( uint ik = 0; ik < UV.rows(); ik++ )
-			{
-				for ( uint jk = 0; jk < UV.cols(); jk++)
-				{
-					std::cerr << UV(ik,jk) << " ";
-				}
-				std::cerr << std::endl;
-			}
-		}
-		
-		
-		B.resize(newRows[0].size(),2*rowIndices.size());
-		for (uint j = 0; j < 2*rowIndices.size(); j++)
-		{
-			NICE::Vector B_row;
-			computeInverseKernelMultiply(U.getColumn(j),B_row);
-			for (uint i = 0; i < newRows[0].size(); i++)
-			{
-				B(i,j) = B_row[i];
-			}
-		}
-		
-		if (verbose)
-		{
-			std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- B:"  << std::endl;
-			for ( uint ik = 0; ik < B.rows(); ik++ )
-			{
-				for ( uint jk = 0; jk < B.cols(); jk++)
-				{
-					std::cerr << B(ik,jk) << " ";
-				}
-				std::cerr << std::endl;
-			}
-		}
-		
-		F.resize(2*rowIndices.size(),2*rowIndices.size());
-		F.setIdentity();
-		Matrix V_B (2*rowIndices.size(),2*rowIndices.size());
-		V_B.multiply(V,B);
-		F += V_B;
-		
-		if (verbose)
-		{
-			std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- F:"  << std::endl;
-			for ( uint ik = 0; ik < F.rows(); ik++ )
-			{
-				for ( uint jk = 0; jk < F.cols(); jk++)
-				{
-					std::cerr << F(ik,jk) << " ";
-				}
-				std::cerr << std::endl;
-			}
-		}
-
-		//invert F!
-		F_inv = invert(F);
-
-		if (verbose)
-		{
-			std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- F_inv:"  << std::endl;
-			for ( uint ik = 0; ik < F_inv.rows(); ik++ )
-			{
-				for ( uint jk = 0; jk < F_inv.cols(); jk++)
-				{
-					std::cerr << F_inv(ik,jk) << " ";
-				}
-				std::cerr << std::endl;
-			}
-		}
-		
-		NICE::Matrix MultiplicationResult( F.rows(), F_inv.cols(), 0.0 );
-		MultiplicationResult.multiply(F,F_inv);
-		
-		if (verbose)
-		{
-			std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- F-inversion MultiplicationResult:"  << std::endl;
-			for ( uint ik = 0; ik < MultiplicationResult.rows(); ik++ )
-			{
-				for ( uint jk = 0; jk < MultiplicationResult.cols(); jk++)
-				{
-					std::cerr << MultiplicationResult(ik,jk) << " ";
-				}
-				std::cerr << std::endl;
-			}
-		}
-		
-		Matrix prod_1;
-		prod_1.multiply(V,inverseKernelMatrix);
-		
-		if (verbose)
-		{
-			std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- prod_1:"  << std::endl;
-			for ( uint ik = 0; ik < prod_1.rows(); ik++ )
-			{
-				for ( uint jk = 0; jk < prod_1.cols(); jk++)
-				{
-					std::cerr << prod_1(ik,jk) << " ";
-				}
-				std::cerr << std::endl;
-			}
-		}
-		
-		Matrix prod_2;
-		prod_2.multiply(F_inv,prod_1);
-		
-		if (verbose)
-		{
-			std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- prod_2:"  << std::endl;
-			for ( uint ik = 0; ik < prod_2.rows(); ik++ )
-			{
-				for ( uint jk = 0; jk < prod_2.cols(); jk++)
-				{
-					std::cerr << prod_2(ik,jk) << " ";
-				}
-				std::cerr << std::endl;
-			}
-		}
-
-		Matrix prod_3;
-		prod_3.multiply(B,prod_2);
-		
-		if (verbose)
-		{
-			std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- prod_3:"  << std::endl;
-			for ( uint ik = 0; ik < prod_3.rows(); ik++ )
-			{
-				for ( uint jk = 0; jk < prod_3.cols(); jk++)
-				{
-					std::cerr << prod_3(ik,jk) << " ";
-				}
-				std::cerr << std::endl;
-			}
-		}
-		inverseKernelMatrix = inverseKernelMatrix - prod_3;
-		
-		//remember the new kernel entries for the next time
-		for (uint i = 0; i < rowIndices.size(); i++)
-		{
-			for ( uint ik = 0; ik < kernelMatrix.rows(); ik++ )
-			{
-				kernelMatrix(ik,rowIndices[i]) = (newRows[i])[ik];
-				kernelMatrix(rowIndices[i],ik) = (newRows[i])[ik];
-			}
-		}
-	}
-	else
-	{
-		std::cerr << "Failure" << std::endl;
-	}
+  if ( ( rowIndices.size() != 0 ) && ( rowIndices.size() == newRows.size() ) )
+  {
+    std::vector<NICE::Vector> unity_vectors;
+    std::vector<NICE::Vector> diff_vectors;
+    for ( uint j = 0; j < rowIndices.size(); j++ )
+    {
+      NICE::Vector unity_vector ( newRows[0].size(), 0.0 );
+      unity_vector[rowIndices[j] ] = 1.0;
+      unity_vectors.push_back ( unity_vector );
+
+      NICE::Vector a = newRows[j] - kernelMatrix.getRow ( rowIndices[j] );
+      for ( uint x = 0; x < rowIndices.size(); x++ )
+      {
+        a[rowIndices[x] ] /= 2.0;
+      }
+      diff_vectors.push_back ( a );
+    }
+
+    U.resize ( newRows[0].size(), 2*rowIndices.size() );
+    V.resize ( 2*rowIndices.size(), newRows[0].size() );
+
+    for ( uint i = 0; i < newRows[0].size(); i++ )
+    {
+      for ( uint j = 0; j < rowIndices.size(); j++ )
+      {
+        U ( i, rowIndices.size() + j ) = ( unity_vectors[j] ) [i];
+        U ( i, j ) = ( diff_vectors[j] ) [i];
+
+        V ( rowIndices.size() + j, i ) = ( diff_vectors[j] ) [i];
+        V ( j, i ) = ( unity_vectors[j] ) [i];
+      }
+    }
+
+    if ( verbose )
+    {
+      std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- U: " << U << std::endl;
+      std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- V: " << V  << std::endl;
+    }
+
+    NICE::Matrix UV ( newRows[0].size(), newRows[0].size() );
+    UV.multiply ( U, V );
+
+    if ( verbose )
+    {
+      // we have to consider the entries which are added twice
+      for ( int x = 0; x < ( int ) rowIndices.size(); x++ )
+      {
+        for ( int y = x; y < ( int ) rowIndices.size(); y++ )
+        {
+          UV ( rowIndices[x] , rowIndices[y] ) /= 2.0;
+          if ( x != y )
+            UV ( rowIndices[y] , rowIndices[x] ) /= 2.0;
+        }
+      }
+    }
+
+    if ( verbose )
+    {
+      std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- UV:"  << UV << std::endl;
+    }
+
+
+    B.resize ( newRows[0].size(), 2*rowIndices.size() );
+    for ( uint j = 0; j < 2*rowIndices.size(); j++ )
+    {
+      NICE::Vector B_row;
+      computeInverseKernelMultiply ( U.getColumn ( j ), B_row );
+      for ( uint i = 0; i < newRows[0].size(); i++ )
+      {
+        B ( i, j ) = B_row[i];
+      }
+    }
+
+    if ( verbose )
+    {
+      std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- B:"  << B << std::endl;
+    }
+
+    F.resize ( 2*rowIndices.size(), 2*rowIndices.size() );
+    F.setIdentity();
+    Matrix V_B ( 2*rowIndices.size(), 2*rowIndices.size() );
+    V_B.multiply ( V, B );
+    F += V_B;
+
+    if ( verbose )
+    {
+      std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- F:"  << F << std::endl;
+    }
+
+    //invert F!
+    //we can't rely on methods like cholesky decomposition, since F has not to be positive definite
+    F_inv = invert ( F );
+
+    if ( verbose )
+    {
+      std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- F_inv:"  << F_inv <<std::endl;
+    }
+
+    if ( verbose )
+    {
+      NICE::Matrix MultiplicationResult ( F.rows(), F_inv.cols(), 0.0 );
+      MultiplicationResult.multiply ( F, F_inv );  
+      std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- F-inversion MultiplicationResult:"  << MultiplicationResult << std::endl;
+    }
+
+    Matrix prod_1;  
+    prod_1.multiply ( V, inverseKernelMatrix );
+    std::cerr << "prod_1: " << prod_1.rows() << " x " << prod_1.cols() << std::endl;
+    
+    std::cerr << "v and inverse matrix multiplied" << std::endl;
+
+    if ( verbose )
+    {
+      std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- prod_1:"  << prod_1 << std::endl;
+    }
+
+    Matrix prod_2;   
+    prod_2.resize(F.rows(), prod_1.cols());
+          
+    prod_2.multiply ( F_inv, prod_1 );
+
+    if ( verbose )
+    {
+      std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- prod_2:"  << prod_2 << std::endl;
+    }
+
+    std::cerr << "B: " << B.rows() << " x " << B.cols() << std::endl;
+    Matrix prod_3;
+    prod_3.multiply ( B, prod_2 );
+    
+    std::cerr << "prod_3 created: " << prod_3.rows() << " x " << prod_3.cols() << std::endl;
+
+    if ( verbose )
+    {
+      std::cerr << std::endl << "KernelData::perform_Rank_2k_Update -- prod_3:"  << prod_3 << std::endl;
+    }
+    inverseKernelMatrix = inverseKernelMatrix - prod_3;
+
+    //remember the new kernel entries for the next time
+    for ( uint i = 0; i < rowIndices.size(); i++ )
+    {
+      for ( uint ik = 0; ik < kernelMatrix.rows(); ik++ )
+      {
+        kernelMatrix ( ik, rowIndices[i] ) = ( newRows[i] ) [ik];
+        kernelMatrix ( rowIndices[i], ik ) = ( newRows[i] ) [ik];
+      }
+    }
+  }
+  else
+  {
+    std::cerr << "Failure" << std::endl;
+  }
 }
 
-void KernelData::delete_one_row(const int & rowIndex)
+void KernelData::delete_one_row ( const int & rowIndex )
 {
-	if ( (inverseKernelMatrix.rows() != 0) && (inverseKernelMatrix.cols() != 0)) 
-	{
-		inverseKernelMatrix.deleteCol(rowIndex);
-		inverseKernelMatrix.deleteRow(rowIndex);
-	}
-
-	if ( (choleskyMatrix.rows() != 0) && (choleskyMatrix.cols() != 0)) 
-	{
-		choleskyMatrix.deleteCol(rowIndex);
-		choleskyMatrix.deleteRow(rowIndex);
-	}
-	
-	if ( (kernelMatrix.rows() != 0) && (kernelMatrix.cols() != 0)) 
-	{
-		kernelMatrix.deleteCol(rowIndex);
-		kernelMatrix.deleteRow(rowIndex);
-	}
+  if ( ( inverseKernelMatrix.rows() != 0 ) && ( inverseKernelMatrix.cols() != 0 ) )
+  {
+    inverseKernelMatrix.deleteCol ( rowIndex );
+    inverseKernelMatrix.deleteRow ( rowIndex );
+  }
+
+  if ( ( choleskyMatrix.rows() != 0 ) && ( choleskyMatrix.cols() != 0 ) )
+  {
+    choleskyMatrix.deleteCol ( rowIndex );
+    choleskyMatrix.deleteRow ( rowIndex );
+  }
+
+  if ( ( kernelMatrix.rows() != 0 ) && ( kernelMatrix.cols() != 0 ) )
+  {
+    kernelMatrix.deleteCol ( rowIndex );
+    kernelMatrix.deleteRow ( rowIndex );
+  }
 }
 
-void KernelData::delete_multiple_rows(std::vector<int> & indices)
+void KernelData::delete_multiple_rows ( std::vector<int> & indices )
 {
-	if ( (inverseKernelMatrix.rows() >= indices.size()) && (inverseKernelMatrix.cols() >= indices.size())) 
-	{
-		inverseKernelMatrix.deleteCols(indices);
-		inverseKernelMatrix.deleteRows(indices);
-	}
-
-	if ( (choleskyMatrix.rows() >= indices.size()) && (choleskyMatrix.cols() >= indices.size())) 
-	{
-		choleskyMatrix.deleteCols(indices);
-		choleskyMatrix.deleteRows(indices);
-	}
-	
-	if ( (kernelMatrix.rows() >= indices.size()) && (kernelMatrix.cols() >= indices.size())) 
-	{
-		kernelMatrix.deleteCols(indices);
-		kernelMatrix.deleteRows(indices);
-	}
+  if ( ( inverseKernelMatrix.rows() >= indices.size() ) && ( inverseKernelMatrix.cols() >= indices.size() ) )
+  {
+    inverseKernelMatrix.deleteCols ( indices );
+    inverseKernelMatrix.deleteRows ( indices );
+  }
+
+  if ( ( choleskyMatrix.rows() >= indices.size() ) && ( choleskyMatrix.cols() >= indices.size() ) )
+  {
+    choleskyMatrix.deleteCols ( indices );
+    choleskyMatrix.deleteRows ( indices );
+  }
+
+  if ( ( kernelMatrix.rows() >= indices.size() ) && ( kernelMatrix.cols() >= indices.size() ) )
+  {
+    kernelMatrix.deleteCols ( indices );
+    kernelMatrix.deleteRows ( indices );
+  }
 }
 
-void KernelData::setKernelMatrix(const NICE::Matrix & k_matrix)
+void KernelData::setKernelMatrix ( const NICE::Matrix & k_matrix )
 {
-	kernelMatrix = k_matrix;
+  kernelMatrix = k_matrix;
 }
 
 void KernelData::increase_size_by_One()
 {
-	NICE::Matrix new_Kernel(kernelMatrix.rows()+1, kernelMatrix.cols()+1);
-	new_Kernel.setBlock(0, 0, kernelMatrix);
-	for (uint i = 0; i < kernelMatrix.rows()-1; i++)
-	{
-		new_Kernel(i,kernelMatrix.cols()) = 0.0;
-		new_Kernel(kernelMatrix.rows(),i) = 0.0;
-	}
-	new_Kernel(kernelMatrix.rows(),kernelMatrix.cols()) = 1.0;
-	//NOTE Maybe it would be more efficient to work directly with pointers to the memory
-	kernelMatrix.resize(new_Kernel.rows(), new_Kernel.cols());
-	kernelMatrix = new_Kernel;
-	
-	new_Kernel.setBlock(0, 0, inverseKernelMatrix);
-	//NOTE Maybe it would be more efficient to work directly with pointers to the memory
-	inverseKernelMatrix.resize(new_Kernel.rows(), new_Kernel.cols());
-	inverseKernelMatrix = new_Kernel;
-
-	new_Kernel.setBlock(0, 0, choleskyMatrix);
-	//NOTE Maybe it would be more efficient to work directly with pointers to the memory
-	choleskyMatrix.resize(new_Kernel.rows(), new_Kernel.cols());
-	choleskyMatrix = new_Kernel;
+  NICE::Matrix new_Kernel ( kernelMatrix.rows() + 1, kernelMatrix.cols() + 1 );
+  new_Kernel.setBlock ( 0, 0, kernelMatrix );
+  for ( uint i = 0; i < kernelMatrix.rows() - 1; i++ )
+  {
+    new_Kernel ( i, kernelMatrix.cols() ) = 0.0;
+    new_Kernel ( kernelMatrix.rows(), i ) = 0.0;
+  }
+  new_Kernel ( kernelMatrix.rows(), kernelMatrix.cols() ) = 1.0;
+  //NOTE Maybe it would be more efficient to work directly with pointers to the memory
+  kernelMatrix.resize ( new_Kernel.rows(), new_Kernel.cols() );
+  kernelMatrix = new_Kernel;
+
+  new_Kernel.setBlock ( 0, 0, inverseKernelMatrix );
+  //NOTE Maybe it would be more efficient to work directly with pointers to the memory
+  inverseKernelMatrix.resize ( new_Kernel.rows(), new_Kernel.cols() );
+  inverseKernelMatrix = new_Kernel;
+
+  new_Kernel.setBlock ( 0, 0, choleskyMatrix );
+  //NOTE Maybe it would be more efficient to work directly with pointers to the memory
+  choleskyMatrix.resize ( new_Kernel.rows(), new_Kernel.cols() );
+  choleskyMatrix = new_Kernel;
 }
 
-void KernelData::increase_size_by_k(const uint & k)
+void KernelData::increase_size_by_k ( const uint & k )
 {
-	NICE::Matrix new_Kernel(kernelMatrix.rows()+k, kernelMatrix.cols()+k);
-	new_Kernel.setBlock(0, 0, kernelMatrix);
-	for (uint i = 0; i < kernelMatrix.rows()-1; i++)
-	{
-		for (uint j = 0; j < k; j++)
-		{
-			new_Kernel(i,kernelMatrix.cols()+j) = 0.0;
-			new_Kernel(kernelMatrix.rows()+j,i) = 0.0;
-		}
-	}
-	for (uint j = 0; j < k; j++)
-	{
-		new_Kernel(kernelMatrix.rows()+j,kernelMatrix.cols()+j) = 1.0;
-	}
-	//NOTE Maybe it would be more efficient to work directly with pointers to the memory
-	kernelMatrix.resize(new_Kernel.rows(), new_Kernel.cols());
-	kernelMatrix = new_Kernel;
-	
-	new_Kernel.setBlock(0, 0, inverseKernelMatrix);
-	//NOTE Maybe it would be more efficient to work directly with pointers to the memory
-	inverseKernelMatrix.resize(new_Kernel.rows(), new_Kernel.cols());
-	inverseKernelMatrix = new_Kernel;
-
-	new_Kernel.setBlock(0, 0, choleskyMatrix);
-	//NOTE Maybe it would be more efficient to work directly with pointers to the memory
-	choleskyMatrix.resize(new_Kernel.rows(), new_Kernel.cols());
-	choleskyMatrix = new_Kernel;
+  NICE::Matrix new_Kernel ( kernelMatrix.rows() + k, kernelMatrix.cols() + k );
+  new_Kernel.setBlock ( 0, 0, kernelMatrix );
+  for ( uint i = 0; i < kernelMatrix.rows() - 1; i++ )
+  {
+    for ( uint j = 0; j < k; j++ )
+    {
+      new_Kernel ( i, kernelMatrix.cols() + j ) = 0.0;
+      new_Kernel ( kernelMatrix.rows() + j, i ) = 0.0;
+    }
+  }
+  for ( uint j = 0; j < k; j++ )
+  {
+    new_Kernel ( kernelMatrix.rows() + j, kernelMatrix.cols() + j ) = 1.0;
+  }
+  //NOTE Maybe it would be more efficient to work directly with pointers to the memory
+  kernelMatrix.resize ( new_Kernel.rows(), new_Kernel.cols() );
+  kernelMatrix = new_Kernel;
+
+  new_Kernel.setBlock ( 0, 0, inverseKernelMatrix );
+  //NOTE Maybe it would be more efficient to work directly with pointers to the memory
+  inverseKernelMatrix.resize ( new_Kernel.rows(), new_Kernel.cols() );
+  inverseKernelMatrix = new_Kernel;
+
+  new_Kernel.setBlock ( 0, 0, choleskyMatrix );
+  //NOTE Maybe it would be more efficient to work directly with pointers to the memory
+  choleskyMatrix.resize ( new_Kernel.rows(), new_Kernel.cols() );
+  choleskyMatrix = new_Kernel;
 }

+ 1 - 1
math/kernels/KernelData.h

@@ -61,7 +61,7 @@ class KernelData
 		KernelData( const NICE::Config *conf, const std::string & section = "Kernel" );
 		
 		/** the config contains information about numerical setting of the cholesky factorization etc. */
-		KernelData( const NICE::Config *conf, const NICE::Matrix & kernelMatrix, const std::string & section = "Kernel" );
+		KernelData( const NICE::Config *conf, const NICE::Matrix & kernelMatrix, const std::string & section = "Kernel", bool updateCholesky = true );
 		  
 		/** simple destructor */
 		virtual ~KernelData();

+ 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 "vislearning/matlabAccess/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;
+}

+ 1 - 1
optimization/quadprog/QuadProg++.cpp

@@ -728,7 +728,7 @@ void cholesky_decomposition(Matrix<double>& A)
 	}
 	NICE::Matrix L;
 	L.resize(n,n);
-	NICE::CholeskyRobust *cra = new NICE::CholeskyRobustAuto(true);
+	NICE::CholeskyRobust *cra = new NICE::CholeskyRobustAuto(false);
 	cra->robustChol ( M, L );
 	//copy back
 	for (i = 0; i < n; i++)

+ 46 - 0
progs/ImagenetBinary.conf

@@ -0,0 +1,46 @@
+[main]
+# whether to use eriks folder (only works on dionysos)
+imageNetLocal = false
+shareParameters = true
+noise = 0.1
+sigma = 1.0
+
+#GP variance approximation
+sigmaGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarSigma.txt
+noiseGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarNoise.txt
+#GP variance
+sigmaGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarSigma.txt
+noiseGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarNoise.txt
+#GP mean approximation
+sigmaGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarSigma.txt
+noiseGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarNoise.txt
+#GP mean
+sigmaGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarSigma.txt
+noiseGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarNoise.txt
+#Parzen
+sigmaGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarSigma.txt
+noiseGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarNoise.txt
+#SVDD
+sigmaGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarSigma.txt
+noiseGPVarApproxFile = /home/luetz/code/nice/vislearning/progs/gpvarNoise.txt
+
+indexOfFirstClass = 0
+indexOfLastClass = 0
+runsPerClassToAverageTraining = 1000
+runsPerClassToAverageTesting = 1
+
+nrOfExamplesPerClass = 100
+
+GPSRMean = true
+GPSRVar = true
+GPMean = false
+GPVar = false
+GPMeanApprox = false
+GPVarApprox = false
+GPOptMean = false
+GPOptVar = false
+Parzen = false
+SVDD = false
+
+[GPSR]
+nrOfRegressors = 50

+ 1000 - 0
progs/approxVarNoise.txt

@@ -0,0 +1,1000 @@
+0.025
+0.025
+0.025
+0.025
+0.2
+0.2
+0.025
+0.15
+0.15
+0.025
+0.025
+0.1
+0.025
+0.125
+0.2
+0.2
+0.1
+0.025
+0.2
+0.05
+0.175
+0.2
+0.025
+0.05
+0.025
+0.025
+0.075
+0.2
+0.025
+0.025
+0.025
+0.175
+0.025
+0.2
+0.025
+0.025
+0.025
+0.025
+0.15
+0.025
+0.025
+0.05
+0.2
+0.125
+0.1
+0.15
+0.175
+0.025
+0.2
+0.025
+0.025
+0.075
+0.1
+0.025
+0.025
+0.025
+0.125
+0.15
+0.025
+0.025
+0.025
+0.075
+0.025
+0.125
+0.025
+0.025
+0.025
+0.025
+0.2
+0.025
+0.025
+0.025
+0.025
+0.05
+0.2
+0.075
+0.025
+0.025
+0.025
+0.075
+0.025
+0.05
+0.2
+0.025
+0.025
+0.175
+0.125
+0.025
+0.025
+0.075
+0.05
+0.025
+0.2
+0.2
+0.2
+0.2
+0.025
+0.175
+0.025
+0.025
+0.1
+0.2
+0.2
+0.05
+0.2
+0.025
+0.2
+0.2
+0.2
+0.2
+0.2
+0.2
+0.025
+0.05
+0.025
+0.2
+0.025
+0.025
+0.2
+0.2
+0.025
+0.025
+0.175
+0.025
+0.2
+0.2
+0.1
+0.1
+0.1
+0.025
+0.2
+0.125
+0.2
+0.025
+0.075
+0.2
+0.075
+0.025
+0.2
+0.075
+0.175
+0.025
+0.025
+0.15
+0.125
+0.2
+0.2
+0.025
+0.025
+0.025
+0.025
+0.2
+0.2
+0.2
+0.025
+0.2
+0.2
+0.15
+0.075
+0.025
+0.175
+0.2
+0.2
+0.2
+0.025
+0.025
+0.025
+0.025
+0.2
+0.025
+0.025
+0.2
+0.025
+0.025
+0.15
+0.2
+0.15
+0.15
+0.05
+0.1
+0.2
+0.2
+0.2
+0.2
+0.2
+0.175
+0.025
+0.2
+0.05
+0.05
+0.025
+0.025
+0.025
+0.075
+0.025
+0.2
+0.2
+0.025
+0.2
+0.2
+0.025
+0.15
+0.025
+0.025
+0.2
+0.025
+0.025
+0.075
+0.025
+0.2
+0.2
+0.2
+0.025
+0.2
+0.025
+0.2
+0.175
+0.025
+0.025
+0.025
+0.2
+0.2
+0.025
+0.2
+0.025
+0.025
+0.1
+0.025
+0.025
+0.2
+0.025
+0.025
+0.2
+0.025
+0.05
+0.025
+0.025
+0.2
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.05
+0.025
+0.05
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.175
+0.025
+0.2
+0.025
+0.175
+0.1
+0.025
+0.15
+0.2
+0.175
+0.05
+0.025
+0.175
+0.025
+0.2
+0.025
+0.025
+0.025
+0.2
+0.025
+0.2
+0.025
+0.2
+0.025
+0.2
+0.2
+0.025
+0.025
+0.175
+0.025
+0.025
+0.2
+0.025
+0.2
+0.2
+0.1
+0.025
+0.2
+0.025
+0.025
+0.025
+0.025
+0.025
+0.125
+0.05
+0.025
+0.15
+0.2
+0.025
+0.025
+0.05
+0.025
+0.025
+0.025
+0.025
+0.175
+0.025
+0.025
+0.025
+0.2
+0.05
+0.2
+0.1
+0.025
+0.2
+0.15
+0.025
+0.025
+0.025
+0.025
+0.175
+0.2
+0.15
+0.025
+0.025
+0.05
+0.025
+0.125
+0.05
+0.2
+0.15
+0.025
+0.2
+0.025
+0.2
+0.025
+0.05
+0.025
+0.025
+0.2
+0.025
+0.175
+0.05
+0.15
+0.125
+0.025
+0.15
+0.125
+0.15
+0.025
+0.025
+0.025
+0.025
+0.025
+0.2
+0.075
+0.025
+0.15
+0.025
+0.025
+0.025
+0.175
+0.025
+0.025
+0.125
+0.2
+0.025
+0.075
+0.175
+0.025
+0.15
+0.025
+0.2
+0.075
+0.125
+0.2
+0.025
+0.1
+0.025
+0.025
+0.2
+0.025
+0.05
+0.025
+0.025
+0.125
+0.2
+0.025
+0.05
+0.025
+0.175
+0.125
+0.075
+0.025
+0.025
+0.2
+0.125
+0.125
+0.025
+0.075
+0.025
+0.025
+0.05
+0.05
+0.025
+0.075
+0.025
+0.025
+0.025
+0.025
+0.15
+0.075
+0.025
+0.025
+0.05
+0.2
+0.175
+0.15
+0.025
+0.025
+0.025
+0.025
+0.025
+0.175
+0.025
+0.2
+0.025
+0.025
+0.1
+0.025
+0.2
+0.05
+0.025
+0.025
+0.05
+0.2
+0.025
+0.025
+0.075
+0.175
+0.2
+0.075
+0.025
+0.2
+0.025
+0.025
+0.075
+0.1
+0.025
+0.175
+0.175
+0.025
+0.2
+0.125
+0.2
+0.025
+0.175
+0.025
+0.175
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.05
+0.025
+0.175
+0.05
+0.025
+0.025
+0.2
+0.025
+0.05
+0.075
+0.15
+0.025
+0.025
+0.025
+0.05
+0.2
+0.2
+0.2
+0.125
+0.025
+0.025
+0.025
+0.025
+0.175
+0.025
+0.025
+0.175
+0.025
+0.025
+0.2
+0.2
+0.075
+0.025
+0.025
+0.025
+0.05
+0.1
+0.2
+0.025
+0.2
+0.025
+0.2
+0.025
+0.025
+0.2
+0.025
+0.2
+0.15
+0.025
+0.15
+0.025
+0.2
+0.2
+0.2
+0.2
+0.15
+0.175
+0.15
+0.025
+0.2
+0.025
+0.2
+0.175
+0.2
+0.2
+0.025
+0.05
+0.1
+0.175
+0.175
+0.025
+0.2
+0.2
+0.175
+0.025
+0.05
+0.15
+0.025
+0.025
+0.2
+0.025
+0.2
+0.2
+0.125
+0.025
+0.025
+0.025
+0.025
+0.2
+0.2
+0.2
+0.025
+0.2
+0.075
+0.025
+0.1
+0.2
+0.2
+0.025
+0.025
+0.025
+0.075
+0.025
+0.025
+0.025
+0.2
+0.05
+0.175
+0.2
+0.175
+0.05
+0.2
+0.025
+0.2
+0.175
+0.075
+0.025
+0.025
+0.025
+0.025
+0.2
+0.2
+0.05
+0.2
+0.025
+0.025
+0.025
+0.025
+0.075
+0.2
+0.2
+0.2
+0.025
+0.025
+0.2
+0.075
+0.075
+0.025
+0.2
+0.2
+0.2
+0.2
+0.025
+0.025
+0.2
+0.025
+0.2
+0.075
+0.2
+0.2
+0.2
+0.2
+0.2
+0.2
+0.025
+0.2
+0.2
+0.2
+0.025
+0.2
+0.075
+0.15
+0.025
+0.025
+0.025
+0.025
+0.125
+0.2
+0.025
+0.025
+0.025
+0.025
+0.025
+0.2
+0.025
+0.2
+0.025
+0.175
+0.175
+0.125
+0.025
+0.2
+0.05
+0.025
+0.2
+0.2
+0.175
+0.025
+0.025
+0.025
+0.1
+0.025
+0.15
+0.025
+0.025
+0.025
+0.025
+0.1
+0.2
+0.025
+0.1
+0.025
+0.025
+0.2
+0.125
+0.025
+0.2
+0.025
+0.2
+0.025
+0.025
+0.025
+0.025
+0.125
+0.025
+0.025
+0.025
+0.025
+0.025
+0.125
+0.025
+0.025
+0.025
+0.025
+0.025
+0.15
+0.1
+0.1
+0.025
+0.025
+0.2
+0.025
+0.075
+0.025
+0.025
+0.025
+0.025
+0.2
+0.175
+0.2
+0.075
+0.2
+0.025
+0.15
+0.2
+0.025
+0.025
+0.025
+0.2
+0.025
+0.025
+0.025
+0.025
+0.025
+0.2
+0.05
+0.025
+0.2
+0.025
+0.025
+0.175
+0.05
+0.1
+0.2
+0.025
+0.125
+0.025
+0.2
+0.2
+0.2
+0.05
+0.025
+0.075
+0.2
+0.025
+0.025
+0.075
+0.025
+0.075
+0.025
+0.125
+0.15
+0.075
+0.125
+0.025
+0.175
+0.05
+0.15
+0.175
+0.025
+0.025
+0.175
+0.025
+0.15
+0.125
+0.025
+0.125
+0.05
+0.025
+0.15
+0.2
+0.175
+0.2
+0.175
+0.025
+0.075
+0.2
+0.2
+0.2
+0.15
+0.025
+0.125
+0.2
+0.2
+0.025
+0.2
+0.025
+0.2
+0.025
+0.025
+0.025
+0.025
+0.1
+0.025
+0.125
+0.2
+0.025
+0.025
+0.025
+0.025
+0.2
+0.05
+0.05
+0.175
+0.2
+0.2
+0.025
+0.2
+0.025
+0.025
+0.2
+0.2
+0.025
+0.2
+0.15
+0.2
+0.025
+0.2
+0.175
+0.2
+0.025
+0.025
+0.025
+0.125
+0.15
+0.025
+0.025
+0.025
+0.025
+0.025
+0.175
+0.025
+0.1
+0.025
+0.175
+0.2
+0.025
+0.15
+0.1
+0.2
+0.025
+0.2
+0.025
+0.2
+0.075
+0.2
+0.025
+0.175
+0.2
+0.025
+0.175
+0.025
+0.05
+0.075
+0.025
+0.175
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.2
+0.2
+0.025
+0.2
+0.15
+0.025
+0.025
+0.2
+0.025
+0.1
+0.2
+0.2
+0.2
+0.2
+0.125
+0.2
+0.2
+0.125
+0.05
+0.025
+0.025
+0.025
+0.175
+0.2
+0.1
+0.175
+0.2
+0.025
+0.025
+0.025
+0.2
+0.025
+0.025
+0.2
+0.025
+0.2
+0.075
+0.025
+0.175
+0.075
+0.175
+0.075
+0.025
+0.025
+0.15
+0.025
+0.15
+0.175
+0.05
+0.025
+0.175
+0.025
+0.2
+0.025
+0.025
+0.025
+0.025
+0.175
+0.05
+0.2
+0.05
+0.025
+0.2
+0.075
+0.025
+0.025
+0.025
+0.2
+0.2
+0.2
+0.2
+0.175
+0.025
+0.125
+0.075
+0.025
+0.025
+0.025
+0.125
+0.025
+0.125
+0.025
+0.05
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.025
+0.05
+0.025
+0.025
+0.025
+0.025
+0.025
+0.2
+0.2
+0.2
+0.2
+0.175
+0.075
+0.025
+0.2
+0.1
+0.125
+0.2
+0.025
+0.025
+0.025
+0.2
+0.05
+0.025
+0.025
+0.025
+0.025
+0.175
+0.025
+0.2
+0.2
+0.025
+0.2
+0.175
+0.025
+0.125
+0.025
+0.2
+0.2
+0.15
+0.15
+0.2
+0.025
+0.05
+0.025

+ 1000 - 0
progs/approxVarSigma.txt

@@ -0,0 +1,1000 @@
+2
+2
+0.75
+2
+0.5
+1.5
+2
+1
+2
+0.5
+1
+2
+0.75
+1.5
+0.75
+0.75
+1.25
+0.75
+0.5
+0.5
+2
+1
+0.75
+1.25
+0.75
+0.75
+2
+1
+0.5
+2
+1
+0.75
+0.75
+0.75
+0.75
+0.5
+2
+2
+0.75
+0.75
+0.75
+2
+0.75
+1
+1
+0.75
+0.75
+1
+2
+1.25
+0.5
+1
+2
+0.5
+2
+2
+2
+2
+0.75
+1
+0.25
+0.75
+0.5
+1.25
+0.25
+0.75
+2
+0.75
+0.25
+2
+0.5
+0.5
+0.75
+1
+0.5
+0.5
+0.75
+0.75
+0.75
+2
+0.75
+1.25
+1
+0.75
+1
+1.25
+2
+0.75
+1.25
+0.25
+2
+0.75
+0.75
+1
+1
+0.75
+0.75
+2
+1.25
+0.75
+0.75
+1
+1.25
+1
+0.5
+0.5
+0.5
+0.5
+1.25
+0.5
+1
+0.5
+0.5
+0.75
+0.5
+0.5
+0.75
+0.5
+1
+0.75
+0.5
+0.5
+1
+2
+0.75
+0.5
+2
+1
+0.75
+0.5
+0.75
+1.75
+0.75
+0.5
+0.75
+0.5
+1
+0.5
+0.5
+0.5
+0.75
+0.75
+2
+2
+0.75
+0.75
+0.75
+0.75
+1
+0.75
+1
+1
+1
+0.75
+0.75
+0.75
+0.5
+1.75
+0.5
+0.5
+2
+1
+0.5
+0.75
+0.75
+0.5
+2
+1.25
+0.75
+1
+0.75
+1.75
+0.75
+0.75
+1
+0.75
+1.5
+1.25
+1
+0.5
+0.75
+0.75
+0.75
+1
+2
+1
+2
+0.75
+0.5
+0.25
+0.75
+0.25
+0.5
+1
+0.75
+0.5
+0.5
+0.5
+0.75
+1.25
+0.5
+0.75
+0.25
+2
+0.5
+0.5
+2
+1
+0.5
+0.5
+1
+1
+0.5
+0.75
+0.5
+1.5
+1
+0.75
+0.75
+0.25
+0.5
+0.5
+0.75
+0.5
+0.5
+0.25
+2
+0.75
+0.75
+0.5
+0.75
+0.5
+0.75
+0.5
+1
+0.5
+0.5
+2
+0.75
+0.5
+0.75
+0.5
+0.5
+0.25
+2
+0.5
+0.25
+0.25
+0.25
+0.5
+0.5
+0.5
+0.25
+0.5
+0.75
+0.75
+0.5
+0.75
+0.5
+0.75
+1
+2
+0.5
+2
+0.75
+2
+2
+0.5
+2
+1.25
+2
+2
+2
+1.25
+0.75
+0.75
+1.5
+0.5
+0.75
+0.5
+0.25
+0.75
+0.25
+1.25
+0.5
+0.25
+0.25
+0.75
+0.25
+0.25
+1.5
+2
+2
+0.5
+2
+0.75
+0.5
+2
+0.75
+2
+0.5
+0.75
+2
+1.5
+1
+0.5
+1.25
+0.75
+0.25
+0.25
+2
+0.75
+2
+2
+0.25
+0.25
+1
+0.75
+0.25
+0.25
+0.5
+0.75
+2
+0.75
+2
+0.75
+2
+2
+2
+0.75
+0.5
+1
+0.25
+0.75
+0.25
+0.75
+2
+0.75
+1
+0.75
+0.5
+0.75
+1
+1
+1
+0.75
+0.5
+0.5
+2
+2
+2
+0.75
+2
+2
+0.75
+0.75
+1.5
+0.5
+1
+0.25
+1
+2
+2
+1
+2
+2
+1
+1.5
+1.5
+0.75
+2
+0.5
+0.5
+2
+2
+0.5
+2
+1.25
+0.5
+1.5
+2
+2
+2
+2
+0.5
+0.25
+0.5
+1.75
+0.75
+0.25
+0.25
+0.25
+2
+0.25
+0.75
+0.75
+2
+1
+2
+2
+2
+2
+0.75
+2
+0.5
+2
+0.25
+0.75
+1.75
+0.5
+0.5
+0.75
+0.5
+0.75
+0.5
+0.5
+0.25
+0.75
+0.75
+0.25
+2
+0.75
+0.75
+1
+0.5
+0.5
+2
+2
+0.5
+0.25
+0.5
+0.5
+0.5
+0.25
+0.5
+0.25
+0.75
+2
+0.25
+0.75
+0.75
+0.5
+2
+2
+2
+2
+2
+2
+0.5
+0.25
+0.75
+0.25
+2
+2
+0.75
+0.5
+2
+0.75
+0.75
+1
+1
+1
+0.75
+0.5
+2
+2
+0.5
+0.25
+0.5
+1
+0.5
+0.75
+0.25
+0.25
+2
+2
+1
+2
+0.75
+2
+2
+0.5
+2
+2
+0.75
+0.75
+0.75
+0.5
+0.5
+0.5
+1.25
+0.5
+2
+0.5
+2
+1
+1
+0.25
+2
+2
+1
+1
+2
+2
+2
+1
+1
+2
+2
+2
+0.75
+2
+0.75
+0.5
+2
+0.5
+1
+0.75
+0.25
+2
+0.25
+2
+0.25
+2
+2
+0.25
+1.5
+2
+2
+2
+0.75
+0.75
+1
+1
+2
+0.25
+2
+1
+0.25
+0.5
+2
+2
+2
+2
+0.75
+2
+2
+1.75
+2
+0.25
+2
+2
+0.75
+2
+0.75
+0.25
+1.25
+2
+0.75
+0.25
+0.25
+0.25
+0.5
+1
+2
+0.75
+2
+0.25
+0.25
+2
+2
+1
+0.25
+1.5
+2
+1
+2
+1.25
+1
+2
+2
+2
+2
+0.5
+0.75
+2
+1.5
+2
+0.25
+0.25
+0.5
+0.25
+2
+0.25
+2
+2
+2
+0.25
+0.25
+0.25
+0.75
+2
+0.5
+2
+0.75
+1.25
+0.25
+0.25
+0.25
+0.25
+0.25
+0.25
+0.75
+2
+0.25
+0.75
+0.25
+0.25
+2
+1.25
+0.25
+2
+2
+0.25
+2
+0.25
+0.25
+0.75
+0.25
+0.25
+2
+1.5
+2
+0.75
+2
+2
+1.25
+0.75
+2
+0.5
+0.25
+0.25
+0.25
+0.25
+0.5
+0.25
+0.25
+0.25
+0.25
+0.25
+2
+1
+2
+0.25
+0.25
+2
+0.75
+1
+2
+1
+0.75
+2
+2
+1.5
+0.5
+0.75
+0.75
+1
+0.75
+1.5
+0.75
+2
+2
+1
+2
+2
+2
+2
+0.75
+2
+0.5
+0.75
+1.5
+0.75
+0.75
+2
+2
+1
+2
+0.75
+0.5
+2
+2
+2
+2
+2
+2
+1.75
+2
+2
+1.25
+2
+1.75
+0.75
+2
+0.5
+1
+2
+2
+0.75
+0.75
+2
+2
+0.5
+0.75
+2
+0.25
+2
+2
+1
+0.25
+2
+1
+0.5
+2
+2
+2
+2
+1
+0.25
+1.25
+2
+0.25
+0.75
+0.75
+2
+0.75
+1.75
+0.75
+2
+2
+0.75
+2
+0.75
+2
+2
+0.75
+0.75
+1
+1
+2
+0.25
+2
+2
+1.25
+0.75
+1
+2
+1
+2
+2
+2
+2
+1
+1
+1.5
+2
+2
+2
+0.5
+0.75
+2
+2
+2
+0.5
+0.75
+0.5
+1
+0.25
+0.25
+0.5
+0.5
+0.5
+2
+0.5
+0.75
+0.75
+0.75
+0.5
+0.5
+0.75
+0.75
+0.5
+0.5
+2
+0.5
+2
+0.75
+2
+2
+0.75
+2
+0.75
+1
+0.75
+1.25
+2
+2
+2
+0.75
+2
+2
+1.5
+2
+2
+1
+1.5
+1.25
+1
+1.25
+0.25
+1.5
+0.75
+0.75
+1
+0.75
+2
+1
+0.5
+1
+0.5
+2
+2
+0.75
+2
+0.75
+0.75
+0.25
+1
+0.75
+2
+0.75
+0.75
+0.75
+2
+0.75
+1
+0.25
+0.75
+0.25
+0.75
+2
+2
+2
+2
+2
+2
+2
+2
+0.75
+2
+0.5
+0.75
+0.5
+2
+0.25
+0.75
+0.5
+0.75
+0.25
+2
+0.75
+0.75
+1
+1.5
+2
+0.25
+0.5
+0.5
+0.25
+0.75
+0.75
+1.25
+1
+2
+1.75
+1
+0.25
+0.75
+2
+1.5
+0.25
+1.25
+0.25
+2
+2
+0.25
+2
+1.5
+2
+2
+0.75
+1.25
+1
+2
+2
+0.25
+1.25
+0.75
+1
+2
+2
+2
+2
+2
+1.25
+2
+2
+0.25
+1.25
+0.5
+0.75
+1
+2
+2
+0.75
+1.5
+2
+1.5
+2
+1
+2
+1
+0.75
+0.25
+0.5
+1
+2
+0.75
+1
+1.25
+1
+0.75
+2
+2
+1.25
+1
+1
+0.25
+0.75
+2
+0.75
+2
+0.25
+1
+1.75
+2
+2
+0.5
+0.25
+0.75
+0.75
+1.5
+0.25
+1
+0.75
+1
+2
+0.25
+1.25
+1.5
+2
+1.25
+1.5
+2
+2
+0.25
+2
+0.75
+2
+0.25
+1.25
+2
+2
+2
+2
+0.75
+2
+2
+2
+2
+2
+0.75
+2
+2
+2
+2
+0.5
+2
+2

+ 9 - 4
progs/libdepend.inc

@@ -1,4 +1,9 @@
-$(call PKG_DEPEND_EXT,OPENMP)
-$(call PKG_DEPEND_EXT,OPENCV)
-$(call PKG_DEPEND_INT,objrec/iclassifier)
-$(call PKG_DEPEND_INT,vislearning/classifier)
+$(call PKG_DEPEND_INT,core/basics)
+$(call PKG_DEPEND_INT,core/algebra)
+$(call PKG_DEPEND_INT,vislearning/math)
+$(call PKG_DEPEND_INT,vislearning/baselib)
+$(call PKG_DEPEND_INT,vislearning/cbaselib)
+$(call PKG_DEPEND_INT,vislearning/classifier/kernelclassifier)
+$(call PKG_DEPEND_INT,vislearning/matlabAccess)
+
+

+ 149 - 0
progs/testImageNetBinary.cpp

@@ -0,0 +1,149 @@
+/** 
+* @file testImageNetBinary.cpp
+* @brief perform ImageNet tests with binary tasks for OCC
+* @author Alexander Lütz
+* @date 23-05-2012 (dd-mm-yyyy)
+
+*/
+#include "core/basics/Config.h"
+
+#include "vislearning/cbaselib/ClassificationResults.h"
+#include "vislearning/baselib/ProgressBar.h"
+
+#include "vislearning/matlabAccess/MatFileIO.h"
+#include "vislearning/matlabAccess/ImageNetData.h"
+
+#include "vislearning/classifier/kernelclassifier/KCGPOneClass.h"
+#include "vislearning/classifier/kernelclassifier/KCGPApproxOneClass.h"
+
+#include "vislearning/math/kernels/KernelData.h"
+#include "vislearning/math/kernels/Kernel.h"
+#include "vislearning/math/kernels/KernelRBF.h"
+#include "vislearning/math/kernels/KernelExp.h"
+
+// #include "fast-hik/tools.h"
+
+
+using namespace std;
+using namespace NICE;
+using namespace OBJREC;
+
+
+/** 
+    test the basic functionality of fast-hik hyperparameter optimization 
+*/
+int main (int argc, char **argv)
+{   
+  std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
+
+  Config conf ( argc, argv );
+  string resultsfile = conf.gS("main", "results", "results.txt" );
+  int positiveClass = conf.gI("main", "positive_class");
+
+  std::cerr << "Positive class is " << positiveClass << std::endl;
+  
+  sparse_t data;
+  NICE::Vector y;
+  
+  std::cerr << "Reading ImageNet data ..." << std::endl;
+  bool imageNetLocal = conf.gB("main", "imageNetLocal" , false);
+  string imageNetPath;
+  if (imageNetLocal)
+    imageNetPath = "/users2/rodner/data/imagenet/devkit-1.0/";
+  else
+    imageNetPath = "/home/dbv/bilder/imagenet/devkit-1.0/";
+
+  ImageNetData imageNet ( imageNetPath + "demo/" );
+
+//   imageNet.getBatchData ( data, y, "train", "training" );
+  LabeledSetVector train;
+  imageNet.loadDataAsLabeledSetVector( train );
+  
+  //set up the kernel function
+  double rbf_sigma = conf.gD("main", "rbf_sigma", -2.0 );
+  KernelRBF kernelFunction ( rbf_sigma, 0.0 );
+    //KernelExp kernelFunction ( rbf_sigma, 0.0, 0.0 );
+
+  //set up our OC-classifier
+  string classifierName = conf.gS("main", "classifier", "KCGPApproxOneClass");
+  
+  KernelClassifier *classifier;
+  if(strcmp("KCGPApproxOneClass",classifierName.c_str())==0)
+  {
+    classifier = new KCGPApproxOneClass ( &conf, &kernelFunction );
+  }
+  else if (strcmp("KCGPOneClass",classifierName.c_str())==0) {
+    classifier = new KCGPOneClass ( &conf, &kernelFunction );
+  }
+  else{ //default
+    classifier = new KCGPApproxOneClass ( &conf, &kernelFunction );
+  }
+  //and perform the training
+  classifier->teach( train );    
+
+//   uint n = y.size();
+//   
+//   set<int> positives;
+//   set<int> negatives;
+// 
+//   map< int, set<int> > mysets;
+//   for ( uint i = 0 ; i < n; i++ )
+//     mysets[ y[i] ].insert ( i );
+// 
+//   if ( mysets[ positiveClass ].size() == 0 ) 
+//     fthrow(Exception, "Class " << positiveClass << " is not available.");
+// 
+//   // add our positive examples
+//   for ( set<int>::const_iterator i = mysets[positiveClass].begin(); i != mysets[positiveClass].end(); i++ )
+//     positives.insert ( *i );
+// 
+//   int Nneg = conf.gI("main", "nneg", 1 );
+//   for ( map<int, set<int> >::const_iterator k = mysets.begin(); k != mysets.end(); k++ )
+//   {
+//     int classno = k->first;
+//     if ( classno == positiveClass )
+//       continue;
+//     const set<int> & s = k->second;
+//     uint ind = 0;
+//     for ( set<int>::const_iterator i = s.begin(); (i != s.end() && ind < Nneg); i++,ind++  )
+//       negatives.insert ( *i );
+//   }
+//   std::cerr << "Number of positive examples: " << positives.size() << std::endl;
+//   std::cerr << "Number of negative examples: " << negatives.size() << std::endl;
+
+  // ------------------------------ TESTING ------------------------------
+ 
+  std::cerr << "Reading ImageNet test data files (takes some seconds)..." << std::endl;
+  imageNet.preloadData ( "val", "testing" );
+  imageNet.loadExternalLabels ( imageNetPath + "data/ILSVRC2010_validation_ground_truth.txt" );
+ 
+  ClassificationResults results;
+  std::cerr << "Classification step ... with " << imageNet.getNumPreloadedExamples() << " examples" << std::endl;
+  ProgressBar pb;
+  for ( uint i = 0 ; i < (uint)imageNet.getNumPreloadedExamples(); i++ )
+  {
+    pb.update ( imageNet.getNumPreloadedExamples() );
+
+    const SparseVector & svec = imageNet.getPreloadedExample ( i );
+    NICE::Vector vec;
+    svec.convertToVectorT( vec );
+
+    // classification step
+    ClassificationResult r = classifier->classify ( vec );
+    
+    // set ground truth label
+    r.classno_groundtruth = (((int)imageNet.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+    results.push_back ( r );
+  }
+
+  std::cerr << "Writing results to " << resultsfile << std::endl;
+  results.writeWEKA ( resultsfile, 0 );
+  double perfvalue = results.getBinaryClassPerformance( ClassificationResults::PERF_AUC );
+
+  std::cerr << "Performance: " << perfvalue << std::endl;
+  
+  //don't waste memory
+  delete classifier;
+  
+  return 0;
+}

+ 1775 - 0
progs/testImageNetBinaryBruteForce.cpp

@@ -0,0 +1,1775 @@
+/** 
+* @file testImageNetBinaryBruteForce.cpp
+* @brief perform ImageNet tests with binary tasks for OCC using GP mean and variance, sophisticated approximations of both, Parzen Density Estimation and SVDD
+* @author Alexander Lütz
+* @date 23-05-2012 (dd-mm-yyyy)
+*/
+
+#include <ctime>
+#include <time.h>
+
+#include "core/basics/Config.h"
+#include "core/basics/Timer.h"
+#include "core/algebra/CholeskyRobust.h"
+#include "core/algebra/DiagonalMatrixApprox.h"
+#include "core/vector/Algorithms.h"
+#include "core/vector/SparseVectorT.h"
+
+
+#include "vislearning/cbaselib/ClassificationResults.h"
+#include "vislearning/baselib/ProgressBar.h"
+#include "vislearning/classifier/kernelclassifier/KCMinimumEnclosingBall.h"
+
+#include "vislearning/matlabAccess/MatFileIO.h"
+#include "vislearning/matlabAccess/ImageNetData.h"
+
+using namespace std;
+using namespace NICE;
+using namespace OBJREC;
+
+// --------------- THE KERNEL FUNCTION ( exponential kernel with euclidian distance ) ----------------------
+double measureDistance ( const NICE::SparseVector & a, const NICE::SparseVector & b, const double & sigma = 2.0)
+{
+  double inner_sum(0.0);
+
+  double d;      
+  
+  //new version, where we needed on average 0.001707 s for each test sample
+  NICE::SparseVector::const_iterator aIt = a.begin();
+  NICE::SparseVector::const_iterator bIt = b.begin();
+   
+  //compute the euclidian distance between both feature vectores (given as SparseVectors)
+  while ( (aIt != a.end()) && (bIt != b.end()) )
+  {
+    if (aIt->first == bIt->first)
+    {
+      d = ( aIt->second - bIt->second );      
+      inner_sum += d * d;
+      aIt++;
+      bIt++;
+    }
+    else if ( aIt->first < bIt->first)
+    {
+      inner_sum += aIt->second * aIt->second;
+      aIt++;      
+    }
+    else
+    {
+      inner_sum += bIt->second * bIt->second;
+      bIt++;       
+    }
+  }
+  
+  //compute remaining values, if b reached the end but not a
+  while (aIt != a.end())
+  {
+    inner_sum += aIt->second * aIt->second;
+    aIt++; 
+  }
+  //compute remaining values, if a reached the end but not b
+  while (bIt != b.end())
+  {
+    inner_sum += bIt->second * bIt->second;
+    bIt++; 
+  }  
+
+  //normalization of the exponent
+  inner_sum /= (2.0*sigma*sigma);
+  
+  //finally, compute the RBF-kernel score (RBF = radial basis function)
+  return exp(-inner_sum);
+}
+
+// --------------- INPUT METHOD ----------------------
+void readParameters(string & filename, const int & size, NICE::Vector & parameterVector)
+{
+  //we read the parameters which are given from a Matlab-Script (each line contains a single number, which is the optimal parameter for this class)
+  
+  parameterVector.resize(size);
+  parameterVector.set(0.0);
+  
+  ifstream is(filename.c_str());
+
+  if ( !is.good() )
+      fthrow(IOException, "Unable to read parameters.");  
+//
+  string tmp;
+  int cnt(0);
+  while (! is.eof())
+  {
+    is >> tmp;
+    parameterVector[cnt] = atof(tmp.c_str());
+    cnt++;
+  }
+//   
+  is.close(); 
+}
+
+//------------------- TRAINING METHODS --------------------
+
+void inline trainGPMean(NICE::Vector & GPMeanRightPart, const double & noise, const NICE::Matrix & kernelMatrix, const int & nrOfExamplesPerClass, const int & classNumber, const int & runsPerClassToAverageTraining )
+{
+
+    Timer tTrainPrecise;
+    tTrainPrecise.start();      
+
+    for (int run = 0; run < runsPerClassToAverageTraining; run++)
+    {  
+    
+      CholeskyRobust cr  ( false /* verbose*/, 0.0 /*noiseStep*/, false /* useCuda*/);
+      
+      NICE::Matrix choleskyMatrix (nrOfExamplesPerClass, nrOfExamplesPerClass, 0.0);
+      
+      //compute the cholesky decomposition of K in order to compute K^{-1} \cdot y
+      cr.robustChol ( kernelMatrix, choleskyMatrix );  
+      
+      GPMeanRightPart.resize(nrOfExamplesPerClass);
+      GPMeanRightPart.set(0.0);
+      
+      NICE::Vector y(nrOfExamplesPerClass,1.0); //OCC setting :)
+      
+      // pre-compute K^{-1} \cdot y, which is the same for every new test sample
+      choleskySolveLargeScale ( choleskyMatrix, y, GPMeanRightPart );
+    }
+ 
+    tTrainPrecise.stop(); 
+    std::cerr << "Precise time used for GPMean training class " << classNumber << ": " << tTrainPrecise.getLast()/(double)runsPerClassToAverageTraining << std::endl;    
+}  
+
+void inline trainGPVar(NICE::Matrix & choleskyMatrix, const double & noise, const NICE::Matrix & kernelMatrix, const int & nrOfExamplesPerClass, const int & classNumber, const int & runsPerClassToAverageTraining )
+{
+
+    Timer tTrainPrecise;
+    tTrainPrecise.start();     
+    
+    for (int run = 0; run < runsPerClassToAverageTraining; run++)
+    {  
+      CholeskyRobust cr  ( false /* verbose*/, 0.0 /*noiseStep*/, false /* useCuda*/);
+      
+      choleskyMatrix.resize(nrOfExamplesPerClass, nrOfExamplesPerClass);
+      choleskyMatrix.set(0.0);      
+      
+      //compute the cholesky decomposition of K in order to compute K^{-1} \cdot k_* for new test samples
+      cr.robustChol ( kernelMatrix, choleskyMatrix );   
+    }
+ 
+    tTrainPrecise.stop(); 
+    std::cerr << "Precise time used for GPVar training class " << classNumber << ": " << tTrainPrecise.getLast()/(double)runsPerClassToAverageTraining << std::endl;    
+}
+
+void inline trainGPMeanApprox(NICE::Vector & GPMeanApproxRightPart, const double & noise, const NICE::Matrix & kernelMatrix, const int & nrOfExamplesPerClass, const int & classNumber, const int & runsPerClassToAverageTraining )
+{
+
+    Timer tTrainPrecise;
+    tTrainPrecise.start();     
+    
+    for (int run = 0; run < runsPerClassToAverageTraining; run++)
+    {  
+      NICE::Vector matrixDInv(nrOfExamplesPerClass,0.0);
+      //compute D 
+      //start with adding some noise, if necessary
+      if (noise != 0.0)
+        matrixDInv.set(noise);
+      else
+        matrixDInv.set(0.0);    
+      
+      // the approximation creates a diagonal matrix (which is easy to invert)
+      // with entries equal the row sums of the original kernel matrix
+      for (int i = 0; i < nrOfExamplesPerClass; i++)
+      {
+        for (int j = i; j < nrOfExamplesPerClass; j++)
+        {
+          matrixDInv[i] += kernelMatrix(i,j);
+          if (i != j)
+            matrixDInv[j] += kernelMatrix(i,j);
+        }
+      }
+      
+      //compute its inverse (and multiply every element with the label vector, which contains only one-entries and therefore be skipped...)
+      GPMeanApproxRightPart.resize(nrOfExamplesPerClass);    
+      for (int i = 0; i < nrOfExamplesPerClass; i++)
+      {
+        GPMeanApproxRightPart[i] = 1.0 / matrixDInv[i];
+      } 
+    }
+    
+    
+    tTrainPrecise.stop(); 
+    std::cerr << "Precise time used for GPMeanApprox training class " << classNumber << ": " << tTrainPrecise.getLast()/(double)runsPerClassToAverageTraining << std::endl;    
+}
+
+void inline trainGPVarApprox(NICE::Vector & matrixDInv, const double & noise, const NICE::Matrix & kernelMatrix, const int & nrOfExamplesPerClass, const int & classNumber, const int & runsPerClassToAverageTraining )
+{
+
+    std::cerr << "nrOfExamplesPerClass : " << nrOfExamplesPerClass << std::endl;
+  
+    Timer tTrainPreciseTimer;
+    tTrainPreciseTimer.start();     
+
+    for (int run = 0; run < runsPerClassToAverageTraining; run++)
+    {
+      matrixDInv.resize(nrOfExamplesPerClass);
+      matrixDInv.set(0.0);
+      //compute D 
+      //start with adding some noise, if necessary
+      if (noise != 0.0)
+        matrixDInv.set(noise);
+      else
+        matrixDInv.set(0.0);    
+      
+      // the approximation creates a diagonal matrix (which is easy to invert)
+      // with entries equal the row sums of the original kernel matrix      
+      for (int i = 0; i < nrOfExamplesPerClass; i++)
+      {
+        for (int j = i; j < nrOfExamplesPerClass; j++)
+        {
+          matrixDInv[i] += kernelMatrix(i,j);
+          if (i != j)
+            matrixDInv[j] += kernelMatrix(i,j);
+        }
+      }
+      
+      //compute its inverse
+      for (int i = 0; i < nrOfExamplesPerClass; i++)
+      {
+        matrixDInv[i] = 1.0 / matrixDInv[i];
+      }
+    }
+    
+    tTrainPreciseTimer.stop(); 
+    std::cerr << "Precise time used for GPVarApprox training class " << classNumber << ": " << tTrainPreciseTimer.getLast()/(double)runsPerClassToAverageTraining << std::endl;    
+}
+
+// GP subset of regressors
+void inline trainGPSRMean(NICE::Vector & GPMeanRightPart, const double & noise, const NICE::Matrix & kernelMatrix, const int & nrOfExamplesPerClass, const int & classNumber, const int & runsPerClassToAverageTraining, const int & nrOfRegressors, std::vector<int> & indicesOfChosenExamples )
+{
+  std::vector<int> examplesToChoose;
+  indicesOfChosenExamples.clear();
+  
+  //add all examples for possible choice
+  for (int i = 0; i < nrOfExamplesPerClass; i++)
+  {
+    examplesToChoose.push_back(i);
+  }
+  
+  //now chose randomly some examples as active subset
+  int index;
+  for (int i = 0; i < std::min(nrOfRegressors,nrOfExamplesPerClass); i++)
+  {
+    index = rand() % examplesToChoose.size();
+    indicesOfChosenExamples.push_back(examplesToChoose[index]);
+    examplesToChoose.erase(examplesToChoose.begin() + index);
+  }
+  
+  NICE::Matrix Kmn (indicesOfChosenExamples.size(), nrOfExamplesPerClass, 0.0);
+  int rowCnt(0);
+  //set every row
+  for (uint i = 0; i < indicesOfChosenExamples.size(); i++, rowCnt++ )
+  {
+    //set every element of this row
+    NICE::Vector col = kernelMatrix.getRow(indicesOfChosenExamples[i]);
+    for (int j = 0; j < nrOfExamplesPerClass; j++)
+    {
+      Kmn(rowCnt,j) = col(j);
+    }
+  }
+  
+  //we could speed this up if we would order the indices
+  NICE::Matrix Kmm (indicesOfChosenExamples.size(), indicesOfChosenExamples.size(), 0.0);
+  double tmp(0.0);
+  for (uint i = 0; i < indicesOfChosenExamples.size(); i++ )
+  {
+    for (uint j = i; j < indicesOfChosenExamples.size(); j++ )
+    {
+      tmp = kernelMatrix(indicesOfChosenExamples[i], indicesOfChosenExamples[j]);
+      Kmm(i,j) = tmp;
+      if (i != j)
+        Kmm(j,i) = tmp;
+    }
+  }
+  
+
+    Timer tTrainPrecise;
+    tTrainPrecise.start();      
+
+    for (int run = 0; run < runsPerClassToAverageTraining; run++)
+    {  
+      NICE::Matrix innerMatrix;
+      innerMatrix.multiply(Kmn, Kmn, false /* tranpose first matrix*/, true /* transpose second matrix*/);
+      
+      innerMatrix.addScaledMatrix( noise, Kmm );
+      
+      NICE::Vector y(nrOfExamplesPerClass,1.0); //OCC setting :) 
+      NICE::Vector projectedLabels;
+      projectedLabels.multiply(Kmn,y);
+      
+      CholeskyRobust cr  ( false /* verbose*/, 0.0 /*noiseStep*/, false /* useCuda*/);
+      
+      NICE::Matrix choleskyMatrix (nrOfExamplesPerClass, nrOfExamplesPerClass, 0.0);
+      
+      //compute the cholesky decomposition of K in order to compute K^{-1} \cdot y
+      cr.robustChol ( innerMatrix, choleskyMatrix );  
+      
+      GPMeanRightPart.resize(indicesOfChosenExamples.size());
+      GPMeanRightPart.set(0.0);
+      
+      // pre-compute K^{-1} \cdot y, which is the same for every new test sample
+      choleskySolveLargeScale ( choleskyMatrix, projectedLabels, GPMeanRightPart );
+    }
+ 
+    tTrainPrecise.stop(); 
+    std::cerr << "Precise time used for GPSRMean training class " << classNumber << ": " << tTrainPrecise.getLast()/(double)runsPerClassToAverageTraining << std::endl;    
+}
+
+// GP subset of regressors
+void inline trainGPSRVar(NICE::Matrix & choleskyMatrix, const double & noise, const NICE::Matrix & kernelMatrix, const int & nrOfExamplesPerClass, const int & classNumber, const int & runsPerClassToAverageTraining, const int & nrOfRegressors, std::vector<int> & indicesOfChosenExamples )
+{
+  std::vector<int> examplesToChoose;
+  indicesOfChosenExamples.clear();
+  
+  //add all examples for possible choice
+  for (int i = 0; i < nrOfExamplesPerClass; i++)
+  {
+    examplesToChoose.push_back(i);
+  }
+  
+  //now chose randomly some examples as active subset
+  int index;
+  for (int i = 0; i < std::min(nrOfRegressors,nrOfExamplesPerClass); i++)
+  {
+    index = rand() % examplesToChoose.size();
+    indicesOfChosenExamples.push_back(examplesToChoose[index]);
+    examplesToChoose.erase(examplesToChoose.begin() + index);
+  }
+  
+  NICE::Matrix Kmn (indicesOfChosenExamples.size(), nrOfExamplesPerClass, 0.0);
+  int rowCnt(0);
+  //set every row
+  for (uint i = 0; i < indicesOfChosenExamples.size(); i++, rowCnt++ )
+  {
+    //set every element of this row
+    NICE::Vector col = kernelMatrix.getRow(indicesOfChosenExamples[i]);
+    for (int j = 0; j < nrOfExamplesPerClass; j++)
+    {
+      Kmn(rowCnt,j) = col(j);
+    }
+  }
+  
+  //we could speed this up if we would order the indices
+  NICE::Matrix Kmm (indicesOfChosenExamples.size(), indicesOfChosenExamples.size(), 0.0);
+  double tmp(0.0);
+  for (uint i = 0; i < indicesOfChosenExamples.size(); i++ )
+  {
+    for (uint j = i; j < indicesOfChosenExamples.size(); j++ )
+    {
+      tmp = kernelMatrix(indicesOfChosenExamples[i], indicesOfChosenExamples[j]);
+      Kmm(i,j) = tmp;
+      if (i != j)
+        Kmm(j,i) = tmp;
+    }
+  }
+  
+
+    Timer tTrainPrecise;
+    tTrainPrecise.start();      
+
+    for (int run = 0; run < runsPerClassToAverageTraining; run++)
+    {  
+      NICE::Matrix innerMatrix;
+      innerMatrix.multiply(Kmn, Kmn, false /* tranpose first matrix*/, true /* transpose second matrix*/);
+      
+      innerMatrix.addScaledMatrix( noise, Kmm );
+           
+      CholeskyRobust cr  ( false /* verbose*/, 0.0 /*noiseStep*/, false /* useCuda*/);
+      
+      choleskyMatrix.resize( nrOfExamplesPerClass, nrOfExamplesPerClass );
+      choleskyMatrix.set( 0.0 );
+      
+      //compute the cholesky decomposition of K in order to compute K^{-1} \cdot y
+      cr.robustChol ( innerMatrix, choleskyMatrix );  
+     }
+ 
+    tTrainPrecise.stop(); 
+    std::cerr << "Precise time used for GPSRVar training class " << classNumber << ": " << tTrainPrecise.getLast()/(double)runsPerClassToAverageTraining << std::endl;    
+}
+
+// GP FITC approx
+void inline trainGPFITCMean(NICE::Vector & GPMeanRightPart, const double & noise, const NICE::Matrix & kernelMatrix, const int & nrOfExamplesPerClass, const int & classNumber, const int & runsPerClassToAverageTraining, const int & nrOfRegressors, std::vector<int> & indicesOfChosenExamples )
+{
+  std::vector<int> examplesToChoose;
+  indicesOfChosenExamples.clear();
+  
+  //add all examples for possible choice
+  for (int i = 0; i < nrOfExamplesPerClass; i++)
+  {
+    examplesToChoose.push_back(i);
+  }
+  
+  //now chose randomly some examples as active subset
+  int index;
+  for (int i = 0; i < std::min(nrOfRegressors,nrOfExamplesPerClass); i++)
+  {
+    index = rand() % examplesToChoose.size();
+    indicesOfChosenExamples.push_back(examplesToChoose[index]);
+    examplesToChoose.erase(examplesToChoose.begin() + index);
+  }
+  
+  NICE::Vector diagK (nrOfExamplesPerClass, 0.0);
+  //set every element
+  for (int i = 0; i < nrOfExamplesPerClass; i++ )
+  {
+    diagK(i) = kernelMatrix(i,i);
+  }
+  
+  NICE::Matrix Ku (indicesOfChosenExamples.size(), nrOfExamplesPerClass, 0.0);
+  int rowCnt(0);
+  //set every row
+  for (uint i = 0; i < indicesOfChosenExamples.size(); i++, rowCnt++ )
+  {
+    //set every element of this row
+    NICE::Vector col = kernelMatrix.getRow(indicesOfChosenExamples[i]);
+    for (int j = 0; j < nrOfExamplesPerClass; j++)
+    {
+      Ku(rowCnt,j) = col(j);
+    }
+  }
+  
+  //we could speed this up if we would order the indices
+  NICE::Matrix Kuu (indicesOfChosenExamples.size(), indicesOfChosenExamples.size(), 0.0);
+  double tmp(0.0);
+  for (uint i = 0; i < indicesOfChosenExamples.size(); i++ )
+  {
+    for (uint j = i; j < indicesOfChosenExamples.size(); j++ )
+    {
+      tmp = kernelMatrix(indicesOfChosenExamples[i], indicesOfChosenExamples[j]);
+      Kuu(i,j) = tmp;
+      if (i != j)
+        Kuu(j,i) = tmp;
+    }
+  }
+  
+  NICE::Vector y(nrOfExamplesPerClass,1.0); //OCC setting :) 
+  
+    Timer tTrainPrecise;
+    tTrainPrecise.start();      
+
+    for (int run = 0; run < runsPerClassToAverageTraining; run++)
+    {       
+      
+//       NICE::Vector projectedLabels;
+//       projectedLabels.multiply(Kmn,y);
+      
+      CholeskyRobust cr  ( false /* verbose*/, 0.0 /*noiseStep*/, false /* useCuda*/);
+      
+      NICE::Matrix Luu (nrOfExamplesPerClass, nrOfExamplesPerClass, 0.0);
+      cr.robustChol ( Kuu, Luu );  
+      
+      NICE::Matrix V (Ku);
+      choleskySolveMatrixLargeScale( Luu, V);
+      
+      NICE::Vector dg (diagK);
+      NICE::Vector sumV (diagK.size(),0.0);
+      for (uint i=0; i<V.cols(); i++)
+      {
+        for (uint j=0; j<V.rows(); j++)
+        {
+          sumV(i) += V(j,i)*V(j,i);
+        }
+        sumV(i) += noise;
+      }
+      dg += sumV;
+      
+      for (uint i=0; i<V.cols(); i++)
+      {
+        for (uint j=0; j<V.rows(); j++)
+        {
+          V(j,i) /= sqrt(dg(i));
+        }
+      }     
+      
+      NICE::Matrix Lu (indicesOfChosenExamples.size(), indicesOfChosenExamples.size(), 0.0);
+      NICE::Matrix tmpVV (indicesOfChosenExamples.size(), indicesOfChosenExamples.size(), 0.0);
+      tmpVV.multiply(V,V,false,true);
+      tmpVV.addIdentity(1.0);
+      cr.robustChol ( tmpVV, Lu );
+      
+      NICE::Vector r (dg);
+      for (uint i=0; i<r.size(); i++)
+      {
+        r(i) = 1.0/sqrt(r(i));
+      }
+      
+      NICE::Vector be (indicesOfChosenExamples.size(), 0.0);
+      choleskySolveLargeScale (Lu, V*r, be);
+      choleskySolveLargeScale (Lu.transpose(), be, be);
+        
+      GPMeanRightPart.resize(indicesOfChosenExamples.size());
+      GPMeanRightPart.set(0.0);
+      
+      choleskySolveLargeScale ( Luu.transpose(), be, GPMeanRightPart );
+    }
+ 
+    tTrainPrecise.stop(); 
+    std::cerr << "Precise time used for GPFITCMean training class " << classNumber << ": " << tTrainPrecise.getLast()/(double)runsPerClassToAverageTraining << std::endl;    
+}
+
+// GP FITC approx
+void inline trainGPFITCVar(NICE::Matrix & choleskyMatrix, const double & noise, const NICE::Matrix & kernelMatrix, const int & nrOfExamplesPerClass, const int & classNumber, const int & runsPerClassToAverageTraining, const int & nrOfRegressors, std::vector<int> & indicesOfChosenExamples )
+{
+  std::vector<int> examplesToChoose;
+  indicesOfChosenExamples.clear();
+  
+  //add all examples for possible choice
+  for (int i = 0; i < nrOfExamplesPerClass; i++)
+  {
+    examplesToChoose.push_back(i);
+  }
+  
+  //now chose randomly some examples as active subset
+  int index;
+  for (int i = 0; i < std::min(nrOfRegressors,nrOfExamplesPerClass); i++)
+  {
+    index = rand() % examplesToChoose.size();
+    indicesOfChosenExamples.push_back(examplesToChoose[index]);
+    examplesToChoose.erase(examplesToChoose.begin() + index);
+  }
+  
+  NICE::Vector diagK (nrOfExamplesPerClass, 0.0);
+  //set every element
+  for (int i = 0; i < nrOfExamplesPerClass; i++ )
+  {
+    diagK(i) = kernelMatrix(i,i);
+  }
+  
+  NICE::Matrix Ku (indicesOfChosenExamples.size(), nrOfExamplesPerClass, 0.0);
+  int rowCnt(0);
+  //set every row
+  for (uint i = 0; i < indicesOfChosenExamples.size(); i++, rowCnt++ )
+  {
+    //set every element of this row
+    NICE::Vector col = kernelMatrix.getRow(indicesOfChosenExamples[i]);
+    for (int j = 0; j < nrOfExamplesPerClass; j++)
+    {
+      Ku(rowCnt,j) = col(j);
+    }
+  }
+  
+  //we could speed this up if we would order the indices
+  NICE::Matrix Kuu (indicesOfChosenExamples.size(), indicesOfChosenExamples.size(), 0.0);
+  double tmp(0.0);
+  for (uint i = 0; i < indicesOfChosenExamples.size(); i++ )
+  {
+    for (uint j = i; j < indicesOfChosenExamples.size(); j++ )
+    {
+      tmp = kernelMatrix(indicesOfChosenExamples[i], indicesOfChosenExamples[j]);
+      Kuu(i,j) = tmp;
+      if (i != j)
+        Kuu(j,i) = tmp;
+    }
+  }
+  
+  NICE::Vector y(nrOfExamplesPerClass,1.0); //OCC setting :) 
+  
+    Timer tTrainPrecise;
+    tTrainPrecise.start();      
+
+    for (int run = 0; run < runsPerClassToAverageTraining; run++)
+    {       
+      
+//       NICE::Vector projectedLabels;
+//       projectedLabels.multiply(Kmn,y);
+      
+      CholeskyRobust cr  ( false /* verbose*/, 0.0 /*noiseStep*/, false /* useCuda*/);
+      
+      NICE::Matrix Luu (nrOfExamplesPerClass, nrOfExamplesPerClass, 0.0);
+      cr.robustChol ( Kuu, Luu );  
+      
+      NICE::Matrix V (Ku);
+      choleskySolveMatrixLargeScale( Luu, V);
+      
+      NICE::Vector dg (diagK);
+      NICE::Vector sumV (diagK.size(),0.0);
+      for (uint i=0; i<V.cols(); i++)
+      {
+        for (uint j=0; j<V.rows(); j++)
+        {
+          sumV(i) += V(j,i)*V(j,i);
+        }
+        sumV(i) += noise;
+      }
+      dg += sumV;
+      
+      for (uint i=0; i<V.cols(); i++)
+      {
+        for (uint j=0; j<V.rows(); j++)
+        {
+          V(j,i) /= sqrt(dg(i));
+        }
+      }     
+      
+      NICE::Matrix Lu (indicesOfChosenExamples.size(), indicesOfChosenExamples.size(), 0.0);
+      NICE::Matrix tmpVV (indicesOfChosenExamples.size(), indicesOfChosenExamples.size(), 0.0);
+      tmpVV.multiply(V,V,false,true);
+      tmpVV.addIdentity(1.0);
+      cr.robustChol ( tmpVV, Lu );
+      
+      NICE::Matrix iKuu (indicesOfChosenExamples.size(), indicesOfChosenExamples.size(), 0.0);
+      iKuu.addIdentity(1.0);
+      choleskySolveMatrixLargeScale ( Luu.transpose(), iKuu );
+      choleskySolveMatrixLargeScale ( Luu, iKuu );
+      
+      NICE::Matrix LuLuu (indicesOfChosenExamples.size(), indicesOfChosenExamples.size(), 0.0);
+      LuLuu.multiply(Lu,Luu);
+      choleskyMatrix.setIdentity();
+      choleskySolveMatrixLargeScale ( LuLuu.transpose(), choleskyMatrix);
+      choleskySolveMatrixLargeScale ( LuLuu, choleskyMatrix);
+      
+      choleskyMatrix -= iKuu;
+    }
+ 
+    tTrainPrecise.stop();  
+    std::cerr << "Precise time used for GPFITCVar training class " << classNumber << ": " << tTrainPrecise.getLast()/(double)runsPerClassToAverageTraining << std::endl;    
+}
+
+void inline trainGPOptMean(NICE::Vector & rightPartGPOptMean, const double & noise, const NICE::Matrix & kernelMatrix, const int & nrOfExamplesPerClass, const int & classNumber, const int & runsPerClassToAverageTraining )
+{
+    DiagonalMatrixApprox diagApprox ( true /*verbose*/ );
+//     rightPartGPOptMean.resize(nrOfExamplesPerClass);
+    
+    NICE::Matrix kInv( nrOfExamplesPerClass, nrOfExamplesPerClass, 0.0 );
+    CholeskyRobust cr  ( false /* verbose*/, 0.0 /*noiseStep*/, false /* useCuda*/);
+
+    Timer tTrainPrecise;
+    tTrainPrecise.start();     
+    
+    for (int run = 0; run < runsPerClassToAverageTraining; run++)
+    { 
+      cr.robustCholInv ( kernelMatrix, kInv );
+      
+      //we initialize the D-Matrix with the approximation we use in other methods (row sums of kernel matrix)
+      rightPartGPOptMean.resize(nrOfExamplesPerClass);
+      rightPartGPOptMean.set(0.0);
+      //compute D 
+      //start with adding some noise, if necessary
+      if (noise != 0.0)
+        rightPartGPOptMean.set(noise);
+      else
+        rightPartGPOptMean.set(0.0);    
+      
+      // the approximation creates a diagonal matrix (which is easy to invert)
+      // with entries equal the row sums of the original kernel matrix      
+      for (int i = 0; i < nrOfExamplesPerClass; i++)
+      {
+        for (int j = i; j < nrOfExamplesPerClass; j++)
+        {
+          rightPartGPOptMean[i] += kernelMatrix(i,j);
+          if (i != j)
+            rightPartGPOptMean[j] += kernelMatrix(i,j);
+        }
+      }
+      
+      //compute its inverse
+      for (int i = 0; i < nrOfExamplesPerClass; i++)
+      {
+        rightPartGPOptMean[i] = 1.0 / rightPartGPOptMean[i];
+      }      
+      
+//       rightPartGPOptMean.set(0.0);
+      
+      //compute optimal diagonal matrix
+      diagApprox.approx ( kernelMatrix, rightPartGPOptMean );
+      
+    }
+ 
+    tTrainPrecise.stop(); 
+    std::cerr << "Precise time used for GPOptMean training class " << classNumber << ": " << tTrainPrecise.getLast()/(double)runsPerClassToAverageTraining << std::endl;    
+}
+
+void inline trainGPOptVar(NICE::Vector & DiagGPOptVar, const double & noise, const NICE::Matrix & kernelMatrix, const int & nrOfExamplesPerClass, const int & classNumber, const int & runsPerClassToAverageTraining )
+{
+    DiagonalMatrixApprox diagApprox ( true /*verbose*/ );
+    DiagGPOptVar.resize(nrOfExamplesPerClass);
+    
+    NICE::Matrix kInv( nrOfExamplesPerClass, nrOfExamplesPerClass, 0.0 );
+    CholeskyRobust cr  ( false /* verbose*/, 0.0 /*noiseStep*/, false /* useCuda*/);    
+    
+    Timer tTrainPrecise;
+    tTrainPrecise.start();     
+    
+    for (int run = 0; run < runsPerClassToAverageTraining; run++)
+    { 
+      cr.robustCholInv ( kernelMatrix, kInv );
+      
+//       DiagGPOptVar.set(0.0);
+      
+      //we initialize the D-Matrix with the approximation we use in other methods (row sums of kernel matrix)
+      DiagGPOptVar.resize(nrOfExamplesPerClass);
+      DiagGPOptVar.set(0.0);
+      //compute D 
+      //start with adding some noise, if necessary
+      if (noise != 0.0)
+        DiagGPOptVar.set(noise);
+      else
+        DiagGPOptVar.set(0.0);    
+      
+      // the approximation creates a diagonal matrix (which is easy to invert)
+      // with entries equal the row sums of the original kernel matrix      
+      for (int i = 0; i < nrOfExamplesPerClass; i++)
+      {
+        for (int j = i; j < nrOfExamplesPerClass; j++)
+        {
+          DiagGPOptVar[i] += kernelMatrix(i,j);
+          if (i != j)
+            DiagGPOptVar[j] += kernelMatrix(i,j);
+        }
+      }
+      
+      //compute its inverse
+      for (int i = 0; i < nrOfExamplesPerClass; i++)
+      {
+        DiagGPOptVar[i] = 1.0 / DiagGPOptVar[i];
+      }         
+      
+      //compute optimal diagonal matrix
+      diagApprox.approx ( kernelMatrix, DiagGPOptVar );
+    }
+ 
+    tTrainPrecise.stop(); 
+    std::cerr << "Precise time used for GPOptVar training class " << classNumber << ": " << tTrainPrecise.getLast()/(double)runsPerClassToAverageTraining << std::endl;    
+}
+
+KCMinimumEnclosingBall *trainSVDD( const double & noise, const NICE::Matrix kernelMatrix, const int & nrOfExamplesPerClass, const int & classNumber, const int & runsPerClassToAverageTraining )
+{
+ 
+    Config conf;
+    // set the outlier ratio (Paul optimized this paramter FIXME)
+    conf.sD( "SVDD", "outlier_fraction", 0.1 );
+    conf.sB( "SVDD", "verbose", false );
+    KCMinimumEnclosingBall *svdd = new KCMinimumEnclosingBall ( &conf, NULL /* no kernel function */, "SVDD" /* config section */);
+    KernelData kernelData ( &conf, kernelMatrix, "Kernel" , false /* update cholesky */ );
+ 
+    Timer tTrainPrecise;
+    tTrainPrecise.start();     
+
+    for (int run = 0; run < runsPerClassToAverageTraining; run++)
+    {     
+    
+      NICE::Vector y(nrOfExamplesPerClass,1.0); //OCC setting :)
+      // KCMinimumEnclosingBall does not store the kernel data object, therefore, we are save with passing a local copy
+      svdd->teach ( &kernelData, y );
+    }
+    
+    tTrainPrecise.stop(); 
+    std::cerr << "Precise time used for SVDD training class " << classNumber << ": " << tTrainPrecise.getLast()/(double)runsPerClassToAverageTraining << std::endl;        
+
+    return svdd;
+}
+
+// ------------- EVALUATION METHODS ---------------------
+void inline evaluateGPVarApprox(const NICE::Vector & kernelVector, const double & kernelSelf, const NICE::Vector & matrixDInv, ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting)
+{
+    double uncertainty;
+    
+    Timer tTestSingle;
+    tTestSingle.start();
+      
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    {       
+      // uncertainty = k{**} - \k_*^T \cdot D^{-1} \cdot k_*  where D is our nice approximation of K
+      
+      NICE::Vector rightPart (kernelVector.size());
+      for (uint j = 0; j < kernelVector.size(); j++)
+      {
+        rightPart[j] = kernelVector[j] * matrixDInv[j];
+      }
+
+      uncertainty = kernelSelf - kernelVector.scalarProduct ( rightPart );
+    }
+      
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+    
+    FullVector scores ( 2 );
+    scores[0] = 0.0;
+    scores[1] = 1.0 - uncertainty;
+
+    r = ClassificationResult ( scores[1]<0.5 ? 0 : 1, scores );    
+}
+
+void inline evaluateGPVar(const NICE::Vector & kernelVector, const double & kernelSelf, const NICE::Matrix & choleskyMatrix, ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting)
+{
+    double uncertainty;
+    
+    Timer tTestSingle;
+    tTestSingle.start();
+      
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    {       
+      // uncertainty = k{**} - \k_*^T \cdot D^{-1} \cdot k_*       
+      
+      NICE::Vector rightPart (kernelVector.size(),0.0);      
+      choleskySolveLargeScale ( choleskyMatrix, kernelVector, rightPart );
+      
+      uncertainty = kernelSelf - kernelVector.scalarProduct ( rightPart );
+    }
+      
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+    
+    FullVector scores ( 2 );
+    scores[0] = 0.0;
+    scores[1] = 1.0 - uncertainty;
+
+    r = ClassificationResult ( scores[1]<0.5 ? 0 : 1, scores );    
+}
+
+void inline evaluateGPMeanApprox(const NICE::Vector & kernelVector, const NICE::Vector & rightPart, ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting)
+{
+    double mean;
+  
+    Timer tTestSingle;
+    tTestSingle.start();
+      
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    { 
+      // \mean = \k_*^T \cdot D^{-1} \cdot y  where D is our nice approximation of K    
+      mean = kernelVector.scalarProduct ( rightPart );
+    }
+      
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+    
+    FullVector scores ( 2 );
+    scores[0] = 0.0;
+    scores[1] = mean;
+
+    r = ClassificationResult ( scores[1]<0.5 ? 0 : 1, scores );    
+}
+
+void inline evaluateGPMean(const NICE::Vector & kernelVector,  const NICE::Vector & GPMeanRightPart, ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting)
+{
+    double mean;
+    
+    Timer tTestSingle;
+    tTestSingle.start();
+    
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    {
+      // \mean = \k_*^T \cdot K^{-1} \cdot y      
+      mean = kernelVector.scalarProduct ( GPMeanRightPart );
+    }
+
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+    
+    FullVector scores ( 2 );
+    scores[0] = 0.0;
+    scores[1] = mean;
+
+    r = ClassificationResult ( scores[1]<0.5 ? 0 : 1, scores );    
+}
+
+void inline evaluateGPSRMean(const NICE::Vector & kernelVector,  const NICE::Vector & GPSRMeanRightPart, ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting, const int & nrOfRegressors, const std::vector<int> & indicesOfChosenExamples)
+{
+    double mean;
+    
+    //grep the entries corresponding to the active set
+    NICE::Vector kernelVectorM;
+    kernelVectorM.resize(nrOfRegressors);
+    for (int i = 0; i < nrOfRegressors; i++)
+    {
+      kernelVectorM[i] = kernelVector[indicesOfChosenExamples[i]];
+    }
+
+    Timer tTestSingle;
+    tTestSingle.start();
+    
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    {
+      // \mean = \k_*^T \cdot K^{-1} \cdot y    
+      mean = kernelVectorM.scalarProduct ( GPSRMeanRightPart );
+    }
+
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+    
+    FullVector scores ( 2 );
+    scores[0] = 0.0;
+    scores[1] = mean;
+
+    r = ClassificationResult ( scores[1]<0.5 ? 0 : 1, scores );    
+}
+
+void inline evaluateGPSRVar(const NICE::Vector & kernelVector,  const NICE::Matrix & choleskyMatrix, ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting, const int & nrOfRegressors, std::vector<int> & indicesOfChosenExamples, const double & noise)
+{
+    double uncertainty;
+    
+    //grep the entries corresponding to the active set
+    NICE::Vector kernelVectorM;
+    kernelVectorM.resize(nrOfRegressors);
+    for (int i = 0; i < nrOfRegressors; i++)
+    {
+      kernelVectorM[i] = kernelVector[indicesOfChosenExamples[i]];
+    } 
+    
+    Timer tTestSingle;
+    tTestSingle.start();
+    
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    {
+      NICE::Vector rightPart (nrOfRegressors,0.0);      
+      
+      choleskySolveLargeScale ( choleskyMatrix, kernelVectorM, rightPart );
+      
+      uncertainty = noise*kernelVectorM.scalarProduct ( rightPart );
+    }
+
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+    
+    FullVector scores ( 2 );
+    scores[0] = 0.0;
+    scores[1] = 1.0 - uncertainty;
+
+    r = ClassificationResult ( scores[1]<0.5 ? 0 : 1, scores );    
+}
+
+void inline evaluateGPFITCMean(const NICE::Vector & kernelVector,  const NICE::Vector & GPFITCMeanRightPart, ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting, const int & nrOfRegressors, const std::vector<int> & indicesOfChosenExamples)
+{
+    double mean;
+    
+    //grep the entries corresponding to the active set
+    NICE::Vector kernelVectorM;
+    kernelVectorM.resize(nrOfRegressors);
+    for (int i = 0; i < nrOfRegressors; i++)
+    {
+      kernelVectorM[i] = kernelVector[indicesOfChosenExamples[i]];
+    }
+
+    Timer tTestSingle;
+    tTestSingle.start();
+    
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    {
+      // \mean = \k_*^T \cdot K^{-1} \cdot y    
+      mean = kernelVectorM.scalarProduct ( GPFITCMeanRightPart );
+    }
+
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+    
+    FullVector scores ( 2 );
+    scores[0] = 0.0;
+    scores[1] = mean;
+
+    r = ClassificationResult ( scores[1]<0.5 ? 0 : 1, scores );    
+}
+
+void inline evaluateGPFITCVar(const NICE::Vector & kernelVector,  const NICE::Matrix & choleskyMatrix, ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting, const int & nrOfRegressors, std::vector<int> & indicesOfChosenExamples, const double & noise)
+{
+    double uncertainty;
+    
+    //grep the entries corresponding to the active set
+    NICE::Vector kernelVectorM;
+    kernelVectorM.resize(nrOfRegressors);
+    for (int i = 0; i < nrOfRegressors; i++)
+    {
+      kernelVectorM[i] = kernelVector[indicesOfChosenExamples[i]];
+    } 
+    
+    Timer tTestSingle;
+    tTestSingle.start();
+    
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    {
+      NICE::Vector tmp (nrOfRegressors,0.0);  
+      tmp = choleskyMatrix*kernelVectorM;
+      tmp *= kernelVectorM;
+           
+      uncertainty = 1.0 + tmp.Sum();
+    }
+
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+    
+    FullVector scores ( 2 );
+    scores[0] = 0.0;
+    scores[1] = 1.0 - uncertainty;
+
+    r = ClassificationResult ( scores[1]<0.5 ? 0 : 1, scores );    
+}
+
+//this method is completely the same as evaluateGPMeanApprox, but for convenience, it is its own method
+void inline evaluateGPOptMean(const NICE::Vector & kernelVector, const NICE::Vector & rightPart, ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting)
+{
+    double mean;
+  
+    Timer tTestSingle;
+    tTestSingle.start();
+      
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    { 
+      // \mean = \k_*^T \cdot D^{-1} \cdot y  where D is our nice approximation of K    
+      mean = kernelVector.scalarProduct ( rightPart );
+    }
+      
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+    
+    FullVector scores ( 2 );
+    scores[0] = 0.0;
+    scores[1] = mean;
+
+    r = ClassificationResult ( scores[1]<0.5 ? 0 : 1, scores );    
+}
+
+//this method is completely the same as evaluateGPVarApprox, but for convenience, it is its own method
+void inline evaluateGPOptVar(const NICE::Vector & kernelVector, const double & kernelSelf, const NICE::Vector & matrixDInv, ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting)
+{
+    double uncertainty;
+    
+    Timer tTestSingle;
+    tTestSingle.start();
+      
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    {       
+      // uncertainty = k{**} - \k_*^T \cdot D^{-1} \cdot k_*  where D is our nice approximation of K
+      
+      NICE::Vector rightPart (kernelVector.size());
+      for (uint j = 0; j < kernelVector.size(); j++)
+      {
+        rightPart[j] = kernelVector[j] * matrixDInv[j];
+      }
+
+      uncertainty = kernelSelf - kernelVector.scalarProduct ( rightPart );
+    }
+      
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+    
+    FullVector scores ( 2 );
+    scores[0] = 0.0;
+    scores[1] = 1.0 - uncertainty;
+
+    r = ClassificationResult ( scores[1]<0.5 ? 0 : 1, scores );    
+}
+
+void inline evaluateParzen(const NICE::Vector & kernelVector,  ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting)
+{
+    double score;
+    
+    Timer tTestSingle;
+    tTestSingle.start();
+    
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    {      
+      //the Parzen score is nothing but the averaged similarity to every training sample
+      score = kernelVector.Sum() / (double) kernelVector.size(); //maybe we could directly call kernelVector.Mean() here
+    }
+      
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+    
+    FullVector scores ( 2 );
+    scores[0] = 0.0;
+    scores[1] = score;
+
+    r = ClassificationResult ( scores[1]<0.5 ? 0 : 1, scores );    
+}
+
+void inline evaluateSVDD( KCMinimumEnclosingBall *svdd, const NICE::Vector & kernelVector,  ClassificationResult & r, double & timeForSingleExamples, const int & runsPerClassToAverageTesting)
+{
+    Timer tTestSingle;
+    tTestSingle.start();
+      
+    for (int run = 0; run < runsPerClassToAverageTesting; run++)
+    {        
+      // In the following, we assume that we are using a Gaussian kernel
+      r = svdd->classifyKernel ( kernelVector, 1.0 /* kernel self */ );
+    }
+
+    tTestSingle.stop();
+    timeForSingleExamples += tTestSingle.getLast()/(double)runsPerClassToAverageTesting;      
+}
+
+/** 
+    test the basic functionality of fast-hik hyperparameter optimization 
+*/
+int main (int argc, char **argv)
+{   
+  std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
+
+  Config conf ( argc, argv );
+  string resultsfile = conf.gS("main", "results", "results.txt" );
+  int nrOfExamplesPerClass = conf.gI("main", "nrOfExamplesPerClass", 50);
+  nrOfExamplesPerClass = std::min(nrOfExamplesPerClass, 100); // we do not have more than 100 examples per class
+  
+  //which classes to considere? we assume consecutive class numers
+  int indexOfFirstClass = conf.gI("main", "indexOfFirstClass", 0);
+  indexOfFirstClass = std::max(indexOfFirstClass, 0); //we do not have less than 0 classes
+  int indexOfLastClass = conf.gI("main", "indexOfLastClass", 999);
+  indexOfLastClass = std::min(indexOfLastClass, 999); //we do not have more than 1000 classes
+  
+  int nrOfClassesToConcidere =  (indexOfLastClass - indexOfLastClass)+1;
+  
+  //repetitions for every class to achieve reliable time evalutions
+  int runsPerClassToAverageTraining = conf.gI( "main", "runsPerClassToAverageTraining", 1 ); 
+  int runsPerClassToAverageTesting = conf.gI( "main", "runsPerClassToAverageTesting", 1 );
+  
+  // share parameters among methods and classes?
+  bool shareParameters = conf.gB("main" , "shareParameters", true);
+  
+  //which methods do we want to use?
+  bool GPMeanApprox = conf.gB( "main", "GPMeanApprox", false);
+  bool GPVarApprox = conf.gB( "main", "GPVarApprox", false);  
+  bool GPMean = conf.gB( "main", "GPMean", false);
+  bool GPVar = conf.gB( "main", "GPVar", false);
+  bool GPSRMean = conf.gB( "main", "GPSRMean", false);
+  bool GPSRVar = conf.gB( "main", "GPSRVar", false);  
+  bool GPFITCMean = conf.gB( "main", "GPFITCMean", false);
+  bool GPFITCVar = conf.gB( "main", "GPFITCVar", false); 
+  bool GPOptMean = conf.gB( "main", "GPOptMean", false);
+  bool GPOptVar = conf.gB( "main", "GPOptVar", false);    
+  bool Parzen = conf.gB( "main", "Parzen", false);
+  bool SVDD = conf.gB( "main", "SVDD", false);  
+  
+  if (GPMeanApprox)
+    std::cerr << "GPMeanApprox used" << std::endl;
+  else 
+    std::cerr << "GPMeanApprox not used" << std::endl;
+  if (GPVarApprox)
+    std::cerr << "GPVarApprox used" << std::endl;
+  else 
+    std::cerr << "GPVarApprox not used" << std::endl;
+  if (GPMean)
+    std::cerr << "GPMean used" << std::endl;
+  else 
+    std::cerr << "GPMean not used" << std::endl;
+  if (GPVar)
+    std::cerr << "GPVar used" << std::endl;
+  else 
+    std::cerr << "GPVar not used" << std::endl;
+  if (GPSRMean)
+    std::cerr << "GPSRMean used" << std::endl;
+  else 
+    std::cerr << "GPSRMean not used" << std::endl;
+  if (GPSRVar)
+    std::cerr << "GPSRVar used" << std::endl;
+  else 
+    std::cerr << "GPSRVar not used" << std::endl;
+  if (GPFITCMean)
+    std::cerr << "GPFITCMean used" << std::endl;
+  else 
+    std::cerr << "GPFITCMean not used" << std::endl;
+  if (GPFITCVar)
+    std::cerr << "GPFITCVar used" << std::endl;
+  else 
+    std::cerr << "GPFITCVar not used" << std::endl; 
+  if (GPOptMean)
+    std::cerr << "GPOptMean used" << std::endl;
+  else 
+    std::cerr << "GPOptMean not used" << std::endl;
+  if (GPOptVar)
+    std::cerr << "GPOptVar used" << std::endl;
+  else 
+    std::cerr << "GPOptVar not used" << std::endl;  
+  if (Parzen)
+    std::cerr << "Parzen used" << std::endl;
+  else 
+    std::cerr << "Parzen not used" << std::endl;
+  if (SVDD)
+    std::cerr << "SVDD used" << std::endl;
+  else 
+    std::cerr << "SVDD not used" << std::endl;
+
+  
+  // GP variance approximation  
+  NICE::Vector sigmaGPVarApproxParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseGPVarApproxParas(nrOfClassesToConcidere,0.0);
+  // GP variance  
+  NICE::Vector sigmaGPVarParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseGPVarParas(nrOfClassesToConcidere,0.0);
+  //GP mean approximation  
+  NICE::Vector sigmaGPMeanApproxParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseGPMeanApproxParas(nrOfClassesToConcidere,0.0);
+  //GP mean  
+  NICE::Vector sigmaGPMeanParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseGPMeanParas(nrOfClassesToConcidere,0.0);
+  //GP SR mean  
+  NICE::Vector sigmaGPSRMeanParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseGPSRMeanParas(nrOfClassesToConcidere,0.0);
+  //GP SR var
+  NICE::Vector sigmaGPSRVarParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseGPSRVarParas(nrOfClassesToConcidere,0.0);
+  //GP FITC mean  
+  NICE::Vector sigmaGPFITCMeanParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseGPFITCMeanParas(nrOfClassesToConcidere,0.0);
+  //GP FITC var
+  NICE::Vector sigmaGPFITCVarParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseGPFITCVarParas(nrOfClassesToConcidere,0.0);  
+  //GP Opt mean  
+  NICE::Vector sigmaGPOptMeanParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseGPOptMeanParas(nrOfClassesToConcidere,0.0);
+  //GP Opt var
+  NICE::Vector sigmaGPOptVarParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseGPOptVarParas(nrOfClassesToConcidere,0.0);  
+  //Parzen  
+  NICE::Vector sigmaParzenParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseParzenParas(nrOfClassesToConcidere,0.0);
+  //SVDD  
+  NICE::Vector sigmaSVDDParas(nrOfClassesToConcidere,0.0);
+  NICE::Vector noiseSVDDParas(nrOfClassesToConcidere,0.0);
+    
+  if (!shareParameters)
+  {
+    //read the optimal parameters for the different methods
+    
+    // GP variance approximation
+    string sigmaGPVarApproxFile = conf.gS("main", "sigmaGPVarApproxFile", "approxVarSigma.txt");  
+    string noiseGPVarApproxFile = conf.gS("main", "noiseGPVarApproxFile", "approxVarNoise.txt");   
+    // GP variance
+    string sigmaGPVarFile = conf.gS("main", "sigmaGPVarFile", "approxVarSigma.txt");  
+    string noiseGPVarFile = conf.gS("main", "noiseGPVarFile", "approxVarNoise.txt");  
+    //GP mean approximation
+    string sigmaGPMeanApproxFile = conf.gS("main", "sigmaGPMeanApproxFile", "approxVarSigma.txt");  
+    string noiseGPMeanApproxFile = conf.gS("main", "noiseGPMeanApproxFile", "approxVarNoise.txt");    
+    //GP mean
+    string sigmaGPMeanFile = conf.gS("main", "sigmaGPMeanFile", "approxVarSigma.txt");  
+    string noiseGPMeanFile = conf.gS("main", "noiseGPMeanFile", "approxVarNoise.txt");      
+    //Parzen
+    string sigmaParzenFile = conf.gS("main", "sigmaParzenFile", "approxVarSigma.txt");  
+    string noiseParzenFile = conf.gS("main", "noiseParzenFile", "approxVarNoise.txt");    
+    //SVDD
+    string sigmaSVDDFile = conf.gS("main", "sigmaSVDDFile", "approxVarSigma.txt");  
+    string noiseSVDDFile = conf.gS("main", "noiseSVDDFile", "approxVarNoise.txt");      
+
+    // GP variance approximation    
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaGPVarApproxParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseGPVarApproxParas);  
+    // GP variance    
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaGPVarParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseGPVarParas);  
+    //GP mean approximation   
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaGPMeanApproxParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseGPMeanApproxParas);  
+    //GP mean  
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaGPMeanParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseGPMeanParas); 
+    //GP SR mean  
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaGPSRMeanParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseGPSRMeanParas);
+    //GP SR var  
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaGPSRVarParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseGPSRVarParas); 
+    //GP FITC mean  
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaGPFITCMeanParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseGPFITCMeanParas);
+    //GP FITC var  
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaGPFITCVarParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseGPFITCVarParas);      
+    //GP Opt mean  
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaGPOptMeanParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseGPOptMeanParas);
+    //GP Opt var  
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaGPOptVarParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseGPOptVarParas);     
+    //Parzen    
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaParzenParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseParzenParas);  
+    //SVDD    
+    readParameters(sigmaGPVarApproxFile,nrOfClassesToConcidere, sigmaSVDDParas);
+    readParameters(noiseGPVarApproxFile,nrOfClassesToConcidere, noiseSVDDParas);   
+  }
+  else
+  {
+    //use static variables for all methods and classis
+    double noise = conf.gD( "main", "noise", 0.01 );
+    double sigma = conf.gD( "main", "sigma", 1.0 );
+    
+    sigmaGPVarApproxParas.set(sigma);
+    noiseGPVarApproxParas.set(noise);
+    // GP variance  
+    sigmaGPVarParas.set(sigma);
+    noiseGPVarParas.set(noise);
+    //GP mean approximation  
+    sigmaGPMeanApproxParas.set(sigma);
+    noiseGPMeanApproxParas.set(noise);
+    //GP mean  
+    sigmaGPMeanParas.set(sigma);
+    noiseGPMeanParas.set(noise);
+    //GP SR mean  
+    sigmaGPSRMeanParas.set(sigma);
+    noiseGPSRMeanParas.set(noise);
+    //GP SR var  
+    sigmaGPSRVarParas.set(sigma);
+    noiseGPSRVarParas.set(noise); 
+    //GP FITC mean  
+    sigmaGPFITCMeanParas.set(sigma);
+    noiseGPFITCMeanParas.set(noise);
+    //GP FITC var  
+    sigmaGPFITCVarParas.set(sigma);
+    noiseGPFITCVarParas.set(noise);
+    //GP Opt mean  
+    sigmaGPOptMeanParas.set(sigma);
+    noiseGPOptMeanParas.set(noise);
+    //GP Opt var  
+    sigmaGPOptVarParas.set(sigma);
+    noiseGPOptVarParas.set(noise);    
+    //Parzen  
+    sigmaParzenParas.set(sigma);
+    noiseParzenParas.set(noise);
+    //SVDD  
+    sigmaSVDDParas.set(sigma);
+    noiseSVDDParas.set(noise);    
+  }
+  
+  
+  // -------- optimal parameters read --------------  
+  
+  std::vector<SparseVector> trainingData;
+  NICE::Vector y;
+  
+  std::cerr << "Reading ImageNet data ..." << std::endl;
+  bool imageNetLocal = conf.gB("main", "imageNetLocal" , false);
+  string imageNetPath;
+  if (imageNetLocal)
+    imageNetPath = "/users2/rodner/data/imagenet/devkit-1.0/";
+  else
+    imageNetPath = "/home/dbv/bilder/imagenet/devkit-1.0/";
+
+  ImageNetData imageNetTrain ( imageNetPath + "demo/" );
+
+  imageNetTrain.preloadData( "train", "training" );
+  trainingData = imageNetTrain.getPreloadedData();
+  y = imageNetTrain.getPreloadedLabels();
+    
+  std::cerr << "Reading of training data finished" << std::endl;
+  std::cerr << "trainingData.size(): " << trainingData.size() << std::endl;
+  std::cerr << "y.size(): " << y.size() << std::endl;
+  
+  std::cerr << "Reading ImageNet test data files (takes some seconds)..." << std::endl;
+  ImageNetData imageNetTest ( imageNetPath + "demo/" );
+  imageNetTest.preloadData ( "val", "testing" );
+  imageNetTest.loadExternalLabels ( imageNetPath + "data/ILSVRC2010_validation_ground_truth.txt" );  
+  
+  double OverallPerformanceGPVarApprox(0.0);
+  double OverallPerformanceGPVar(0.0);
+  double OverallPerformanceGPMeanApprox(0.0);
+  double OverallPerformanceGPMean(0.0);
+  double OverallPerformanceGPSRMean(0.0);
+  double OverallPerformanceGPSRVar(0.0);  
+  double OverallPerformanceGPFITCMean(0.0);
+  double OverallPerformanceGPFITCVar(0.0); 
+  double OverallPerformanceGPOptMean(0.0);
+  double OverallPerformanceGPOptVar(0.0);   
+  double OverallPerformanceParzen(0.0);
+  double OverallPerformanceSVDD(0.0);
+
+  
+  double kernelSigmaGPVarApprox;
+  double kernelSigmaGPVar;
+  double kernelSigmaGPMeanApprox;
+  double kernelSigmaGPMean;
+  double kernelSigmaGPSRMean;
+  double kernelSigmaGPSRVar;
+  double kernelSigmaGPFITCMean;
+  double kernelSigmaGPFITCVar; 
+  double kernelSigmaGPOptMean;
+  double kernelSigmaGPOptVar;  
+  double kernelSigmaParzen;
+  double kernelSigmaSVDD;
+  
+  for (int cl = indexOfFirstClass; cl <= indexOfLastClass; cl++)
+  {
+    std::cerr << "run for class " << cl << std::endl;
+    int positiveClass = cl+1; //labels are from 1 to 1000, but our indices from 0 to 999
+    // ------------------------------ TRAINING ------------------------------
+  
+    kernelSigmaGPVarApprox = sigmaGPVarApproxParas[cl];
+    kernelSigmaGPVar = sigmaGPVarParas[cl];
+    kernelSigmaGPMeanApprox = sigmaGPMeanApproxParas[cl];
+    kernelSigmaGPMean = sigmaGPMeanParas[cl];
+    kernelSigmaGPSRMean = sigmaGPSRMeanParas[cl];
+    kernelSigmaGPSRVar = sigmaGPSRVarParas[cl];
+    kernelSigmaGPFITCMean = sigmaGPFITCMeanParas[cl];
+    kernelSigmaGPFITCVar = sigmaGPFITCVarParas[cl];    
+    kernelSigmaGPOptMean = sigmaGPOptMeanParas[cl];
+    kernelSigmaGPOptVar = sigmaGPOptVarParas[cl];    
+    kernelSigmaParzen = sigmaParzenParas[cl];
+    kernelSigmaSVDD = sigmaSVDDParas[cl];
+    
+    Timer tTrain;
+    tTrain.start();
+    
+    //compute the kernel matrix, which will be shared among all methods in this scenario       
+    NICE::Matrix kernelMatrix(nrOfExamplesPerClass, nrOfExamplesPerClass, 0.0);
+    
+    //NOTE in theory we have to compute a single kernel Matrix for every method, since every method may have its own optimal parameter
+    // I'm sure, we can speed it up a bit and compute it only for every different parameter
+    //nonetheless, it's not as nice as we originally thought (same matrix for every method) 
+    
+    //NOTE Nonetheless, since we're only interested in runtimes, we can ignore this
+           
+    //now sum up all entries of each row in the original kernel matrix
+    double kernelScore(0.0);
+    for (int i = cl*100; i < cl*100+nrOfExamplesPerClass; i++)
+    {
+      for (int j = i; j < cl*100+nrOfExamplesPerClass; j++)
+      {
+        kernelScore = measureDistance(trainingData[i],trainingData[j], kernelSigmaGPVarApprox);
+        kernelMatrix(i-cl*100,j-cl*100) = kernelScore;
+        
+        if (i != j)
+            kernelMatrix(j-cl*100,i-cl*100) = kernelScore;
+      }
+    }  
+    
+    // now call the individual training methods
+    
+    //train GP Mean Approx
+    NICE::Vector GPMeanApproxRightPart;
+    if (GPMeanApprox)
+      trainGPMeanApprox(GPMeanApproxRightPart, noiseGPMeanApproxParas[cl], kernelMatrix, nrOfExamplesPerClass, cl, runsPerClassToAverageTraining );    
+    
+    //train GP Var Approx    
+    NICE::Vector matrixDInv;
+    if (GPVarApprox)
+      trainGPVarApprox(matrixDInv, noiseGPVarApproxParas[cl], kernelMatrix, nrOfExamplesPerClass, cl, runsPerClassToAverageTraining );
+         
+    //train GP Mean
+    NICE::Vector GPMeanRightPart;
+    if (GPMean)
+      trainGPMean(GPMeanRightPart, noiseGPMeanParas[cl], kernelMatrix, nrOfExamplesPerClass, cl, runsPerClassToAverageTraining );    
+    
+    //train GP Var
+    NICE::Matrix GPVarCholesky;
+    if (GPVar)
+      trainGPVar(GPVarCholesky, noiseGPVarParas[cl], kernelMatrix, nrOfExamplesPerClass, cl, runsPerClassToAverageTraining );       
+    
+    int nrOfRegressors (0);
+    //train GP SR Mean
+    NICE::Vector GPSRMeanRightPart;
+    std::vector<int> indicesOfChosenExamplesGPSRMean;
+    nrOfRegressors = conf.gI( "GPSR", "nrOfRegressors", nrOfExamplesPerClass/2);
+    nrOfRegressors = std::min( nrOfRegressors, nrOfExamplesPerClass );
+    if (GPSRMean)
+      trainGPSRMean(GPSRMeanRightPart, noiseGPSRMeanParas[cl], kernelMatrix, nrOfExamplesPerClass, cl, runsPerClassToAverageTraining, nrOfRegressors, indicesOfChosenExamplesGPSRMean );        
+    
+    //train GP SR Var
+    NICE::Matrix GPSRVarCholesky;   
+    std::vector<int> indicesOfChosenExamplesGPSRVar;
+    if (GPSRVar)
+      trainGPSRVar(GPSRVarCholesky, noiseGPSRVarParas[cl], kernelMatrix, nrOfExamplesPerClass, cl, runsPerClassToAverageTraining, nrOfRegressors, indicesOfChosenExamplesGPSRVar );  
+    
+    //train GP FITC Mean
+    NICE::Vector GPFITCMeanRightPart;
+    std::vector<int> indicesOfChosenExamplesGPFITCMean;
+    nrOfRegressors = conf.gI( "GPFITC", "nrOfRegressors", nrOfExamplesPerClass/5);
+    nrOfRegressors = std::min( nrOfRegressors, nrOfExamplesPerClass );
+    if (GPFITCMean)
+      trainGPFITCMean(GPFITCMeanRightPart, noiseGPFITCMeanParas[cl], kernelMatrix, nrOfExamplesPerClass, cl, runsPerClassToAverageTraining, nrOfRegressors, indicesOfChosenExamplesGPFITCMean ); 
+
+     //train GP FITC Var
+    NICE::Matrix GPFITCVarCholesky;   
+    std::vector<int> indicesOfChosenExamplesGPFITCVar;
+    if (GPFITCVar)
+      trainGPFITCVar(GPFITCVarCholesky, noiseGPFITCVarParas[cl], kernelMatrix, nrOfExamplesPerClass, cl, runsPerClassToAverageTraining, nrOfRegressors, indicesOfChosenExamplesGPFITCVar );    
+    
+    //train GP Opt Mean
+    NICE::Vector GPOptMeanRightPart;
+    if (GPOptMean)
+      trainGPOptMean(GPOptMeanRightPart, noiseGPOptMeanParas[cl], kernelMatrix, nrOfExamplesPerClass, cl, runsPerClassToAverageTraining );
+    std::cerr << "GPOptMeanRightPart: " << std::endl; std::cerr << GPOptMeanRightPart << std::endl;
+    
+    //train GP Opt Var
+    NICE::Vector DiagGPOptVar;
+    if (GPOptVar)
+      trainGPOptVar(DiagGPOptVar, noiseGPOptVarParas[cl], kernelMatrix, nrOfExamplesPerClass, cl, runsPerClassToAverageTraining );     
+    std::cerr << "DiagGPOptVar: " << std::endl; std::cerr << DiagGPOptVar << std::endl;
+    
+    //train Parzen 
+    //nothing to do :)
+    
+    //train SVDD
+    KCMinimumEnclosingBall *svdd;
+    if (SVDD)
+      svdd = trainSVDD(noiseSVDDParas[cl], kernelMatrix, nrOfExamplesPerClass, cl, runsPerClassToAverageTraining );
+  
+    tTrain.stop();
+    std::cerr << "Time used for training class " << cl << ": " << tTrain.getLast() << std::endl;      
+       
+    std::cerr << "training done - now perform the evaluation" << std::endl;
+
+
+    // ------------------------------ TESTING ------------------------------
+   
+    std::cerr << "Classification step ... with " << imageNetTest.getNumPreloadedExamples() << " examples" << std::endl;
+    
+    ClassificationResults resultsGPVarApprox;
+    ClassificationResults resultsGPVar;
+    ClassificationResults resultsGPMeanApprox;
+    ClassificationResults resultsGPMean;
+    ClassificationResults resultsGPSRMean;
+    ClassificationResults resultsGPSRVar;  
+    ClassificationResults resultsGPFITCMean;
+    ClassificationResults resultsGPFITCVar;
+    ClassificationResults resultsGPOptMean;
+    ClassificationResults resultsGPOptVar;    
+    ClassificationResults resultsParzen;
+    ClassificationResults resultsSVDD;       
+    
+    ProgressBar pb;
+    Timer tTest;
+    tTest.start();    
+    Timer tTestSingle;
+    
+    double timeForSingleExamplesGPVarApprox(0.0);    
+    double timeForSingleExamplesGPVar(0.0);
+    double timeForSingleExamplesGPMeanApprox(0.0);    
+    double timeForSingleExamplesGPMean(0.0);    
+    double timeForSingleExamplesGPSRMean(0.0);
+    double timeForSingleExamplesGPSRVar(0.0);
+    double timeForSingleExamplesGPFITCMean(0.0);
+    double timeForSingleExamplesGPFITCVar(0.0);
+    double timeForSingleExamplesGPOptMean(0.0);
+    double timeForSingleExamplesGPOptVar(0.0);    
+    double timeForSingleExamplesParzen(0.0);    
+    double timeForSingleExamplesSVDD(0.0);    
+    
+    for ( uint i = 0 ; i < (uint)imageNetTest.getNumPreloadedExamples(); i++ )
+    {
+      pb.update ( imageNetTest.getNumPreloadedExamples() );
+
+      const SparseVector & svec = imageNetTest.getPreloadedExample ( i );
+
+      //NOTE: again we should use method-specific optimal parameters. If we're only interested in the runtimes, this doesn't matter
+      
+      //compute (self) similarities
+      double kernelSelf (measureDistance(svec,svec, kernelSigmaGPVarApprox) );
+      NICE::Vector kernelVector (nrOfExamplesPerClass, 0.0);
+      
+      for (int j = 0; j < nrOfExamplesPerClass; j++)
+      {
+        kernelVector[j] = measureDistance(trainingData[j+cl*100],svec, kernelSigmaGPVarApprox);
+      }     
+      
+      //call the individual test-methods
+      
+      //evaluate GP Var Approx
+      ClassificationResult rGPVarApprox;      
+      if (GPVarApprox)
+        evaluateGPVarApprox( kernelVector, kernelSelf, matrixDInv, rGPVarApprox, timeForSingleExamplesGPVarApprox, runsPerClassToAverageTesting );
+      
+      //evaluate GP Var
+      ClassificationResult rGPVar;
+      if (GPVar)
+        evaluateGPVar( kernelVector, kernelSelf, GPVarCholesky, rGPVar, timeForSingleExamplesGPVar, runsPerClassToAverageTesting );      
+      
+      //evaluate GP Mean Approx
+      ClassificationResult rGPMeanApprox;      
+      if (GPMeanApprox)
+        evaluateGPMeanApprox( kernelVector, matrixDInv, rGPMeanApprox, timeForSingleExamplesGPMeanApprox, runsPerClassToAverageTesting );
+      
+      //evaluate GP Mean
+      ClassificationResult rGPMean;
+      if (GPMean)
+        evaluateGPMean( kernelVector, GPMeanRightPart, rGPMean, timeForSingleExamplesGPMean, runsPerClassToAverageTesting );       
+       
+      //evaluate GP SR Mean
+      ClassificationResult rGPSRMean;
+      if (GPSRMean)
+        evaluateGPSRMean( kernelVector, GPSRMeanRightPart, rGPSRMean, timeForSingleExamplesGPSRMean, runsPerClassToAverageTesting, nrOfRegressors, indicesOfChosenExamplesGPSRMean );       
+      
+      //evaluate GP SR Var
+      ClassificationResult rGPSRVar;
+      if (GPSRVar)
+        evaluateGPSRVar( kernelVector, GPSRVarCholesky, rGPSRVar, timeForSingleExamplesGPSRVar, runsPerClassToAverageTesting, nrOfRegressors, indicesOfChosenExamplesGPSRVar, noiseGPSRVarParas[cl] );  
+      
+      //evaluate GP FITC Mean
+      ClassificationResult rGPFITCMean;
+      if (GPFITCMean)
+        evaluateGPFITCMean( kernelVector, GPFITCMeanRightPart, rGPFITCMean, timeForSingleExamplesGPFITCMean, runsPerClassToAverageTesting, nrOfRegressors, indicesOfChosenExamplesGPFITCMean );       
+      
+      //evaluate GP FITC Var
+      ClassificationResult rGPFITCVar;
+      if (GPFITCVar)
+        evaluateGPFITCVar( kernelVector, GPFITCVarCholesky, rGPFITCVar, timeForSingleExamplesGPFITCVar, runsPerClassToAverageTesting, nrOfRegressors, indicesOfChosenExamplesGPFITCVar, noiseGPFITCVarParas[cl] );             
+      
+      //evaluate GP Opt Mean
+      ClassificationResult rGPOptMean;
+      if (GPOptMean)
+        evaluateGPOptMean( kernelVector, GPOptMeanRightPart, rGPOptMean, timeForSingleExamplesGPOptMean, runsPerClassToAverageTesting );       
+      
+      //evaluate GP Opt Var
+      ClassificationResult rGPOptVar;
+      if (GPOptVar)
+        evaluateGPOptVar( kernelVector, kernelSelf, DiagGPOptVar, rGPOptVar, timeForSingleExamplesGPOptVar, runsPerClassToAverageTesting );   
+      
+      //evaluate Parzen
+      ClassificationResult rParzen;
+      if (Parzen)
+        evaluateParzen( kernelVector, rParzen, timeForSingleExamplesParzen, runsPerClassToAverageTesting ); 
+      
+      //evaluate SVDD
+      ClassificationResult rSVDD;
+      if (SVDD)
+        evaluateSVDD( svdd, kernelVector, rSVDD, timeForSingleExamplesSVDD, runsPerClassToAverageTesting );       
+
+      
+      // set ground truth label
+      rGPVarApprox.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+      rGPVar.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+      rGPMeanApprox.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+      rGPMean.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+      rGPSRMean.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+      rGPSRVar.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+      rGPFITCMean.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+      rGPFITCVar.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+      rGPOptMean.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+      rGPOptVar.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;      
+      rParzen.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+      rSVDD.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+
+      //remember the results for the evaluation lateron
+      resultsGPVarApprox.push_back ( rGPVarApprox );
+      resultsGPVar.push_back ( rGPVar );
+      resultsGPMeanApprox.push_back ( rGPMeanApprox );
+      resultsGPMean.push_back ( rGPMean );
+      resultsGPSRMean.push_back ( rGPSRMean );
+      resultsGPSRVar.push_back ( rGPSRVar );
+      resultsGPFITCMean.push_back ( rGPFITCMean );
+      resultsGPFITCVar.push_back ( rGPFITCVar );
+      resultsGPOptMean.push_back ( rGPOptMean );
+      resultsGPOptVar.push_back ( rGPOptVar );      
+      resultsParzen.push_back ( rParzen );
+      resultsSVDD.push_back ( rSVDD );      
+    }
+    
+    tTest.stop();
+    std::cerr << "Time used for evaluating class " << cl << ": " << tTest.getLast() << std::endl;       
+    
+    timeForSingleExamplesGPVarApprox/= imageNetTest.getNumPreloadedExamples();
+    timeForSingleExamplesGPVar/= imageNetTest.getNumPreloadedExamples();
+    timeForSingleExamplesGPMeanApprox/= imageNetTest.getNumPreloadedExamples();
+    timeForSingleExamplesGPMean/= imageNetTest.getNumPreloadedExamples();
+    timeForSingleExamplesGPSRMean/= imageNetTest.getNumPreloadedExamples();
+    timeForSingleExamplesGPSRVar/= imageNetTest.getNumPreloadedExamples();
+    timeForSingleExamplesGPFITCMean/= imageNetTest.getNumPreloadedExamples();
+    timeForSingleExamplesGPFITCVar/= imageNetTest.getNumPreloadedExamples();
+    timeForSingleExamplesGPOptMean/= imageNetTest.getNumPreloadedExamples();
+    timeForSingleExamplesGPOptVar/= imageNetTest.getNumPreloadedExamples();    
+    timeForSingleExamplesParzen/= imageNetTest.getNumPreloadedExamples();
+    timeForSingleExamplesSVDD/= imageNetTest.getNumPreloadedExamples();
+    
+    std::cerr << "GPVarApprox -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesGPVarApprox << std::endl;    
+    std::cerr << "GPVar -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesGPVar << std::endl;    
+    std::cerr << "GPMeanApprox -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesGPMeanApprox << std::endl;    
+    std::cerr << "GPMean -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesGPMean << std::endl;    
+    std::cerr << "GPSRMean -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesGPSRMean << std::endl;    
+    std::cerr << "GPSRVar -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesGPSRVar << std::endl;    
+    std::cerr << "GPFITCMean -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesGPFITCMean << std::endl;    
+    std::cerr << "GPFITCVar -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesGPFITCVar << std::endl; 
+    std::cerr << "GPOptMean -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesGPOptMean << std::endl;    
+    std::cerr << "GPOptVar -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesGPOptVar << std::endl;    
+    std::cerr << "Parzen -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesParzen << std::endl;    
+    std::cerr << "SVDD -- time used for evaluation single elements of class " << cl << " : " << timeForSingleExamplesSVDD << std::endl;    
+
+    // run the AUC-evaluation
+    double perfvalueGPVarApprox( 0.0 );
+    double perfvalueGPVar( 0.0 );
+    double perfvalueGPMeanApprox( 0.0 );
+    double perfvalueGPMean( 0.0 );
+    double perfvalueGPSRMean( 0.0 );
+    double perfvalueGPSRVar( 0.0 );
+    double perfvalueGPFITCMean( 0.0 );
+    double perfvalueGPFITCVar( 0.0 );    
+    double perfvalueGPOptMean( 0.0 );
+    double perfvalueGPOptVar( 0.0 );    
+    double perfvalueParzen( 0.0 );
+    double perfvalueSVDD( 0.0 );     
+
+    if (GPVarApprox)
+      perfvalueGPVarApprox = resultsGPVarApprox.getBinaryClassPerformance( ClassificationResults::PERF_AUC );    
+    if (GPVar)
+      perfvalueGPVar = resultsGPVar.getBinaryClassPerformance( ClassificationResults::PERF_AUC );
+    if (GPMeanApprox)
+      perfvalueGPMeanApprox = resultsGPMeanApprox.getBinaryClassPerformance( ClassificationResults::PERF_AUC );
+    if (GPMean)
+      perfvalueGPMean = resultsGPMean.getBinaryClassPerformance( ClassificationResults::PERF_AUC );
+    if (GPSRMean)
+      perfvalueGPSRMean = resultsGPSRMean.getBinaryClassPerformance( ClassificationResults::PERF_AUC );
+    if (GPSRVar)
+      perfvalueGPSRVar = resultsGPSRVar.getBinaryClassPerformance( ClassificationResults::PERF_AUC );
+    if (GPFITCMean)
+      perfvalueGPFITCMean = resultsGPFITCMean.getBinaryClassPerformance( ClassificationResults::PERF_AUC );
+    if (GPFITCVar)
+      perfvalueGPFITCVar = resultsGPFITCVar.getBinaryClassPerformance( ClassificationResults::PERF_AUC );    
+    if (GPOptMean)
+      perfvalueGPOptMean = resultsGPOptMean.getBinaryClassPerformance( ClassificationResults::PERF_AUC );
+    if (GPOptVar)
+      perfvalueGPOptVar = resultsGPOptVar.getBinaryClassPerformance( ClassificationResults::PERF_AUC );    
+    if (Parzen)
+      perfvalueParzen = resultsParzen.getBinaryClassPerformance( ClassificationResults::PERF_AUC );
+    if (SVDD)
+      perfvalueSVDD = resultsSVDD.getBinaryClassPerformance( ClassificationResults::PERF_AUC );  
+
+
+    std::cerr << "Performance GPVarApprox: " << perfvalueGPVarApprox << std::endl;
+    std::cerr << "Performance GPVar: " << perfvalueGPVar << std::endl;
+    std::cerr << "Performance GPMeanApprox: " << perfvalueGPMeanApprox << std::endl;
+    std::cerr << "Performance GPMean: " << perfvalueGPMean << std::endl;
+    std::cerr << "Performance GPSRMean: " << perfvalueGPSRMean << std::endl;
+    std::cerr << "Performance GPSRVar: " << perfvalueGPSRVar << std::endl;
+    std::cerr << "Performance GPFITCMean: " << perfvalueGPFITCMean << std::endl;
+    std::cerr << "Performance GPFITCVar: " << perfvalueGPFITCVar << std::endl;    
+    std::cerr << "Performance GPOptMean: " << perfvalueGPOptMean << std::endl;
+    std::cerr << "Performance GPOptVar: " << perfvalueGPOptVar << std::endl;    
+    std::cerr << "Performance Parzen: " << perfvalueParzen << std::endl;
+    std::cerr << "Performance SVDD: " << perfvalueSVDD << std::endl;    
+    
+    OverallPerformanceGPVarApprox += perfvalueGPVar;    
+    OverallPerformanceGPVar += perfvalueGPVarApprox;
+    OverallPerformanceGPMeanApprox += perfvalueGPMeanApprox;
+    OverallPerformanceGPMean += perfvalueGPMean;
+    OverallPerformanceGPSRMean += perfvalueGPSRMean;
+    OverallPerformanceGPSRVar += perfvalueGPSRVar;
+    OverallPerformanceGPFITCMean += perfvalueGPFITCMean;
+    OverallPerformanceGPFITCVar += perfvalueGPFITCVar;   
+    OverallPerformanceGPOptMean += perfvalueGPOptMean;
+    OverallPerformanceGPOptVar += perfvalueGPOptVar;    
+    OverallPerformanceParzen += perfvalueParzen;
+    OverallPerformanceSVDD += perfvalueSVDD;   
+
+    // clean up memory used by SVDD
+    if (SVDD)    
+      delete svdd;
+  }
+  
+  OverallPerformanceGPVarApprox /= nrOfClassesToConcidere;
+  OverallPerformanceGPVar /= nrOfClassesToConcidere;
+  OverallPerformanceGPMeanApprox /= nrOfClassesToConcidere;
+  OverallPerformanceGPMean /= nrOfClassesToConcidere;
+  OverallPerformanceGPSRMean /= nrOfClassesToConcidere;
+  OverallPerformanceGPSRVar /= nrOfClassesToConcidere;
+  OverallPerformanceGPFITCMean /= nrOfClassesToConcidere;
+  OverallPerformanceGPFITCVar /= nrOfClassesToConcidere;
+  OverallPerformanceGPOptMean /= nrOfClassesToConcidere;
+  OverallPerformanceGPOptVar /= nrOfClassesToConcidere;  
+  OverallPerformanceParzen /= nrOfClassesToConcidere;
+  OverallPerformanceSVDD /= nrOfClassesToConcidere;  
+  
+  std::cerr << "overall performance GPVarApprox: " << OverallPerformanceGPVarApprox << std::endl;
+  std::cerr << "overall performance GPVar: " << OverallPerformanceGPVar << std::endl;
+  std::cerr << "overall performance GPMeanApprox: " << OverallPerformanceGPMeanApprox << std::endl;
+  std::cerr << "overall performance GPMean: " << OverallPerformanceGPMean << std::endl;
+  std::cerr << "overall performance GPSRMean: " << OverallPerformanceGPSRMean << std::endl;
+  std::cerr << "overall performance GPSRVar: " << OverallPerformanceGPSRVar << std::endl;
+  std::cerr << "overall performance GPFITCMean: " << OverallPerformanceGPFITCMean << std::endl;
+  std::cerr << "overall performance GPFITCVar: " << OverallPerformanceGPFITCVar << std::endl;
+  std::cerr << "overall performance GPOptMean: " << OverallPerformanceGPOptMean << std::endl;
+  std::cerr << "overall performance GPOptVar: " << OverallPerformanceGPOptVar << std::endl;  
+  std::cerr << "overall performance Parzen: " << OverallPerformanceParzen << std::endl;
+  std::cerr << "overall performance SVDD: " << OverallPerformanceSVDD << std::endl;  
+  
+  return 0;
+}

+ 280 - 0
progs/testImageNetBinaryGPBaseline.cpp

@@ -0,0 +1,280 @@
+/** 
+* @file testImageNetBinaryGPBaseline.cpp
+* @brief perform ImageNet tests with binary tasks for OCC using the baseline GP
+* @author Alexander Lütz
+* @date 29-05-2012 (dd-mm-yyyy)
+
+*/
+#include "core/basics/Config.h"
+#include "core/basics/Timer.h"
+#include "core/vector/SparseVectorT.h"
+#include "core/algebra/CholeskyRobust.h"
+#include "core/vector/Algorithms.h"
+
+#include "vislearning/cbaselib/ClassificationResults.h"
+#include "vislearning/baselib/ProgressBar.h"
+
+#include "vislearning/matlabAccess/MatFileIO.h"
+#include "vislearning/matlabAccess/ImageNetData.h"
+
+// #include "fast-hik/tools.h"
+
+using namespace std;
+using namespace NICE;
+using namespace OBJREC;
+
+double measureDistance ( const NICE::SparseVector & a, const NICE::SparseVector & b, const double & sigma = 2.0)//, const bool & verbose = false)
+{
+  double inner_sum(0.0);
+
+  double d;    
+    
+  //new version, where we needed on average 0.001707 s for each test sample
+  NICE::SparseVector::const_iterator aIt = a.begin();
+  NICE::SparseVector::const_iterator bIt = b.begin();
+   
+  while ( (aIt != a.end()) && (bIt != b.end()) )
+  {
+    if (aIt->first == bIt->first)
+    {
+      d = ( aIt->second - bIt->second );      
+      inner_sum += d * d;
+      aIt++;
+      bIt++;
+    }
+    else if ( aIt->first < bIt->first)
+    {
+      inner_sum += aIt->second * aIt->second;
+      aIt++;      
+    }
+    else
+    {
+      inner_sum += bIt->second * bIt->second;
+      bIt++;       
+    }
+  }
+  
+  //compute remaining values, if b reached the end but not a
+  while (aIt != a.end())
+  {
+    inner_sum += aIt->second * aIt->second;
+    aIt++; 
+  }
+  //compute remaining values, if a reached the end but not b
+  while (bIt != b.end())
+  {
+    inner_sum += bIt->second * bIt->second;
+    bIt++; 
+  }  
+  inner_sum /= (2.0*sigma*sigma);
+  
+  return exp(-inner_sum); //expValue;
+}
+
+void readParameters(const string & filename, const int & size, NICE::Vector & parameterVector)
+{
+  parameterVector.resize(size);
+  parameterVector.set(0.0);
+  
+  ifstream is(filename.c_str());
+  if ( !is.good() )
+    fthrow(IOException, "Unable to read parameters.");  
+//
+  string tmp;
+  int cnt(0);
+  while (! is.eof())
+  {
+    is >> tmp;
+    parameterVector[cnt] = atof(tmp.c_str());
+    cnt++;
+  }
+//   
+  is.close(); 
+}
+
+
+/** 
+    test the basic functionality of fast-hik hyperparameter optimization 
+*/
+int main (int argc, char **argv)
+{   
+  std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
+
+  Config conf ( argc, argv );
+  string resultsfile = conf.gS("main", "results", "results.txt" );
+  double kernelSigma = conf.gD("main", "kernelSigma", 2.0);
+  int nrOfExamplesPerClass = conf.gI("main", "nrOfExamplesPerClass", 50);
+  nrOfExamplesPerClass = std::min(nrOfExamplesPerClass, 100); // we do not have more than 100 examples per class
+  int nrOfClassesToConcidere = conf.gI("main", "nrOfClassesToConcidere", 1000);
+  nrOfClassesToConcidere = std::min(nrOfClassesToConcidere, 1000); //we do not have more than 1000 classes
+
+  string sigmaFile = conf.gS("main", "sigmaFile", "approxVarSigma.txt");  
+  string noiseFile = conf.gS("main", "noiseFile", "approxVarNoise.txt");  
+  
+  
+  NICE::Vector sigmaParas(nrOfClassesToConcidere,kernelSigma);
+  NICE::Vector noiseParas(nrOfClassesToConcidere,0.0);
+  
+  readParameters(sigmaFile,nrOfClassesToConcidere, sigmaParas);
+  readParameters(noiseFile,nrOfClassesToConcidere, noiseParas);
+  
+  std::vector<SparseVector> trainingData;
+  NICE::Vector y;
+  
+  std::cerr << "Reading ImageNet data ..." << std::endl;
+  bool imageNetLocal = conf.gB("main", "imageNetLocal" , false);
+  string imageNetPath;
+  if (imageNetLocal)
+    imageNetPath = "/users2/rodner/data/imagenet/devkit-1.0/";
+  else
+    imageNetPath = "/home/dbv/bilder/imagenet/devkit-1.0/";
+
+  ImageNetData imageNetTrain ( imageNetPath + "demo/" );
+
+  imageNetTrain.preloadData( "train", "training" );
+  trainingData = imageNetTrain.getPreloadedData();
+  y = imageNetTrain.getPreloadedLabels();
+    
+  std::cerr << "Reading of training data finished" << std::endl;
+  std::cerr << "trainingData.size(): " << trainingData.size() << std::endl;
+  std::cerr << "y.size(): " << y.size() << std::endl;
+  
+  std::cerr << "Reading ImageNet test data files (takes some seconds)..." << std::endl;
+  ImageNetData imageNetTest ( imageNetPath + "demo/" );
+  imageNetTest.preloadData ( "val", "testing" );
+  imageNetTest.loadExternalLabels ( imageNetPath + "data/ILSVRC2010_validation_ground_truth.txt" );  
+  
+  double OverallPerformance(0.0);  
+  
+  for (int cl = 0; cl < nrOfClassesToConcidere; cl++)
+  {
+    std::cerr << "run for class " << cl << std::endl;
+    int positiveClass = cl+1;
+    // ------------------------------ TRAINING ------------------------------
+  
+    kernelSigma = sigmaParas[cl];
+    
+    std::cerr << "using sigma: " << kernelSigma << " and noise " << noiseParas[cl] << std::endl;
+    Timer tTrain;
+    tTrain.start();
+    NICE::Matrix kernelMatrix (nrOfExamplesPerClass, nrOfExamplesPerClass, 0.0);
+      
+    //now compute the kernelScores for every element
+    double kernelScore(0.0);
+    for (int i = cl*100; i < cl*100+nrOfExamplesPerClass; i++)
+    {
+      for (int j = i; j < cl*100+nrOfExamplesPerClass; j++)
+      {
+        kernelScore = measureDistance(trainingData[i],trainingData[j], kernelSigma);//optimalParameters[cl]);
+        kernelMatrix(i-cl*100,j-cl*100) = kernelScore;
+        if (i != j)
+          kernelMatrix(j-cl*100,i-cl*100) = kernelScore;
+      }
+    }  
+    
+    //adding some noise, if necessary
+    if (noiseParas[cl] != 0.0)
+    {
+      kernelMatrix.addIdentity(noiseParas[cl]);
+    }
+    else
+    {
+      //zero was already set
+    }    
+   
+    //compute its inverse
+    //noise is already added :)
+    Timer tTrainPrecise;
+    tTrainPrecise.start();     
+    
+    CholeskyRobust cr  ( false /* verbose*/, 0.0 /*noiseStep*/, false /* useCuda*/);
+    
+    NICE::Matrix choleskyMatrix (nrOfExamplesPerClass, nrOfExamplesPerClass, 0.0);      
+    cr.robustChol ( kernelMatrix, choleskyMatrix );    
+    
+    tTrainPrecise.stop(); 
+    std::cerr << "Precise time used for training class " << cl << ": " << tTrainPrecise.getLast() << std::endl;    
+    
+    tTrain.stop();
+    std::cerr << "Time used for training class " << cl << ": " << tTrain.getLast() << std::endl;    
+       
+    std::cerr << "training done - now perform the evaluation" << std::endl;
+
+
+    // ------------------------------ TESTING ------------------------------
+   
+    ClassificationResults results;
+    std::cerr << "Classification step ... with " << imageNetTest.getNumPreloadedExamples() << " examples" << std::endl;
+    ProgressBar pb;
+    Timer tTest;
+    tTest.start();    
+    Timer tTestSingle;
+    double timeForSingleExamples(0.0);
+    for ( uint i = 0 ; i < (uint)imageNetTest.getNumPreloadedExamples(); i++ )
+    {
+      pb.update ( imageNetTest.getNumPreloadedExamples() );
+
+      //get the precomputed features
+      const SparseVector & svec = imageNetTest.getPreloadedExample ( i );
+      
+      //compute (self-)similarities
+      double kernelSelf (measureDistance(svec,svec, kernelSigma) );
+      NICE::Vector kernelVector (nrOfExamplesPerClass, 0.0);
+      
+      for (int j = 0; j < nrOfExamplesPerClass; j++)
+      {
+        kernelVector[j] = measureDistance(trainingData[j+cl*100],svec, kernelSigma);
+      }     
+      
+      //compute the resulting score
+      tTestSingle.start();
+      NICE::Vector rightPart (nrOfExamplesPerClass);
+      choleskySolveLargeScale ( choleskyMatrix, kernelVector, rightPart );
+        
+      double uncertainty = kernelSelf - kernelVector.scalarProduct ( rightPart );
+      tTestSingle.stop();
+      timeForSingleExamples += tTestSingle.getLast();
+      
+      //this is the standard score-object needed for the evaluation
+      FullVector scores ( 2 );
+      scores[0] = 0.0;
+      scores[1] = 1.0 - uncertainty;
+
+      ClassificationResult r ( scores[1]<0.5 ? 0 : 1, scores );    
+      
+      // set ground truth label
+      r.classno_groundtruth = (((int)imageNetTest.getPreloadedLabel ( i )) == positiveClass) ? 1 : 0;
+      
+      //we could write the resulting score on the command line
+//       std::cerr << "scores: " << std::endl;
+//       scores >> std::cerr;
+      //as well as the ground truth label
+//       std::cerr << "gt: " <<  r.classno_groundtruth << " -- " << r.classno << std::endl;
+      
+      results.push_back ( r );
+    }
+    
+    tTest.stop();
+    std::cerr << "Time used for evaluating class " << cl << ": " << tTest.getLast() << std::endl;       
+    
+    timeForSingleExamples/= imageNetTest.getNumPreloadedExamples();
+    std::cerr << "Time used for evaluation single elements of class " << cl << " : " << timeForSingleExamples << std::endl;
+    
+
+    // we could also write the results to an external file. Note, that this file will be overwritten in every iteration
+    // so if you want to store all results, you should add a suffix with the class number
+//     std::cerr << "Writing results to " << resultsfile << std::endl;
+//     results.writeWEKA ( resultsfile, 1 );
+    double perfvalue = results.getBinaryClassPerformance( ClassificationResults::PERF_AUC );
+
+    std::cerr << "Performance: " << perfvalue << std::endl;
+    
+    OverallPerformance += perfvalue;    
+  }
+  
+  OverallPerformance /= nrOfClassesToConcidere;
+  
+  std::cerr << "overall performance: " << OverallPerformance << std::endl;
+  
+  return 0;
+}