SpECTRE Documentation Coverage Report
Current view: top level - DataStructures - SpinWeighted.hpp Hit Total Coverage
Commit: 1d64892952139ddfbae7cdbdcd87dce73af8d9fe Lines: 39 112 34.8 %
Date: 2025-12-12 21:49:13
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 1.14