SpECTRE Documentation Coverage Report
Current view: top level - DataStructures - Index.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 36.4 % 22 8
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            1 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : /// \file
       5              : /// Defines class template Index.
       6              : 
       7              : #pragma once
       8              : 
       9              : #include <array>
      10              : #include <concepts>
      11              : #include <cstddef>
      12              : #include <limits>
      13              : #include <ostream>
      14              : 
      15              : #include "Utilities/ErrorHandling/Assert.hpp"
      16              : #include "Utilities/ForceInline.hpp"
      17              : #include "Utilities/Gsl.hpp"
      18              : #include "Utilities/MakeArray.hpp"
      19              : 
      20              : namespace PUP {
      21              : class er;
      22              : }  // namespace PUP
      23              : 
      24              : /// \ingroup DataStructuresGroup
      25              : /// An integer multi-index.
      26              : ///
      27              : /// \tparam Dim the number of integers in the Index.
      28              : template <size_t Dim>
      29            1 : class Index {
      30              :  public:
      31              :   /// Construct with each element set to the same value.
      32            1 :   explicit Index(const size_t i0 = std::numeric_limits<size_t>::max())
      33              :       : indices_(make_array<Dim>(i0)) {}
      34              : 
      35              :   /// Construct specifying value in each dimension
      36              :   template <std::integral... I>
      37              :     requires(sizeof...(I) == Dim and sizeof...(I) > 1)
      38            1 :   explicit Index(I... i) : indices_(make_array(static_cast<size_t>(i)...)) {}
      39              : 
      40            0 :   explicit Index(std::array<size_t, Dim> i) : indices_(std::move(i)) {}
      41              : 
      42            0 :   size_t operator[](const size_t d) const { return gsl::at(indices_, d); }
      43            0 :   size_t& operator[](const size_t d) { return gsl::at(indices_, d); }
      44              : 
      45            0 :   typename std::array<size_t, Dim>::iterator begin() {
      46              :     return indices_.begin();
      47              :   }
      48            0 :   typename std::array<size_t, Dim>::const_iterator begin() const {
      49              :     return indices_.begin();
      50              :   }
      51              : 
      52            0 :   typename std::array<size_t, Dim>::iterator end() { return indices_.end(); }
      53            0 :   typename std::array<size_t, Dim>::const_iterator end() const {
      54              :     return indices_.end();
      55              :   }
      56              : 
      57            0 :   size_t size() const { return Dim; }
      58              : 
      59              :   /// The product of the indices.
      60              :   /// If Dim = 0, the product is defined as 1.
      61              :   template <size_t N = Dim>
      62              :     requires(N > 0)
      63            1 :   constexpr size_t product() const {
      64              :     return indices_[N - 1] * product<N - 1>();
      65              :   }
      66              :   /// \cond
      67              :   // Specialization for N = 0 to stop recursion
      68              :   template <size_t N = Dim>
      69              :     requires(N == 0)
      70              :   constexpr size_t product() const {
      71              :     return 1;
      72              :   }
      73              :   /// \endcond
      74              : 
      75              :   /// Return a smaller Index with the d-th element removed.
      76              :   ///
      77              :   /// \param d the element to remove.
      78              :   template <size_t N = Dim>
      79              :     requires(N > 0)
      80            1 :   Index<Dim - 1> slice_away(const size_t d) const {
      81              :     ASSERT(d < Dim,
      82              :            "Can't slice dimension " << d << " from an Index<" << Dim << ">");
      83              :     std::array<size_t, Dim - 1> t{};
      84              :     for (size_t i = 0; i < d; ++i) {
      85              :       gsl::at(t, i) = gsl::at(indices_, i);
      86              :     }
      87              :     for (size_t i = d + 1; i < Dim; ++i) {
      88              :       gsl::at(t, i - 1) = gsl::at(indices_, i);
      89              :     }
      90              :     return Index<Dim - 1>(t);
      91              :   }
      92              : 
      93              :   /// \cond
      94              :   // NOLINTNEXTLINE(google-runtime-references)
      95              :   void pup(PUP::er& p);
      96              :   /// \endcond
      97              : 
      98              :   template <size_t N>
      99            0 :   friend std::ostream& operator<<(std::ostream& os,  // NOLINT
     100              :                                   const Index<N>& i);
     101              : 
     102            0 :   const size_t* data() const { return indices_.data(); }
     103            0 :   size_t* data() { return indices_.data(); }
     104              : 
     105            0 :   const std::array<size_t, Dim>& indices() const { return indices_; }
     106              : 
     107              :  private:
     108            0 :   std::array<size_t, Dim> indices_;
     109              : };
     110              : 
     111              : /// \ingroup DataStructuresGroup
     112              : /// Get the collapsed index into a 1D array of the data corresponding to this
     113              : /// Index. Note that the first dimension of the Index varies fastest when
     114              : /// computing the collapsed index.
     115              : template <size_t N>
     116            1 : size_t collapsed_index(const Index<N>& index, const Index<N>& extents);
     117              : 
     118              : /// \ingroup DataStructuresGroup
     119              : /// This is the inverse function of collapsed_index. Given a collapsed (1D)
     120              : /// index and the extents of the array, return the Index corresponding to that
     121              : /// collapsed index. Note that the first dimension of the Index varies fastest
     122              : /// when computing the collapsed index.
     123              : template <size_t Dim>
     124            1 : Index<Dim> expanded_index(size_t index, const Index<Dim>& extents);
     125              : 
     126              : template <size_t N>
     127            0 : std::ostream& operator<<(std::ostream& os, const Index<N>& i);
     128              : 
     129              : /// \cond HIDDEN_SYMBOLS
     130              : #ifdef SPECTRE_DEBUG
     131              : namespace Index_detail {
     132              : template <size_t Dim>
     133              : void collapsed_index_check(const Index<Dim>& index, const Index<Dim>& extents) {
     134              :   for (size_t d = 0; d < Dim; ++d) {
     135              :     ASSERT(index[d] < extents[d], "The requested index in the dimension "
     136              :                                       << d << " with value " << index[d]
     137              :                                       << " exceeds the number of grid "
     138              :                                          "points "
     139              :                                       << extents[d]);
     140              :   }
     141              : }
     142              : }  // namespace Index_detail
     143              : #endif
     144              : 
     145              : // the specializations are in the header file so they can be inlined. We use
     146              : // specializations to avoid having loops since this computation is very
     147              : // straightforward.
     148              : template <>
     149              : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<0>& /*index*/,
     150              :                                              const Index<0>& /*extents*/) {
     151              :   return 0;
     152              : }
     153              : 
     154              : template <>
     155              : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<1>& index,
     156              :                                              const Index<1>& extents) {
     157              :   (void)extents;
     158              : #ifdef SPECTRE_DEBUG
     159              :   Index_detail::collapsed_index_check(index, extents);
     160              : #endif
     161              :   return index[0];
     162              : }
     163              : 
     164              : template <>
     165              : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<2>& index,
     166              :                                              const Index<2>& extents) {
     167              : #ifdef SPECTRE_DEBUG
     168              :   Index_detail::collapsed_index_check(index, extents);
     169              : #endif
     170              :   return index[0] + extents[0] * index[1];
     171              : }
     172              : 
     173              : template <>
     174              : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<3>& index,
     175              :                                              const Index<3>& extents) {
     176              : #ifdef SPECTRE_DEBUG
     177              :   Index_detail::collapsed_index_check(index, extents);
     178              : #endif
     179              :   return index[0] + extents[0] * (index[1] + extents[1] * index[2]);
     180              : }
     181              : 
     182              : template <>
     183              : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<4>& index,
     184              :                                              const Index<4>& extents) {
     185              : #ifdef SPECTRE_DEBUG
     186              :   Index_detail::collapsed_index_check(index, extents);
     187              : #endif
     188              :   return index[0] +
     189              :          extents[0] *
     190              :              (index[1] + extents[1] * (index[2] + extents[2] * index[3]));
     191              : }
     192              : 
     193              : template <>
     194              : SPECTRE_ALWAYS_INLINE Index<1> expanded_index(size_t index,
     195              :                                               const Index<1>& extents) {
     196              :   (void)extents;
     197              :   return Index<1>{index};
     198              : }
     199              : 
     200              : template <>
     201              : SPECTRE_ALWAYS_INLINE Index<2> expanded_index(size_t index,
     202              :                                               const Index<2>& extents) {
     203              :   const size_t ix = index % extents[0];
     204              :   const size_t iy = index / extents[0];
     205              :   return Index<2>{{ix, iy}};
     206              : }
     207              : 
     208              : template <>
     209              : SPECTRE_ALWAYS_INLINE Index<3> expanded_index(size_t index,
     210              :                                               const Index<3>& extents) {
     211              :   const size_t ix = index % extents[0];
     212              :   const size_t iy = (index / extents[0]) % extents[1];
     213              :   const size_t iz = (index / extents[0]) / extents[1];
     214              :   return Index<3>{{ix, iy, iz}};
     215              : }
     216              : 
     217              : template <size_t N>
     218              : bool operator==(const Index<N>& lhs, const Index<N>& rhs);
     219              : 
     220              : template <size_t N>
     221              : bool operator!=(const Index<N>& lhs, const Index<N>& rhs);
     222              : /// \endcond
        

Generated by: LCOV version 2.0-1