sablib
Loading...
Searching...
No Matches
polyfit.h
Go to the documentation of this file.
1
6
7#ifndef __SABLIB_POLYFIT_H__
8#define __SABLIB_POLYFIT_H__
9
10#include <stdexcept>
11#include <Eigen/Eigen>
12
13namespace sablib {
14
23template <typename Derived>
24const Eigen::MatrixX<typename Derived::PlainObject::Scalar>
25Vandermonde(const Eigen::MatrixBase<Derived> & x, const unsigned int polyorder)
26{
27 // Although parameters are received as MatrixBase<Derived>, only vector classes are allowed.
28 // Others will be rejected at compile time.
29 static_assert(Derived::IsVectorAtCompileTime, "Error: x is not vector.");
30
31 if(x.size() == 0) {
32 throw std::invalid_argument("Vandermonde(): the length of x is zero.");
33 }
34
35 if(polyorder == 0) {
36 throw std::invalid_argument("Vandermonde(): polyorder is zero.");
37 }
38
39 using Scalar = typename Derived::PlainObject::Scalar;
40 unsigned int n = x.size();
41 unsigned int m = polyorder + 1;
42 Eigen::MatrixX<Scalar> V(n, m);
43
44 for(unsigned int i = 0; i < n; ++i) {
45 Scalar val = 1.0;
46
47 for(unsigned int j = 0; j < m; ++j) {
48 V(i, j) = val;
49 val *= x(i);
50 }
51 }
52
53 return V;
54}
55
64template <typename Derived>
65const typename Derived::PlainObject
67 const Eigen::MatrixX<typename Derived::PlainObject::Scalar> & V,
68 const Eigen::MatrixBase<Derived> & y
69)
70{
71 // Although parameters are received as MatrixBase<Derived>, only vector classes are allowed.
72 // Others will be rejected at compile time.
73 static_assert(Derived::IsVectorAtCompileTime, "Error: y is not vector.");
74
75 if(V.rows() != y.size()) {
76 throw std::invalid_argument("PolyFit(): the sizes of y and V do not match.");
77 }
78
79 return (V.transpose() * V).ldlt().solve(V.transpose() * y);
80}
81
93template <typename Derived>
94const typename Derived::PlainObject
95PolyFit(const Eigen::MatrixBase<Derived> & x, const Eigen::MatrixBase<Derived> & y, const unsigned int polyorder)
96{
97 // Although parameters are received as MatrixBase<Derived>, only vector classes are allowed.
98 // Others will be rejected at compile time.
99 static_assert(Derived::IsVectorAtCompileTime, "Error: x or y is not vector.");
100
101 if(x.size() != y.size()) {
102 throw std::invalid_argument("PolyFit(): x and y must have the same size.");
103 }
104
105 if(polyorder + 1 > x.size()) {
106 throw std::invalid_argument("PolyFit(): polyorder is too high for the number of points.");
107 }
108
109 return PolyFit(Vandermonde(x, polyorder), y);
110}
111
120template <typename Derived>
121const typename Derived::PlainObject
123 const Eigen::MatrixBase<Derived> & coeff,
124 const Eigen::MatrixX<typename Derived::PlainObject::Scalar> & V
125)
126{
127 // Although parameters are received as MatrixBase<Derived>, only vector classes are allowed.
128 // Others will be rejected at compile time.
129 static_assert(Derived::IsVectorAtCompileTime, "Error: coeff is not vector.");
130
131 if(coeff.size() == 0) {
132 throw std::invalid_argument("PolyVal(): the length of coeff is zero.");
133 }
134
135 if(V.cols() != coeff.size()) {
136 throw std::invalid_argument("PolyVal(): the sizes of V and coeff do not match.");
137 }
138
139 return V * coeff;
140}
141
149template <typename Derived>
150const typename Derived::PlainObject
151PolyVal(const Eigen::MatrixBase<Derived> & coeff, const Eigen::MatrixBase<Derived> & x)
152{
153 // Although parameters are received as MatrixBase<Derived>, only vector classes are allowed.
154 // Others will be rejected at compile time.
155 static_assert(Derived::IsVectorAtCompileTime, "Error: coeff or x is not vector.");
156
157 return PolyVal(coeff, Vandermonde(x, coeff.size() - 1));
158}
159
168template <typename Derived>
169const typename Derived::PlainObject::Scalar
170PolyVal(const Eigen::MatrixBase<Derived> & coeff, const typename Derived::PlainObject::Scalar x)
171{
172 // Although parameters are received as MatrixBase<Derived>, only vector classes are allowed.
173 // Others will be rejected at compile time.
174 static_assert(Derived::IsVectorAtCompileTime, "Error: coeff is not vector.");
175
176 if(coeff.size() == 0) {
177 throw std::invalid_argument("PolyVal(): the length of coeff is zero.");
178 }
179
180 typename Derived::PlainObject::Scalar val = 0, xx = 1.0;
181
182 for(int i = 0; i < coeff.size(); i++) {
183 val += coeff(i) * xx;
184 xx *= x;
185 }
186
187 return val;
188}
189
190}; // namespace sablib
191
192#endif // __SABLIB_POLYFIT_H__
const Derived::PlainObject PolyFit(const Eigen::MatrixX< typename Derived::PlainObject::Scalar > &V, const Eigen::MatrixBase< Derived > &y)
Solves the polynomial least squares fitting problem using a pre-calculated Vandermonde matrix.
Definition polyfit.h:66
const Derived::PlainObject PolyVal(const Eigen::MatrixBase< Derived > &coeff, const Eigen::MatrixX< typename Derived::PlainObject::Scalar > &V)
Evaluates the polynomial at specified points using a pre-calculated Vandermonde matrix.
Definition polyfit.h:122
const Eigen::MatrixX< typename Derived::PlainObject::Scalar > Vandermonde(const Eigen::MatrixBase< Derived > &x, const unsigned int polyorder)
Generates a Vandermonde matrix for a given vector and polynomial order.
Definition polyfit.h:25