File indexing completed on 2025-04-19 08:55:34
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <cstdlib>
0012 #include <vector>
0013
0014 #include "H5_definitions.hpp"
0015 #include "H5Utils.hpp"
0016
0017 #include "../H5PropertyList.hpp"
0018 #include "h5s_wrapper.hpp"
0019
0020 namespace HighFive {
0021
0022 class ElementSet {
0023 public:
0024
0025
0026
0027
0028
0029 explicit ElementSet(std::initializer_list<std::size_t> list);
0030
0031
0032
0033
0034 explicit ElementSet(std::initializer_list<std::vector<std::size_t>> list);
0035
0036
0037
0038
0039
0040 explicit ElementSet(const std::vector<std::size_t>& element_ids);
0041
0042
0043
0044
0045 explicit ElementSet(const std::vector<std::vector<std::size_t>>& element_ids);
0046
0047 private:
0048 std::vector<std::size_t> _ids;
0049
0050 template <typename Derivate>
0051 friend class SliceTraits;
0052 };
0053
0054 namespace detail {
0055
0056 template <class To, class From>
0057 inline std::vector<To> convertSizeVector(const std::vector<From>& from) {
0058 std::vector<To> to(from.size());
0059 std::copy(from.cbegin(), from.cend(), to.begin());
0060
0061 return to;
0062 }
0063 }
0064
0065 inline std::vector<hsize_t> toHDF5SizeVector(const std::vector<size_t>& from) {
0066 return detail::convertSizeVector<hsize_t>(from);
0067 }
0068
0069 inline std::vector<size_t> toSTLSizeVector(const std::vector<hsize_t>& from) {
0070 return detail::convertSizeVector<size_t>(from);
0071 }
0072
0073 struct RegularHyperSlab {
0074 RegularHyperSlab() = default;
0075
0076 RegularHyperSlab(std::vector<size_t> offset_,
0077 std::vector<size_t> count_ = {},
0078 std::vector<size_t> stride_ = {},
0079 std::vector<size_t> block_ = {})
0080 : offset(toHDF5SizeVector(offset_))
0081 , count(toHDF5SizeVector(count_))
0082 , stride(toHDF5SizeVector(stride_))
0083 , block(toHDF5SizeVector(block_)) {}
0084
0085 static RegularHyperSlab fromHDF5Sizes(std::vector<hsize_t> offset_,
0086 std::vector<hsize_t> count_ = {},
0087 std::vector<hsize_t> stride_ = {},
0088 std::vector<hsize_t> block_ = {}) {
0089 RegularHyperSlab slab;
0090 slab.offset = offset_;
0091 slab.count = count_;
0092 slab.stride = stride_;
0093 slab.block = block_;
0094
0095 return slab;
0096 }
0097
0098 size_t rank() const {
0099 return std::max(std::max(offset.size(), count.size()),
0100 std::max(stride.size(), block.size()));
0101 }
0102
0103
0104 std::vector<size_t> packedDims() const {
0105 auto n_dims = rank();
0106 auto dims = std::vector<size_t>(n_dims, 0);
0107
0108 for (size_t i = 0; i < n_dims; ++i) {
0109 dims[i] = count[i] * (block.empty() ? 1 : block[i]);
0110 }
0111
0112 return dims;
0113 }
0114
0115 std::vector<hsize_t> offset;
0116 std::vector<hsize_t> count;
0117 std::vector<hsize_t> stride;
0118 std::vector<hsize_t> block;
0119 };
0120
0121 class HyperSlab {
0122 public:
0123 HyperSlab() {
0124 selects.emplace_back(RegularHyperSlab{}, Op::None);
0125 };
0126
0127 explicit HyperSlab(const RegularHyperSlab& sel) {
0128 selects.emplace_back(sel, Op::Set);
0129 }
0130
0131 HyperSlab operator|(const RegularHyperSlab& sel) const {
0132 auto ret = *this;
0133 ret |= sel;
0134 return ret;
0135 }
0136
0137 HyperSlab& operator|=(const RegularHyperSlab& sel) {
0138 selects.emplace_back(sel, Op::Or);
0139 return *this;
0140 }
0141
0142 HyperSlab operator&(const RegularHyperSlab& sel) const {
0143 auto ret = *this;
0144 ret &= sel;
0145 return ret;
0146 }
0147
0148 HyperSlab& operator&=(const RegularHyperSlab& sel) {
0149 selects.emplace_back(sel, Op::And);
0150 return *this;
0151 }
0152
0153 HyperSlab operator^(const RegularHyperSlab& sel) const {
0154 auto ret = *this;
0155 ret ^= sel;
0156 return ret;
0157 }
0158
0159 HyperSlab& operator^=(const RegularHyperSlab& sel) {
0160 selects.emplace_back(sel, Op::Xor);
0161 return *this;
0162 }
0163
0164 HyperSlab& notA(const RegularHyperSlab& sel) {
0165 selects.emplace_back(sel, Op::NotA);
0166 return *this;
0167 }
0168
0169 HyperSlab& notB(const RegularHyperSlab& sel) {
0170 selects.emplace_back(sel, Op::NotB);
0171 return *this;
0172 }
0173
0174 DataSpace apply(const DataSpace& space_) const {
0175 return apply_impl(space_);
0176 }
0177
0178 private:
0179 enum class Op {
0180 Noop,
0181 Set,
0182 Or,
0183 And,
0184 Xor,
0185 NotB,
0186 NotA,
0187 Append,
0188 Prepend,
0189 Invalid,
0190 None,
0191 };
0192
0193 H5S_seloper_t convert(Op op) const {
0194 switch (op) {
0195 case Op::Noop:
0196 return H5S_SELECT_NOOP;
0197 case Op::Set:
0198 return H5S_SELECT_SET;
0199 case Op::Or:
0200 return H5S_SELECT_OR;
0201 case Op::And:
0202 return H5S_SELECT_AND;
0203 case Op::Xor:
0204 return H5S_SELECT_XOR;
0205 case Op::NotB:
0206 return H5S_SELECT_NOTB;
0207 case Op::NotA:
0208 return H5S_SELECT_NOTA;
0209 case Op::Append:
0210 return H5S_SELECT_APPEND;
0211 case Op::Prepend:
0212 return H5S_SELECT_PREPEND;
0213 case Op::Invalid:
0214 return H5S_SELECT_INVALID;
0215 default:
0216 throw DataSpaceException("Invalid HyperSlab operation.");
0217 }
0218 }
0219
0220 struct Select_: public RegularHyperSlab {
0221 Select_(const RegularHyperSlab& sel, Op op_)
0222 : RegularHyperSlab(sel)
0223 , op(op_) {}
0224
0225 Op op;
0226 };
0227
0228 std::vector<Select_> selects;
0229
0230 protected:
0231 DataSpace select_none(const DataSpace& outer_space) const {
0232 auto space = outer_space.clone();
0233 detail::h5s_select_none(space.getId());
0234 return space;
0235 }
0236
0237 void select_hyperslab(DataSpace& space, const Select_& sel) const {
0238 detail::h5s_select_hyperslab(space.getId(),
0239 convert(sel.op),
0240 sel.offset.empty() ? nullptr : sel.offset.data(),
0241 sel.stride.empty() ? nullptr : sel.stride.data(),
0242 sel.count.empty() ? nullptr : sel.count.data(),
0243 sel.block.empty() ? nullptr : sel.block.data());
0244 }
0245
0246 #if H5_VERSION_GE(1, 10, 6)
0247
0248 size_t detect_streak(Select_ const* begin, Select_ const* end, Op op) const {
0249 assert(op == Op::Or);
0250 auto it = std::find_if(begin, end, [op](const Select_& sel) { return sel.op != op; });
0251 return static_cast<size_t>(it - begin);
0252 }
0253
0254 DataSpace combine_selections(const DataSpace& left_space,
0255 Op op,
0256 const DataSpace& right_space) const {
0257 return detail::make_data_space(
0258 H5Scombine_select(left_space.getId(), convert(op), right_space.getId()));
0259 }
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272 DataSpace reduce_streak(const DataSpace& outer_space,
0273 Select_ const* begin,
0274 Select_ const* end,
0275 Op op) const {
0276 assert(op == Op::Or);
0277
0278 if (begin == end) {
0279 throw std::runtime_error("Broken logic in 'DataSpace::reduce_streak'.");
0280 }
0281
0282 std::ptrdiff_t distance = end - begin;
0283 if (distance == 1) {
0284 auto space = select_none(outer_space);
0285 select_hyperslab(space, *begin);
0286 return space;
0287 }
0288
0289 Select_ const* mid = begin + distance / 2;
0290 auto right_space = reduce_streak(outer_space, begin, mid, op);
0291 auto left_space = reduce_streak(outer_space, mid, end, op);
0292
0293 return combine_selections(left_space, op, right_space);
0294 }
0295
0296 DataSpace apply_impl(const DataSpace& space_) const {
0297 auto space = space_.clone();
0298 auto n_selects = selects.size();
0299 for (size_t i = 0; i < n_selects; ++i) {
0300 auto begin = selects.data() + i;
0301 auto end = selects.data() + n_selects;
0302
0303 auto n_ors = detect_streak(begin, end, Op::Or);
0304
0305 if (n_ors > 1) {
0306 auto right_space = reduce_streak(space_, begin, begin + n_ors, Op::Or);
0307
0308
0309 if (detail::h5s_get_select_type(space.getId()) == H5S_SEL_NONE) {
0310 space = right_space;
0311 } else {
0312 space = combine_selections(space, Op::Or, right_space);
0313 }
0314 i += n_ors - 1;
0315 } else if (selects[i].op == Op::None) {
0316 detail::h5s_select_none(space.getId());
0317 } else {
0318 select_hyperslab(space, selects[i]);
0319 }
0320 }
0321 return space;
0322 }
0323 #else
0324 DataSpace apply_impl(const DataSpace& space_) const {
0325 auto space = space_.clone();
0326 for (const auto& sel: selects) {
0327 if (sel.op == Op::None) {
0328 detail::h5s_select_none(space.getId());
0329 } else {
0330 select_hyperslab(space, sel);
0331 }
0332 }
0333 return space;
0334 }
0335 #endif
0336 };
0337
0338 template <typename Derivate>
0339 class SliceTraits {
0340 public:
0341
0342
0343
0344
0345
0346
0347
0348
0349 Selection select(const HyperSlab& hyperslab) const;
0350
0351
0352
0353
0354
0355
0356
0357
0358 Selection select(const HyperSlab& hyperslab, const DataSpace& memspace) const;
0359
0360
0361
0362
0363
0364
0365
0366
0367 Selection select(const std::vector<size_t>& offset,
0368 const std::vector<size_t>& count,
0369 const std::vector<size_t>& stride = {},
0370 const std::vector<size_t>& block = {}) const;
0371
0372
0373
0374
0375
0376
0377 Selection select(const std::vector<size_t>& columns) const;
0378
0379
0380
0381
0382 Selection select(const ElementSet& elements) const;
0383
0384 template <typename T>
0385 T read(const DataTransferProps& xfer_props = DataTransferProps()) const;
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397 template <typename T>
0398 void read(T& array, const DataTransferProps& xfer_props = DataTransferProps()) const;
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411 template <typename T>
0412 void read(T* array,
0413 const DataType& dtype,
0414 const DataTransferProps& xfer_props = DataTransferProps()) const;
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427 template <typename T>
0428 void read(T* array, const DataTransferProps& xfer_props = DataTransferProps()) const;
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439 template <typename T>
0440 void read_raw(T* array,
0441 const DataType& dtype,
0442 const DataTransferProps& xfer_props = DataTransferProps()) const;
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453 template <typename T>
0454 void read_raw(T* array, const DataTransferProps& xfer_props = DataTransferProps()) const;
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464 template <typename T>
0465 void write(const T& buffer, const DataTransferProps& xfer_props = DataTransferProps());
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481 template <typename T>
0482 void write_raw(const T* buffer,
0483 const DataType& mem_datatype,
0484 const DataTransferProps& xfer_props = DataTransferProps());
0485
0486
0487
0488
0489
0490
0491
0492
0493 template <typename T>
0494 void write_raw(const T* buffer, const DataTransferProps& xfer_props = DataTransferProps());
0495 };
0496
0497 }