HDF5 boost multi array transparent support

This commit is contained in:
Guilhem Lavaux 2014-05-20 16:16:46 +02:00
parent 1d59f4e93d
commit 47255ea25a
3 changed files with 243 additions and 0 deletions

175
src/hdf5_array.hpp Normal file
View file

@ -0,0 +1,175 @@
#ifndef __COSMO_HDF5_ARRAY_HPP
#define __COSMO_HDF5_ARRAY_HPP
#include <string>
#include <stdint.h>
#include <boost/static_assert.hpp>
#include <boost/utility.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/multi_array.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <vector>
#include <H5Cpp.h>
namespace CosmoTool {
//!_______________________________________________________________________________________
//!
//! map types to HDF5 types
//!
//!
//! Leo Goodstadt (04 March 2013), improved with enable_if by Guilhem Lavaux (May 2014)
//!_______________________________________________________________________________________
template<typename T, class Enable = void> struct get_hdf5_data_type
{
static H5::PredType type()
{
BOOST_MPL_ASSERT_MSG(0, Unknown_HDF5_data_type, ());
return H5::PredType::NATIVE_DOUBLE;
}
};
#define HDF5_TYPE(tl, thdf5) \
template<typename T> struct get_hdf5_data_type<T, typename boost::enable_if<boost::is_same<T, tl> >::type> \
{ static H5::PredType type() { return H5::PredType::thdf5; }; }
HDF5_TYPE(char , NATIVE_CHAR);
HDF5_TYPE(long long , NATIVE_LLONG);
HDF5_TYPE(unsigned long long, NATIVE_ULLONG);
HDF5_TYPE(int8_t , NATIVE_INT8);
HDF5_TYPE(uint8_t , NATIVE_UINT8);
HDF5_TYPE(int16_t , NATIVE_INT16);
HDF5_TYPE(uint16_t , NATIVE_UINT16);
HDF5_TYPE(int32_t , NATIVE_INT32);
HDF5_TYPE(uint32_t , NATIVE_UINT32);
HDF5_TYPE(int64_t , NATIVE_INT64);
HDF5_TYPE(uint64_t , NATIVE_UINT64);
HDF5_TYPE(float , NATIVE_FLOAT);
HDF5_TYPE(double , NATIVE_DOUBLE);
HDF5_TYPE(long double , NATIVE_LDOUBLE);
#undef HDF5_TYPE
//!_______________________________________________________________________________________
//!
//! write_hdf5 multi_array
//!
//! \author leo Goodstadt (04 March 2013)
//!
//!_______________________________________________________________________________________
template<typename T, std::size_t DIMENSIONS, typename hdf5_data_type>
void hdf5_write_array(H5::CommonFG& fg, const std::string& data_set_name,
const boost::multi_array<T, DIMENSIONS>& data,
const hdf5_data_type& datatype)
{
std::vector<hsize_t> dimensions(data.shape(), data.shape() + DIMENSIONS);
H5::DataSpace dataspace(DIMENSIONS, dimensions.data());
H5::DataSet dataset = fg.createDataSet(data_set_name, datatype, dataspace);
dataset.write(data.data(), datatype);
}
/* HDF5 complex type */
template<typename T>
class hdf5_ComplexType
{
public:
H5::CompType type;
hdf5_ComplexType()
: type(sizeof(std::complex<T>))
{
get_hdf5_data_type<T> hdf_data_type;
type.insertMember("r", 0, hdf_data_type.type());
type.insertMember("i", sizeof(T), hdf_data_type.type());
type.pack();
}
static const hdf5_ComplexType<T> *ctype()
{
static hdf5_ComplexType<T> singleton;
return &singleton;
}
};
template<typename T, std::size_t DIMENSIONS>
void hdf5_write_array(H5::CommonFG& fg, const std::string& data_set_name, const boost::multi_array<T, DIMENSIONS>& data )
{
get_hdf5_data_type<T> hdf_data_type;
hdf5_write_array(fg, data_set_name, data, hdf_data_type.type());
}
template<typename T, std::size_t DIMENSIONS>
void hdf5_write_array(H5::CommonFG& fg, const std::string& data_set_name, const boost::multi_array<std::complex<T>, DIMENSIONS>& data )
{
hdf5_write_array(fg, data_set_name, data, hdf5_ComplexType<T>::ctype()->type);
}
// HDF5 array reader
//
// Author Guilhem Lavaux (May 2014)
class InvalidDimensions: virtual std::exception {
};
template<std::size_t r>
struct hdf5_extent_gen {
typedef typename boost::detail::multi_array::extent_gen<r> type;
static inline type build(hsize_t *d)
{
return (hdf5_extent_gen<r-1>::build(d))[d[r-1]];
}
};
template<>
struct hdf5_extent_gen<0> {
static inline boost::multi_array_types::extent_gen build(hsize_t *d)
{
return boost::extents;
}
};
template<typename T, std::size_t DIMENSIONS, typename hdf5_data_type>
void hdf5_read_array(H5::CommonFG& fg, const std::string& data_set_name,
boost::multi_array<T, DIMENSIONS>& data,
const hdf5_data_type& datatype)
{
H5::DataSet dataset = fg.openDataSet(data_set_name);
H5::DataSpace dataspace = dataset.getSpace();
std::vector<hsize_t> dimensions(DIMENSIONS);
if (dataspace.getSimpleExtentNdims() != DIMENSIONS)
{
throw InvalidDimensions();
}
dataspace.getSimpleExtentDims(dimensions.data());
data.resize(hdf5_extent_gen<DIMENSIONS>::build(dimensions.data()));
dataset.read(data.data(), datatype);
}
template<typename T, std::size_t DIMENSIONS>
void hdf5_read_array(H5::CommonFG& fg, const std::string& data_set_name, boost::multi_array<T, DIMENSIONS>& data )
{
get_hdf5_data_type<T> hdf_data_type;
hdf5_read_array(fg, data_set_name, data, hdf_data_type.type());
}
template<typename T, std::size_t DIMENSIONS>
void hdf5_read_array(H5::CommonFG& fg, const std::string& data_set_name, boost::multi_array<std::complex<T>, DIMENSIONS>& data )
{
hdf5_read_array(fg, data_set_name, data, hdf5_ComplexType<T>::ctype()->type);
}
};
#endif