SpECTRE Documentation Coverage Report
Current view: top level - DataStructures - MathWrapper.hpp Hit Total Coverage
Commit: 3c072f0ce967e2e56649d3fa12aa2a0e4fe2a42e Lines: 15 40 37.5 %
Date: 2024-04-23 20:50:18
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 <array>
       7             : #include <complex>
       8             : #include <cstddef>
       9             : #include <type_traits>
      10             : 
      11             : #include "DataStructures/ComplexDataVector.hpp"
      12             : #include "DataStructures/DataVector.hpp"
      13             : #include "Utilities/Gsl.hpp"
      14             : #include "Utilities/TMPL.hpp"
      15             : 
      16             : /// \ingroup DataStructuresGroup
      17             : /// A comma-separated list of valid template arguments to MathWrapper.
      18             : /// Useful for explicit instantiations.
      19             : ///
      20             : /// \snippet Helpers/DataStructures/MathWrapperDetail.cpp MATH_WRAPPER_TYPES_instantiate
      21           1 : #define MATH_WRAPPER_TYPES \
      22             :   double, std::complex<double>, DataVector, ComplexDataVector
      23             : 
      24             : /// \ingroup DataStructuresGroup
      25             : /// Type-erased data for performing math on.
      26             : ///
      27             : /// This class can only be instantiated with possibly const-qualified
      28             : /// types from \ref MATH_WRAPPER_TYPES, which can be assumed to
      29             : /// support the mathematical operations of a linear-algebra vector.
      30             : /// Instances of this class with those template arguments can be
      31             : /// created using overloads of `make_math_wrapper` (passing a `const
      32             : /// T&` for const versions and a `gsl::not_null<T*>` for mutable
      33             : /// versions).  Other data structures (such as `Variables`) can add
      34             : /// additional overloads implemented on top of these basic ones.
      35             : ///
      36             : /// \snippet Test_MathWrapper.cpp MathWrapper
      37             : template <typename T>
      38           1 : class MathWrapper {
      39             :  private:
      40           0 :   using MutableT = std::remove_const_t<T>;
      41             : 
      42             :   static_assert(
      43             :       tmpl::list_contains_v<tmpl::list<MATH_WRAPPER_TYPES>, MutableT>);
      44             : 
      45             :   template <typename U = T,
      46             :             bool IsVector =
      47             :                 not(std::is_same_v<std::decay_t<T>, double> or
      48             :                     std::is_same_v<std::decay_t<T>, std::complex<double>>),
      49             :             bool IsConst = std::is_const_v<T>>
      50           0 :   struct Impl {
      51           0 :     using scalar_type = std::remove_const_t<U>;
      52           0 :     T& data;
      53           0 :     Impl(const gsl::not_null<T*> data_in) : data(*data_in) {}
      54             :   };
      55             : 
      56             :   template <typename U>
      57           0 :   struct Impl<U, true, false> {
      58           0 :     using scalar_type = typename U::value_type;
      59             :     // NOLINTNEXTLINE(spectre-mutable)
      60           0 :     mutable T data;
      61           0 :     Impl(const gsl::not_null<T*> data_in) : data(std::move(*data_in)) {}
      62             :   };
      63             : 
      64             :   template <typename U>
      65           0 :   struct Impl<U, true, true> {
      66           0 :     using scalar_type = typename U::value_type;
      67           0 :     const T data;
      68             :     // Need to invoke the move-from-mutable constructor on DataVector, etc.
      69           0 :     Impl(const gsl::not_null<MutableT*> data_in) : data(std::move(*data_in)) {}
      70             :   };
      71             : 
      72           0 :   explicit MathWrapper(const gsl::not_null<MutableT*> data) : data_(data) {}
      73             : 
      74           0 :   friend MathWrapper<T> make_math_wrapper(
      75             :       tmpl::conditional_t<std::is_const_v<T>, T&, gsl::not_null<T*>>);
      76             : 
      77             :  public:
      78             :   /// The class's template parameter.
      79           1 :   using value_type = T;
      80             :   /// Scalar type for linear-algebra operations.  Either double or
      81             :   /// std::complex<double>.
      82           1 :   using scalar_type = typename Impl<>::scalar_type;
      83             : 
      84           0 :   T& operator*() const { return data_.data; }
      85             : 
      86           0 :   MathWrapper(MathWrapper&&) = default;
      87             : 
      88           0 :   MathWrapper() = delete;
      89           0 :   MathWrapper(const MathWrapper&) = delete;
      90           0 :   MathWrapper& operator=(const MathWrapper&) = delete;
      91           0 :   MathWrapper& operator=(MathWrapper&&) = delete;
      92             : 
      93             :   /// Convert MathWrapper wrapping a mutable value to one wrapping a
      94             :   /// const one.
      95             :   ///
      96             :   /// These methods will fail to compile if called on a MathWrapper
      97             :   /// wrapping a const value.  The `to_const` method is useful because
      98             :   /// C++ fails to resolve the implicit conversion in many cases.
      99             :   /// @{
     100           1 :   operator MathWrapper<const T>() const;
     101             : 
     102           1 :   MathWrapper<const T> to_const() const {
     103             :     return static_cast<MathWrapper<const T>>(*this);
     104             :   }
     105             :   /// @}
     106             : 
     107             :  private:
     108           0 :   Impl<> data_;
     109             : };
     110             : 
     111             : /// \ingroup DataStructuresGroup
     112             : /// A fundamental overload of the MathWrapper construction functions.
     113             : ///
     114             : /// Additional overloads can be implemented in terms of the
     115             : /// fundamental overloads.
     116             : /// @{
     117           1 : inline MathWrapper<double> make_math_wrapper(
     118             :     const gsl::not_null<double*> data) {
     119             :   return MathWrapper<double>(data);
     120             : }
     121             : 
     122           1 : inline MathWrapper<const double> make_math_wrapper(const double& data) {
     123             :   return MathWrapper<const double>(const_cast<double*>(&data));
     124             : }
     125             : 
     126           1 : inline MathWrapper<std::complex<double>> make_math_wrapper(
     127             :     const gsl::not_null<std::complex<double>*> data) {
     128             :   return MathWrapper<std::complex<double>>(data);
     129             : }
     130             : 
     131           1 : inline MathWrapper<const std::complex<double>> make_math_wrapper(
     132             :     const std::complex<double>& data) {
     133             :   return MathWrapper<const std::complex<double>>(
     134             :       const_cast<std::complex<double>*>(&data));
     135             : }
     136             : 
     137           1 : inline MathWrapper<DataVector> make_math_wrapper(
     138             :     const gsl::not_null<DataVector*> data) {
     139             :   DataVector referencing(data->data(), data->size());
     140             :   return MathWrapper<DataVector>(&referencing);
     141             : }
     142             : 
     143           1 : inline MathWrapper<const DataVector> make_math_wrapper(const DataVector& data) {
     144             :   DataVector referencing(const_cast<double*>(data.data()), data.size());
     145             :   return MathWrapper<const DataVector>(&referencing);
     146             : }
     147             : 
     148           1 : inline MathWrapper<ComplexDataVector> make_math_wrapper(
     149             :     const gsl::not_null<ComplexDataVector*> data) {
     150             :   ComplexDataVector referencing(data->data(), data->size());
     151             :   return MathWrapper<ComplexDataVector>(&referencing);
     152             : }
     153             : 
     154           1 : inline MathWrapper<const ComplexDataVector> make_math_wrapper(
     155             :     const ComplexDataVector& data) {
     156             :   ComplexDataVector referencing(const_cast<std::complex<double>*>(data.data()),
     157             :                                 data.size());
     158             :   return MathWrapper<const ComplexDataVector>(&referencing);
     159             : }
     160             : /// @}
     161             : 
     162             : template <typename T>
     163             : MathWrapper<T>::operator MathWrapper<const T>() const {
     164             :   return make_math_wrapper(data_.data);
     165             : }
     166             : 
     167             : template <typename T, size_t N>
     168           0 : auto make_math_wrapper(const gsl::not_null<std::array<T, N>*> array) {
     169             :   DataVector referencing(array->data(), array->size());
     170             :   return make_math_wrapper(&referencing);
     171             : }
     172             : 
     173             : template <typename T, size_t N>
     174           0 : auto make_math_wrapper(const std::array<T, N>& array) {
     175             :   const DataVector referencing(const_cast<double*>(array.data()), array.size());
     176             :   return make_math_wrapper(referencing);
     177             : }
     178             : 
     179             : /// \ingroup DataStructuresGroup
     180             : /// The `value_type` for a MathWrapper wrapping `T`.
     181             : template <typename T>
     182           1 : using math_wrapper_type = typename decltype(make_math_wrapper(
     183             :     std::declval<tmpl::conditional_t<std::is_const_v<T>, const T&,
     184             :                                      gsl::not_null<T*>>>()))::value_type;

Generated by: LCOV version 1.14