eigen3-hdf5/eigen3-hdf5-extend.hpp

239 lines
6.8 KiB
C++
Raw Normal View History

2019-08-10 09:41:30 +00:00
#ifndef EIGEN3_HDF5_EXTEND_HPP_
#define EIGEN3_HDF5_EXTEND_HPP_
#include <typeinfo>
#include <string>
#include <vector>
#include <H5Cpp.h>
#include <Eigen/Dense>
#include <eigen3-hdf5.hpp>
namespace Eigen3HDF5
{
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Function to copy vector<Vector> into MatrixX
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
namespace internal_math
{
template<typename Scalar>
bool convert_vectorVectorX_to_MatrixX( const std::vector<Eigen::Matrix<Scalar, Eigen::Dynamic, 1> >& vec_of_vecX, Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>& MatX )
{
// size of vector
int nvector_size = vec_of_vecX.size();
// error check
if ( nvector_size == 0 ) { return( false ); }
// size of each VectorXd
int nVectorX_size = vec_of_vecX[0].size();
// allocate size
MatX.resize( nVectorX_size, nvector_size );
// Loop and copy to MatriX*
for ( int i = 0; i < nvector_size; i++ )
{
// error check
if ( vec_of_vecX[i].size() != nVectorX_size )
{
MatX.resize( 0, 0 );
return( false );
}
// copy to MatrixXd
MatX.col( i ) = vec_of_vecX[i];
}
return( true );
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
// native std::vector all except std<string>
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T, typename A>
void save( H5::CommonFG& h5group, const std::string& name, const std::vector<T, A>& var )
{
// Part 2: set dimension to 1 (single value)
hsize_t dim[1];
dim[0] = var.size();
// Part 3: create the type
H5::DataSpace space( 1, dim );
// Part 4:
if ( typeid( T ) == typeid( int ) )
{
H5::DataSet dataset( h5group.createDataSet( name, H5::PredType::NATIVE_INT32, space ) );
dataset.write( var.data(), H5::PredType::NATIVE_INT32 );
}
else
if ( typeid( T ) == typeid( float ) )
{
H5::DataSet dataset( h5group.createDataSet( name, H5::PredType::NATIVE_FLOAT, space ) );
dataset.write( var.data(), H5::PredType::NATIVE_FLOAT );
}
else
if ( typeid( T ) == typeid( double ) )
{
H5::DataSet dataset( h5group.createDataSet( name, H5::PredType::NATIVE_DOUBLE, space ) );
dataset.write( var.data(), H5::PredType::NATIVE_DOUBLE );
}
else
if ( typeid( T ) == typeid( char ) )
{
H5::DataSet dataset( h5group.createDataSet( name, H5::PredType::NATIVE_CHAR, space ) );
dataset.write( var.data(), H5::PredType::NATIVE_CHAR );
}
else
{
// not implemented
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This function saves a vector of variable length string to hdf5
// see: http://stackoverflow.com/questions/581209/how-to-best-write-out-a-stdvector-stdstring-container-to-a-hdf5-dataset
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
inline void save( H5::CommonFG& h5group, const std::string& name, const std::vector<std::string>& var )
{
// Part 1: grab pointers to the chars
std::vector<const char*> chars;
for ( const auto& str : var )
{
chars.push_back( str.data() );
}
// Part 2: get the dim, rank = 1 (1D array)
hsize_t dim[1];
dim[0] = chars.size();
// Part 3: create the type
H5::DataSpace space( 1, dim );
auto s_type = H5::StrType( H5::PredType::C_S1, H5T_VARIABLE );
// Part 4: write the output to a scalar dataset
H5::DataSet dataset( h5group.createDataSet( name, s_type, space ) );
dataset.write( chars.data(), s_type );
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
// std::vector<Eigen::VectorX*>
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename Scalar>
void save( H5::CommonFG& h5group, const std::string& name, const std::vector<Eigen::Matrix<Scalar, Eigen::Dynamic, 1> >& vec_of_vecX )
{
// Part 1: create MatrixX* to store final results
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> MatX;
// Part 2: copy vector<VectorX> into MatrixX
internal_math::convert_vectorVectorX_to_MatrixX( vec_of_vecX, MatX );
// Part 3: save MatrixX using Eigenhdf5
save( h5group, name, MatX );
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
// save "simple" data (int/float/bool)
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
void save_simple( H5::CommonFG& h5group, const std::string& name, const T& var )
{
// Part 2: set dimension to 1 (single value)
hsize_t dim[1];
dim[0] = 1;
// Part 3: create the type
H5::DataSpace space( 1, dim );
// Part 4:
if ( typeid( T ) == typeid( int ) )
{
H5::DataSet dataset( h5group.createDataSet( name, H5::PredType::NATIVE_INT32, space ) );
dataset.write( &var, H5::PredType::NATIVE_INT32 );
}
else
if ( typeid( T ) == typeid( float ) )
{
H5::DataSet dataset( h5group.createDataSet( name, H5::PredType::NATIVE_FLOAT, space ) );
dataset.write( &var, H5::PredType::NATIVE_FLOAT );
}
else
if ( typeid( T ) == typeid( double ) )
{
H5::DataSet dataset( h5group.createDataSet( name, H5::PredType::NATIVE_DOUBLE, space ) );
dataset.write( &var, H5::PredType::NATIVE_DOUBLE );
}
else
if ( typeid( T ) == typeid( char ) )
{
H5::DataSet dataset( h5group.createDataSet( name, H5::PredType::NATIVE_CHAR, space ) );
dataset.write( &var, H5::PredType::NATIVE_CHAR );
}
else
if ( typeid( T ) == typeid( bool ) )
{
// cast to int since hdf5 doesnt support boolean
int int_from_bool = int(var);
H5::DataSet dataset( h5group.createDataSet( name, H5::PredType::NATIVE_INT32, space ) );
dataset.write( &int_from_bool, H5::PredType::NATIVE_INT32 );
}
else
{
// not implemented
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This function saves a vector of variable length string to hdf5
// see: http://stackoverflow.com/questions/581209/how-to-best-write-out-a-stdvector-stdstring-container-to-a-hdf5-dataset
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
inline void save_simple( H5::CommonFG& h5group, const std::string& name, const std::string& var )
{
// Part 1: grab pointers to the chars
const char* c = var.c_str();
// Part 2: get the dim, rank = 1 (1D array)
hsize_t dim[1];
dim[0] = 1;
// Part 3: create the type
H5::DataSpace space( 1, dim );
auto s_type = H5::StrType( H5::PredType::C_S1, H5T_VARIABLE );
// Part 4: write the output to a scalar dataset
H5::DataSet dataset( h5group.createDataSet( name, s_type, space ) );
dataset.write( &c, s_type );
}
} // namespace Eigen3HDF5
#endif