Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Polynomial.inl
1 /*
2 Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7 
8 Redistributions of source code must retain the above copyright notice, this list of
9 conditions and the following disclaimer. Redistributions in binary form must reproduce
10 the above copyright notice, this list of conditions and the following disclaimer
11 in the documentation and/or other materials provided with the distribution.
12 
13 Neither the name of the Johns Hopkins University nor the names of its contributors
14 may be used to endorse or promote products derived from this software without specific
15 prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
20 SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26 DAMAGE.
27 */
28 
29 #include <float.h>
30 #include <math.h>
31 #include <algorithm>
32 #include "Factor.h"
33 
35 // Polynomial //
37 template<int Degree>
38 Polynomial<Degree>::Polynomial(void){memset(coefficients,0,sizeof(double)*(Degree+1));}
39 template<int Degree>
40 template<int Degree2>
42  memset(coefficients,0,sizeof(double)*(Degree+1));
43  for(int i=0;i<=Degree && i<=Degree2;i++){coefficients[i]=P.coefficients[i];}
44 }
45 
46 
47 template<int Degree>
48 template<int Degree2>
50  int d=Degree<Degree2?Degree:Degree2;
51  memset(coefficients,0,sizeof(double)*(Degree+1));
52  memcpy(coefficients,p.coefficients,sizeof(double)*(d+1));
53  return *this;
54 }
55 
56 template<int Degree>
57 Polynomial<Degree-1> Polynomial<Degree>::derivative(void) const{
58  Polynomial<Degree-1> p;
59  for(int i=0;i<Degree;i++){p.coefficients[i]=coefficients[i+1]*(i+1);}
60  return p;
61 }
62 
63 template<int Degree>
66  p.coefficients[0]=0;
67  for(int i=0;i<=Degree;i++){p.coefficients[i+1]=coefficients[i]/(i+1);}
68  return p;
69 }
70 template<> double Polynomial< 0 >::operator() ( double t ) const { return coefficients[0]; }
71 template<> double Polynomial< 1 >::operator() ( double t ) const { return coefficients[0]+coefficients[1]*t; }
72 template<> double Polynomial< 2 >::operator() ( double t ) const { return coefficients[0]+(coefficients[1]+coefficients[2]*t)*t; }
73 template<int Degree>
74 double Polynomial<Degree>::operator() ( double t ) const{
75  double v=coefficients[Degree];
76  for( int d=Degree-1 ; d>=0 ; d-- ) v = v*t + coefficients[d];
77  return v;
78 }
79 template<int Degree>
80 double Polynomial<Degree>::integral( double tMin , double tMax ) const
81 {
82  double v=0;
83  double t1,t2;
84  t1=tMin;
85  t2=tMax;
86  for(int i=0;i<=Degree;i++){
87  v+=coefficients[i]*(t2-t1)/(i+1);
88  if(t1!=-DBL_MAX && t1!=DBL_MAX){t1*=tMin;}
89  if(t2!=-DBL_MAX && t2!=DBL_MAX){t2*=tMax;}
90  }
91  return v;
92 }
93 template<int Degree>
95  for(int i=0;i<=Degree;i++){if(coefficients[i]!=p.coefficients[i]){return 0;}}
96  return 1;
97 }
98 template<int Degree>
100  for(int i=0;i<=Degree;i++){if(coefficients[i]==p.coefficients[i]){return 0;}}
101  return 1;
102 }
103 template<int Degree>
104 int Polynomial<Degree>::isZero(void) const{
105  for(int i=0;i<=Degree;i++){if(coefficients[i]!=0){return 0;}}
106  return 1;
107 }
108 template<int Degree>
109 void Polynomial<Degree>::setZero(void){memset(coefficients,0,sizeof(double)*(Degree+1));}
110 
111 template<int Degree>
113  for(int i=0;i<=Degree;i++){coefficients[i]+=p.coefficients[i]*s;}
114  return *this;
115 }
116 template<int Degree>
118  for(int i=0;i<=Degree;i++){coefficients[i]+=p.coefficients[i];}
119  return *this;
120 }
121 template<int Degree>
123  for(int i=0;i<=Degree;i++){coefficients[i]-=p.coefficients[i];}
124  return *this;
125 }
126 template<int Degree>
128  Polynomial q;
129  for(int i=0;i<=Degree;i++){q.coefficients[i]=(coefficients[i]+p.coefficients[i]);}
130  return q;
131 }
132 template<int Degree>
134  Polynomial q;
135  for(int i=0;i<=Degree;i++) {q.coefficients[i]=coefficients[i]-p.coefficients[i];}
136  return q;
137 }
138 template<int Degree>
139 void Polynomial<Degree>::Scale(const Polynomial& p,double w,Polynomial& q){
140  for(int i=0;i<=Degree;i++){q.coefficients[i]=p.coefficients[i]*w;}
141 }
142 template<int Degree>
143 void Polynomial<Degree>::AddScaled(const Polynomial& p1,double w1,const Polynomial& p2,double w2,Polynomial& q){
144  for(int i=0;i<=Degree;i++){q.coefficients[i]=p1.coefficients[i]*w1+p2.coefficients[i]*w2;}
145 }
146 template<int Degree>
147 void Polynomial<Degree>::AddScaled(const Polynomial& p1,double w1,const Polynomial& p2,Polynomial& q){
148  for(int i=0;i<=Degree;i++){q.coefficients[i]=p1.coefficients[i]*w1+p2.coefficients[i];}
149 }
150 template<int Degree>
151 void Polynomial<Degree>::AddScaled(const Polynomial& p1,const Polynomial& p2,double w2,Polynomial& q){
152  for(int i=0;i<=Degree;i++){q.coefficients[i]=p1.coefficients[i]+p2.coefficients[i]*w2;}
153 }
154 
155 template<int Degree>
156 void Polynomial<Degree>::Subtract(const Polynomial &p1,const Polynomial& p2,Polynomial& q){
157  for(int i=0;i<=Degree;i++){q.coefficients[i]=p1.coefficients[i]-p2.coefficients[i];}
158 }
159 template<int Degree>
161  out=in;
162  for(int i=0;i<=Degree;i++){out.coefficients[i]=-out.coefficients[i];}
163 }
164 
165 template<int Degree>
167  Polynomial q=*this;
168  for(int i=0;i<=Degree;i++){q.coefficients[i]=-q.coefficients[i];}
169  return q;
170 }
171 template<int Degree>
172 template<int Degree2>
175  for(int i=0;i<=Degree;i++){for(int j=0;j<=Degree2;j++){q.coefficients[i+j]+=coefficients[i]*p.coefficients[j];}}
176  return q;
177 }
178 
179 template<int Degree>
181 {
182  coefficients[0]+=s;
183  return *this;
184 }
185 template<int Degree>
187 {
188  coefficients[0]-=s;
189  return *this;
190 }
191 template<int Degree>
193 {
194  for(int i=0;i<=Degree;i++){coefficients[i]*=s;}
195  return *this;
196 }
197 template<int Degree>
199 {
200  for(int i=0;i<=Degree;i++){coefficients[i]/=s;}
201  return *this;
202 }
203 template<int Degree>
205 {
206  Polynomial<Degree> q=*this;
207  q.coefficients[0]+=s;
208  return q;
209 }
210 template<int Degree>
212 {
213  Polynomial q=*this;
214  q.coefficients[0]-=s;
215  return q;
216 }
217 template<int Degree>
219 {
220  Polynomial q;
221  for(int i=0;i<=Degree;i++){q.coefficients[i]=coefficients[i]*s;}
222  return q;
223 }
224 template<int Degree>
226 {
227  Polynomial q;
228  for( int i=0 ; i<=Degree ; i++ ) q.coefficients[i] = coefficients[i]/s;
229  return q;
230 }
231 template<int Degree>
233 {
234  Polynomial q=*this;
235  double s2=1.0;
236  for(int i=0;i<=Degree;i++){
237  q.coefficients[i]*=s2;
238  s2/=s;
239  }
240  return q;
241 }
242 template<int Degree>
244 {
246  for(int i=0;i<=Degree;i++){
247  double temp=1;
248  for(int j=i;j>=0;j--){
249  q.coefficients[j]+=coefficients[i]*temp;
250  temp*=-t*j;
251  temp/=(i-j+1);
252  }
253  }
254  return q;
255 }
256 template<int Degree>
257 void Polynomial<Degree>::printnl(void) const{
258  for(int j=0;j<=Degree;j++){
259  printf("%6.4f x^%d ",coefficients[j],j);
260  if(j<Degree && coefficients[j+1]>=0){printf("+");}
261  }
262  printf("\n");
263 }
264 template<int Degree>
265 void Polynomial<Degree>::getSolutions(double c,std::vector<double>& roots,double EPS) const
266 {
267  double r[4][2];
268  int rCount=0;
269  roots.clear();
270  switch(Degree){
271  case 1:
272  rCount=Factor(coefficients[1],coefficients[0]-c,r,EPS);
273  break;
274  case 2:
275  rCount=Factor(coefficients[2],coefficients[1],coefficients[0]-c,r,EPS);
276  break;
277  case 3:
278  rCount=Factor(coefficients[3],coefficients[2],coefficients[1],coefficients[0]-c,r,EPS);
279  break;
280 // case 4:
281 // rCount=Factor(coefficients[4],coefficients[3],coefficients[2],coefficients[1],coefficients[0]-c,r,EPS);
282 // break;
283  default:
284  printf("Can't solve polynomial of degree: %d\n",Degree);
285  }
286  for(int i=0;i<rCount;i++){
287  if(fabs(r[i][1])<=EPS){
288  roots.push_back(r[i][0]);
289  }
290  }
291 }
292 template< >
294 {
295  Polynomial p;
296  p.coefficients[0] = 1.;
297  return p;
298 }
299 template<int Degree >
301 {
302  Polynomial p;
303  if( i>0 )
304  {
306  p -= _p;
307  p.coefficients[0] += _p(1);
308  }
309  if( i<Degree )
310  {
312  p += _p;
313  }
314  return p;
315 }