HighFive 3.3.0
HighFive - Header-only C++ HDF5 interface
Loading...
Searching...
No Matches
H5Slice_traits.hpp
Go to the documentation of this file.
1/*
2 * Copyright (c), 2017, Adrien Devresse <adrien.devresse@epfl.ch>
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 <cstdlib>
12#include <vector>
13
14#include "H5_definitions.hpp"
15#include "H5Utils.hpp"
17
18#include "../H5PropertyList.hpp"
19#include "h5s_wrapper.hpp"
20
21namespace HighFive {
22
24 public:
30 ElementSet(std::initializer_list<std::size_t> list);
35 ElementSet(std::initializer_list<std::vector<std::size_t>> list);
41 explicit ElementSet(const std::vector<std::size_t>& element_ids);
46 explicit ElementSet(const std::vector<std::vector<std::size_t>>& element_ids);
47
48 private:
49 std::vector<std::size_t> _ids;
50
51 template <typename Derivate>
52 friend class SliceTraits;
53};
54
55inline std::vector<hsize_t> toHDF5SizeVector(const std::vector<size_t>& from) {
56 return detail::convertSizeVector<hsize_t>(from);
57}
58
59inline std::vector<size_t> toSTLSizeVector(const std::vector<hsize_t>& from) {
60 return detail::convertSizeVector<size_t>(from);
61}
62
66template <typename Impl>
68 public:
69 DataSpace apply(const DataSpace& space) const {
70 return static_cast<const Impl&>(*this).apply(space);
71 }
72};
73
75 RegularHyperSlab() = default;
76
77 explicit RegularHyperSlab(const std::vector<size_t>& offset_,
78 const std::vector<size_t>& count_ = {},
79 const std::vector<size_t>& stride_ = {},
80 const std::vector<size_t>& block_ = {})
81 : offset(toHDF5SizeVector(offset_))
82 , count(toHDF5SizeVector(count_))
83 , stride(toHDF5SizeVector(stride_))
84 , block(toHDF5SizeVector(block_)) {}
85
86 static RegularHyperSlab fromHDF5Sizes(std::vector<hsize_t> offset_,
87 std::vector<hsize_t> count_ = {},
88 std::vector<hsize_t> stride_ = {},
89 std::vector<hsize_t> block_ = {}) {
91 slab.offset = std::move(offset_);
92 slab.count = std::move(count_);
93 slab.stride = std::move(stride_);
94 slab.block = std::move(block_);
95
96 return slab;
97 }
98
99 size_t rank() const {
100 return std::max(std::max(offset.size(), count.size()),
101 std::max(stride.size(), block.size()));
102 }
103
105 std::vector<size_t> packedDims() const {
106 auto n_dims = rank();
107 auto dims = std::vector<size_t>(n_dims, 0);
108
109 for (size_t i = 0; i < n_dims; ++i) {
110 dims[i] = count[i] * (block.empty() ? 1 : block[i]);
111 }
112
113 return dims;
114 }
115
116 std::vector<hsize_t> offset;
117 std::vector<hsize_t> count;
118 std::vector<hsize_t> stride;
119 std::vector<hsize_t> block;
120};
121
122class HyperSlab: public HyperSlabInterface<HyperSlab> {
123 public:
125 selects.emplace_back(RegularHyperSlab{}, Op::None);
126 };
127
128 explicit HyperSlab(const RegularHyperSlab& sel) {
129 selects.emplace_back(sel, Op::Set);
130 }
131
133 auto ret = *this;
134 ret |= sel;
135 return ret;
136 }
137
139 selects.emplace_back(sel, Op::Or);
140 return *this;
141 }
142
144 auto ret = *this;
145 ret &= sel;
146 return ret;
147 }
148
150 selects.emplace_back(sel, Op::And);
151 return *this;
152 }
153
155 auto ret = *this;
156 ret ^= sel;
157 return ret;
158 }
159
161 selects.emplace_back(sel, Op::Xor);
162 return *this;
163 }
164
166 selects.emplace_back(sel, Op::NotA);
167 return *this;
168 }
169
171 selects.emplace_back(sel, Op::NotB);
172 return *this;
173 }
174
175 DataSpace apply(const DataSpace& space_) const {
176 return apply_impl(space_);
177 }
178
179 private:
180 enum class Op {
181 Noop,
182 Set,
183 Or,
184 And,
185 Xor,
186 NotB,
187 NotA,
188 Append,
189 Prepend,
190 Invalid,
191 None,
192 };
193
194 H5S_seloper_t convert(Op op) const {
195 switch (op) {
196 case Op::Noop:
197 return H5S_SELECT_NOOP;
198 case Op::Set:
199 return H5S_SELECT_SET;
200 case Op::Or:
201 return H5S_SELECT_OR;
202 case Op::And:
203 return H5S_SELECT_AND;
204 case Op::Xor:
205 return H5S_SELECT_XOR;
206 case Op::NotB:
207 return H5S_SELECT_NOTB;
208 case Op::NotA:
209 return H5S_SELECT_NOTA;
210 case Op::Append:
211 return H5S_SELECT_APPEND;
212 case Op::Prepend:
213 return H5S_SELECT_PREPEND;
214 case Op::Invalid:
215 return H5S_SELECT_INVALID;
216 default:
217 throw DataSpaceException("Invalid HyperSlab operation.");
218 }
219 }
220
221 struct Select_: public RegularHyperSlab {
222 Select_(const RegularHyperSlab& sel, Op op_)
223 : RegularHyperSlab(sel)
224 , op(op_) {}
225
226 Op op;
227 };
228
229 std::vector<Select_> selects;
230
231 protected:
232 DataSpace select_none(const DataSpace& outer_space) const {
233 auto space = outer_space.clone();
234 detail::h5s_select_none(space.getId());
235 return space;
236 }
237
238 void select_hyperslab(DataSpace& space, const Select_& sel) const {
239 detail::h5s_select_hyperslab(space.getId(),
240 convert(sel.op),
241 sel.offset.empty() ? nullptr : sel.offset.data(),
242 sel.stride.empty() ? nullptr : sel.stride.data(),
243 sel.count.empty() ? nullptr : sel.count.data(),
244 sel.block.empty() ? nullptr : sel.block.data());
245 }
246
247#if H5_VERSION_GE(1, 10, 6)
249 size_t detect_streak(Select_ const* begin, Select_ const* end, Op op) const {
250 assert(op == Op::Or);
251 auto const* it =
252 std::find_if(begin, end, [op](const Select_& sel) { return sel.op != op; });
253 return static_cast<size_t>(it - begin);
254 }
255
256 DataSpace combine_selections(const DataSpace& left_space,
257 Op op,
258 const DataSpace& right_space) const {
259 assert(op == Op::Or);
260
261 auto left_type = detail::h5s_get_select_type(left_space.getId());
262 auto right_type = detail::h5s_get_select_type(right_space.getId());
263
264 // Since HDF5 doesn't allow `combine_selections` with a None
265 // selection, we need to avoid the issue:
266 if (left_type == H5S_SEL_NONE) {
267 return right_space;
268 } else if (right_type == H5S_SEL_NONE) {
269 return left_space;
270 } else if (left_type == H5S_SEL_ALL) {
271 return left_space;
272 } else if (right_type == H5S_SEL_ALL) {
273 return right_space;
274 } else {
275 return detail::make_data_space(
276 detail::h5s_combine_select(left_space.getId(), convert(op), right_space.getId()));
277 }
278 }
279
291 DataSpace reduce_streak(const DataSpace& outer_space,
292 Select_ const* begin,
293 Select_ const* end,
294 Op op) const {
295 assert(op == Op::Or);
296
297 if (begin == end) {
298 throw std::runtime_error("Broken logic in 'DataSpace::reduce_streak'.");
299 }
300
301 std::ptrdiff_t distance = end - begin;
302 if (distance == 1) {
303 auto space = select_none(outer_space);
304 select_hyperslab(space, *begin);
305 return space;
306 }
307
308 Select_ const* mid = begin + distance / 2;
309 auto right_space = reduce_streak(outer_space, begin, mid, op);
310 auto left_space = reduce_streak(outer_space, mid, end, op);
311
312 return combine_selections(left_space, op, right_space);
313 }
314
315 DataSpace apply_impl(const DataSpace& space_) const {
316 auto space = space_.clone();
317 auto n_selects = selects.size();
318 for (size_t i = 0; i < n_selects; ++i) {
319 auto const* const begin = selects.data() + i;
320 auto const* const end = selects.data() + n_selects;
321
322 auto n_ors = detect_streak(begin, end, Op::Or);
323
324 if (n_ors > 1) {
325 auto right_space = reduce_streak(space_, begin, begin + n_ors, Op::Or);
326 space = combine_selections(space, Op::Or, right_space);
327 i += n_ors - 1;
328 } else if (selects[i].op == Op::None) {
329 detail::h5s_select_none(space.getId());
330 } else {
331 select_hyperslab(space, selects[i]);
332 }
333 }
334 return space;
335 }
336#else
337 DataSpace apply_impl(const DataSpace& space_) const {
338 auto space = space_.clone();
339 for (const auto& sel: selects) {
340 if (sel.op == Op::None) {
341 detail::h5s_select_none(space.getId());
342 } else {
343 select_hyperslab(space, sel);
344 }
345 }
346 return space;
347 }
348#endif
349};
350
418 public:
419 template <class... Slices>
420 explicit ProductSet(const Slices&... slices);
421
422 private:
423 HyperSlab slab;
424 std::vector<size_t> shape;
425
426 template <typename Derivate>
427 friend class SliceTraits;
428};
429
430template <typename Derivate>
432 public:
441 template <class Impl>
442 Selection select(const HyperSlabInterface<Impl>& hyper_slab) const;
443
451 Selection select(const HyperSlab& hyper_slab, const DataSpace& memspace) const;
452
460 Selection select(const std::vector<size_t>& offset,
461 const std::vector<size_t>& count,
462 const std::vector<size_t>& stride = {},
463 const std::vector<size_t>& block = {}) const;
464
470 Selection select(const std::vector<size_t>& columns) const;
471
475 Selection select(const ElementSet& elements) const;
476
482 Selection select(const ProductSet& product_set) const;
483
484 template <typename T>
485 T read(const DataTransferProps& xfer_props = DataTransferProps()) const;
486
497 template <typename T>
498 void read(T& array, const DataTransferProps& xfer_props = DataTransferProps()) const;
499
509 template <typename T>
510 void read_raw(T* array,
511 const DataType& mem_datatype,
512 const DataTransferProps& xfer_props = DataTransferProps()) const;
513
523 template <typename T>
524 void read_raw(T* array, const DataTransferProps& xfer_props = DataTransferProps()) const;
525
526
534 template <typename T>
535 void write(const T& buffer, const DataTransferProps& xfer_props = DataTransferProps());
536
551 template <typename T>
552 void write_raw(const T* buffer,
553 const DataType& mem_datatype,
554 const DataTransferProps& xfer_props = DataTransferProps());
555
563 template <typename T>
564 void write_raw(const T* buffer, const DataTransferProps& xfer_props = DataTransferProps());
565
575 Selection squeezeMemSpace(const std::vector<size_t>& axes) const;
576
586 Selection reshapeMemSpace(const std::vector<size_t>& dims) const;
587};
588
589} // namespace HighFive
Class representing the space (dimensions) of a DataSet.
Definition H5DataSpace.hpp:39
DataSpace clone() const
Create a copy of the DataSpace which will have different id.
Definition H5Dataspace_misc.hpp:96
HDF5 Data Type.
Definition H5DataType.hpp:62
Definition H5Slice_traits.hpp:23
Definition H5Slice_traits.hpp:122
HyperSlab & notA(const RegularHyperSlab &sel)
Definition H5Slice_traits.hpp:165
DataSpace apply_impl(const DataSpace &space_) const
Definition H5Slice_traits.hpp:337
HyperSlab & notB(const RegularHyperSlab &sel)
Definition H5Slice_traits.hpp:170
HyperSlab operator&(const RegularHyperSlab &sel) const
Definition H5Slice_traits.hpp:143
HyperSlab operator^(const RegularHyperSlab &sel) const
Definition H5Slice_traits.hpp:154
HyperSlab operator|(const RegularHyperSlab &sel) const
Definition H5Slice_traits.hpp:132
HyperSlab & operator&=(const RegularHyperSlab &sel)
Definition H5Slice_traits.hpp:149
HyperSlab()
Definition H5Slice_traits.hpp:124
void select_hyperslab(DataSpace &space, const Select_ &sel) const
Definition H5Slice_traits.hpp:238
HyperSlab & operator^=(const RegularHyperSlab &sel)
Definition H5Slice_traits.hpp:160
DataSpace select_none(const DataSpace &outer_space) const
Definition H5Slice_traits.hpp:232
HyperSlab(const RegularHyperSlab &sel)
Definition H5Slice_traits.hpp:128
HyperSlab & operator|=(const RegularHyperSlab &sel)
Definition H5Slice_traits.hpp:138
DataSpace apply(const DataSpace &space_) const
Definition H5Slice_traits.hpp:175
A CRTP base class for hyper slab-like objects.
Definition H5Slice_traits.hpp:67
DataSpace apply(const DataSpace &space) const
Definition H5Slice_traits.hpp:69
hid_t getId() const noexcept
getId
Definition H5Object_misc.hpp:75
Selects the Cartesian product of slices.
Definition H5Slice_traits.hpp:417
HDF5 property Lists.
Definition H5PropertyList.hpp:138
Selection: represent a view on a slice/part of a dataset.
Definition H5Selection.hpp:27
Definition H5Slice_traits.hpp:431
Selection squeezeMemSpace(const std::vector< size_t > &axes) const
Return a Selection with axes squeezed from the memspace.
Definition H5Slice_traits_misc.hpp:465
T read(const DataTransferProps &xfer_props=DataTransferProps()) const
Definition H5Slice_traits_misc.hpp:321
void write(const T &buffer, const DataTransferProps &xfer_props=DataTransferProps())
Definition H5Slice_traits_misc.hpp:404
void read_raw(T *array, const DataType &mem_datatype, const DataTransferProps &xfer_props=DataTransferProps()) const
Definition H5Slice_traits_misc.hpp:375
Selection reshapeMemSpace(const std::vector< size_t > &dims) const
Return a Selection with a simple memspace with dims.
Definition H5Slice_traits_misc.hpp:476
Selection select(const HyperSlabInterface< Impl > &hyper_slab) const
Select an hyper_slab in the current Slice/Dataset.
Definition H5Slice_traits_misc.hpp:233
void write_raw(const T *buffer, const DataType &mem_datatype, const DataTransferProps &xfer_props=DataTransferProps())
Definition H5Slice_traits_misc.hpp:430
PropertyList< PropertyType::DATASET_XFER > DataTransferProps
Definition H5PropertyList.hpp:179
Definition assert_compatible_spaces.hpp:15
std::vector< size_t > toSTLSizeVector(const std::vector< hsize_t > &from)
Definition H5Slice_traits.hpp:59
std::vector< hsize_t > toHDF5SizeVector(const std::vector< size_t > &from)
Definition H5Slice_traits.hpp:55
Definition H5Slice_traits.hpp:74
size_t rank() const
Definition H5Slice_traits.hpp:99
std::vector< hsize_t > offset
Definition H5Slice_traits.hpp:116
RegularHyperSlab(const std::vector< size_t > &offset_, const std::vector< size_t > &count_={}, const std::vector< size_t > &stride_={}, const std::vector< size_t > &block_={})
Definition H5Slice_traits.hpp:77
std::vector< hsize_t > block
Definition H5Slice_traits.hpp:119
std::vector< size_t > packedDims() const
Dimensions when all gaps are removed.
Definition H5Slice_traits.hpp:105
std::vector< hsize_t > count
Definition H5Slice_traits.hpp:117
static RegularHyperSlab fromHDF5Sizes(std::vector< hsize_t > offset_, std::vector< hsize_t > count_={}, std::vector< hsize_t > stride_={}, std::vector< hsize_t > block_={})
Definition H5Slice_traits.hpp:86
std::vector< hsize_t > stride
Definition H5Slice_traits.hpp:118