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

Generated by: LCOV version 1.14