Back to home page

EIC code displayed by LXR

 
 

    


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 
0006 #include <mdspan>
0007 #include <vector>
0008 #include <array>
0009 #include <sstream>
0010 #include <utility>
0011 #include <type_traits>
0012 
0013 namespace HighFive {
0014 namespace details {
0015 
0016 // Specialization for std::mdspan
0017 template <class ElementType, class Extents, class LayoutPolicy, class AccessorPolicy>
0018 struct inspector<std::mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>> {
0019     using type = std::mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>;
0020     using value_type = typename type::element_type;
0021     using base_type = typename inspector<value_type>::base_type;
0022     using hdf5_type = base_type;
0023     using extents_type = typename type::extents_type;
0024     using accessor_type = typename type::accessor_type;
0025 
0026     static constexpr size_t ndim = type::rank();
0027     static constexpr size_t min_ndim = ndim + inspector<value_type>::min_ndim;
0028     static constexpr size_t max_ndim = ndim + inspector<value_type>::max_ndim;
0029 
0030     static constexpr bool is_trivially_copyable =
0031         std::is_trivially_copyable<value_type>::value &&
0032         inspector<value_type>::is_trivially_nestable &&
0033         (std::is_same_v<std::default_accessor<value_type>, accessor_type>
0034 #ifdef __cpp_lib_aligned_accessor
0035          || std::is_same_v<std::aligned_accessor<value_type>, accessor_type>
0036 #endif
0037          ) &&
0038         (std::is_same_v<typename type::layout_type, std::layout_right> ||
0039          (std::is_same_v<typename type::layout_type, std::layout_left> && ndim == 1));
0040     static constexpr bool is_trivially_nestable = false;
0041 
0042   private:
0043     using index_type = typename extents_type::index_type;
0044 
0045     // Helper to access the first element (at index 0 in all dimensions)
0046     static auto get_first_element(const type& val) {
0047         std::array<index_type, ndim> indices{};
0048         return val[indices];
0049     }
0050 
0051     template <typename T>
0052     static auto data_impl(T& val) -> decltype(inspector<value_type>::data(*val.data_handle())) {
0053         if (!is_trivially_copyable) {
0054             throw DataSetException("Invalid use of `inspector<std::mdspan<...>>::data`.");
0055         }
0056 
0057         if (val.empty()) {
0058             return nullptr;
0059         }
0060 
0061         return inspector<value_type>::data(*val.data_handle());
0062     }
0063 
0064   public:
0065     static size_t getRank(const type& val) {
0066         if (val.empty()) {
0067             return min_ndim;
0068         }
0069         return ndim + inspector<value_type>::getRank(get_first_element(val));
0070     }
0071 
0072     static std::vector<size_t> getDimensions(const type& val) {
0073         std::vector<size_t> sizes;
0074         sizes.reserve(ndim);
0075         for (size_t r = 0; r < ndim; ++r) {
0076             sizes.push_back(val.extent(r));
0077         }
0078         if (!val.empty()) {
0079             auto s = inspector<value_type>::getDimensions(get_first_element(val));
0080             sizes.insert(sizes.end(), s.begin(), s.end());
0081         }
0082         return sizes;
0083     }
0084 
0085     static void prepare(type& val, const std::vector<size_t>& dims) {
0086         if (dims.size() < ndim) {
0087             std::ostringstream os;
0088             os << "Impossible to pair DataSet with " << dims.size()
0089                << " dimensions into an mdspan with rank " << ndim << ".";
0090             throw DataSpaceException(os.str());
0091         }
0092 
0093         // Check that dimensions match
0094         for (size_t r = 0; r < ndim; ++r) {
0095             if (dims[r] != val.extent(r)) {
0096                 std::ostringstream os;
0097                 os << "Mismatching dimensions for mdspan: expected " << val.extent(r)
0098                    << " for dimension " << r << ", but got " << dims[r] << ".";
0099                 throw DataSpaceException(os.str());
0100             }
0101         }
0102     }
0103 
0104     static hdf5_type* data(type& val) {
0105         return data_impl(val);
0106     }
0107 
0108     static const hdf5_type* data(const type& val) {
0109         return data_impl(val);
0110     }
0111 
0112     static void serialize(const type& val, const std::vector<size_t>& dims, hdf5_type* m) {
0113         auto subdims = std::vector<size_t>(dims.begin() + ndim, dims.end());
0114         auto subsize = compute_total_size(subdims);
0115 
0116         std::array<index_type, ndim> indices{};
0117         auto iterate = [&](auto& self, size_t dim) -> void {
0118             if (dim == ndim) {
0119                 // Base case: serialize element
0120                 inspector<value_type>::serialize(val[indices], subdims, m);
0121                 m += subsize;
0122             } else {
0123                 // Recursive case: iterate over current dimension
0124                 const auto n = static_cast<index_type>(val.extent(dim));
0125                 for (indices[dim] = 0; indices[dim] < n; ++indices[dim]) {
0126                     self(self, dim + 1);
0127                 }
0128             }
0129         };
0130 
0131         iterate(iterate, 0);
0132     }
0133 
0134     static void unserialize(const hdf5_type* vec_align,
0135                             const std::vector<size_t>& dims,
0136                             type& val) {
0137         if (dims.size() < ndim) {
0138             std::ostringstream os;
0139             os << "Impossible to pair DataSet with " << dims.size()
0140                << " dimensions into an mdspan with rank " << ndim << ".";
0141             throw DataSpaceException(os.str());
0142         }
0143 
0144         auto subdims = std::vector<size_t>(dims.begin() + ndim, dims.end());
0145         auto subsize = compute_total_size(subdims);
0146 
0147         std::array<index_type, ndim> indices{};
0148         auto iterate = [&](auto& self, size_t dim) -> void {
0149             if (dim == ndim) {
0150                 // Base case: unserialize element
0151                 inspector<value_type>::unserialize(vec_align, subdims, val[indices]);
0152                 vec_align += subsize;
0153             } else {
0154                 // Recursive case: iterate over current dimension
0155                 const auto n = static_cast<index_type>(dims[dim]);
0156                 for (indices[dim] = 0; indices[dim] < n; ++indices[dim]) {
0157                     self(self, dim + 1);
0158                 }
0159             }
0160         };
0161 
0162         iterate(iterate, 0);
0163     }
0164 };
0165 
0166 }  // namespace details
0167 }  // namespace HighFive