h5gt 0.2.0
C++ wrapper for HDF5 library (based on HighFive project)
Loading...
Searching...
No Matches
H5ConverterEigen_misc.hpp
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
13namespace h5gt {
14
15namespace details {
16
17
18//compute size for single Eigen Matrix
19template <typename T, int M, int N>
20inline 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
25template <typename T, int M, int N>
26inline 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 H5GT_USE_BOOST
31// compute size for boost::multi_array of Eigens
32template <typename T, size_t Dims>
33inline 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
42template <typename T, int M, int N>
43struct 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, const DataType& type)
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
71template <typename T, int M, int N>
72inline 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
84template <typename T, int M, int N>
85struct 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, const DataType& type)
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 H5GT_USE_BOOST
134template <typename T, int M, int N, std::size_t Dims>
135struct 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, const DataType& type)
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 // H5GT_USE_BOOST
185
186} // namespace details
187
188} // namespace h5gt
Exception specific to h5gt DataSet interface.
Definition H5Exception.hpp:115
Class representing the space (dimensions) of a dataset.
Definition H5DataSpace.hpp:37
std::vector< size_t > getDimensions() const
getDimensions
Definition H5Dataspace_misc.hpp:103
HDF5 Data Type.
Definition H5DataType.hpp:48
Definition H5Converter_misc.hpp:124