SpECTRE Documentation Coverage Report
Current view: top level - DataStructures - Index.hpp Hit Total Coverage
Commit: fb144cfca92c3773ae2a942619781e0e583aa113 Lines: 7 21 33.3 %
Date: 2023-06-02 00:56:01
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 < Dim; ++i) {
      89             :       if (i < d) {
      90             :         gsl::at(t, i) = gsl::at(indices_, i);
      91             :       } else if (i > d) {
      92             :         gsl::at(t, i - 1) = gsl::at(indices_, i);
      93             :       }
      94             :     }
      95             :     return Index<Dim - 1>(t);
      96             :   }
      97             : 
      98             :   /// \cond
      99             :   // NOLINTNEXTLINE(google-runtime-references)
     100             :   void pup(PUP::er& p);
     101             :   /// \endcond
     102             : 
     103             :   template <size_t N>
     104           0 :   friend std::ostream& operator<<(std::ostream& os,  // NOLINT
     105             :                                   const Index<N>& i);
     106             : 
     107           0 :   const size_t* data() const { return indices_.data(); }
     108           0 :   size_t* data() { return indices_.data(); }
     109             : 
     110           0 :   const std::array<size_t, Dim>& indices() const { return indices_; }
     111             : 
     112             :  private:
     113           0 :   std::array<size_t, Dim> indices_;
     114             : };
     115             : 
     116             : /// \ingroup DataStructuresGroup
     117             : /// Get the collapsed index into a 1D array of the data corresponding to this
     118             : /// Index. Note that the first dimension of the Index varies fastest when
     119             : /// computing the collapsed index.
     120             : template <size_t N>
     121           1 : size_t collapsed_index(const Index<N>& index, const Index<N>& extents);
     122             : 
     123             : template <size_t N>
     124           0 : std::ostream& operator<<(std::ostream& os, const Index<N>& i);
     125             : 
     126             : /// \cond HIDDEN_SYMBOLS
     127             : #ifdef SPECTRE_DEBUG
     128             : namespace Index_detail {
     129             : template <size_t Dim>
     130             : void collapsed_index_check(const Index<Dim>& index, const Index<Dim>& extents) {
     131             :   for (size_t d = 0; d < Dim; ++d) {
     132             :     ASSERT(index[d] < extents[d], "The requested index in the dimension "
     133             :                                       << d << " with value " << index[d]
     134             :                                       << " exceeds the number of grid "
     135             :                                          "points "
     136             :                                       << extents[d]);
     137             :   }
     138             : }
     139             : }  // namespace Index_detail
     140             : #endif
     141             : 
     142             : // the specializations are in the header file so they can be inlined. We use
     143             : // specializations to avoid having loops since this computation is very
     144             : // straightforward.
     145             : template <>
     146             : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<0>& /*index*/,
     147             :                                              const Index<0>& /*extents*/) {
     148             :   return 0;
     149             : }
     150             : 
     151             : template <>
     152             : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<1>& index,
     153             :                                              const Index<1>& extents) {
     154             :   (void)extents;
     155             : #ifdef SPECTRE_DEBUG
     156             :   Index_detail::collapsed_index_check(index, extents);
     157             : #endif
     158             :   return index[0];
     159             : }
     160             : 
     161             : template <>
     162             : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<2>& index,
     163             :                                              const Index<2>& extents) {
     164             : #ifdef SPECTRE_DEBUG
     165             :   Index_detail::collapsed_index_check(index, extents);
     166             : #endif
     167             :   return index[0] + extents[0] * index[1];
     168             : }
     169             : 
     170             : template <>
     171             : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<3>& index,
     172             :                                              const Index<3>& extents) {
     173             : #ifdef SPECTRE_DEBUG
     174             :   Index_detail::collapsed_index_check(index, extents);
     175             : #endif
     176             :   return index[0] + extents[0] * (index[1] + extents[1] * index[2]);
     177             : }
     178             : 
     179             : template <>
     180             : SPECTRE_ALWAYS_INLINE size_t collapsed_index(const Index<4>& index,
     181             :                                              const Index<4>& extents) {
     182             : #ifdef SPECTRE_DEBUG
     183             :   Index_detail::collapsed_index_check(index, extents);
     184             : #endif
     185             :   return index[0] +
     186             :          extents[0] *
     187             :              (index[1] + extents[1] * (index[2] + extents[2] * index[3]));
     188             : }
     189             : 
     190             : template <size_t N>
     191             : bool operator==(const Index<N>& lhs, const Index<N>& rhs);
     192             : 
     193             : template <size_t N>
     194             : bool operator!=(const Index<N>& lhs, const Index<N>& rhs);
     195             : /// \endcond

Generated by: LCOV version 1.14