SpECTRE Documentation Coverage Report
Current view: top level - Utilities - MakeWithValue.hpp Hit Total Coverage
Commit: 52f20d7d69c179a8fabd675cc9d8c5355c7d621c Lines: 10 17 58.8 %
Date: 2024-04-17 15:32:38
Legend: Lines: hit not hit

          Line data    Source code
       1           1 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : ///\file
       5             : /// Defines make_with_value
       6             : 
       7             : #pragma once
       8             : 
       9             : #include <array>
      10             : #include <complex>
      11             : #include <functional>
      12             : #include <type_traits>
      13             : #include <vector>
      14             : 
      15             : #include "Utilities/Algorithm.hpp"
      16             : #include "Utilities/ErrorHandling/Assert.hpp"
      17             : #include "Utilities/ForceInline.hpp"
      18             : #include "Utilities/MakeArray.hpp"
      19             : #include "Utilities/TaggedTuple.hpp"
      20             : 
      21             : /// \ingroup DataStructuresGroup
      22             : /// Implementations of make_with_value.
      23             : namespace MakeWithValueImpls {
      24             : /// Defines a method for determining the number of points represented
      25             : /// by an object.  This allows the object to appear as the input to
      26             : /// make_with_value.
      27             : ///
      28             : /// The MakeWithValueImpls::number_of_points convenience wrapper is
      29             : /// provided to simplify calling this.
      30             : template <typename T, typename = std::nullptr_t>
      31           1 : struct NumberOfPoints {
      32             :   /// The default implementation will produce a compile-time error.
      33           1 :   [[noreturn]] static SPECTRE_ALWAYS_INLINE size_t apply(const T& /*input*/) {
      34             :     static_assert(typename tmpl::has_type<T, std::false_type>::type{},
      35             :                   "Do not know how to obtain a size from this type.  Either "
      36             :                   "implement NumberOfPoints or specialize MakeWithValueImpl "
      37             :                   "for the type you are trying to create.");
      38             :   }
      39             : };
      40             : 
      41             : /// The number of points represented by an object.
      42             : template <typename T>
      43           1 : size_t number_of_points(const T& input) {
      44             :   return NumberOfPoints<T>::apply(input);
      45             : }
      46             : 
      47             : /// Defines a method for producing an object representing a given
      48             : /// number of points.
      49             : ///
      50             : /// Do not call these functions directly.  Use make_with_value
      51             : /// instead, which can take a size as its first argument.
      52             : template <typename R, typename = std::nullptr_t>
      53           1 : struct MakeWithSize {
      54             :   /// The default implementation will produce a compile-time error.
      55             :   /// In specializations, the \p value parameter need not be a template.
      56             :   template <typename T>
      57           1 :   [[noreturn]] static SPECTRE_ALWAYS_INLINE R apply(const size_t /*size*/,
      58             :                                                     const T& /*value*/) {
      59             :     static_assert(typename tmpl::has_type<R, std::false_type>::type{},
      60             :                   "Do not know how to create a sized object of this type.  "
      61             :                   "Either implement MakeWithSize or specialize "
      62             :                   "MakeWithValueImpl for the type you are trying to create.");
      63             :   }
      64             : };
      65             : 
      66             : template <typename R, typename T, typename = std::nullptr_t>
      67           0 : struct MakeWithValueImpl {
      68             :   /// The default implementation uses \ref number_of_points and MakeWithSize.
      69             :   template <typename ValueType>
      70           1 :   static SPECTRE_ALWAYS_INLINE R apply(const T& input, const ValueType value) {
      71             :     return MakeWithSize<R>::apply(number_of_points(input), value);
      72             :   }
      73             : };
      74             : }  // namespace MakeWithValueImpls
      75             : 
      76             : /// \ingroup DataStructuresGroup
      77             : /// \brief Given an object of type `T`, create an object of type `R` whose
      78             : /// elements are initialized to `value`.
      79             : ///
      80             : /// \details This function is useful in function templates in order to
      81             : /// initialize the return type of a function template with `value` for functions
      82             : /// that can be called either at a single grid-point or to fill a data structure
      83             : /// at the same set of grid-points as the `input`
      84             : 
      85             : /// \tparam ValueType The type of `value`. For most containers, this will be
      86             : /// `double`.
      87             : ///
      88             : /// \see MakeWithValueImpls, set_number_of_grid_points
      89             : template <typename R, typename T, typename ValueType>
      90           1 : SPECTRE_ALWAYS_INLINE std::remove_const_t<R> make_with_value(
      91             :     const T& input, const ValueType& value) {
      92             :   return MakeWithValueImpls::MakeWithValueImpl<std::remove_const_t<R>,
      93             :                                                T>::apply(input, value);
      94             : }
      95             : 
      96             : namespace MakeWithValueImpls {
      97             : template <>
      98           0 : struct NumberOfPoints<size_t> {
      99           0 :   static SPECTRE_ALWAYS_INLINE size_t apply(const size_t& input) {
     100             :     return input;
     101             :   }
     102             : };
     103             : 
     104             : /// \brief Returns a double initialized to `value` (`input` is ignored)
     105             : template <typename T>
     106           1 : struct MakeWithValueImpl<double, T> {
     107           0 :   static SPECTRE_ALWAYS_INLINE double apply(const T& /* input */,
     108             :                                             const double value) {
     109             :     return value;
     110             :   }
     111             : };
     112             : 
     113             : template <typename T>
     114             : struct MakeWithValueImpl<std::complex<double>, T> {
     115             :   static SPECTRE_ALWAYS_INLINE std::complex<double> apply(
     116             :       const T& /* input */, const std::complex<double> value) {
     117             :     return value;
     118             :   }
     119             : };
     120             : 
     121             : /// \brief Makes a `std::array`; each element of the `std::array`
     122             : /// must be `make_with_value`-creatable from a `InputType`.
     123             : template <size_t Size, typename T, typename InputType>
     124             : struct MakeWithValueImpl<std::array<T, Size>, InputType> {
     125             :   template <typename ValueType>
     126             :   static SPECTRE_ALWAYS_INLINE std::array<T, Size> apply(
     127             :       const InputType& input, const ValueType value) {
     128             :     return make_array<Size>(make_with_value<T>(input, value));
     129             :   }
     130             : };
     131             : 
     132             : template <size_t Size, typename T>
     133             : struct NumberOfPoints<std::array<T, Size>> {
     134             :   static SPECTRE_ALWAYS_INLINE size_t apply(const std::array<T, Size>& input) {
     135             :     static_assert(Size > 0);
     136             :     // size_t is interpreted as the number of points in other
     137             :     // contexts, but that doesn't make sense here.
     138             :     static_assert(not std::is_same_v<T, size_t>,
     139             :                   "Cannot get size from non-vector.");
     140             :     const size_t points = number_of_points(input[0]);
     141             :     ASSERT(
     142             :         alg::all_of(input,
     143             :                     [&](const T& t) { return number_of_points(t) == points; }),
     144             :         "Inconsistent number of points in array entries.");
     145             :     return points;
     146             :   }
     147             : };
     148             : 
     149             : template <typename T>
     150             : struct NumberOfPoints<std::vector<T>> {
     151             :   static SPECTRE_ALWAYS_INLINE size_t apply(const std::vector<T>& input) {
     152             :     // size_t is interpreted as the number of points in other
     153             :     // contexts, but that doesn't make sense here.
     154             :     static_assert(not std::is_same_v<T, size_t>,
     155             :                   "Cannot get number_of_points from non-vector.");
     156             :     ASSERT(not input.empty(),
     157             :            "Cannot get number of points from empty std::vector.");
     158             :     const size_t points = number_of_points(input[0]);
     159             :     ASSERT(
     160             :         alg::all_of(input,
     161             :                     [&](const T& t) { return number_of_points(t) == points; }),
     162             :         "Inconsistent number of points in vector entries.");
     163             :     return points;
     164             :   }
     165             : };
     166             : 
     167             : template <typename T>
     168             : struct NumberOfPoints<std::reference_wrapper<T>> {
     169             :   static SPECTRE_ALWAYS_INLINE size_t apply(
     170             :       const std::reference_wrapper<T>& input) {
     171             :     return number_of_points(input.get());
     172             :   }
     173             : };
     174             : 
     175             : /// \brief Makes a `TaggedTuple`; each element of the `TaggedTuple`
     176             : /// must be `make_with_value`-creatable from a `T`.
     177             : template <typename... Tags, typename T>
     178           1 : struct MakeWithValueImpl<tuples::TaggedTuple<Tags...>, T> {
     179             :   template <typename ValueType>
     180           0 :   static SPECTRE_ALWAYS_INLINE tuples::TaggedTuple<Tags...> apply(
     181             :       const T& input, const ValueType value) {
     182             :     return tuples::TaggedTuple<Tags...>(
     183             :         make_with_value<typename Tags::type>(input, value)...);
     184             :   }
     185             : };
     186             : 
     187             : template <typename Tag, typename... Tags>
     188           0 : struct NumberOfPoints<tuples::TaggedTuple<Tag, Tags...>> {
     189           0 :   static SPECTRE_ALWAYS_INLINE size_t apply(
     190             :       const tuples::TaggedTuple<Tag, Tags...>& input) {
     191             :     const size_t points = number_of_points(tuples::get<Tag>(input));
     192             :     ASSERT((... and (number_of_points(tuples::get<Tags>(input)) == points)),
     193             :            "Inconsistent number of points in tuple entries.");
     194             :     return points;
     195             :   }
     196             : };
     197             : }  // namespace MakeWithValueImpls

Generated by: LCOV version 1.14