SpECTRE Documentation Coverage Report
Current view: top level - DataStructures - Index.hpp Hit Total Coverage
Commit: 1f2210958b4f38fdc0400907ee7c6d5af5111418 Lines: 8 22 36.4 %
Date: 2025-12-05 05:03:31
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 1.14