DUNE-FUNCTIONS (unstable)

polynomial.hh
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_FUNCTIONS_ANALYTICFUNCTIONS_POLYNOMIAL_HH
4 #define DUNE_FUNCTIONS_ANALYTICFUNCTIONS_POLYNOMIAL_HH
5 
6 #include <cmath>
7 #include <initializer_list>
8 #include <vector>
9 
10 
11 #include <dune/common/hybridutilities.hh>
12 
13 namespace Dune {
14 namespace Functions {
15 
16 namespace Impl {
17 
18  // Compute coefficients of derivative of polynomial.
19  // Overload for std::vector
20  template<class K, class Allocator>
21  auto polynomialDerivativeCoefficients(const std::vector<K, Allocator>& coefficients) {
22  if (coefficients.size()==0)
23  return std::vector<K, Allocator>();
24  std::vector<K, Allocator> dpCoefficients(coefficients.size()-1);
25  for (size_t i=1; i<coefficients.size(); ++i)
26  dpCoefficients[i-1] = coefficients[i]*K(i);
27  return dpCoefficients;
28  }
29 
30  // Compute coefficients of derivative of polynomial.
31  // Overload for std::array
32  template<class K, unsigned long n>
33  auto polynomialDerivativeCoefficients(const std::array<K, n>& coefficients) {
34  if constexpr (n==0)
35  return coefficients;
36  else
37  {
38  std::array<K, n-1> dpCoefficients;
39  for (size_t i=1; i<coefficients.size(); ++i)
40  dpCoefficients[i-1] = coefficients[i]*K(i);
41  return dpCoefficients;
42  }
43  }
44 
45  // Compute coefficients of derivative of polynomial.
46  // Helper function for the std::integer_sequence overload.
47  // With C++20 this can be avoided, because lambda function
48  // can partially specify template arguments which allows
49  // to do the same inline.
50  template<class I, I i0, I... i, class J, J j0, J... j>
51  auto polynomialDerivativeCoefficientsHelper(std::integer_sequence<I, i0, i...>, std::integer_sequence<J, j0, j...>) {
52  return std::integer_sequence<I, i*I(j)...>();
53  }
54 
55  // Compute coefficients of derivative of polynomial.
56  // Overload for std::integer_sequence
57  template<class I, I... i>
58  auto polynomialDerivativeCoefficients(std::integer_sequence<I, i...> coefficients) {
59  if constexpr (sizeof...(i)==0)
60  return coefficients;
61  else
62  return polynomialDerivativeCoefficientsHelper(coefficients, std::make_index_sequence<sizeof...(i)>());
63  }
64 
65  // Compute coefficients of derivative of polynomial.
66  // Overload for std::tuple
67  template<class...T>
68  auto polynomialDerivativeCoefficients(const std::tuple<T...>& coefficients) {
69  if constexpr (sizeof...(T)==0)
70  return coefficients;
71  else
72  {
73  // Notice that std::multiplies<void> has issues with signed types.
74  // E.g., `decltype(-2,2ul)` is `long unsigned int`.
75  // Hence the same is deduced as return type in std::multiplies.
76  // To avoid this, we explicitly pass the exponent `i+1` as signed type.
77  // If the coefficient is signed, both types are now signed and
78  // so is the deduced result type of std::multiplies.
79  auto mult = Dune::Hybrid::hybridFunctor(std::multiplies());
80  return Dune::unpackIntegerSequence([&](auto... i) {
81  return std::tuple(mult(std::get<i+1>(coefficients), std::integral_constant<long signed int, i+1>()) ...);
82  }, std::make_index_sequence<sizeof...(T)-1>());
83  }
84  }
85 
86 } // namespace Impl in Dune::Functions::
87 
88 
89 
116 template<class K, class C=std::vector<K>>
118 {
119  template<class CC>
120  struct IsIntegerSequence : public std::false_type {};
121 
122  template<class I, I... i>
123  struct IsIntegerSequence<std::integer_sequence<I, i...>> : public std::true_type {};
124 
125 public:
126 
128  using Coefficients = C;
129 
131  Polynomial() = default;
132 
142  coefficients_(std::move(coefficients))
143  {}
144 
146  K operator() (const K& x) const
147  {
148  auto y = K(0);
149  auto n = Dune::Hybrid::size(coefficients_);
150  Dune::Hybrid::forEach(Dune::range(n), [&](auto i) {
151  y += Dune::Hybrid::elementAt(coefficients_, i) * std::pow(x, int(i));
152  });
153  return y;
154  }
155 
157  bool operator==(const Polynomial& other) const
158  {
159  if constexpr (IsIntegerSequence<Coefficients>::value)
160  return true;
161  else
162  return coefficients()==other.coefficients();
163  }
164 
174  friend auto derivative(const Polynomial& p)
175  {
176  auto derivativeCoefficients = Impl::polynomialDerivativeCoefficients(p.coefficients());
177  using DerivativeCoefficients = decltype(derivativeCoefficients);
178  return Polynomial<K, DerivativeCoefficients>(std::move(derivativeCoefficients));
179  }
180 
182  const Coefficients& coefficients() const
183  {
184  return coefficients_;
185  }
186 
187 private:
188  Coefficients coefficients_;
189 };
190 
191 
192 
193 template<class K>
194 Polynomial(std::vector<K>) -> Polynomial<K, std::vector<K>>;
195 
196 template<class K, unsigned long n>
197 Polynomial(std::array<K,n>) -> Polynomial<K, std::array<K,n>>;
198 
199 template<class K, K... ci>
200 Polynomial(std::integer_sequence<K, ci...>) -> Polynomial<K, std::integer_sequence<K,ci...>>;
201 
202 template<class K>
203 Polynomial(std::initializer_list<K>) -> Polynomial<K, std::vector<K>>;
204 
205 
206 
219 template<class K, class Coefficients>
220 auto makePolynomial(Coefficients coefficients)
221 {
222  return Polynomial<K, Coefficients>(std::move(coefficients));
223 }
224 
234 template<class K, class C>
235 auto makePolynomial(std::initializer_list<C> coefficients)
236 {
237  return Polynomial<K>(std::move(coefficients));
238 }
239 
240 
241 
242 
243 
244 }} // namespace Dune::Functions
245 
246 
247 
248 #endif // DUNE_FUNCTIONS_ANALYTICFUNCTIONS_POLYNOMIAL_HH
A univariate polynomial implementation.
Definition: polynomial.hh:118
const Coefficients & coefficients() const
Obtain reference to coefficient vector.
Definition: polynomial.hh:182
Polynomial()=default
Default constructor.
K operator()(const K &x) const
Evaluate polynomial.
Definition: polynomial.hh:146
C Coefficients
The type of the stored coefficient container.
Definition: polynomial.hh:128
Polynomial(Coefficients coefficients)
Create from container of coefficients.
Definition: polynomial.hh:141
bool operator==(const Polynomial &other) const
Comparison of coefficients.
Definition: polynomial.hh:157
friend auto derivative(const Polynomial &p)
Obtain derivative of Polynomial function.
Definition: polynomial.hh:174
Definition: polynomial.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 13, 22:30, 2024)