Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
PPolynomial.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 "Factor.h"
30 
32 // StartingPolynomial //
34 template<int Degree>
35 template<int Degree2>
38  if(start>p.start){sp.start=start;}
39  else{sp.start=p.start;}
40  sp.p=this->p*p.p;
41  return sp;
42 }
43 template<int Degree>
46  q.start=start*s;
47  q.p=p.scale(s);
48  return q;
49 }
50 template<int Degree>
53  q.start=start+s;
54  q.p=p.shift(s);
55  return q;
56 }
57 
58 
59 template<int Degree>
61  if(start<sp.start){return 1;}
62  else{return 0;}
63 }
64 template<int Degree>
65 int StartingPolynomial<Degree>::Compare(const void* v1,const void* v2){
66  double d=(static_cast<const StartingPolynomial*>(v1))->start-(static_cast<const StartingPolynomial*>(v2))->start;
67  if (d<0) {return -1;}
68  else if (d>0) {return 1;}
69  else {return 0;}
70 }
71 
73 // PPolynomial //
75 template<int Degree>
77  polyCount=0;
78  polys=NULL;
79 }
80 template<int Degree>
82  polyCount=0;
83  polys=NULL;
84  set(p.polyCount);
85  memcpy(polys,p.polys,sizeof( StartingPolynomial<Degree> )*p.polyCount);
86 }
87 
88 template<int Degree>
90  if(polyCount){free(polys);}
91  polyCount=0;
92  polys=NULL;
93 }
94 template<int Degree>
96  int i,c=0;
97  set(count);
99  for( i=0 ; i<count ; i++ )
100  {
101  if( !c || sps[i].start!=polys[c-1].start ) polys[c++] = sps[i];
102  else{polys[c-1].p+=sps[i].p;}
103  }
104  reset( c );
105 }
106 template <int Degree>
107 int PPolynomial<Degree>::size(void) const{return int(sizeof(StartingPolynomial<Degree>)*polyCount);}
108 
109 template<int Degree>
110 void PPolynomial<Degree>::set( size_t size )
111 {
112  if(polyCount){free(polys);}
113  polyCount=0;
114  polys=NULL;
115  polyCount=size;
116  if(size){
117  polys=static_cast<StartingPolynomial<Degree>*>(malloc(sizeof(StartingPolynomial<Degree>)*size));
118  memset(polys,0,sizeof(StartingPolynomial<Degree>)*size);
119  }
120 }
121 template<int Degree>
122 void PPolynomial<Degree>::reset( size_t newSize )
123 {
124  polyCount=newSize;
125  StartingPolynomial<Degree>* tmp = static_cast<StartingPolynomial<Degree>*>(realloc(polys,sizeof(StartingPolynomial<Degree>)*newSize));
126  if (!tmp)
127  free(polys);
128  polys=tmp;
129 }
130 
131 template<int Degree>
133  set(p.polyCount);
134  memcpy(polys,p.polys,sizeof(StartingPolynomial<Degree>)*p.polyCount);
135  return *this;
136 }
137 
138 template<int Degree>
139 template<int Degree2>
141  set(p.polyCount);
142  for(int i=0;i<int(polyCount);i++){
143  polys[i].start=p.polys[i].start;
144  polys[i].p=p.polys[i].p;
145  }
146  return *this;
147 }
148 
149 template<int Degree>
150 double PPolynomial<Degree>::operator ()( double t ) const
151 {
152  double v=0;
153  for( int i=0 ; i<int(polyCount) && t>polys[i].start ; i++ ) v+=polys[i].p(t);
154  return v;
155 }
156 
157 template<int Degree>
158 double PPolynomial<Degree>::integral( double tMin , double tMax ) const
159 {
160  int m=1;
161  double start,end,s,v=0;
162  start=tMin;
163  end=tMax;
164  if(tMin>tMax){
165  m=-1;
166  start=tMax;
167  end=tMin;
168  }
169  for(int i=0;i<int(polyCount) && polys[i].start<end;i++){
170  if(start<polys[i].start){s=polys[i].start;}
171  else{s=start;}
172  v+=polys[i].p.integral(s,end);
173  }
174  return v*m;
175 }
176 template<int Degree>
177 double PPolynomial<Degree>::Integral(void) const{return integral(polys[0].start,polys[polyCount-1].start);}
178 template<int Degree>
180  PPolynomial q;
181  int i,j;
182  size_t idx=0;
183  q.set(polyCount+p.polyCount);
184  i=j=-1;
185 
186  while(idx<q.polyCount){
187  if (j>=int(p.polyCount)-1) {q.polys[idx]= polys[++i];}
188  else if (i>=int( polyCount)-1) {q.polys[idx]=p.polys[++j];}
189  else if(polys[i+1].start<p.polys[j+1].start){q.polys[idx]= polys[++i];}
190  else {q.polys[idx]=p.polys[++j];}
191  idx++;
192  }
193  return q;
194 }
195 template<int Degree>
197  PPolynomial q;
198  int i,j;
199  size_t idx=0;
200  q.set(polyCount+p.polyCount);
201  i=j=-1;
202 
203  while(idx<q.polyCount){
204  if (j>=int(p.polyCount)-1) {q.polys[idx]= polys[++i];}
205  else if (i>=int( polyCount)-1) {q.polys[idx].start=p.polys[++j].start;q.polys[idx].p=p.polys[j].p*(-1.0);}
206  else if(polys[i+1].start<p.polys[j+1].start){q.polys[idx]= polys[++i];}
207  else {q.polys[idx].start=p.polys[++j].start;q.polys[idx].p=p.polys[j].p*(-1.0);}
208  idx++;
209  }
210  return q;
211 }
212 template<int Degree>
214  int i,j;
215  StartingPolynomial<Degree>* oldPolys=polys;
216  size_t idx=0,cnt=0,oldPolyCount=polyCount;
217  polyCount=0;
218  polys=NULL;
219  set(oldPolyCount+p.polyCount);
220  i=j=-1;
221  while(cnt<polyCount){
222  if (j>=int( p.polyCount)-1) {polys[idx]=oldPolys[++i];}
223  else if (i>=int(oldPolyCount)-1) {polys[idx].start= p.polys[++j].start;polys[idx].p=p.polys[j].p*scale;}
224  else if (oldPolys[i+1].start<p.polys[j+1].start){polys[idx]=oldPolys[++i];}
225  else {polys[idx].start= p.polys[++j].start;polys[idx].p=p.polys[j].p*scale;}
226  if(idx && polys[idx].start==polys[idx-1].start) {polys[idx-1].p+=polys[idx].p;}
227  else{idx++;}
228  cnt++;
229  }
230  free(oldPolys);
231  reset(idx);
232  return *this;
233 }
234 template<int Degree>
235 template<int Degree2>
239  int i,j,spCount=int(polyCount*p.polyCount);
240 
242  for(i=0;i<int(polyCount);i++){
243  for(j=0;j<int(p.polyCount);j++){
244  sp[i*p.polyCount+j]=polys[i]*p.polys[j];
245  }
246  }
247  q.set(sp,spCount);
248  free(sp);
249  return q;
250 }
251 template<int Degree>
252 template<int Degree2>
255  q.set(polyCount);
256  for(int i=0;i<int(polyCount);i++){
257  q.polys[i].start=polys[i].start;
258  q.polys[i].p=polys[i].p*p;
259  }
260  return q;
261 }
262 template<int Degree>
264 {
265  PPolynomial q;
266  q.set(polyCount);
267  for(size_t i=0;i<polyCount;i++){q.polys[i]=polys[i].scale(s);}
268  return q;
269 }
270 template<int Degree>
272 {
273  PPolynomial q;
274  q.set(polyCount);
275  for(size_t i=0;i<polyCount;i++){q.polys[i]=polys[i].shift(s);}
276  return q;
277 }
278 template<int Degree>
279 PPolynomial<Degree-1> PPolynomial<Degree>::derivative(void) const{
280  PPolynomial<Degree-1> q;
281  q.set(polyCount);
282  for(size_t i=0;i<polyCount;i++){
283  q.polys[i].start=polys[i].start;
284  q.polys[i].p=polys[i].p.derivative();
285  }
286  return q;
287 }
288 template<int Degree>
290  int i;
292  q.set(polyCount);
293  for(i=0;i<int(polyCount);i++){
294  q.polys[i].start=polys[i].start;
295  q.polys[i].p=polys[i].p.integral();
296  q.polys[i].p-=q.polys[i].p(q.polys[i].start);
297  }
298  return q;
299 }
300 template<int Degree>
301 PPolynomial<Degree>& PPolynomial<Degree>::operator += ( double s ) {polys[0].p+=s;}
302 template<int Degree>
303 PPolynomial<Degree>& PPolynomial<Degree>::operator -= ( double s ) {polys[0].p-=s;}
304 template<int Degree>
306 {
307  for(int i=0;i<int(polyCount);i++){polys[i].p*=s;}
308  return *this;
309 }
310 template<int Degree>
312 {
313  for(size_t i=0;i<polyCount;i++){polys[i].p/=s;}
314  return *this;
315 }
316 template<int Degree>
318 {
319  PPolynomial q=*this;
320  q+=s;
321  return q;
322 }
323 template<int Degree>
325 {
326  PPolynomial q=*this;
327  q-=s;
328  return q;
329 }
330 template<int Degree>
332 {
333  PPolynomial q=*this;
334  q*=s;
335  return q;
336 }
337 template<int Degree>
339 {
340  PPolynomial q=*this;
341  q/=s;
342  return q;
343 }
344 
345 template<int Degree>
346 void PPolynomial<Degree>::printnl(void) const{
348 
349  if(!polyCount){
351  printf("[-Infinity,Infinity]\n");
352  }
353  else{
354  for(size_t i=0;i<polyCount;i++){
355  printf("[");
356  if (polys[i ].start== DBL_MAX){printf("Infinity,");}
357  else if (polys[i ].start==-DBL_MAX){printf("-Infinity,");}
358  else {printf("%f,",polys[i].start);}
359  if(i+1==polyCount) {printf("Infinity]\t");}
360  else if (polys[i+1].start== DBL_MAX){printf("Infinity]\t");}
361  else if (polys[i+1].start==-DBL_MAX){printf("-Infinity]\t");}
362  else {printf("%f]\t",polys[i+1].start);}
363  p=p+polys[i].p;
364  p.printnl();
365  }
366  }
367  printf("\n");
368 }
369 template< >
371 {
372  PPolynomial q;
373  q.set(2);
374 
375  q.polys[0].start=-radius;
376  q.polys[1].start= radius;
377 
378  q.polys[0].p.coefficients[0]= 1.0;
379  q.polys[1].p.coefficients[0]=-1.0;
380  return q;
381 }
382 template<int Degree >
384 {
385  return PPolynomial< Degree-1 >::BSpline().MovingAverage( radius );
386 }
387 template<int Degree>
389 {
393 
394  sps=static_cast<StartingPolynomial<Degree+1>*>(malloc(sizeof(StartingPolynomial<Degree+1>)*polyCount*2));
395 
396  for(int i=0;i<int(polyCount);i++){
397  sps[2*i ].start=polys[i].start-radius;
398  sps[2*i+1].start=polys[i].start+radius;
399  p=polys[i].p.integral()-polys[i].p.integral()(polys[i].start);
400  sps[2*i ].p=p.shift(-radius);
401  sps[2*i+1].p=p.shift( radius)*-1;
402  }
403  A.set(sps,int(polyCount*2));
404  free(sps);
405  return A*1.0/(2*radius);
406 }
407 template<int Degree>
408 void PPolynomial<Degree>::getSolutions(double c,std::vector<double>& roots,double EPS,double min,double max) const{
410  std::vector<double> tempRoots;
411 
412  p.setZero();
413  for(size_t i=0;i<polyCount;i++){
414  p+=polys[i].p;
415  if(polys[i].start>max){break;}
416  if(i<polyCount-1 && polys[i+1].start<min){continue;}
417  p.getSolutions(c,tempRoots,EPS);
418  for(size_t j=0;j<tempRoots.size();j++){
419  if(tempRoots[j]>polys[i].start && (i+1==polyCount || tempRoots[j]<=polys[i+1].start)){
420  if(tempRoots[j]>min && tempRoots[j]<max){roots.push_back(tempRoots[j]);}
421  }
422  }
423  }
424 }
425 
426 template<int Degree>
427 void PPolynomial<Degree>::write(FILE* fp,int samples,double min,double max) const{
428  fwrite(&samples,sizeof(int),1,fp);
429  for(int i=0;i<samples;i++){
430  double x=min+i*(max-min)/(samples-1);
431  float v=(*this)(x);
432  fwrite(&v,sizeof(float),1,fp);
433  }
434 }