File indexing completed on 2025-12-13 10:15:24
0001 #pragma once
0002 #ifdef H5_USE_BOOST
0003
0004 #include "bits/H5Inspector_decl.hpp"
0005 #include "H5Exception.hpp"
0006
0007 #include <boost/multi_array.hpp>
0008
0009 #include <boost/serialization/vector.hpp>
0010 #include <boost/numeric/ublas/matrix.hpp>
0011
0012 namespace HighFive {
0013 namespace details {
0014
0015 template <typename T, size_t Dims>
0016 struct inspector<boost::multi_array<T, Dims>> {
0017 using type = boost::multi_array<T, Dims>;
0018 using value_type = T;
0019 using base_type = typename inspector<value_type>::base_type;
0020 using hdf5_type = typename inspector<value_type>::hdf5_type;
0021
0022 static constexpr size_t ndim = Dims;
0023 static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
0024 static constexpr bool is_trivially_copyable = std::is_trivially_copyable<value_type>::value &&
0025 inspector<value_type>::is_trivially_copyable;
0026
0027 static std::vector<size_t> getDimensions(const type& val) {
0028 std::vector<size_t> sizes;
0029 for (size_t i = 0; i < ndim; ++i) {
0030 sizes.push_back(val.shape()[i]);
0031 }
0032 auto s = inspector<value_type>::getDimensions(val.data()[0]);
0033 sizes.insert(sizes.end(), s.begin(), s.end());
0034 return sizes;
0035 }
0036
0037 static size_t getSizeVal(const type& val) {
0038 return compute_total_size(getDimensions(val));
0039 }
0040
0041 static size_t getSize(const std::vector<size_t>& dims) {
0042 return compute_total_size(dims);
0043 }
0044
0045 static void prepare(type& val, const std::vector<size_t>& dims) {
0046 if (dims.size() < ndim) {
0047 std::ostringstream os;
0048 os << "Only '" << dims.size() << "' given but boost::multi_array is of size '" << ndim
0049 << "'.";
0050 throw DataSpaceException(os.str());
0051 }
0052 boost::array<typename type::index, Dims> ext;
0053 std::copy(dims.begin(), dims.begin() + ndim, ext.begin());
0054 val.resize(ext);
0055 std::vector<size_t> next_dims(dims.begin() + Dims, dims.end());
0056 std::size_t size = std::accumulate(dims.begin(),
0057 dims.begin() + Dims,
0058 std::size_t{1},
0059 std::multiplies<size_t>());
0060 for (size_t i = 0; i < size; ++i) {
0061 inspector<value_type>::prepare(*(val.origin() + i), next_dims);
0062 }
0063 }
0064
0065 static hdf5_type* data(type& val) {
0066 return inspector<value_type>::data(*val.data());
0067 }
0068
0069 static const hdf5_type* data(const type& val) {
0070 return inspector<value_type>::data(*val.data());
0071 }
0072
0073 template <class It>
0074 static void serialize(const type& val, It m) {
0075 size_t size = val.num_elements();
0076 size_t subsize = inspector<value_type>::getSizeVal(*val.origin());
0077 for (size_t i = 0; i < size; ++i) {
0078 inspector<value_type>::serialize(*(val.origin() + i), m + i * subsize);
0079 }
0080 }
0081
0082 template <class It>
0083 static void unserialize(It vec_align, const std::vector<size_t>& dims, type& val) {
0084 std::vector<size_t> next_dims(dims.begin() + ndim, dims.end());
0085 size_t subsize = compute_total_size(next_dims);
0086 for (size_t i = 0; i < val.num_elements(); ++i) {
0087 inspector<value_type>::unserialize(vec_align + i * subsize,
0088 next_dims,
0089 *(val.origin() + i));
0090 }
0091 }
0092 };
0093
0094 template <typename T>
0095 struct inspector<boost::numeric::ublas::matrix<T>> {
0096 using type = boost::numeric::ublas::matrix<T>;
0097 using value_type = unqualified_t<T>;
0098 using base_type = typename inspector<value_type>::base_type;
0099 using hdf5_type = typename inspector<value_type>::hdf5_type;
0100
0101 static constexpr size_t ndim = 2;
0102 static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
0103 static constexpr bool is_trivially_copyable = std::is_trivially_copyable<value_type>::value &&
0104 inspector<value_type>::is_trivially_copyable;
0105
0106 static std::vector<size_t> getDimensions(const type& val) {
0107 std::vector<size_t> sizes{val.size1(), val.size2()};
0108 auto s = inspector<value_type>::getDimensions(val(0, 0));
0109 sizes.insert(sizes.end(), s.begin(), s.end());
0110 return sizes;
0111 }
0112
0113 static size_t getSizeVal(const type& val) {
0114 return compute_total_size(getDimensions(val));
0115 }
0116
0117 static size_t getSize(const std::vector<size_t>& dims) {
0118 return compute_total_size(dims);
0119 }
0120
0121 static void prepare(type& val, const std::vector<size_t>& dims) {
0122 if (dims.size() < ndim) {
0123 std::ostringstream os;
0124 os << "Impossible to pair DataSet with " << dims.size() << " dimensions into a " << ndim
0125 << " boost::numeric::ublas::matrix";
0126 throw DataSpaceException(os.str());
0127 }
0128 val.resize(dims[0], dims[1], false);
0129 }
0130
0131 static hdf5_type* data(type& val) {
0132 return inspector<value_type>::data(val(0, 0));
0133 }
0134
0135 static const hdf5_type* data(const type& val) {
0136 return inspector<value_type>::data(val(0, 0));
0137 }
0138
0139 static void serialize(const type& val, hdf5_type* m) {
0140 size_t size = val.size1() * val.size2();
0141 size_t subsize = inspector<value_type>::getSizeVal(val(0, 0));
0142 for (size_t i = 0; i < size; ++i) {
0143 inspector<value_type>::serialize(*(&val(0, 0) + i), m + i * subsize);
0144 }
0145 }
0146
0147 static void unserialize(const hdf5_type* vec_align,
0148 const std::vector<size_t>& dims,
0149 type& val) {
0150 std::vector<size_t> next_dims(dims.begin() + ndim, dims.end());
0151 size_t subsize = compute_total_size(next_dims);
0152 size_t size = val.size1() * val.size2();
0153 for (size_t i = 0; i < size; ++i) {
0154 inspector<value_type>::unserialize(vec_align + i * subsize,
0155 next_dims,
0156 *(&val(0, 0) + i));
0157 }
0158 }
0159 };
0160
0161 }
0162 }
0163
0164 #endif