Eigen-Contrib  5.0.1
 
Loading...
Searching...
No Matches
Stencil.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// SPDX-FileCopyrightText: The Eigen Authors
5// SPDX-License-Identifier: MPL-2.0
6
7#ifndef EIGEN_NUMERICALDIFF_STENCIL_H
8#define EIGEN_NUMERICALDIFF_STENCIL_H
9
10// IWYU pragma: private
11#include "./InternalHeaderCheck.h"
12
13namespace Eigen {
14
52template <int Derivative, typename Scalar, int Size>
53class Stencil {
54 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
55 static_assert(Size >= 0, "Stencil requires a fixed-size point set");
56 static_assert(Derivative >= 0 && Derivative < Size, "Stencil requires at least `Derivative + 1` points");
57
58 public:
59 static constexpr int DerivativeOrder = Derivative;
60 static constexpr int PointCount = Size;
61
64
67 template <typename Derived>
68 explicit constexpr Stencil(const DenseBase<Derived>& points) {
69 static_assert(Derived::IsVectorAtCompileTime, "Stencil requires a 1D dense expression");
70 static_assert(Derived::SizeAtCompileTime == Size, "Stencil requires exactly `Size` points");
71 for (Index i = 0; i < Size; ++i) m_points[i] = points.coeff(i);
72 computeWeights();
73 }
74
78 explicit constexpr Stencil(const Scalar (&points)[Size]) {
79 for (Index i = 0; i < Size; ++i) m_points[i] = points[i];
80 computeWeights();
81 }
82
84 ArrayType weights() const { return Map<const ArrayType>(m_weights); }
85
87 ArrayType points() const { return Map<const ArrayType>(m_points); }
88
92 constexpr const Scalar& weight(Index i) const { return m_weights[i]; }
93
96 constexpr const Scalar& point(Index i) const { return m_points[i]; }
97
98 private:
99 // Fornberg's recursion (1988), in the in-place algorithmic form given by Fornberg (1998).
100 // `delta[nu][m]` is the weight of `points[nu]` in the order-`m` formula built from `points[0..n]`
101 // so far; each column `nu` only ever reads/writes its own entries as `n` grows, so a single working
102 // table can be updated in place.
103 constexpr void computeWeights() {
104 Scalar delta[Size][Derivative + 1]{};
105 delta[0][0] = Scalar(1);
106
107 for (Index n = 1; n < Size; ++n) {
108 const Index mn = numext::mini(n, Index(Derivative));
109 const Scalar c4 = m_points[n];
110 // c1/c2 = product_{j<n-1} ((x_{n-1}-x_j)/(x_n-x_j)) / (x_n-x_{n-1}).
111 // Form the ratio directly to avoid overflow/underflow of the individual products.
112 Scalar ratio(1);
113 for (Index nu = 0; nu < n; ++nu) {
114 const Scalar c3 = m_points[n] - m_points[nu];
115 eigen_assert(!(c3 == Scalar(0)) && "Stencil points must be pairwise distinct");
116 if (nu == n - 1) {
117 ratio /= c3;
118 delta[n][0] = -ratio * (m_points[n - 1] * delta[n - 1][0]);
119 for (Index m = mn; m >= 1; --m)
120 delta[n][m] = ratio * (Scalar(m) * delta[n - 1][m - 1] - m_points[n - 1] * delta[n - 1][m]);
121 } else {
122 ratio *= (m_points[n - 1] - m_points[nu]) / c3;
123 }
124 for (Index m = mn; m >= 1; --m) delta[nu][m] = (c4 * delta[nu][m] - Scalar(m) * delta[nu][m - 1]) / c3;
125 delta[nu][0] = c4 * delta[nu][0] / c3;
126 }
127 }
128
129 for (Index nu = 0; nu < Size; ++nu) m_weights[nu] = delta[nu][Derivative];
130 }
131
132 // NOTE: C arrays instead of `std::array` (through `Eigen::array`) is intentional since
133 // non-`const` `operator[]` is only `constexpr` in C++17, not C++14.
134 Scalar m_points[Size]{};
135 Scalar m_weights[Size]{};
136};
137
138// Redundant out-of-class definitions are required pre-C++17 but deprecated since.
139#if EIGEN_COMP_CXXVER < 17
140template <int Derivative, typename Scalar, int Size>
141constexpr int Stencil<Derivative, Scalar, Size>::DerivativeOrder;
142template <int Derivative, typename Scalar, int Size>
143constexpr int Stencil<Derivative, Scalar, Size>::PointCount;
144#endif
145
150template <int Derivative, typename Derived>
155
159template <int Derivative, typename Scalar, int Size>
163
164} // namespace Eigen
165
166#endif
ArrayType points() const
Definition Stencil.h:87
constexpr const Scalar & weight(Index i) const
Definition Stencil.h:92
Array< Scalar, Size, 1 > ArrayType
Definition Stencil.h:63
ArrayType weights() const
Definition Stencil.h:84
constexpr const Scalar & point(Index i) const
Definition Stencil.h:96
constexpr Stencil< Derivative, typename Derived::Scalar, Derived::SizeAtCompileTime > makeStencil(const DenseBase< Derived > &points)
Definition Stencil.h:151
constexpr Stencil(const Scalar(&points)[Size])
Definition Stencil.h:78
constexpr Stencil< Derivative, Scalar, Size > makeStencil(const Scalar(&points)[Size])
Definition Stencil.h:160
constexpr Stencil(const DenseBase< Derived > &points)
Definition Stencil.h:68
Namespace containing all symbols from the Eigen library.