[vsipl++] Matlab IO Patch

Jules Bergmann jules at codesourcery.com
Tue May 30 20:18:24 UTC 2006


Assem Salama wrote:
> Everyone,
>  This patch adds the support for reading in views from a matlab binary 
> file. Note that this will only work if dims and types match. It doesn't 
> create a matrix suitable for the current data set.
> 
> Thanks,
> Assem Salama
> 
> 
> ------------------------------------------------------------------------
> 

> Index: matlab.hpp
> ===================================================================
> RCS file: matlab.hpp

This file is in the src/vsip_csl directory, correct?

> diff -N matlab.hpp
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ matlab.hpp	26 May 2006 20:03:54 -0000
> @@ -0,0 +1,287 @@
> +#ifndef VSIP_CSL_MATLAB_HPP
> +#define VSIP_CSL_MATLAB_HPP
> +
> +#include <iostream>
> +#include <vsip/impl/metaprogramming.hpp>
> +#include <vsip/impl/fns_elementwise.hpp>
> +#include <vsip/impl/length.hpp>
> +#include <vsip/impl/domain-utils.hpp>
> +
> +namespace vsip_csl
> +{
> +
> +namespace matlab
> +{
> +  struct data_element
> +  {
> +    int32_t type;
> +    int32_t size;
> +  };
> +
> +  template <int Dim>
> +  struct view_header
> +  {
> +    data_element header;
> +    data_element array_flags_header;
> +    char array_flags[8];
> +    data_element dim_header;
> +    int32_t dim[Dim + Dim%2]; //the dim has to be alligned to an 8 byte boundary
                                                   ^ spelling: 'aligned'
> +    data_element array_name_header;
> +  };
> +
> +  // helper struct to get the imaginary part of a view.
> +  template <typename ViewT,
> +            bool IsComplex =
> +	      vsip::impl::Is_complex<typename ViewT::value_type>::value>
> +  struct Subview_helper;
> +
> +  template <typename ViewT>
> +  struct Subview_helper<ViewT,true>
> +  {
> +    typedef typename ViewT::realview_type realview_type;
> +    typedef typename ViewT::imagview_type imagview_type;
> +
> +    static realview_type real(ViewT v) { return v.real(); }
> +    static imagview_type imag(ViewT v) { return v.imag(); }
> +  };
> +
> +  template <typename ViewT>
> +  struct Subview_helper<ViewT,false>
> +  {
> +    typedef ViewT realview_type;
> +    typedef ViewT imagview_type;
> +
> +    static realview_type real(ViewT v) { return v; }
> +    static imagview_type imag(ViewT v) { return v; }
> +  };
> +
> +
> +  // generic readers that allows us to read a generic type and cast to another
> +  
> +  // the read function for real
> +  template <typename T1,
> +            typename T2,
> +	    typename Block0,
> +	    template <typename,typename> class View>
> +  void read(std::istream& is,View<T2,Block0> v,vsip::impl::Bool_type<true>)
> +  {

Since you use the value 'View<T2, Block0>::dim' several t
imes below, it would be helpful to create a variable for it:

	dimension_type const dim = View<T2, Block0>::dim;

> +    vsip::Index<View<T2,Block0>::dim> my_index;
> +    vsip::impl::Length<View<T2,Block0>::dim> v_extent = extent(v);
> +    int num_points = 1;
> +    typedef typename vsip::impl::Scalar_of<T2>::type scalar_type;
> +    T1 data;
> +
> +    // get num_points
> +    for(int i=0;i<View<T2,Block0>::dim;i++) num_points *= v.size(i);

When iterating over dimensions, you should use 'dimension_type' instead
of int.  I.e.

	for (dimension_type i=0; i<View<...>::dim; ++i)

View<...>::dim is of type 'dimension_type'.  Using an int will generally
work, but will cause gcc to issue warnings about comparison between
signed and unsigned values when compiled with '-Wall -W'.

Also,

	length_type num_points = v.size();

should work.  View::size() with no arguments returns the total size of 
the view.  Also, it returns a value of type 'length_type', not 'int'.

> +
> +    // set index to 0
> +    for(int i=0;i<View<T2,Block0>::dim;i++) my_index[i] = 0;

This shouldn't be necessary, the constructor for Index should initialize 
all of its values to 0.


> +
> +    // read all the points
> +    for(int i=0;i<num_points;i++) {
> +      is.read(reinterpret_cast<char*>(&data),sizeof(data));
> +      put(v,my_index,scalar_type(data));
> +
> +      // increment index
> +      my_index = vsip::impl::next(v_extent,my_index);

We need to extend next to take dimension-ordering into account.  Right 
now it is row-major by default.  I'll post something for this.

> +    }
> +
> +  }
> +
> +  // the read function for complex
> +  template <typename T1,
> +            typename T2,
> +	    typename Block0,
> +	    template <typename,typename> class View>
> +  void read(std::istream& is,View<T2,Block0> v,vsip::impl::Bool_type<false>)
> +  {
> +    vsip::Index<View<T2,Block0>::dim> my_index;
> +    vsip::impl::Length<View<T2,Block0>::dim> v_extent = extent(v);
> +    int num_points = 1;
> +    typename Subview_helper<View<T2,Block0> >::imagview_type imag_view =
> +      Subview_helper<View<T2,Block0> >::imag(v);
> +    typedef typename vsip::impl::Scalar_of<T2>::type scalar_type;
> +    T1 data;
> +
> +    // get num_points
> +    for(int i=0;i<View<T2,Block0>::dim;i++) num_points *= v.size(i);
> +
> +    // read all the points
> +    for(int i=0;i<num_points;i++) {
> +      is.read(reinterpret_cast<char*>(&data),sizeof(data));
> +      put(imag_view,my_index,scalar_type(data));
> +
> +      // increment index
> +      my_index = vsip::impl::next(v_extent,my_index);
> +    }
> +  }

These two variants of read are pretty much the same, except the second 
one puts values into the imaginary subview.

If you move the call to Subview_helper into operator>> below, you can 
eliminate one of the definitions.



> +
> +  struct header
> +  {
> +    char description[116];
> +    char subsyt_data[8];
> +    char version[2];
> +    char endian[2];
> +  };
> +
> +  // constants for matlab binary format
> +
> +  // data types
> +  static int const miINT8           = 1;
> +  static int const miUINT8          = 2;
> +  static int const miINT16          = 3;
> +  static int const miUINT16         = 4;
> +  static int const miINT32          = 5;
> +  static int const miUINT32         = 6;
> +  static int const miSINGLE         = 7;
> +  static int const miDOUBLE         = 9;
> +  static int const miINT64          = 12;
> +  static int const miUINT64         = 13;
> +  static int const miMATRIX         = 14;
> +  static int const miCOMPRESSED     = 15;
> +  static int const miUTF8           = 16;
> +  static int const miUTF16          = 17;
> +  static int const miUTF32          = 18;
> +  
> +  // class types
> +  static int const mxCELL_CLASS     = 1;
> +  static int const mxSTRUCT_CLASS   = 2;
> +  static int const mxOBJECT_CLASS   = 3;
> +  static int const mxCHAR_CLASS     = 4;
> +  static int const mxSPARSE_CLASS   = 5;
> +  static int const mxDOUBLE_CLASS   = 6;
> +  static int const mxSINGLE_CLASS   = 7;
> +  static int const mxINT8_CLASS     = 8;
> +  static int const mxUINT8_CLASS    = 9;
> +  static int const mxINT16_CLASS    = 10;
> +  static int const mxUINT16_CLASS   = 11;
> +  static int const mxINT32_CLASS    = 12;
> +  static int const mxUINT32_CLASS   = 13;
> +
> +  // matlab header traits
> +  template <int size,bool is_signed,bool is_int>
> +  struct Matlab_header_traits

You should leave the base case undefined.  That way attempts to use a 
size we haven't defined (such as size=5 or something) will be caught as 
compile errors.

> +  { 
> +    static int const value_type = 0;
> +    static int const class_type = 0;
> +  };
> +
> +  template <>
> +  struct Matlab_header_traits<1, true, true> // char
> +  { 
> +    static int const value_type = miINT8;
> +    static int const class_type = mxINT8_CLASS; 
> +  };
> +
> +  template <>
> +  struct Matlab_header_traits<1, false, true> // unsigned char
> +  { 
> +    static int const value_type = miUINT8;
> +    static int const class_type = mxUINT8_CLASS; 
> +  };
> +
> +  template <>
> +  struct Matlab_header_traits<2, true, true> // short
> +  { 
> +    static int const value_type = miINT16;
> +    static int const class_type = mxINT16_CLASS; 
> +  };
> +
> +  template <>
> +  struct Matlab_header_traits<2, false, true> // unsigned short
> +  { 
> +    static int const value_type = miUINT16;
> +    static int const class_type = mxUINT16_CLASS; 
> +  };
> +
> +  template <>
> +  struct Matlab_header_traits<4, true, true> // int
> +  { 
> +    static int const value_type= miINT32;
> +    static int const class_type= mxINT32_CLASS;
> +  };
> +
> +  template <>
> +  struct Matlab_header_traits<4, false, true> // unsigned int
> +  { 
> +    static int const value_type= miUINT32;
> +    static int const class_type= mxUINT32_CLASS;
> +  };
> +
> +  template <>
> +  struct Matlab_header_traits<4, true, false> // float
> +  { 
> +    static int const value_type= miSINGLE;
> +    static int const class_type= mxSINGLE_CLASS;
> +  };
> +
> +  template <>
> +  struct Matlab_header_traits<8, true, false> // double
> +  { 
> +    static int const value_type= miDOUBLE;
> +    static int const class_type= mxDOUBLE_CLASS;
> +  };
> +
> +  // matlab desired layouts
> +  template <template <typename,typename> class View>
> +  struct Matlab_desired_LP;
> +
> +  template<> struct Matlab_desired_LP<vsip::const_Vector>
> +  { typedef vsip::impl::Layout<1,vsip::col1_type,
> +                     vsip::impl::Stride_unit_dense,vsip::impl::Cmplx_split_fmt>
> +      type; 
> +  };
> +
> +  template<> struct Matlab_desired_LP<vsip::const_Matrix>
> +  { typedef vsip::impl::Layout<2,vsip::col2_type,
> +                     vsip::impl::Stride_unit_dense,vsip::impl::Cmplx_split_fmt>
> +      type; 
> +  };
> +  
> +  template<> struct Matlab_desired_LP<vsip::const_Tensor>
> +  { typedef vsip::impl::Layout<3,vsip::col3_type,
> +                     vsip::impl::Stride_unit_dense,vsip::impl::Cmplx_split_fmt>
> +      type; 
> +  };
> +
> +  template<> struct Matlab_desired_LP<vsip::Vector>
> +  { typedef vsip::impl::Layout<1,vsip::col1_type,
> +                     vsip::impl::Stride_unit_dense,vsip::impl::Cmplx_split_fmt>
> +      type; 
> +  };
> +
> +  template<> struct Matlab_desired_LP<vsip::Matrix>
> +  { typedef vsip::impl::Layout<2,vsip::col2_type,
> +                     vsip::impl::Stride_unit_dense,vsip::impl::Cmplx_split_fmt>
> +      type; 
> +  };
> +  
> +  template<> struct Matlab_desired_LP<vsip::Tensor>
> +  { typedef vsip::impl::Layout<3,vsip::col3_type,
> +                     vsip::impl::Stride_unit_dense,vsip::impl::Cmplx_split_fmt>
> +      type; 
> +  };
> +
> +  // helper function to return the real and imaginary part of a pointer
> +  
> +  template<typename T>
> +  inline T* get_real_ptr(std::pair<T*,T*> ptr,vsip::impl::Bool_type<true>) 
> +    { return ptr.first; }
> +  template<typename T>
> +  inline T* get_real_ptr(T* ptr,vsip::impl::Bool_type<false>)
> +    { return ptr; }

You shouldn't need the Bool_type<...> variable to disambiguate these 
overloads.

> +
> +  template<typename T>
> +  inline T* get_imag_ptr(std::pair<T*,T*> ptr,vsip::impl::Bool_type<true>) 
> +    { return ptr.second; }
> +  template<typename T>
> +  inline T* get_imag_ptr(T* ptr,vsip::impl::Bool_type<false>)
> +    { return ptr; }
> +
> +
> +
> +} // namesapce matlab
> +
> +} // namespace vsip_csl
> +
> +#endif // VSIP_CSL_MATLAB_HPP
> Index: matlab_bin_formatter.hpp
> ===================================================================
> RCS file: matlab_bin_formatter.hpp
> diff -N matlab_bin_formatter.hpp
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ matlab_bin_formatter.hpp	26 May 2006 20:03:54 -0000
> @@ -0,0 +1,353 @@
> +/* Copyright (c) 2005, 2006 by CodeSourcery.  All rights reserved. */
> +
> +/** @file    vsip_csl/matlab_bin_formatter.hpp
> +    @author  Assem Salama
> +    @date    2006-05-22
> +    @brief   VSIPL++ CodeSourcery Library: Matlab binary formatter
> +*/
> +
> +#ifndef VSIP_CSL_MATLAB_BIN_FORMATTER_HPP
> +#define VSIP_CSL_MATLAB_BIN_FORMATTER_HPP
> +
> +#include <stdint.h>
> +#include <string>
> +#include <limits>
> +#include <vsip_csl/matlab.hpp>
> +#include <vsip/impl/fns_scalar.hpp>
> +#include <vsip/impl/fns_elementwise.hpp>
> +#include <vsip/impl/metaprogramming.hpp>
> +#include <vsip/impl/view_traits.hpp>
> +#include <vsip/impl/extdata.hpp>
> +
> +namespace vsip_csl
> +{
> +
> +  template <typename ViewT>
> +  struct Matlab_bin_formatter
> +  {
> +    Matlab_bin_formatter(ViewT v,std::string const& name) :
> +      v(v), view_name(name)  {}
> +
> +    ViewT v;
> +    std::string view_name;
> +
> +  };
> +
> +  struct Matlab_bin_hdr
> +  {
> +    Matlab_bin_hdr(std::string const& descr, std::string const& end) : 
> +      description(descr),version("MATLAB 5.0 : "),endian(end) {}
> +    Matlab_bin_hdr(std::string const& descr) : 
> +      description(descr),version("MATLAB 5.0 : "),endian("MI") {}
> +    Matlab_bin_hdr() : 
> +      description(" "),version("MATLAB 5.0 : "),endian("MI") {}
> +
> +    // description
> +    std::string version;
> +    std::string description;
> +    std::string endian;
> +
> +  };
> +} // namespace vsip_csl
> +
> +/****************************************************************************
> + * Definitions
> + ***************************************************************************/
> +
> +namespace vsip_csl
> +{
> +
> +// operator to write matlab header
> +inline
> +std::ostream&
> +operator<<(
> +  std::ostream&           o,
> +  Matlab_bin_hdr const&   h)
> +{
> +  matlab::header m_hdr;
> +
> +  // set hdr to spaces
> +  memset(&(m_hdr),' ',sizeof(m_hdr));
> +  strncpy(m_hdr.description, h.version.data(), h.version.length());
> +  strncpy(m_hdr.description+h.version.length(), h.description.data(),
> +    h.description.length());
> +  m_hdr.version[1] = 0x01; m_hdr.version[0] = 0x00;
> +  m_hdr.endian[0]=h.endian[0];
> +  m_hdr.endian[1]=h.endian[1];
> +
> +  // write header
> +  o.write(reinterpret_cast<char*>(&m_hdr),sizeof(m_hdr));
> +
> +  return o;
> +}
> +// operator to write a view to a matlab file
> +template <typename T,
> +          typename Block0,
> +	  template <typename,typename> class const_View>
> +inline
> +std::ostream&
> +operator<<(
> +  std::ostream&                                       o,
> +  Matlab_bin_formatter<const_View<T,Block0> > const&  mbf)
> +{
> +  typedef typename vsip::impl::Scalar_of<T>::type scalar_type;
> +  matlab::data_element temp_data_element;
> +  int    sz;
> +  matlab::view_header<vsip::impl::Dim_of_view<const_View>::dim > m_view;
> +  int    num_points = 1;
> +  int    v_dims = vsip::impl::Dim_of_view<const_View>::dim;
> +
> +  memset(&m_view,0,sizeof(m_view));
> +
> +  // matrix data type
> +  m_view.header.type = matlab::miMATRIX;
> +  m_view.header.size = 1; // TEMP
> +
> +  // array flags
> +  m_view.array_flags_header.type = matlab::miUINT32;
> +  m_view.array_flags_header.size = 8;
> +  if(vsip::impl::Is_complex<T>::value) 
> +    m_view.array_flags[1] |= 0x8; // Complex
> +
> +  // fill in class
> +  m_view.array_flags[0] = 
> +    matlab::Matlab_header_traits<sizeof(scalar_type),
> +                  std::numeric_limits<scalar_type>::is_signed,
> +                  std::numeric_limits<scalar_type>::is_integer>::class_type;
> +
> +  // make sure we found a matching trait
> +  assert(m_view.array_flags[0] != 0);
> +  
> +  // dimension sizes
> +  m_view.dim_header.type = matlab::miINT32;
> +  m_view.dim_header.size = v_dims*4; // 4 bytes per dimension
> +  // fill in dimension
> +  for(int i =0;i<v_dims;i++)
> +  {
> +    m_view.dim[i] = mbf.v.size(i);
> +    num_points *= mbf.v.size(i);
> +  }
> +
> +  // if this view is a vector, we need to make second dimension a one
> +  if(v_dims == 1)
> +  {
> +    m_view.dim_header.size += 4;
> +    m_view.dim[1] = 1;
> +  }
> +
> +  // array name
> +  m_view.array_name_header.type = matlab::miINT8;
> +  m_view.array_name_header.size = mbf.view_name.length();
> +
> +
> +  // calculate size
> +  sz = sizeof(m_view)-8;
> +  sz += mbf.view_name.length();
> +  sz += (8-mbf.view_name.length())&0x7;
> +  sz += 8; // 8 bytes of header for real data
> +  if(vsip::impl::Is_complex<T>::value) sz += 8; // 8 more for complex data
> +  sz += num_points*sizeof(T);
> +  m_view.header.size = sz;
> +
> +  o.write(reinterpret_cast<char*>(&m_view),sizeof(m_view));
> +
> +  // write array name
> +  o.write(mbf.view_name.c_str(),mbf.view_name.length());
> +  // pad
> +  { 
> +    char c=0;
> +    for(int i=0;i < ((8-mbf.view_name.length())&0x7);i++) o.write(&c,1);
> +  }
> +
> +  // write real part
> +  {
> +    
> +
> +    vsip::impl::Ext_data<Block0,
> +	                 typename matlab::Matlab_desired_LP<const_View>::type >

This Ext_data usage is good, but there are two problems:

First, if data isn't in the right format (dense, column-major, split if 
complex), this is going to require a memory allocation to reformat the 
data.  It is possible that transforming the data then performing IO with 
large blocks is more efficient than performing IO on small blocks, but 
the memory allocation/deallocation isn't good.  My guess is that we 
could get by with this (IO routines are mostly going to be done outside 
of the computation loop, and what embedded system is going to save data 
in matlab format anyways?).

However, to be safe, we should avoid this memory allocation.  We can do 
this by checking the cost of the Ext_data.

	// If cost == 0, no memory allocation will be done
	if (vsip::impl::Ext_data_cost<Block0,
                typename matlab::Matlab_desired_LP<const_View>::type >
	       ::value == 0)
	{
	   ... current code ...
	}
	else
	{
	   explicit loop, similar to read functionality.
	}


Second, assuming we were to leave this as is without the cost check, 
there is an identical Ext_data object below.  If data is not in the 
right format, it would do an allocation and copy as well, which would be 
overhead.

> +	     
> +	     m_ext(mbf.v.block());
> +
> +    temp_data_element.type = matlab::Matlab_header_traits<sizeof(scalar_type),
> +                  std::numeric_limits<scalar_type>::is_signed,
> +                  std::numeric_limits<scalar_type>::is_integer>::value_type;
> +
> +    temp_data_element.size = num_points*sizeof(scalar_type);
> +    o.write(reinterpret_cast<char*>(&temp_data_element),
> +              sizeof(temp_data_element));
> +    o.write(reinterpret_cast<char*>
> +         (matlab::get_real_ptr<scalar_type>(m_ext.data(),
> +            vsip::impl::Bool_type<vsip::impl::Is_complex<T>::value>())),
> +              num_points*sizeof(scalar_type));
> +  }
> +
> +  if(!vsip::impl::Is_complex<T>::value) return o; //we are done here
> +
> +  // write imaginary part
> +  {
> +    
> +
> +    vsip::impl::Ext_data<Block0,
> +	                 typename matlab::Matlab_desired_LP<const_View>::type >
> +	     
> +	     m_ext(mbf.v.block());
> +
> +    temp_data_element.type = matlab::Matlab_header_traits<sizeof(scalar_type),
> +                  std::numeric_limits<scalar_type>::is_signed,
> +                  std::numeric_limits<scalar_type>::is_integer>::value_type;
> +
> +    temp_data_element.size = num_points*sizeof(scalar_type);
> +    o.write(reinterpret_cast<char*>(&temp_data_element),
> +              sizeof(temp_data_element));
> +    o.write(reinterpret_cast<char*>
> +         (matlab::get_imag_ptr<scalar_type>(m_ext.data(),
> +            vsip::impl::Bool_type<vsip::impl::Is_complex<T>::value>())),
> +              num_points*sizeof(scalar_type));
> +  }
> +
> +
> +  return o;
> +}
> +
> +// operator to read matlab header
> +inline
> +std::istream&
> +operator>>(
> +  std::istream&           o,
> +  Matlab_bin_hdr          h)
> +{
> +  matlab::header m_hdr;
> +
> +  // read header
> +  o.read(reinterpret_cast<char*>(&m_hdr),sizeof(m_hdr));
> +
> +  h.version[1] = m_hdr.version[1];
> +  h.version[0] = m_hdr.version[0];
> +  h.endian[1] = m_hdr.endian[1];
> +  h.endian[0] = m_hdr.endian[0];
> +
> +  return o;
> +}
> +
> +// operator to read view from matlab file
> +template <typename T,
> +          typename Block0,
> +	  template <typename,typename> class View>
> +inline
> +std::istream&
> +operator>>(
> +  std::istream&                                       is,
> +  Matlab_bin_formatter<View<T,Block0> >               mbf)
> +{
> +  matlab::data_element temp_data_element;
> +  matlab::view_header<vsip::impl::Dim_of_view<View>::dim> m_view;
> +  typedef typename vsip::impl::Scalar_of<T>::type scalar_type;
> +  int v_dim = vsip::impl::Dim_of_view<View>::dim;
> +
> +
> +  // read header
> +  is.read(reinterpret_cast<char*>(&m_view),sizeof(m_view));
> +
> +  // is this complex?
> +  if(vsip::impl::Is_complex<T>::value)
> +    assert(m_view.array_flags[1]&0x8);

This should be an exception.  Something like "Attempting to read 
non-complex matlab view into complex VSIPL++ view".

> +
> +  // is this the same class?
> +  assert(m_view.array_flags[0] == 
> +            (matlab::Matlab_header_traits<sizeof(scalar_type),
> +                  std::numeric_limits<scalar_type>::is_signed,
> +                  std::numeric_limits<scalar_type>::is_integer>::class_type));
> +
> +  // do dimensions agree?
> +  if(v_dim == 1) m_view.dim_header.size -= 4; // special case for vectors
> +  assert(v_dim == (m_view.dim_header.size/4));

Likewise.  "Attempting to read N-dimensional matlab data into 
M-dimensional VSIPL++ view"

> +
> +  for(int i=0;i<v_dim;i++)
> +    assert(mbf.v.size(i) == m_view.dim[i]);

Likewise.

> +
> +  // read array name
> +  if(m_view.array_name_header.type & 0xffff0000)
> +  {
> +    // array name is short
> +
> +    int length = m_view.array_name_header.type >> 16;
> +    /*
> +    strncpy(mbf.view_name.data(),
> +            reinterpret_cast<char*>(&m_view.array_name_header.size),
> +	    length);
> +    mbf.view_name[length] = 0;
> +    */
> +  }
> +  else
> +  {
> +    int length = m_view.array_name_header.size;
> +    char c;
> +    char c_array[128];

How is 128 chosen?  Is that specified as the maximum size in the Matlab 
file spec?  If so, an assertion would be in order 'assert(length < 
128)'.  (Strict less-than since we put a \0 at the end).

If not, should we dynamically allocate c_array?

> +    // the name is longer than 4 bytes
> +    //o.read(mbf.view_name.data(),length);
> +    is.read(c_array,length);
> +    c_array[length] = 0;
> +    // read padding
> +    for(int i=0;i<((8-length)&0x7);i++) is.read(&c,1);
> +  }

