diff --git a/include/highfive/bits/H5Inspector_decl.hpp b/include/highfive/bits/H5Inspector_decl.hpp new file mode 100644 index 000000000..a925df568 --- /dev/null +++ b/include/highfive/bits/H5Inspector_decl.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +namespace HighFive { + +inline size_t compute_total_size(const std::vector& dims) { + return std::accumulate(dims.begin(), dims.end(), size_t{1u}, std::multiplies()); +} + +template +using unqualified_t = typename std::remove_const::type>::type; + + +namespace details { + +template +struct type_helper; + +template +struct inspector; + +} // namespace details +} // namespace HighFive diff --git a/include/highfive/bits/H5Inspector_misc.hpp b/include/highfive/bits/H5Inspector_misc.hpp index 98da8affd..4721db742 100644 --- a/include/highfive/bits/H5Inspector_misc.hpp +++ b/include/highfive/bits/H5Inspector_misc.hpp @@ -21,19 +21,14 @@ #include "string_padding.hpp" -#ifdef H5_USE_BOOST -#include -// starting Boost 1.64, serialization header must come before ublas -#include -#include -#endif #ifdef H5_USE_EIGEN #include #endif +#include "H5Inspector_decl.hpp" -namespace HighFive { +namespace HighFive { namespace details { inline bool checkDimensions(const std::vector& dims, size_t n_dim_requested) { @@ -125,13 +120,6 @@ inline std::vector squeezeDimensions(const std::vector& dims, } // namespace details -inline size_t compute_total_size(const std::vector& dims) { - return std::accumulate(dims.begin(), dims.end(), size_t{1u}, std::multiplies()); -} - -template -using unqualified_t = typename std::remove_const::type>::type; - /***** inspector { using type = T @@ -711,153 +699,6 @@ struct inspector> { }; #endif -#ifdef H5_USE_BOOST -template -struct inspector> { - using type = boost::multi_array; - using value_type = T; - using base_type = typename inspector::base_type; - using hdf5_type = typename inspector::hdf5_type; - - static constexpr size_t ndim = Dims; - static constexpr size_t recursive_ndim = ndim + inspector::recursive_ndim; - static constexpr bool is_trivially_copyable = std::is_trivially_copyable::value && - inspector::is_trivially_copyable; - - static std::vector getDimensions(const type& val) { - std::vector sizes; - for (size_t i = 0; i < ndim; ++i) { - sizes.push_back(val.shape()[i]); - } - auto s = inspector::getDimensions(val.data()[0]); - sizes.insert(sizes.end(), s.begin(), s.end()); - return sizes; - } - - static size_t getSizeVal(const type& val) { - return compute_total_size(getDimensions(val)); - } - - static size_t getSize(const std::vector& dims) { - return compute_total_size(dims); - } - - static void prepare(type& val, const std::vector& dims) { - if (dims.size() < ndim) { - std::ostringstream os; - os << "Only '" << dims.size() << "' given but boost::multi_array is of size '" << ndim - << "'."; - throw DataSpaceException(os.str()); - } - boost::array ext; - std::copy(dims.begin(), dims.begin() + ndim, ext.begin()); - val.resize(ext); - std::vector next_dims(dims.begin() + Dims, dims.end()); - std::size_t size = std::accumulate(dims.begin(), - dims.begin() + Dims, - std::size_t{1}, - std::multiplies()); - for (size_t i = 0; i < size; ++i) { - inspector::prepare(*(val.origin() + i), next_dims); - } - } - - static hdf5_type* data(type& val) { - return inspector::data(*val.data()); - } - - static const hdf5_type* data(const type& val) { - return inspector::data(*val.data()); - } - - template - static void serialize(const type& val, It m) { - size_t size = val.num_elements(); - size_t subsize = inspector::getSizeVal(*val.origin()); - for (size_t i = 0; i < size; ++i) { - inspector::serialize(*(val.origin() + i), m + i * subsize); - } - } - - template - static void unserialize(It vec_align, const std::vector& dims, type& val) { - std::vector next_dims(dims.begin() + ndim, dims.end()); - size_t subsize = compute_total_size(next_dims); - for (size_t i = 0; i < val.num_elements(); ++i) { - inspector::unserialize(vec_align + i * subsize, - next_dims, - *(val.origin() + i)); - } - } -}; - -template -struct inspector> { - using type = boost::numeric::ublas::matrix; - using value_type = unqualified_t; - using base_type = typename inspector::base_type; - using hdf5_type = typename inspector::hdf5_type; - - static constexpr size_t ndim = 2; - static constexpr size_t recursive_ndim = ndim + inspector::recursive_ndim; - static constexpr bool is_trivially_copyable = std::is_trivially_copyable::value && - inspector::is_trivially_copyable; - - static std::vector getDimensions(const type& val) { - std::vector sizes{val.size1(), val.size2()}; - auto s = inspector::getDimensions(val(0, 0)); - sizes.insert(sizes.end(), s.begin(), s.end()); - return sizes; - } - - static size_t getSizeVal(const type& val) { - return compute_total_size(getDimensions(val)); - } - - static size_t getSize(const std::vector& dims) { - return compute_total_size(dims); - } - - static void prepare(type& val, const std::vector& dims) { - if (dims.size() < ndim) { - std::ostringstream os; - os << "Impossible to pair DataSet with " << dims.size() << " dimensions into a " << ndim - << " boost::numeric::ublas::matrix"; - throw DataSpaceException(os.str()); - } - val.resize(dims[0], dims[1], false); - } - - static hdf5_type* data(type& val) { - return inspector::data(val(0, 0)); - } - - static const hdf5_type* data(const type& val) { - return inspector::data(val(0, 0)); - } - - static void serialize(const type& val, hdf5_type* m) { - size_t size = val.size1() * val.size2(); - size_t subsize = inspector::getSizeVal(val(0, 0)); - for (size_t i = 0; i < size; ++i) { - inspector::serialize(*(&val(0, 0) + i), m + i * subsize); - } - } - - static void unserialize(const hdf5_type* vec_align, - const std::vector& dims, - type& val) { - std::vector next_dims(dims.begin() + ndim, dims.end()); - size_t subsize = compute_total_size(next_dims); - size_t size = val.size1() * val.size2(); - for (size_t i = 0; i < size; ++i) { - inspector::unserialize(vec_align + i * subsize, - next_dims, - *(&val(0, 0) + i)); - } - } -}; -#endif } // namespace details } // namespace HighFive diff --git a/include/highfive/boost.hpp b/include/highfive/boost.hpp new file mode 100644 index 000000000..3dd4c9f9e --- /dev/null +++ b/include/highfive/boost.hpp @@ -0,0 +1,161 @@ +#pragma once + +#include "bits/H5Inspector_decl.hpp" +#include "H5Exception.hpp" + +#include +// starting Boost 1.64, serialization header must come before ublas +#include +#include + +namespace HighFive { +namespace details { + +template +struct inspector> { + using type = boost::multi_array; + using value_type = T; + using base_type = typename inspector::base_type; + using hdf5_type = typename inspector::hdf5_type; + + static constexpr size_t ndim = Dims; + static constexpr size_t recursive_ndim = ndim + inspector::recursive_ndim; + static constexpr bool is_trivially_copyable = std::is_trivially_copyable::value && + inspector::is_trivially_copyable; + + static std::vector getDimensions(const type& val) { + std::vector sizes; + for (size_t i = 0; i < ndim; ++i) { + sizes.push_back(val.shape()[i]); + } + auto s = inspector::getDimensions(val.data()[0]); + sizes.insert(sizes.end(), s.begin(), s.end()); + return sizes; + } + + static size_t getSizeVal(const type& val) { + return compute_total_size(getDimensions(val)); + } + + static size_t getSize(const std::vector& dims) { + return compute_total_size(dims); + } + + static void prepare(type& val, const std::vector& dims) { + if (dims.size() < ndim) { + std::ostringstream os; + os << "Only '" << dims.size() << "' given but boost::multi_array is of size '" << ndim + << "'."; + throw DataSpaceException(os.str()); + } + boost::array ext; + std::copy(dims.begin(), dims.begin() + ndim, ext.begin()); + val.resize(ext); + std::vector next_dims(dims.begin() + Dims, dims.end()); + std::size_t size = std::accumulate(dims.begin(), + dims.begin() + Dims, + std::size_t{1}, + std::multiplies()); + for (size_t i = 0; i < size; ++i) { + inspector::prepare(*(val.origin() + i), next_dims); + } + } + + static hdf5_type* data(type& val) { + return inspector::data(*val.data()); + } + + static const hdf5_type* data(const type& val) { + return inspector::data(*val.data()); + } + + template + static void serialize(const type& val, It m) { + size_t size = val.num_elements(); + size_t subsize = inspector::getSizeVal(*val.origin()); + for (size_t i = 0; i < size; ++i) { + inspector::serialize(*(val.origin() + i), m + i * subsize); + } + } + + template + static void unserialize(It vec_align, const std::vector& dims, type& val) { + std::vector next_dims(dims.begin() + ndim, dims.end()); + size_t subsize = compute_total_size(next_dims); + for (size_t i = 0; i < val.num_elements(); ++i) { + inspector::unserialize(vec_align + i * subsize, + next_dims, + *(val.origin() + i)); + } + } +}; + +template +struct inspector> { + using type = boost::numeric::ublas::matrix; + using value_type = unqualified_t; + using base_type = typename inspector::base_type; + using hdf5_type = typename inspector::hdf5_type; + + static constexpr size_t ndim = 2; + static constexpr size_t recursive_ndim = ndim + inspector::recursive_ndim; + static constexpr bool is_trivially_copyable = std::is_trivially_copyable::value && + inspector::is_trivially_copyable; + + static std::vector getDimensions(const type& val) { + std::vector sizes{val.size1(), val.size2()}; + auto s = inspector::getDimensions(val(0, 0)); + sizes.insert(sizes.end(), s.begin(), s.end()); + return sizes; + } + + static size_t getSizeVal(const type& val) { + return compute_total_size(getDimensions(val)); + } + + static size_t getSize(const std::vector& dims) { + return compute_total_size(dims); + } + + static void prepare(type& val, const std::vector& dims) { + if (dims.size() < ndim) { + std::ostringstream os; + os << "Impossible to pair DataSet with " << dims.size() << " dimensions into a " << ndim + << " boost::numeric::ublas::matrix"; + throw DataSpaceException(os.str()); + } + val.resize(dims[0], dims[1], false); + } + + static hdf5_type* data(type& val) { + return inspector::data(val(0, 0)); + } + + static const hdf5_type* data(const type& val) { + return inspector::data(val(0, 0)); + } + + static void serialize(const type& val, hdf5_type* m) { + size_t size = val.size1() * val.size2(); + size_t subsize = inspector::getSizeVal(val(0, 0)); + for (size_t i = 0; i < size; ++i) { + inspector::serialize(*(&val(0, 0) + i), m + i * subsize); + } + } + + static void unserialize(const hdf5_type* vec_align, + const std::vector& dims, + type& val) { + std::vector next_dims(dims.begin() + ndim, dims.end()); + size_t subsize = compute_total_size(next_dims); + size_t size = val.size1() * val.size2(); + for (size_t i = 0; i < size; ++i) { + inspector::unserialize(vec_align + i * subsize, + next_dims, + *(&val(0, 0) + i)); + } + } +}; + +} // namespace details +} // namespace HighFive diff --git a/src/examples/boost_multi_array_2D.cpp b/src/examples/boost_multi_array_2D.cpp index 4bec1ec12..508c3a880 100644 --- a/src/examples/boost_multi_array_2D.cpp +++ b/src/examples/boost_multi_array_2D.cpp @@ -8,11 +8,9 @@ */ #include -#undef H5_USE_BOOST -#define H5_USE_BOOST - #include #include +#include using namespace HighFive; diff --git a/src/examples/boost_multiarray_complex.cpp b/src/examples/boost_multiarray_complex.cpp index 37481db62..34f18f551 100644 --- a/src/examples/boost_multiarray_complex.cpp +++ b/src/examples/boost_multiarray_complex.cpp @@ -9,12 +9,9 @@ #include #include -#undef H5_USE_BOOST -#define H5_USE_BOOST - #include -#include +#include typedef std::complex complex_t; diff --git a/src/examples/boost_ublas_double.cpp b/src/examples/boost_ublas_double.cpp index b025475b9..3889df680 100644 --- a/src/examples/boost_ublas_double.cpp +++ b/src/examples/boost_ublas_double.cpp @@ -8,11 +8,10 @@ */ #include -#undef H5_USE_BOOST -#define H5_USE_BOOST - #include +#include + // In some versions of Boost (starting with 1.64), you have to include the serialization header // before ublas #include diff --git a/tests/unit/tests_high_five_base.cpp b/tests/unit/tests_high_five_base.cpp index 6f1953f4d..fb5929798 100644 --- a/tests/unit/tests_high_five_base.cpp +++ b/tests/unit/tests_high_five_base.cpp @@ -28,6 +28,10 @@ #include #include "tests_high_five.hpp" +#ifdef H5_USE_BOOST +#include +#endif + using namespace HighFive; using Catch::Matchers::Equals; diff --git a/tests/unit/tests_high_five_multi_dims.cpp b/tests/unit/tests_high_five_multi_dims.cpp index 442f1c9cc..9aa4f64a9 100644 --- a/tests/unit/tests_high_five_multi_dims.cpp +++ b/tests/unit/tests_high_five_multi_dims.cpp @@ -15,6 +15,7 @@ #ifdef H5_USE_BOOST #include +#include #endif #include