File indexing completed on 2026-05-10 08:42:09
0001 #pragma once
0002
0003 #include "bits/H5Inspector_decl.hpp"
0004 #include "H5Exception.hpp"
0005 #include "bits/xtensor_header_version.hpp"
0006
0007 #if HIGHFIVE_XTENSOR_HEADER_VERSION == 1
0008 #include <xtensor/xtensor.hpp>
0009 #include <xtensor/xarray.hpp>
0010 #include <xtensor/xadapt.hpp>
0011 #elif HIGHFIVE_XTENSOR_HEADER_VERSION == 2
0012 #include <xtensor/containers/xtensor.hpp>
0013 #include <xtensor/containers/xarray.hpp>
0014 #include <xtensor/containers/xadapt.hpp>
0015 #else
0016 #error "Set HIGHFIVE_XTENSOR_HEADER_VERSION to `1` for pre 0.26; `2` otherwise."
0017 #endif
0018
0019 namespace HighFive {
0020 namespace details {
0021
0022 template <class XTensor>
0023 struct xtensor_get_rank;
0024
0025 template <typename T, size_t N, xt::layout_type L>
0026 struct xtensor_get_rank<xt::xtensor<T, N, L>> {
0027 static constexpr size_t value = N;
0028 };
0029
0030 template <class EC, size_t N, xt::layout_type L, class Tag>
0031 struct xtensor_get_rank<xt::xtensor_adaptor<EC, N, L, Tag>> {
0032 static constexpr size_t value = N;
0033 };
0034
0035 template <class Derived, class XTensorType, xt::layout_type L>
0036 struct xtensor_inspector_base {
0037 using type = XTensorType;
0038 using value_type = typename type::value_type;
0039 using base_type = typename inspector<value_type>::base_type;
0040 using hdf5_type = base_type;
0041
0042 static_assert(std::is_same<value_type, base_type>::value,
0043 "HighFive's XTensor support only works for scalar elements.");
0044
0045 static constexpr bool IsConstExprRowMajor = L == xt::layout_type::row_major;
0046 static constexpr bool is_trivially_copyable = IsConstExprRowMajor &&
0047 std::is_trivially_copyable<value_type>::value &&
0048 inspector<value_type>::is_trivially_copyable;
0049
0050 static constexpr bool is_trivially_nestable = false;
0051
0052 static size_t getRank(const type& val) {
0053
0054 return val.shape().size();
0055 }
0056
0057 static const value_type& getAnyElement(const type& val) {
0058 return val.unchecked(0);
0059 }
0060
0061 static value_type& getAnyElement(type& val) {
0062 return val.unchecked(0);
0063 }
0064
0065 static std::vector<size_t> getDimensions(const type& val) {
0066 auto shape = val.shape();
0067 return {shape.begin(), shape.end()};
0068 }
0069
0070 static void prepare(type& val, const std::vector<size_t>& dims) {
0071 val.resize(Derived::shapeFromDims(dims));
0072 }
0073
0074 static hdf5_type* data(type& val) {
0075 if (!is_trivially_copyable) {
0076 throw DataSetException("Invalid used of `inspector<XTensor>::data`.");
0077 }
0078
0079 if (val.size() == 0) {
0080 return nullptr;
0081 }
0082
0083 return inspector<value_type>::data(getAnyElement(val));
0084 }
0085
0086 static const hdf5_type* data(const type& val) {
0087 if (!is_trivially_copyable) {
0088 throw DataSetException("Invalid used of `inspector<XTensor>::data`.");
0089 }
0090
0091 if (val.size() == 0) {
0092 return nullptr;
0093 }
0094
0095 return inspector<value_type>::data(getAnyElement(val));
0096 }
0097
0098 static void serialize(const type& val, const std::vector<size_t>& dims, hdf5_type* m) {
0099
0100 size_t size = compute_total_size(dims);
0101 xt::adapt(m, size, xt::no_ownership(), dims) = val;
0102 }
0103
0104 static void unserialize(const hdf5_type* vec_align,
0105 const std::vector<size_t>& dims,
0106 type& val) {
0107
0108 size_t size = compute_total_size(dims);
0109 val = xt::adapt(vec_align, size, xt::no_ownership(), dims);
0110 }
0111 };
0112
0113 template <class XTensorType, xt::layout_type L>
0114 struct xtensor_inspector
0115 : public xtensor_inspector_base<xtensor_inspector<XTensorType, L>, XTensorType, L> {
0116 private:
0117 using super = xtensor_inspector_base<xtensor_inspector<XTensorType, L>, XTensorType, L>;
0118
0119 public:
0120 using type = typename super::type;
0121 using value_type = typename super::value_type;
0122 using base_type = typename super::base_type;
0123 using hdf5_type = typename super::hdf5_type;
0124
0125 static constexpr size_t ndim = xtensor_get_rank<XTensorType>::value;
0126 static constexpr size_t min_ndim = ndim + inspector<value_type>::min_ndim;
0127 static constexpr size_t max_ndim = ndim + inspector<value_type>::max_ndim;
0128
0129 static std::array<size_t, ndim> shapeFromDims(const std::vector<size_t>& dims) {
0130 std::array<size_t, ndim> shape;
0131 std::copy(dims.cbegin(), dims.cend(), shape.begin());
0132 return shape;
0133 }
0134 };
0135
0136 template <class XArrayType, xt::layout_type L>
0137 struct xarray_inspector
0138 : public xtensor_inspector_base<xarray_inspector<XArrayType, L>, XArrayType, L> {
0139 private:
0140 using super = xtensor_inspector_base<xarray_inspector<XArrayType, L>, XArrayType, L>;
0141
0142 public:
0143 using type = typename super::type;
0144 using value_type = typename super::value_type;
0145 using base_type = typename super::base_type;
0146 using hdf5_type = typename super::hdf5_type;
0147
0148 static constexpr size_t min_ndim = 0 + inspector<value_type>::min_ndim;
0149 static constexpr size_t max_ndim = 1024 + inspector<value_type>::max_ndim;
0150
0151 static const std::vector<size_t>& shapeFromDims(const std::vector<size_t>& dims) {
0152 return dims;
0153 }
0154 };
0155
0156 template <typename T, size_t N, xt::layout_type L>
0157 struct inspector<xt::xtensor<T, N, L>>: public xtensor_inspector<xt::xtensor<T, N, L>, L> {
0158 private:
0159 using super = xtensor_inspector<xt::xtensor<T, N, L>, L>;
0160
0161 public:
0162 using type = typename super::type;
0163 using value_type = typename super::value_type;
0164 using base_type = typename super::base_type;
0165 using hdf5_type = typename super::hdf5_type;
0166 };
0167
0168 template <typename T, xt::layout_type L>
0169 struct inspector<xt::xarray<T, L>>: public xarray_inspector<xt::xarray<T, L>, L> {
0170 private:
0171 using super = xarray_inspector<xt::xarray<T, L>, L>;
0172
0173 public:
0174 using type = typename super::type;
0175 using value_type = typename super::value_type;
0176 using base_type = typename super::base_type;
0177 using hdf5_type = typename super::hdf5_type;
0178 };
0179
0180 template <typename CT, class... S>
0181 struct inspector<xt::xview<CT, S...>>
0182 : public xarray_inspector<xt::xview<CT, S...>, xt::layout_type::any> {
0183 private:
0184 using super = xarray_inspector<xt::xview<CT, S...>, xt::layout_type::any>;
0185
0186 public:
0187 using type = typename super::type;
0188 using value_type = typename super::value_type;
0189 using base_type = typename super::base_type;
0190 using hdf5_type = typename super::hdf5_type;
0191 };
0192
0193
0194 template <class EC, xt::layout_type L, class SC, class Tag>
0195 struct inspector<xt::xarray_adaptor<EC, L, SC, Tag>>
0196 : public xarray_inspector<xt::xarray_adaptor<EC, L, SC, Tag>, xt::layout_type::any> {
0197 private:
0198 using super = xarray_inspector<xt::xarray_adaptor<EC, L, SC, Tag>, xt::layout_type::any>;
0199
0200 public:
0201 using type = typename super::type;
0202 using value_type = typename super::value_type;
0203 using base_type = typename super::base_type;
0204 using hdf5_type = typename super::hdf5_type;
0205 };
0206
0207 template <class EC, size_t N, xt::layout_type L, class Tag>
0208 struct inspector<xt::xtensor_adaptor<EC, N, L, Tag>>
0209 : public xtensor_inspector<xt::xtensor_adaptor<EC, N, L, Tag>, xt::layout_type::any> {
0210 private:
0211 using super = xtensor_inspector<xt::xtensor_adaptor<EC, N, L, Tag>, xt::layout_type::any>;
0212
0213 public:
0214 using type = typename super::type;
0215 using value_type = typename super::value_type;
0216 using base_type = typename super::base_type;
0217 using hdf5_type = typename super::hdf5_type;
0218 };
0219
0220 }
0221 }