HighFive  2.3.1
HighFive - Header-only C++ HDF5 interface
H5ConverterEigen_misc.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c), 2020, EPFL - Blue Brain Project
3  *
4  * Distributed under the Boost Software License, Version 1.0.
5  * (See accompanying file LICENSE_1_0.txt or copy at
6  * http://www.boost.org/LICENSE_1_0.txt)
7  *
8  */
9 #pragma once
10 
11 #include <Eigen/Eigen>
12 
13 namespace HighFive {
14 
15 namespace details {
16 
17 
18 //compute size for single Eigen Matrix
19 template <typename T, int M, int N>
20 inline size_t compute_total_size(const Eigen::Matrix<T,M,N>& matrix) {
21  return static_cast<size_t>(matrix.rows()) * static_cast<size_t>(matrix.cols());
22 }
23 
24 //compute size for std::vector of Eigens
25 template <typename T, int M, int N>
26 inline size_t compute_total_size(const std::vector<Eigen::Matrix<T,M,N>>& vec) {
27  return vec.size() * compute_total_size(vec[0]);
28 }
29 
30 #ifdef H5_USE_BOOST
31 // compute size for boost::multi_array of Eigens
32 template <typename T, size_t Dims>
33 inline size_t compute_total_size(const boost::multi_array<T, Dims>& vec) {
34  return std::accumulate(vec.origin(), vec.origin() + vec.num_elements(), size_t{0u},
35  [](size_t so_far, const T& v) {
36  return so_far + static_cast<size_t>(v.rows()) * static_cast<size_t>(v.cols());
37  });
38 }
39 #endif
40 
41 // apply conversion to eigen matrix
42 template <typename T, int M, int N>
43 struct data_converter<Eigen::Matrix<T, M, N>, void> {
44 
45  typedef Eigen::Matrix<T, M, N> MatrixTMN;
46 
47  inline data_converter(const DataSpace& space)
48  : _dims(space.getDimensions()) {
49  assert(_dims.size() == 2);
50  }
51 
52  inline T* transform_read(MatrixTMN& array) {
53  if (_dims[0] != static_cast<size_t>(array.rows()) ||
54  _dims[1] != static_cast<size_t>(array.cols())) {
55  array.resize(static_cast<typename MatrixTMN::Index>(_dims[0]),
56  static_cast<typename MatrixTMN::Index>(_dims[1]));
57  }
58  return array.data();
59  }
60 
61  inline const T* transform_write(const MatrixTMN& array) {
62  return array.data();
63  }
64 
65  inline void process_result(MatrixTMN&) {}
66 
67  std::vector<size_t> _dims;
68 };
69 
70 
71 template <typename T, int M, int N>
72 inline void vectors_to_single_buffer(const std::vector<Eigen::Matrix<T,M,N>>& vec,
73  const std::vector<size_t>& dims,
74  const size_t current_dim,
75  std::vector<T>& buffer) {
76 
77  check_dimensions_vector(vec.size(), dims[current_dim], current_dim);
78  for (const auto& k : vec) {
79  std::copy(k.data(), k.data() + k.size(), std::back_inserter(buffer));
80  }
81 }
82 
83 // apply conversion to std::vector of eigen matrix
84 template <typename T, int M, int N>
85 struct data_converter<std::vector<Eigen::Matrix<T,M,N>>, void> {
86 
87  typedef Eigen::Matrix<T, M, N> MatrixTMN;
88 
89  inline data_converter(const DataSpace& space)
90  : _dims(space.getDimensions()), _space(space) {
91  assert(_dims.size() == 3);
92  }
93 
94  inline T * transform_read(std::vector<MatrixTMN>& /* vec */) {
95  _vec_align.resize(compute_total_size(_space.getDimensions()));
96  return _vec_align.data();
97  }
98 
99  inline const T* transform_write(const std::vector<MatrixTMN>& vec) {
100  _vec_align.reserve(compute_total_size(vec));
101  vectors_to_single_buffer<T, M, N>(vec, _dims, 0, _vec_align);
102  return _vec_align.data();
103  }
104 
105  inline void process_result(std::vector<MatrixTMN>& vec) {
106  T* start = _vec_align.data();
107  if (vec.size() > 0) {
108  for(auto& v : vec){
109  v = Eigen::Map<MatrixTMN>(start, v.rows(), v.cols());
110  start += v.rows()*v.cols();
111  }
112  }
113  else if (M == -1 || N == -1) {
114  std::ostringstream ss;
115  ss << "Dynamic size(-1) used without pre-defined vector data layout.\n"
116  << "Initiliaze vector elements using Zero, i.e.:\n"
117  << "\t vector<MatrixXd> vec(5, MatrixXd::Zero(20,5))";
118  throw DataSetException(ss.str());
119  }
120  else {
121  for (size_t i = 0; i < _dims[0]; ++i) {
122  vec.emplace_back(Eigen::Map<MatrixTMN>(start, M, N));
123  start += M * N;
124  }
125  }
126  }
127 
128  std::vector<size_t> _dims;
129  std::vector<typename inspector<T>::base_type> _vec_align;
130  const DataSpace& _space;
131 };
132 
133 #ifdef H5_USE_BOOST
134 template <typename T, int M, int N, std::size_t Dims>
135 struct data_converter<boost::multi_array<Eigen::Matrix<T, M, N>, Dims>, void> {
136  typedef typename boost::multi_array<Eigen::Matrix<T, M, N>, Dims> MultiArrayEigen;
137 
138  inline data_converter(const DataSpace& space)
139  : _dims(space.getDimensions())
140  , _space(space) {
141  assert(_dims.size() == Dims + 2);
142  }
143 
144  inline T* transform_read(const MultiArrayEigen& /*array*/) {
145  _vec_align.resize(compute_total_size(_space.getDimensions()));
146  return _vec_align.data();
147  }
148 
149  inline const T* transform_write(const MultiArrayEigen& array) {
150  _vec_align.reserve(compute_total_size(array));
151  for (auto e = array.origin(); e < array.origin() + array.num_elements(); ++e) {
152  std::copy(e->data(), e->data() + e->size(), std::back_inserter(_vec_align));
153  }
154  return _vec_align.data();
155  }
156 
157  inline void process_result(MultiArrayEigen& vec) {
158  T* start = _vec_align.data();
159  if (M != -1 && N != -1) {
160  for (auto v = vec.origin(); v < vec.origin() + vec.num_elements(); ++v) {
161  *v = Eigen::Map<Eigen::Matrix<T, M, N>>(start, v->rows(), v->cols());
162  start += v->rows() * v->cols();
163  }
164  } else {
165  if (vec.origin()->rows() > 0 && vec.origin()->cols() > 0) {
166  const auto VEC_M = vec.origin()->rows(), VEC_N = vec.origin()->cols();
167  for (auto v = vec.origin(); v < vec.origin() + vec.num_elements(); ++v) {
168  assert(v->rows() == VEC_M && v->cols() == VEC_N);
169  *v = Eigen::Map<Eigen::Matrix<T, M, N>>(start, VEC_M, VEC_N);
170  start += VEC_M * VEC_N;
171  }
172  } else {
173  throw DataSetException(
174  "Dynamic size(-1) used without pre-defined multi_array data layout.\n"
175  "Initialize vector elements using MatrixXd::Zero");
176  }
177  }
178  }
179 
180  std::vector<size_t> _dims;
181  const DataSpace& _space;
182  std::vector<typename inspector<T>::base_type> _vec_align;
183 };
184 #endif // H5_USE_BOOST
185 
186 } // namespace details
187 
188 } // namespace HighFive
Definition: H5_definitions.hpp:15