numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
polynomial_calculator.h
Go to the documentation of this file.
1/*
2 * Copyright 2024 MusicScience37 (Kenta Kabashima)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
20#pragma once
21
22#include <cmath>
23#include <cstddef>
24#include <vector>
25
26#include <Eigen/Core>
27
35
36namespace num_collect::rbf {
37
44template <typename Variable, index_type PolynomialDegree>
46
53template <base::concepts::real_scalar Variable, index_type PolynomialDegree>
54 requires(PolynomialDegree >= 0)
56public:
62 void prepare(index_type num_dimensions) {
63 // No operation.
64 (void)num_dimensions;
65 }
66
74 template <base::concepts::dense_matrix_of<Variable> Matrix>
76 const std::vector<Variable>& variables, Matrix& matrix) const {
77 const auto num_variables = static_cast<index_type>(variables.size());
78 NUM_COLLECT_PRECONDITION(num_variables >= PolynomialDegree + 2,
79 "At least (PolynomialDegree + 2) variables must be given.");
80
81 matrix.resize(num_variables, PolynomialDegree + 1);
82 {
83 // degree = 0 (constant)
84 matrix.col(0) = Eigen::MatrixX<Variable>::Constant(
85 num_variables, 1, static_cast<Variable>(1));
86 }
87 for (index_type degree = 1; degree <= PolynomialDegree; ++degree) {
88 for (index_type i = 0; i < num_variables; ++i) {
89 using std::pow;
90 matrix(i, degree) = static_cast<Variable>(
91 pow(variables[static_cast<std::size_t>(i)], degree));
92 }
93 }
94 }
95
103 [[nodiscard]] auto evaluate_polynomial_for_variable(Variable variable,
104 const Eigen::VectorX<Variable>& coeffs) const -> Variable {
105 NUM_COLLECT_PRECONDITION(coeffs.size() == PolynomialDegree + 1,
106 "Size of coefficients must be (PolynomialDegree + 1).");
107
108 // degree = 0 (constant)
109 auto value = coeffs(0);
110
111 for (index_type degree = 1; degree <= PolynomialDegree; ++degree) {
112 using std::pow;
113 value +=
114 coeffs(degree) * static_cast<Variable>(pow(variable, degree));
115 }
116
117 return value;
118 }
119};
120
127template <base::concepts::dense_vector Variable, index_type PolynomialDegree>
128 requires(PolynomialDegree >= 0)
130public:
132 using scalar_type = typename Variable::Scalar;
133
139 void prepare(index_type num_dimensions) {
140 static_assert(
141 PolynomialDegree < 2, "Currently, up to 1 degree is supported.");
142 index_type num_patterns = 1;
143 if constexpr (PolynomialDegree == 1) {
144 num_patterns += num_dimensions;
145 }
146
147 degrees_.resize(num_patterns, num_dimensions);
148 {
149 // degree = 0 (constant)
150 for (index_type d = 0; d < num_dimensions; ++d) {
151 degrees_(0, d) = 0;
152 }
153 }
154 if constexpr (PolynomialDegree >= 1) {
155 // degree = 1
156 degrees_.bottomRows(num_dimensions) =
157 Eigen::MatrixX<index_type>::Identity(
158 num_dimensions, num_dimensions);
159 }
160 }
161
169 template <base::concepts::dense_matrix_of<scalar_type> Matrix>
171 const std::vector<Variable>& variables, Matrix& matrix) const {
172 const auto num_variables = static_cast<index_type>(variables.size());
173 NUM_COLLECT_PRECONDITION(num_variables > 0, "Variables must be given.");
174 const index_type num_dimensions = variables.front().size();
175
176 const index_type num_patterns = degrees_.rows();
177 matrix.resize(num_variables, num_patterns);
178 for (index_type i = 0; i < num_variables; ++i) {
179 const auto& variable = variables[static_cast<std::size_t>(i)];
180 for (index_type p = 0; p < num_patterns; ++p) {
181 auto value = static_cast<scalar_type>(1);
182 for (index_type d = 0; d < num_dimensions; ++d) {
183 if (degrees_(p, d) > 0) {
184 using std::pow;
185 value *= pow(variable(d), degrees_(p, d));
186 }
187 }
188 matrix(i, p) = value;
189 }
190 }
191 }
192
200 [[nodiscard]] auto evaluate_polynomial_for_variable(Variable variable,
201 const Eigen::VectorX<scalar_type>& coeffs) const -> scalar_type {
202 const index_type num_dimensions = variable.size();
203
204 const index_type num_patterns = degrees_.rows();
205 NUM_COLLECT_PRECONDITION(coeffs.size() == num_patterns,
206 "Size of coefficients must be the same as the number of patterns.");
207
208 auto value = static_cast<scalar_type>(0);
209 for (index_type p = 0; p < num_patterns; ++p) {
210 scalar_type current_term = coeffs(p);
211 for (index_type d = 0; d < num_dimensions; ++d) {
212 if (degrees_(p, d) > 0) {
213 using std::pow;
214 current_term *= pow(variable(d), degrees_(p, d));
215 }
216 }
217 value += current_term;
218 }
219
220 return value;
221 }
222
223private:
225 Eigen::Matrix<index_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>
226 degrees_{};
227};
228
229} // namespace num_collect::rbf
auto evaluate_polynomial_for_variable(Variable variable, const Eigen::VectorX< scalar_type > &coeffs) const -> scalar_type
Evaluate a polynomial for a variable.
void prepare(index_type num_dimensions)
Prepare internal parameters.
void compute_polynomial_term_matrix(const std::vector< Variable > &variables, Matrix &matrix) const
Compute a matrix of polynomial terms.
auto evaluate_polynomial_for_variable(Variable variable, const Eigen::VectorX< Variable > &coeffs) const -> Variable
Evaluate a polynomial for a variable.
Class to calculate polynomials used with RBF interpolation.
Definition of dense_matrix_of concept.
Definition of dense_vector concept.
Definition of exceptions.
Definition of index_type type.
Definition of macros for logging.
std::ptrdiff_t index_type
Type of indices in this library.
Definition index_type.h:33
Namespace of RBF interpolation.
Definition of NUM_COLLECT_PRECONDITION macro.
#define NUM_COLLECT_PRECONDITION(CONDITION,...)
Check whether a precondition is satisfied and throw an exception if not.
Definition of real_scalar concept.