DUNE PDELab (git)

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
13namespace Dune {
14namespace Functions {
15
16namespace 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
116template<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
125public:
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
183 {
184 return coefficients_;
185 }
186
187private:
188 Coefficients coefficients_;
189};
190
191
192
193template<class K>
194Polynomial(std::vector<K>) -> Polynomial<K, std::vector<K>>;
195
196template<class K, unsigned long n>
197Polynomial(std::array<K,n>) -> Polynomial<K, std::array<K,n>>;
198
199template<class K, K... ci>
200Polynomial(std::integer_sequence<K, ci...>) -> Polynomial<K, std::integer_sequence<K,ci...>>;
201
202template<class K>
203Polynomial(std::initializer_list<K>) -> Polynomial<K, std::vector<K>>;
204
205
206
219template<class K, class Coefficients>
220auto makePolynomial(Coefficients coefficients)
221{
222 return Polynomial<K, Coefficients>(std::move(coefficients));
223}
224
234template<class K, class C>
235auto 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
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
const Coefficients & coefficients() const
Obtain reference to coefficient vector.
Definition: polynomial.hh:182
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
decltype(auto) constexpr unpackIntegerSequence(F &&f, std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition: indices.hh:124
friend auto derivative(const Polynomial &p)
Obtain derivative of Polynomial function.
Definition: polynomial.hh:174
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
constexpr decltype(auto) elementAt(Container &&c, Index &&i)
Get element at given position from container.
Definition: hybridutilities.hh:126
Dune namespace.
Definition: alignedallocator.hh:13
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)