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