SpECTRE Documentation Coverage Report
Current view: top level - DataStructures - Index.hpp Hit Total Coverage
Commit: eded15d6fcfa762a5dfde087b28df9bcedd8b386 Lines: 7 21 33.3 %
Date: 2024-04-15 22:23:51
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 <cstddef>
      11             : #include <limits>
      12             : #include <ostream>
      13             : 
      14             : #include "Utilities/ErrorHandling/Assert.hpp"
      15             : #include "Utilities/ForceInline.hpp"
      16             : #include "Utilities/Gsl.hpp"
      17             : #include "Utilities/MakeArray.hpp"
      18             : #include "Utilities/Requires.hpp"
      19             : #include "Utilities/TypeTraits.hpp"  // IWYU pragma: keep
      20             : #include "Utilities/TypeTraits/IsInteger.hpp"
      21             : 
      22             : namespace PUP {
      23             : class er;
      24             : }  // namespace PUP
      25             : 
      26             : /// \ingroup DataStructuresGroup
      27             : /// An integer multi-index.
      28             : ///
      29             : /// \tparam Dim the number of integers in the Index.
      30             : template <size_t Dim>
      31           1 : class Index {
      32             :  public:
      33             :   /// Construct with each element set to the same value.
      34           1 :   explicit Index(const size_t i0 = std::numeric_limits<size_t>::max())
      35             :       : indices_(make_array<Dim>(i0)) {}
      36             : 
      37             :   /// Construct specifying value in each dimension
      38             :   template <typename... I, Requires<(sizeof...(I) > 1)> = nullptr>
      39           1 :   explicit Index(I... i) : indices_(make_array(static_cast<size_t>(i)...)) {
      40             :     static_assert(std::conjunction_v<tt::is_integer<I>...>,
      41             :                   "You must pass in a set of size_t's to Index.");
      42             :     static_assert(Dim == sizeof...(I),
      43             :                   "The number of indices given to Index must be the same as "
      44             :                   "the dimensionality of the Index.");
      45             :   }
      46             : 
      47           0 :   explicit Index(std::array<size_t, Dim> i) : indices_(std::move(i)) {}
      48             : 
      49           0 :   size_t operator[](const size_t d) const { return gsl::at(indices_, d); }
      50           0 :   size_t& operator[](const size_t d) { return gsl::at(indices_, d); }
      51             : 
      52           0 :   typename std::array<size_t, Dim>::iterator begin() {
      53             :     return indices_.begin();
      54             :   }
      55           0 :   typename std::array<size_t, Dim>::const_iterator begin() const {
      56             :     return indices_.begin();
      57             :   }
      58             : 
      59           0 :   typename std::array<size_t, Dim>::iterator end() { return indices_.end(); }
      60           0 :   typename std::array<size_t, Dim>::const_iterator end() const {
      61             :     return indices_.end();
      62             :   }
      63             : 
      64           0 :   size_t size() const { return Dim; }
      65             : 
      66             :   /// The product of the indices.
      67             :   /// If Dim = 0, the product is defined as 1.
      68             :   template <int N = Dim, Requires<(N > 0)> = nullptr>
      69           1 :   constexpr size_t product() const {
      70             :     return indices_[N - 1] * product<N - 1>();
      71             :   }
      72             :   /// \cond
      73             :   // Specialization for N = 0 to stop recursion
      74             :   template <int N = Dim, Requires<(N == 0)> = nullptr>
      75             :   constexpr size_t product() const {
      76             :     return 1;
      77             :   }
      78             :   /// \endcond
      79             : 
      80             :   /// Return a smaller Index with the d-th element removed.
      81             :   ///
      82             :   /// \param d the element to remove.
      83             :   template <size_t N = Dim, Requires<(N > 0)> = nullptr>
      84           1 :   Index<Dim - 1> slice_away(const size_t d) const {
      85             :     ASSERT(d < Dim,
      86             :            "Can't slice dimension " << d << " from an Index<" << Dim << ">");
      87             :     std::array<size_t, Dim - 1> t{};
      88             :     for (size_t i = 0; i < d; ++i) {
      89             :       gsl::at(t, i) = gsl::at(indices_, i);
      90             :     }
      91             :     for (size_t i = d + 1; i < Dim; ++i) {
      92             :       gsl::at(t, i - 1) = gsl::at(indices_, i);
      93             :     }
      94             :     return Index<Dim - 1>(t);
      95             :   }
      96             : 
      97             :   /// \cond
      98             :   // NOLINTNEXTLINE(google-runtime-references)
      99             :   void pup(PUP::er& p);
     100             :   /// \endcond
     101             : 
     102             :   template <size_t N>
     103           0 :   friend std::ostream& operator<<(std::ostream& os,  // NOLINT
     104             :                                   const Index<N>& i);
     105             : 
     106           0 :   const size_t* data() const { return indices_.data(); }
     107           0 :   size_t* data() { return indices_.data(); }
     108             : 
     109           0 :   const std::array<size_t, Dim>& indices() const { return indices_; }
     110             : 
     111             :  private:
     112           0 :   std::array<size_t, Dim> indices_;
     113             : };
     114             : 
     115             : /// \ingroup DataStructuresGroup
     116             : /// Get the collapsed index into a 1D array of the data corresponding to this
     117             : /// Index. Note that the first dimension of the Index varies fastest when
     118             : /// computing the collapsed index.
     119             : template <size_t N>
     120           1 : size_t collapsed_index(const Index<N>& index, const Index<N>& extents);
     121             : 
     122             : template <size_t N>
     123           0 : std::ostream& operator<<(std::ostream& os, const Index<N>& i);
     124             : 
     125             : /// \cond HIDDEN_SYMBOLS
     126             : #ifdef SPECTRE_DEBUG
     127             : namespace Index_detail {
     128             : template <size_t Dim>
     129             : void collapsed_index_check(const Index<Dim>& index, const Index<Dim>& extents) {
     130             :   for (size_t d = 0; d < Dim; ++d) {
     131             :     ASSERT(index[d] < extents[d], "The requested index in the dimension "
     132             :                                       << d << " with value " << index[d]
     133             :                                       << " exceeds the number of grid "
     134             :                                          "points "
     135             :                                       << extents[d]);
     136             :   }
     137             : }
     138             : }  // namespace Index_detail
     139             : #endif
     140             : 
     141             : // the specializations are in the header file so they can be inlined. We use
     142             : // specializations to avoid having loops since this computation is very
     143             : // straightforward.
     144             : template <>
     145             : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<0>& /*index*/,
     146             :                                              const Index<0>& /*extents*/) {
     147             :   return 0;
     148             : }
     149             : 
     150             : template <>
     151             : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<1>& index,
     152             :                                              const Index<1>& extents) {
     153             :   (void)extents;
     154             : #ifdef SPECTRE_DEBUG
     155             :   Index_detail::collapsed_index_check(index, extents);
     156             : #endif
     157             :   return index[0];
     158             : }
     159             : 
     160             : template <>
     161             : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<2>& index,
     162             :                                              const Index<2>& extents) {
     163             : #ifdef SPECTRE_DEBUG
     164             :   Index_detail::collapsed_index_check(index, extents);
     165             : #endif
     166             :   return index[0] + extents[0] * index[1];
     167             : }
     168             : 
     169             : template <>
     170             : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<3>& index,
     171             :                                              const Index<3>& extents) {
     172             : #ifdef SPECTRE_DEBUG
     173             :   Index_detail::collapsed_index_check(index, extents);
     174             : #endif
     175             :   return index[0] + extents[0] * (index[1] + extents[1] * index[2]);
     176             : }
     177             : 
     178             : template <>
     179             : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<4>& index,
     180             :                                              const Index<4>& extents) {
     181             : #ifdef SPECTRE_DEBUG
     182             :   Index_detail::collapsed_index_check(index, extents);
     183             : #endif
     184             :   return index[0] +
     185             :          extents[0] *
     186             :              (index[1] + extents[1] * (index[2] + extents[2] * index[3]));
     187             : }
     188             : 
     189             : template <size_t N>
     190             : bool operator==(const Index<N>& lhs, const Index<N>& rhs);
     191             : 
     192             : template <size_t N>
     193             : bool operator!=(const Index<N>& lhs, const Index<N>& rhs);
     194             : /// \endcond

Generated by: LCOV version 1.14