cgv
Loading...
Searching...
No Matches
polynomial.h
1#pragma once
2
3#include <iostream>
4#include <cmath>
5#include <cassert>
6#include <cgv/math/vec.h>
7#include <cgv/math/mat.h>
8#include <cgv/math/functions.h>
9#include <cgv/math/lin_solve.h>
10
11namespace cgv {
12namespace math {
13
23
24template <typename T>
25
26T poly_val(const vec<T>& p, const T& x)
27{
28 assert(p.size() > 0);
29 T y=p(0);
30
31 for(unsigned i = 1; i<p.size(); i++)
32 y= y*x +p(i);
33
34 return y;
35}
36
41template <typename T>
42vec<T> poly_val(const vec<T>& p, const vec<T>& x)
43
44{
45
46 assert(p.size() > 0);
47 vec<T> y(x.size());
48 y.fill(p(0));
49
50 for(unsigned i = 1; i<p.size(); i++)
51 y= x*y + p(i);
52
53 return y;
54
55}
56
58template <typename T>
59vec<T> poly_mult(const vec<T>& u, const vec<T>& v)
60{
61 unsigned s =u.size() + v.size()-1;
62 vec<double> w(s);
63 for(unsigned k = 1; k <= s; k++)
64 {
65 w(k-1) = 0;
66 int j = 0;
67
68 int jmin = (int)k+1-(int)v.size();
69 if(jmin < 1)
70 jmin = 1;
71
72 int jmax = (int)u.size();
73 if (jmax > (int)k)
74 jmax=k;
75
76
77 for(int j = jmin; j <=jmax; j++)
78 w(k-1)+=u(j-1)*v(k-j);
79 }
80 return w;
81}
82
86template <typename T>
87bool poly_div(const vec<T>& f, const vec<T>& g, vec<T>& q, vec<T>& r)
88{
89 if(g.size() > f.size())
90 {
91 q.resize(1);
92 q(0)=0;
93 r=f;
94 return false;
95 }
96 else
97 {
98 vec<T> p = f;
99 //std::cout << p << std::endl;
100 q.resize(f.size()-g.size()+1);
101 for(unsigned j = 0; g.size()+j <=p.size();j++)
102 {
103 q(j) = p(j)/g(0);
104 for(unsigned i = j; i < g.size()+j; i++)
105 {
106 p(i)= p(i)- q(j)*g(i-j);
107 }
108 //std::cout <<p<<std::endl;
109 }
110 unsigned s=g.size();
111 unsigned a=p.size()-g.size();
112 while(p(a) == 0 && s > 0)
113 {
114 a++;s--;
115 }
116
117 if(s == 0)
118 {
119 r.resize(1);
120 r(0)=0;
121 return true;
122 }
123 else
124 {
125 r=p.sub_vec(a,s);
126 return false;
127 }
128 }
129
130
131}
132
133//returns addition of polynomials u and v
134template <typename T>
135vec<T> poly_add(const vec<T>& u, const vec<T>& v)
136{
137 unsigned n = u.size();
138 unsigned m = v.size();
139
140 vec<double> r;
141 if(n >= m)
142 {
143 r.resize(n);
144 unsigned i = 0;
145 unsigned d = n-m;
146 for(;i < d;i++)
147 r(i) = u(i);
148
149 for(;i < n;i++)
150 r(i) = u(i)+v(i-d);
151 }else
152 {
153 r.resize(m);
154 unsigned i = 0;
155 unsigned d = m-n;
156 for(;i < d;i++)
157 r(i) = v(i);
158 for(;i < m;i++)
159 r(i) = v(i)+u(i-d);
160 }
161
162 return r;
163}
164
165//returns subtraction of polynomials u and v
166template <typename T>
167vec<T> poly_sub(const vec<T>& u, const vec<T>& v)
168{
169 unsigned n = u.size();
170 unsigned m = v.size();
171
172 vec<double> r;
173 if(n >= m)
174 {
175 r.resize(n);
176 unsigned i = 0;
177 unsigned d = n-m;
178 for(;i < d;i++)
179 r(i) = u(i);
180
181 for(;i < n;i++)
182 r(i) = u(i)-v(i-d);
183 }else
184 {
185 r.resize(m);
186 unsigned i = 0;
187 unsigned d = m-n;
188 for(;i < d;i++)
189 r(i) = -v(i);
190 for(;i < m;i++)
191 r(i) = u(i-d)-v(i);
192 }
193
194 return r;
195}
196
197
198//analytic derivation of polynomial p
199template <typename T>
200vec<T> poly_der(const vec<T>& p)
201{
202 assert(p.size() > 0);
203 unsigned n = p.size();
204
205 if(n <= 1)
206 {
207 vec<T> q(1);
208 q(0) = 0;
209 return q;
210 }
211 else
212 {
213 unsigned m = n-1;
214 vec<T> q(m);
215 for(unsigned i = 0; i< m; i++)
216 q(i)= p(i)*(m-i);
217 return q;
218 }
219}
220
221//analytic integrate polynomial p using integration constant k
222template <typename T>
223vec<T> poly_int(const vec<T>& p, const T& k=0)
224{
225 assert(p.size() > 0);
226 unsigned m = p.size()+1;
227
228 vec<T> q(m);
229 for(unsigned i = 0; i < m-1; i++)
230 q(i)= p(i)/(m-i-1);
231
232
233 q(m-1)=k;
234 return q;
235}
236
238template <typename T>
239vec<T> bernstein_polynomial(unsigned j, unsigned g)
240{
241 vec<T> p;
242 p.zeros(j+1);
243 p(0)=1.0;// p = t^j
244
245
246 for(unsigned i = 0; i < g-j; i++)
247 p = poly_mult(p, vec<T>(-1.0,1)); //p=p*(1-t)
248
249 return nchoosek(g,j)*p;
250}
251
252
253//returns lagrange basis polynomial
254template <typename T>
255vec<T> lagrange_basis_polynomial(unsigned i, const vec<T>& u)
256{
257 //polynomial p = 1
258 vec<T> p(1);
259 p(0)=1.0;
260
261 unsigned g = u.size()-1;
262
263 for(unsigned j = 0; j <= g; j++)
264 {
265 if(i == j) continue;
266 p = poly_mult(p, vec<T>(1.0,-u(j))) / (u(i)-u(j));
267 }
268 return p;
269}
270
271
272template <typename T>
273vec<T> newton_basis_polynomial(unsigned i, const vec<T>& u)
274{
275 //polynomial p = 1
276 vec<T> p(1);
277 p(0)=1.0;
278
279 unsigned g = u.size()-1;
280
281 for(unsigned j = 0; j <= g; j++)
282 {
283
284 p = poly_mult(p, vec<T>(1.0,-u(j)));
285 }
286 return p;
287}
288
289
290//returns the vandermonde matrix which can be used for fitting
291//polynomials (for large order polynomials use orthogonal basis instead)
292//x = [ 1 2 3 4] -> V(i,j) x(i)^(n-j) V is n x n with n = x.size()
293
294template <typename T>
295mat<T> vander(const vec<T>& x)
296{
297 return vander(x.size()-1,x);
298}
299
300//returns vandermonde matrix
301template <typename T>
302mat<T> vander(unsigned degree,const vec<T>& x)
303{
304 assert(x.size() >= 1);
305 unsigned n = x.size();
306 cgv::math::mat<T> V(n,degree+1);
307
308 for(unsigned i = 0; i < n; i++)
309 {
310 V(i,degree) = (T)1;
311 for(int j = (int)degree-1; j>= 0; j--)
312 V(i,j)=V(i,j+1)*x(i);
313 }
314
315 return V;
316}
317
318//fit a polynomial of degree n into data such that E = sum_i ||p(X(i)) - Y(i)||² is minimized
319//uses vandermonde matrix and svd solver
320//large degrees can be numerically instable keep n < 10
321//otherwise use orthogonal basis for fitting
322template <typename T>
323vec<T> poly_fit(unsigned n,const vec<T>&X, const vec<T>&Y)
324{
325 mat<T> V = cgv::math::vander(n,X);
326 mat<T> A;
327 vec<T> b,p;
328 AtA(V,A);
329 Atx(V,Y,b);
330 svd_solve(A,b,p);
331 return p;
332}
333
334}
335}
A matrix type (full column major storage) The matrix can be loaded directly into OpenGL without need ...
Definition mat.h:208
the cgv namespace
Definition print.h:11