Here's where we can reduce the number of read functions:

Something like:


	// read real data header
	is.read(reinterpret_cast<char*>(&temp_data_element),
                 sizeof(temp_data_element));
	matlab::read(is, temp_data_element.type,
                      Subview_helper<View<T,Block0> >::real(mbf.v));

	if (vsip::impl::Is_complex<T>::value)
	{
	  // read real data header
	  is.read(reinterpret_cast<char*>(&temp_data_element),
                 sizeof(temp_data_element));
	  matlab::read(is, temp_data_element.type,
                      Subview_helper<View<T,Block0> >::imag(mbf.v));
	}

To do this we would need to move the run-time->compile-time type 
dispatch for matlab into a separate function.

	template <typename ViewT>
	void
	read(
	  std::istream& is,
	  int const     m_type,
	  ViewT         v)
	{
	  if      (m_type == matlab::miINT8)  read<int8_t>(is, view);
	  else if (m_type == matlab::miUNIT8) read<uint8_t>(is, view);
	  ...
	}

	
	


> +
> +  // read data, we will go in this loop twice if we have complex data
> +  for (int i=0;i <= vsip::impl::Is_complex<T>::value;i++)
> +  {
> +
> +    // read data header
> +    is.read(reinterpret_cast<char*>(&temp_data_element),
> +            sizeof(temp_data_element));
> +
> +    // Because we don't know how the data was stored, we need to instantiate
> +    // generic_reader which can read a type and cast into a different one
> +    if(temp_data_element.type == matlab::miINT8) 
> +    {
> +      if(i==0)matlab::read<int8_t>(is,mbf.v,vsip::impl::Bool_type<true>());
> +      else    matlab::read<int8_t>(is,mbf.v,vsip::impl::Bool_type<false>());
> +    }
> +    else if(temp_data_element.type == matlab::miUINT8) 
> +    {
> +      if(i==0)matlab::read<uint8_t>(is,mbf.v,vsip::impl::Bool_type<true>());
> +      else    matlab::read<uint8_t>(is,mbf.v,vsip::impl::Bool_type<false>());
> +    }
> +    else if(temp_data_element.type == matlab::miINT16) 
> +    {
> +      if(i==0)matlab::read<int16_t>(is,mbf.v,vsip::impl::Bool_type<true>());
> +      else    matlab::read<int16_t>(is,mbf.v,vsip::impl::Bool_type<false>());
> +    }
> +    else if(temp_data_element.type == matlab::miUINT16) 
> +    {
> +      if(i==0)matlab::read<uint16_t>(is,mbf.v,vsip::impl::Bool_type<true>());
> +      else    matlab::read<uint16_t>(is,mbf.v,vsip::impl::Bool_type<false>());
> +    }
> +    else if(temp_data_element.type == matlab::miINT32) 
> +    {
> +      if(i==0)matlab::read<int32_t>(is,mbf.v,vsip::impl::Bool_type<true>());
> +      else    matlab::read<int32_t>(is,mbf.v,vsip::impl::Bool_type<false>());
> +    }
> +    else if(temp_data_element.type == matlab::miUINT32) 
> +    {
> +      if(i==0)matlab::read<uint32_t>(is,mbf.v,vsip::impl::Bool_type<true>());
> +      else    matlab::read<uint32_t>(is,mbf.v,vsip::impl::Bool_type<false>());
> +    }
> +    else if(temp_data_element.type == matlab::miSINGLE) 
> +    {
> +      if(i==0)matlab::read<float>(is,mbf.v,vsip::impl::Bool_type<true>());
> +      else    matlab::read<float>(is,mbf.v,vsip::impl::Bool_type<false>());
> +    }
> +    else
> +    {
> +      if(i==0)matlab::read<double>(is,mbf.v,vsip::impl::Bool_type<true>());
> +      else    matlab::read<double>(is,mbf.v,vsip::impl::Bool_type<false>());
> +    }
> +
> +  }
> +
> +}
> +
> +
> +
> +} // namespace vsip_csl
> +
> +#endif // VSIP_CSL_MATLAB_BIN_FORMATTER_HPP
> Index: matlab_text_formatter.hpp
> ===================================================================
> RCS file: matlab_text_formatter.hpp

Text formatter looks good.

-- 
Jules Bergmann
CodeSourcery
jules at codesourcery.com
(650) 331-3385 x705




More information about the vsipl++ mailing list