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

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details
       3              : 
       4              : #pragma once
       5              : 
       6              : #include "DataStructures/ComplexDataVector.hpp"
       7              : #include "DataStructures/VectorImpl.hpp"
       8              : #include "Utilities/ForceInline.hpp"
       9              : #include "Utilities/Requires.hpp"
      10              : #include "Utilities/SetNumberOfGridPoints.hpp"
      11              : #include "Utilities/TypeTraits.hpp"
      12              : 
      13              : /// @{
      14              : /*!
      15              :  * \ingroup DataStructuresGroup
      16              :  * \brief Make a spin-weighted type `T` with spin-weight `Spin`. Mathematical
      17              :  * operators are restricted to addition, subtraction, multiplication and
      18              :  * division, with spin-weights checked for validity.
      19              :  *
      20              :  * \details For a spin-weighted object, we limit operations to those valid for a
      21              :  * pair of spin-weighted quantities - i.e. addition only makes sense when the
      22              :  * two summands possess the same spin weight, and multiplication (or division)
      23              :  * result in a summed (or subtracted) spin weight.
      24              :  */
      25              : template <typename T, int Spin, bool is_vector = is_derived_of_vector_impl_v<T>>
      26            1 : struct SpinWeighted;
      27              : 
      28              : template <typename T, int Spin>
      29            0 : struct SpinWeighted<T, Spin, false> {
      30            0 :   using value_type = T;
      31            0 :   constexpr static int spin = Spin;
      32              : 
      33            0 :   SpinWeighted() = default;
      34            0 :   SpinWeighted(const SpinWeighted&) = default;
      35            0 :   SpinWeighted(SpinWeighted&&) = default;
      36            0 :   SpinWeighted& operator=(const SpinWeighted&) = default;
      37            0 :   SpinWeighted& operator=(SpinWeighted&&) = default;
      38            0 :   ~SpinWeighted() = default;
      39              : 
      40              :   // clang-tidy asks that these be marked explicit, but we actually do not want
      41              :   // them explicit for use in the math operations below.
      42              :   template <typename Rhs>
      43            0 :   SpinWeighted(const SpinWeighted<Rhs, Spin>& rhs)  // NOLINT
      44              :       : data_{rhs.data()} {}
      45              : 
      46              :   template <typename Rhs>
      47            0 :   SpinWeighted(SpinWeighted<Rhs, Spin>&& rhs)  // NOLINT
      48              :       : data_{std::move(rhs.data())} {}
      49              : 
      50            0 :   SpinWeighted(const T& rhs) : data_{rhs} {}        // NOLINT
      51            0 :   SpinWeighted(T&& rhs) : data_{std::move(rhs)} {}  // NOLINT
      52            0 :   explicit SpinWeighted(const size_t size) : data_{size} {}
      53              :   template <typename U>
      54            0 :   SpinWeighted(const size_t size, const U& val) : data_{size, val} {}
      55              : 
      56              :   template <typename Rhs>
      57            0 :   SpinWeighted& operator=(const SpinWeighted<Rhs, Spin>& rhs) {
      58              :     data_ = rhs.data();
      59              :     return *this;
      60              :   }
      61              : 
      62              :   template <typename Rhs>
      63            0 :   SpinWeighted& operator=(SpinWeighted<Rhs, Spin>&& rhs) {
      64              :     data_ = std::move(rhs.data());
      65              :     return *this;
      66              :   }
      67              : 
      68            0 :   SpinWeighted& operator=(const T& rhs) {
      69              :     data_ = rhs;
      70              :     return *this;
      71              :   }
      72            0 :   SpinWeighted& operator=(T&& rhs) {
      73              :     data_ = std::move(rhs);
      74              :     return *this;
      75              :   }
      76              : 
      77              :   template <typename Rhs>
      78            0 :   auto& operator+=(const SpinWeighted<Rhs, Spin>& rhs) {
      79              :     data_ += rhs.data();
      80              :     return *this;
      81              :   }
      82              : 
      83            0 :   auto& operator+=(const T& rhs) {
      84              :     data_ += rhs;
      85              :     return *this;
      86              :   }
      87              : 
      88              :   template <typename Rhs>
      89            0 :   auto& operator-=(const SpinWeighted<Rhs, Spin>& rhs) {
      90              :     data_ -= rhs.data();
      91              :     return *this;
      92              :   }
      93              : 
      94            0 :   auto& operator-=(const T& rhs) {
      95              :     data_ -= rhs;
      96              :     return *this;
      97              :   }
      98              : 
      99            0 :   T& data() { return data_; }
     100            0 :   const T& data() const { return data_; }
     101              : 
     102            0 :   size_t size() const { return data_.size(); }
     103              : 
     104              :   /// Serialization for Charm++
     105              :   // NOLINTNEXTLINE(google-runtime-references)
     106            1 :   void pup(PUP::er& p);
     107              : 
     108              :  private:
     109            0 :   T data_;
     110              : };
     111              : 
     112              : template <typename T, int Spin>
     113            0 : struct SpinWeighted<T, Spin, true> {
     114            0 :   using value_type = T;
     115            0 :   constexpr static int spin = Spin;
     116              : 
     117            0 :   void set_data_ref(const gsl::not_null<T*> rhs) { data_.set_data_ref(rhs); }
     118              : 
     119              :   // needed for invoking the check in `Variables.hpp` that ensures that
     120              :   // default-constructed `Variables` are never used.
     121            0 :   void set_data_ref(const std::nullptr_t null, const size_t size) {
     122              :     data_.set_data_ref(null, size);
     123              :   }
     124              : 
     125            0 :   void set_data_ref(const gsl::not_null<SpinWeighted<T, spin>*> rhs) {
     126              :     data_.set_data_ref(make_not_null(&(rhs->data_)));
     127              :   }
     128              : 
     129              :   template <typename ValueType>
     130            0 :   void set_data_ref(ValueType* const start, const size_t set_size) {
     131              :     data_.set_data_ref(start, set_size);
     132              :   }
     133              : 
     134            0 :   void destructive_resize(const size_t new_size) {
     135              :     data_.destructive_resize(new_size);
     136              :   }
     137              : 
     138            0 :   SpinWeighted() = default;
     139            0 :   SpinWeighted(const SpinWeighted&) = default;
     140            0 :   SpinWeighted(SpinWeighted&&) = default;
     141            0 :   SpinWeighted& operator=(const SpinWeighted&) = default;
     142            0 :   SpinWeighted& operator=(SpinWeighted&&) = default;
     143            0 :   ~SpinWeighted() = default;
     144              : 
     145              :   // clang-tidy asks that these be marked explicit, but we actually do not want
     146              :   // them explicit for use in the math operations below.
     147              :   template <typename Rhs>
     148            0 :   SpinWeighted(const SpinWeighted<Rhs, Spin>& rhs)  // NOLINT
     149              :       : data_{rhs.data()} {}
     150              : 
     151              :   template <typename Rhs>
     152            0 :   SpinWeighted(SpinWeighted<Rhs, Spin>&& rhs)  // NOLINT
     153              :       : data_{std::move(rhs.data())} {}
     154              : 
     155            0 :   SpinWeighted(const T& rhs) : data_{rhs} {}        // NOLINT
     156            0 :   SpinWeighted(T&& rhs) : data_{std::move(rhs)} {}  // NOLINT
     157            0 :   explicit SpinWeighted(const size_t size) : data_{size} {}
     158              :   template <typename U>
     159            0 :   SpinWeighted(const size_t size, const U& val) : data_{size, val} {}
     160              : 
     161              :   template <typename Rhs>
     162            0 :   SpinWeighted& operator=(const SpinWeighted<Rhs, Spin>& rhs) {
     163              :     data_ = rhs.data();
     164              :     return *this;
     165              :   }
     166              : 
     167              :   template <typename Rhs>
     168            0 :   SpinWeighted& operator=(SpinWeighted<Rhs, Spin>&& rhs) {
     169              :     data_ = std::move(rhs.data());
     170              :     return *this;
     171              :   }
     172              : 
     173            0 :   SpinWeighted& operator=(const T& rhs) {
     174              :     data_ = rhs;
     175              :     return *this;
     176              :   }
     177            0 :   SpinWeighted& operator=(T&& rhs) {
     178              :     data_ = std::move(rhs);
     179              :     return *this;
     180              :   }
     181              : 
     182              :   template <typename Rhs>
     183            0 :   auto& operator+=(const SpinWeighted<Rhs, Spin>& rhs) {
     184              :     data_ += rhs.data();
     185              :     return *this;
     186              :   }
     187              : 
     188            0 :   auto& operator+=(const T& rhs) {
     189              :     data_ += rhs;
     190              :     return *this;
     191              :   }
     192              : 
     193              :   template <typename Rhs>
     194            0 :   auto& operator-=(const SpinWeighted<Rhs, Spin>& rhs) {
     195              :     data_ -= rhs.data();
     196              :     return *this;
     197              :   }
     198              : 
     199            0 :   auto& operator-=(const T& rhs) {
     200              :     data_ -= rhs;
     201              :     return *this;
     202              :   }
     203              : 
     204            0 :   T& data() { return data_; }
     205            0 :   const T& data() const { return data_; }
     206              : 
     207            0 :   size_t size() const { return data_.size(); }
     208              : 
     209              :   /// Serialization for Charm++
     210              :   // NOLINTNEXTLINE(google-runtime-references)
     211            1 :   void pup(PUP::er& p);
     212              : 
     213              :  private:
     214            0 :   T data_;
     215              : };
     216              : /// @}
     217              : 
     218              : template <typename T, int Spin>
     219              : void SpinWeighted<T, Spin, true>::pup(PUP::er& p) {
     220              :   p | data_;
     221              : }
     222              : 
     223              : template <typename T, int Spin>
     224              : void SpinWeighted<T, Spin, false>::pup(PUP::er& p) {
     225              :   p | data_;
     226              : }
     227              : 
     228              : /// @{
     229              : /// \ingroup TypeTraitsGroup
     230              : /// \ingroup DataStructuresGroup
     231              : /// This is a `std::true_type` if the provided type is a `SpinWeighted` of any
     232              : /// type and spin, otherwise is a `std::false_type`.
     233              : template <typename T>
     234            1 : struct is_any_spin_weighted : std::false_type {};
     235              : 
     236              : template <typename T, int S>
     237            0 : struct is_any_spin_weighted<SpinWeighted<T, S>> : std::true_type {};
     238              : /// @}
     239              : 
     240              : template <typename T>
     241            0 : constexpr bool is_any_spin_weighted_v = is_any_spin_weighted<T>::value;
     242              : 
     243              : /// @{
     244              : /// \ingroup TypeTraitsGroup
     245              : /// \ingroup DataStructuresGroup
     246              : /// This is a `std::true_type` if the provided type `T` is a `SpinWeighted` of
     247              : /// `InternalType` and any spin, otherwise is a `std::false_type`.
     248              : template <typename InternalType, typename T>
     249            1 : struct is_spin_weighted_of : std::false_type {};
     250              : 
     251              : template <typename InternalType, int S>
     252            0 : struct is_spin_weighted_of<InternalType, SpinWeighted<InternalType, S>>
     253              :     : std::true_type {};
     254              : /// @}
     255              : 
     256              : template <typename InternalType, typename T>
     257            0 : constexpr bool is_spin_weighted_of_v =
     258              :     is_spin_weighted_of<InternalType, T>::value;
     259              : 
     260              : /// @{
     261              : /// \ingroup TypeTraitsGroup
     262              : /// \ingroup DataStructuresGroup
     263              : /// This is a `std::true_type` if the provided type `T1` is a `SpinWeighted` and
     264              : /// `T2` is a `SpinWeighted`, and both have the same internal type, but any
     265              : /// combination of spin weights.
     266              : template <typename T1, typename T2>
     267            1 : struct is_spin_weighted_of_same_type : std::false_type {};
     268              : 
     269              : template <typename T, int Spin1, int Spin2>
     270            0 : struct is_spin_weighted_of_same_type<SpinWeighted<T, Spin1>,
     271              :                                      SpinWeighted<T, Spin2>> : std::true_type {
     272              : };
     273              : /// @}
     274              : 
     275              : template <typename T1, typename T2>
     276            0 : constexpr bool is_spin_weighted_of_same_type_v =
     277              :     is_spin_weighted_of_same_type<T1, T2>::value;
     278              : 
     279              : /// @{
     280              : /// \brief Add two spin-weighted quantities if the types are compatible and
     281              : /// spins are the same. Un-weighted quantities are assumed to be spin 0.
     282              : // These overloads are designed to allow SpinWeighted to wrap Blaze expression
     283              : // templates to ensure efficient math operations, necessitating the
     284              : // `decltype(declval<T>() ...` syntax
     285              : template <typename T1, typename T2, int Spin>
     286              : SPECTRE_ALWAYS_INLINE
     287              :     SpinWeighted<decltype(std::declval<T1>() + std::declval<T2>()), Spin>
     288            1 :     operator+(const SpinWeighted<T1, Spin>& lhs,
     289              :               const SpinWeighted<T2, Spin>& rhs) {
     290              :   return {lhs.data() + rhs.data()};
     291              : }
     292              : template <typename T>
     293              : SPECTRE_ALWAYS_INLINE
     294              :     SpinWeighted<decltype(std::declval<T>() + std::declval<T>()), 0>
     295            1 :     operator+(const SpinWeighted<T, 0>& lhs, const T& rhs) {
     296              :   return {lhs.data() + rhs};
     297              : }
     298              : template <typename T>
     299              : SPECTRE_ALWAYS_INLINE SpinWeighted<
     300              :     decltype(std::declval<T>() + std::declval<get_vector_element_type_t<T>>()),
     301              :     0>
     302            1 : operator+(const SpinWeighted<T, 0>& lhs,
     303              :           const get_vector_element_type_t<T>& rhs) {
     304              :   return {lhs.data() + rhs};
     305              : }
     306              : template <typename T>
     307              : SPECTRE_ALWAYS_INLINE
     308              :     SpinWeighted<decltype(std::declval<T>() + std::declval<T>()), 0>
     309            1 :     operator+(const T& lhs, const SpinWeighted<T, 0>& rhs) {
     310              :   return {lhs + rhs.data()};
     311              : }
     312              : template <typename T>
     313              : SPECTRE_ALWAYS_INLINE SpinWeighted<
     314              :     decltype(std::declval<get_vector_element_type_t<T>>() + std::declval<T>()),
     315              :     0>
     316            1 : operator+(const get_vector_element_type_t<T>& lhs,
     317              :           const SpinWeighted<T, 0>& rhs) {
     318              :   return {lhs + rhs.data()};
     319              : }
     320              : /// @}
     321              : 
     322              : /// @{
     323              : /// \brief Subtract two spin-weighted quantities if the types are compatible and
     324              : /// spins are the same. Un-weighted quantities are assumed to be spin 0.
     325              : // These overloads are designed to allow SpinWeighted to wrap Blaze expression
     326              : // templates to ensure efficient math operations, necessitating the
     327              : // `decltype(declval<T>() ...` syntax
     328              : template <typename T1, typename T2, int Spin>
     329              : SPECTRE_ALWAYS_INLINE
     330              :     SpinWeighted<decltype(std::declval<T1>() - std::declval<T2>()), Spin>
     331            1 :     operator-(const SpinWeighted<T1, Spin>& lhs,
     332              :               const SpinWeighted<T2, Spin>& rhs) {
     333              :   return {lhs.data() - rhs.data()};
     334              : }
     335              : template <typename T>
     336              : SPECTRE_ALWAYS_INLINE
     337              :     SpinWeighted<decltype(std::declval<T>() - std::declval<T>()), 0>
     338            1 :     operator-(const SpinWeighted<T, 0>& lhs, const T& rhs) {
     339              :   return {lhs.data() - rhs};
     340              : }
     341              : template <typename T>
     342              : SPECTRE_ALWAYS_INLINE SpinWeighted<
     343              :     decltype(std::declval<T>() - std::declval<get_vector_element_type_t<T>>()),
     344              :     0>
     345            1 : operator-(const SpinWeighted<T, 0>& lhs,
     346              :           const get_vector_element_type_t<T>& rhs) {
     347              :   return {lhs.data() - rhs};
     348              : }
     349              : template <typename T>
     350              : SPECTRE_ALWAYS_INLINE
     351              :     SpinWeighted<decltype(std::declval<T>() - std::declval<T>()), 0>
     352            1 :     operator-(const T& lhs, const SpinWeighted<T, 0>& rhs) {
     353              :   return {lhs - rhs.data()};
     354              : }
     355              : template <typename T>
     356              : SPECTRE_ALWAYS_INLINE SpinWeighted<
     357              :     decltype(std::declval<get_vector_element_type_t<T>>() - std::declval<T>()),
     358              :     0>
     359            1 : operator-(const get_vector_element_type_t<T>& lhs,
     360              :           const SpinWeighted<T, 0>& rhs) {
     361              :   return {lhs - rhs.data()};
     362              : }
     363              : /// @}
     364              : 
     365              : /// Negation operator preserves spin
     366              : template <typename T, int Spin>
     367              : SPECTRE_ALWAYS_INLINE SpinWeighted<decltype(-std::declval<T>()), Spin>
     368            1 : operator-(const SpinWeighted<T, Spin>& operand) {
     369              :   return {-operand.data()};
     370              : }
     371              : 
     372              : /// Unary `+` operator preserves spin
     373              : template <typename T, int Spin>
     374              : SPECTRE_ALWAYS_INLINE SpinWeighted<decltype(+std::declval<T>()), Spin>
     375            1 : operator+(const SpinWeighted<T, Spin>& operand) {
     376              :   return {+operand.data()};
     377              : }
     378              : 
     379              : /// @{
     380              : /// \brief Multiply two spin-weighted quantities if the types are compatible and
     381              : /// add the spins. Un-weighted quantities are assumed to be spin 0.
     382              : // These overloads are designed to allow SpinWeighted to wrap Blaze expression
     383              : // templates to ensure efficient math operations, necessitating the
     384              : // `decltype(declval<T>() ...` syntax
     385              : template <typename T1, typename T2, int Spin1, int Spin2>
     386              : SPECTRE_ALWAYS_INLINE SpinWeighted<
     387              :     decltype(std::declval<T1>() * std::declval<T2>()), Spin1 + Spin2>
     388            1 : operator*(const SpinWeighted<T1, Spin1>& lhs,
     389              :           const SpinWeighted<T2, Spin2>& rhs) {
     390              :   return {lhs.data() * rhs.data()};
     391              : }
     392              : template <typename T, int Spin>
     393              : SPECTRE_ALWAYS_INLINE
     394              :     SpinWeighted<decltype(std::declval<T>() * std::declval<T>()), Spin>
     395            1 :     operator*(const SpinWeighted<T, Spin>& lhs, const T& rhs) {
     396              :   return {lhs.data() * rhs};
     397              : }
     398              : template <typename T, int Spin>
     399              : SPECTRE_ALWAYS_INLINE SpinWeighted<
     400              :     decltype(std::declval<T>() * std::declval<get_vector_element_type_t<T>>()),
     401              :     Spin>
     402            1 : operator*(const SpinWeighted<T, Spin>& lhs,
     403              :           const get_vector_element_type_t<T>& rhs) {
     404              :   return {lhs.data() * rhs};
     405              : }
     406              : template <typename T, int Spin>
     407              : SPECTRE_ALWAYS_INLINE
     408              :     SpinWeighted<decltype(std::declval<T>() * std::declval<T>()), Spin>
     409            1 :     operator*(const T& lhs, const SpinWeighted<T, Spin>& rhs) {
     410              :   return {lhs * rhs.data()};
     411              : }
     412              : template <typename T, int Spin>
     413              : SPECTRE_ALWAYS_INLINE SpinWeighted<
     414              :     decltype(std::declval<get_vector_element_type_t<T>>() * std::declval<T>()),
     415              :     Spin>
     416            1 : operator*(const get_vector_element_type_t<T>& lhs,
     417              :           const SpinWeighted<T, Spin>& rhs) {
     418              :   return {lhs * rhs.data()};
     419              : }
     420              : /// @}
     421              : 
     422              : /// @{
     423              : /// \brief Divide two spin-weighted quantities if the types are compatible and
     424              : /// subtract the spins. Un-weighted quantities are assumed to be spin 0.
     425              : // These overloads are designed to allow SpinWeighted to wrap Blaze expression
     426              : // templates to ensure efficient math operations, necessitating the
     427              : // `decltype(declval<T>() ...` syntax
     428              : template <typename T1, typename T2, int Spin1, int Spin2>
     429              : SPECTRE_ALWAYS_INLINE SpinWeighted<
     430              :     decltype(std::declval<T1>() / std::declval<T2>()), Spin1 - Spin2>
     431            1 : operator/(const SpinWeighted<T1, Spin1>& lhs,
     432              :           const SpinWeighted<T2, Spin2>& rhs) {
     433              :   return {lhs.data() / rhs.data()};
     434              : }
     435              : template <typename T, int Spin>
     436              : SPECTRE_ALWAYS_INLINE
     437              :     SpinWeighted<decltype(std::declval<T>() / std::declval<T>()), Spin>
     438            1 :     operator/(const SpinWeighted<T, Spin>& lhs, const T& rhs) {
     439              :   return {lhs.data() / rhs};
     440              : }
     441              : template <typename T, int Spin>
     442              : SPECTRE_ALWAYS_INLINE SpinWeighted<
     443              :     decltype(std::declval<T>() / std::declval<get_vector_element_type_t<T>>()),
     444              :     Spin>
     445            1 : operator/(const SpinWeighted<T, Spin>& lhs,
     446              :           const get_vector_element_type_t<T>& rhs) {
     447              :   return {lhs.data() / rhs};
     448              : }
     449              : template <typename T, int Spin>
     450              : SPECTRE_ALWAYS_INLINE
     451              :     SpinWeighted<decltype(std::declval<T>() / std::declval<T>()), -Spin>
     452            1 :     operator/(const T& lhs, const SpinWeighted<T, Spin>& rhs) {
     453              :   return {lhs / rhs.data()};
     454              : }
     455              : template <
     456              :     typename T, int Spin,
     457              :     Requires<not std::is_same_v<T, get_vector_element_type_t<T>>> = nullptr>
     458              : SPECTRE_ALWAYS_INLINE SpinWeighted<
     459              :     decltype(std::declval<get_vector_element_type_t<T>>() / std::declval<T>()),
     460              :     -Spin>
     461            1 : operator/(const get_vector_element_type_t<T>& lhs,
     462              :           const SpinWeighted<T, Spin>& rhs) {
     463              :   return {lhs / rhs.data()};
     464              : }
     465              : /// @}
     466              : 
     467              : /// conjugate the spin-weighted quantity, inverting the spin
     468              : template <typename T, int Spin>
     469              : SPECTRE_ALWAYS_INLINE SpinWeighted<decltype(conj(std::declval<T>())), -Spin>
     470            1 : conj(const SpinWeighted<T, Spin>& value) {
     471              :   return {conj(value.data())};
     472              : }
     473              : 
     474              : /// Take the exponential of the spin-weighted quantity; only valid for
     475              : /// spin-weight = 0
     476              : template <typename T>
     477            1 : SPECTRE_ALWAYS_INLINE SpinWeighted<decltype(exp(std::declval<T>())), 0> exp(
     478              :     const SpinWeighted<T, 0>& value) {
     479              :   return {exp(value.data())};
     480              : }
     481              : 
     482              : /// Take the square-root of the spin-weighted quantity; only valid for
     483              : /// spin-weight = 0
     484              : template <typename T, int Spin>
     485            1 : SPECTRE_ALWAYS_INLINE SpinWeighted<decltype(sqrt(std::declval<T>())), 0> sqrt(
     486              :     const SpinWeighted<T, Spin>& value) {
     487              :   return {sqrt(value.data())};
     488              : }
     489              : 
     490              : /// @{
     491              : /// \brief Test equivalence of spin-weighted quantities if the types are
     492              : /// compatible and spins are the same. Un-weighted quantities are assumed to
     493              : /// be spin 0.
     494              : template <typename T1, typename T2, int Spin>
     495            1 : SPECTRE_ALWAYS_INLINE bool operator==(const SpinWeighted<T1, Spin>& lhs,
     496              :                                       const SpinWeighted<T2, Spin>& rhs) {
     497              :   return lhs.data() == rhs.data();
     498              : }
     499              : template <typename T>
     500            1 : SPECTRE_ALWAYS_INLINE bool operator==(const SpinWeighted<T, 0>& lhs,
     501              :                                       const T& rhs) {
     502              :   return lhs.data() == rhs;
     503              : }
     504              : template <typename T>
     505            1 : SPECTRE_ALWAYS_INLINE bool operator==(const T& lhs,
     506              :                                       const SpinWeighted<T, 0>& rhs) {
     507              :   return lhs == rhs.data();
     508              : }
     509              : /// @}
     510              : 
     511              : /// @{
     512              : /// \brief Test inequivalence of spin-weighted quantities if the types are
     513              : /// compatible and spins are the same. Un-weighted quantities are assumed to be
     514              : /// spin 0.
     515              : template <typename T1, typename T2, int Spin>
     516            1 : SPECTRE_ALWAYS_INLINE bool operator!=(const SpinWeighted<T1, Spin>& lhs,
     517              :                                       const SpinWeighted<T2, Spin>& rhs) {
     518              :   return not(lhs == rhs);
     519              : }
     520              : template <typename T>
     521            1 : SPECTRE_ALWAYS_INLINE bool operator!=(const SpinWeighted<T, 0>& lhs,
     522              :                                       const T& rhs) {
     523              :   return not(lhs == rhs);
     524              : }
     525              : template <typename T>
     526            1 : SPECTRE_ALWAYS_INLINE bool operator!=(const T& lhs,
     527              :                                       const SpinWeighted<T, 0>& rhs) {
     528              :   return not(lhs == rhs);
     529              : }
     530              : /// @}
     531              : 
     532              : /// \ingroup DataStructuresGroup
     533              : /// Make the input `view` a `const` view of the const data `spin_weighted`, at
     534              : /// offset `offset` and length `extent`.
     535              : ///
     536              : /// \warning This DOES modify the (const) input `view`. The reason `view` is
     537              : /// taken by const pointer is to try to insist that the object to be a `const`
     538              : /// view is actually const. Of course, there are ways of subverting this
     539              : /// intended functionality and editing the data pointed into by `view` after
     540              : /// this function is called; doing so is highly discouraged and results in
     541              : /// undefined behavior.
     542              : template <typename SpinWeightedType,
     543              :           Requires<is_any_spin_weighted_v<SpinWeightedType> and
     544              :                    is_derived_of_vector_impl_v<
     545              :                        typename SpinWeightedType::value_type>> = nullptr>
     546            1 : void make_const_view(const gsl::not_null<const SpinWeightedType*> view,
     547              :                      const SpinWeightedType& spin_weighted, const size_t offset,
     548              :                      const size_t extent) {
     549              :   const_cast<SpinWeightedType*>(view.get())  // NOLINT
     550              :       ->set_data_ref(const_cast<             // NOLINT
     551              :                          typename SpinWeightedType::value_type::value_type*>(
     552              :                          spin_weighted.data().data()) +  // NOLINT
     553              :                          offset,
     554              :                      extent);
     555              : }
     556              : 
     557              : /// Stream operator simply forwards
     558              : template <typename T, int Spin>
     559            1 : std::ostream& operator<<(std::ostream& os, const SpinWeighted<T, Spin>& d) {
     560              :   return os << d.data();
     561              : }
     562              : 
     563              : namespace MakeWithValueImpls {
     564              : template <int Spin, typename SpinWeightedType>
     565            0 : struct NumberOfPoints<SpinWeighted<SpinWeightedType, Spin>> {
     566              :   static SPECTRE_ALWAYS_INLINE size_t
     567            0 :   apply(const SpinWeighted<SpinWeightedType, Spin>& input) {
     568              :     return number_of_points(input.data());
     569              :   }
     570              : };
     571              : 
     572              : template <int Spin, typename SpinWeightedType>
     573            0 : struct MakeWithSize<SpinWeighted<SpinWeightedType, Spin>> {
     574              :   template <typename ValueType>
     575            0 :   static SPECTRE_ALWAYS_INLINE SpinWeighted<SpinWeightedType, Spin> apply(
     576              :       const size_t size, const ValueType value) {
     577              :     return SpinWeighted<SpinWeightedType, Spin>{
     578              :         make_with_value<SpinWeightedType>(size, value)};
     579              :   }
     580              : };
     581              : }  // namespace MakeWithValueImpls
     582              : 
     583              : template <int Spin, typename SpinWeightedType>
     584            0 : struct SetNumberOfGridPointsImpls::SetNumberOfGridPointsImpl<
     585              :     SpinWeighted<SpinWeightedType, Spin>> {
     586            0 :   static constexpr bool is_trivial =
     587              :       SetNumberOfGridPointsImpl<SpinWeightedType>::is_trivial;
     588            0 :   static SPECTRE_ALWAYS_INLINE void apply(
     589              :       const gsl::not_null<SpinWeighted<SpinWeightedType, Spin>*> result,
     590              :       const size_t size) {
     591              :     set_number_of_grid_points(make_not_null(&result->data()), size);
     592              :   }
     593              : };
        

Generated by: LCOV version 2.0-1