00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "Polynomial.h"
00034
00035 Polynomial::Polynomial()
00036 {
00037 initialize();
00038 }
00039
00040 Polynomial::Polynomial(Array1D<double> & coeffs)
00041 {
00042 initialize();
00043 initialize(coeffs);
00044 }
00045
00046 void Polynomial::operator=(Polynomial rhs)
00047 {
00048 initialize();
00049 initialize(rhs.coefficients);
00050 }
00051
00052 void Polynomial::initialize()
00053 {
00054 evaluatedF = false;
00055 evaluatedDF = false;
00056 evaluatedD2F = false;
00057
00058
00059 f = 1234.5;
00060 df = 2345.6;
00061 d2f = 3456.7;
00062 x = 4567.8;
00063 }
00064
00065 void Polynomial::initialize(Array1D<double> & coeffs)
00066 {
00067
00068 coefficients = coeffs;
00069
00070
00071 firstDerivativeCoefficients.allocate(coefficients.dim1()-1);
00072
00073 for(int i=0; i<firstDerivativeCoefficients.dim1(); i++)
00074 {
00075 firstDerivativeCoefficients(i) = (i+1)*coefficients(i+1);
00076 }
00077
00078
00079 secondDerivativeCoefficients.allocate(coefficients.dim1()-2);
00080
00081 for(int i=0; i<secondDerivativeCoefficients.dim1(); i++)
00082 {
00083 secondDerivativeCoefficients(i) = (i+2)*(i+1)*coefficients(i+2);
00084 }
00085
00086
00087 thirdDerivativeCoefficients.allocate(coefficients.dim1()-3);
00088
00089 for(int i=0; i<thirdDerivativeCoefficients.dim1(); i++)
00090 {
00091 thirdDerivativeCoefficients(i) = (i+3)*(i+2)*(i+1)*coefficients(i+3);
00092 }
00093 }
00094
00095 void Polynomial::evaluate(double x)
00096 {
00097 this->x = x;
00098 evaluatedF = false;
00099 evaluatedDF = false;
00100 evaluatedD2F = false;
00101 }
00102
00103 double Polynomial::evaluate(double x, Array1D<double> &coeffs)
00104 {
00105 this->x = x;
00106 int n = coeffs.dim1()-1;
00107
00108 if( n < 0 )
00109 {
00110 return 0;
00111 }
00112
00113 double val = coeffs(n);
00114 for(int i=n-1; i >= 0; i--)
00115 {
00116 val = val*x + coeffs(i);
00117 }
00118
00119 return val;
00120 }
00121
00122 void Polynomial::evaluateAll(double x, Array1D<double> & coeffs)
00123 {
00124 this->x = x;
00125
00126 evaluatedF = true;
00127 evaluatedDF = true;
00128 evaluatedD2F = true;
00129
00130 int n = coeffs.dim1()-1;
00131
00132 if( n < 0 ) return;
00133
00134 f = coeffs(n);
00135 df = 0.0;
00136 d2f = 0.0;
00137 for(int i=n-1; i >= 0; i--)
00138 {
00139 d2f = d2f*x + df;
00140 df = df*x + f;
00141 f = f*x + coeffs(i);
00142 }
00143 d2f *= 2;
00144 }
00145
00146 double Polynomial::getFunctionValue()
00147 {
00148 if( evaluatedF ) return f;
00149
00150 evaluateAll(x,coefficients);
00151
00152
00153
00154 return f;
00155 }
00156
00157 double Polynomial::getFunctionValue(double x)
00158 {
00159 return evaluate(x,coefficients);
00160 }
00161
00162 double Polynomial::get_p_a(int ai)
00163 {
00164 return pow(x,ai);
00165 }
00166
00167 double Polynomial::getFirstDerivativeValue()
00168 {
00169 if( evaluatedDF ) return df;
00170
00171 evaluateAll(x,coefficients);
00172
00173
00174
00175 return df;
00176 }
00177
00178 double Polynomial::get_p2_xa(int ai)
00179 {
00180
00181 return ai * pow(x,ai-1);
00182 }
00183
00184 double Polynomial::getSecondDerivativeValue()
00185 {
00186 if( evaluatedD2F ) return d2f;
00187
00188 evaluateAll(x,coefficients);
00189
00190
00191
00192 return d2f;
00193 }
00194
00195 double Polynomial::getThirdDerivativeValue()
00196 {
00197 d3f = evaluate(x,thirdDerivativeCoefficients);
00198
00199 return d3f;
00200 }
00201
00202 double Polynomial::get_p3_xxa(int ai)
00203 {
00204 return (ai-1) * ai * pow(x,ai-2);
00205 }
00206
00207 int Polynomial::getNumberCoefficients()
00208 {
00209 return coefficients.dim1();
00210 }
00211
00212 double Polynomial::getCoefficient(int i)
00213 {
00214 return coefficients(i);
00215 }
00216
00217 Array1D<double> Polynomial::getCoefficients()
00218 {
00219 return coefficients;
00220 }
00221
00222 void Polynomial::print(ostream & strm)
00223 {
00224 strm.unsetf(ios::fixed);
00225 strm.unsetf(ios::scientific);
00226 for(int i=0; i<coefficients.dim1(); i++)
00227 {
00228 if(fabs(coefficients(i)) < 1e-40) continue;
00229 strm << coefficients(i);
00230 if(i == 1)
00231 strm << " x";
00232 else if(i > 0)
00233 strm << " x^" << i;
00234
00235 if(i < coefficients.dim1() - 1 &&
00236 coefficients(i+1) >= 0)
00237 strm << " +";
00238 else
00239 strm << " ";
00240 }
00241 }
00242
00243 Array1D<Complex> Polynomial::getRoots()
00244 {
00245 int numRoots = coefficients.dim1();
00246
00251 for(int i=coefficients.dim1()-1; i>=0; i--)
00252 if( fabs(coefficients(i)) < 1.0e-50)
00253 numRoots--;
00254 else
00255 break;
00256
00257 Array1D<Complex> complexCoeffs(numRoots);
00258
00259 for(int i=0; i<numRoots; i++)
00260 {
00261 complexCoeffs(i) = coefficients(i);
00262 }
00263
00264 bool polish = true;
00265 bool calcOK = true;
00266
00267 Array1D<Complex> roots = zroots(complexCoeffs, polish, &calcOK);
00268
00269 if( !calcOK )
00270 {
00271 throw Exception("ERROR: Problems during the calculation of Polynomial roots!");
00272 }
00273
00274 return roots;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 #define EPSS 1.0e-14 //1.0e-7 default for float implementation
00287 #define MR 8 //don't change this unless you know how to change frac
00288 #define MT 10
00289 #define MAXIT (MT*MR)
00290
00291 void Polynomial::laguer(Array1D<Complex> &a, int m, Complex &x, int *its,
00292 bool *calcOK)
00293 {
00294 Complex cZero(0.0,0.0);
00295
00296 double abx,abp,abm,err;
00297 Complex dx,x1,b,d,f,g,h,sq,gp,gm,g2;
00298 static double frac[MR+1] = {0.0,0.5,0.25,0.75,0.13,0.38,0.62,0.88,1.0};
00299
00300 *calcOK = *calcOK && true;
00301
00302 for(int iter=1; iter<=MAXIT; iter++)
00303 {
00304 *its = iter;
00305 b = a(m);
00306 err = b.abs();
00307 d = cZero;
00308 f = cZero;
00309 abx = x.abs();
00310
00311 for(int j=m-1;j>=0;j--)
00312 {
00313 f = (x*f)+d;
00314 d = (x*d)+b;
00315 b = (x*b)+a(j);
00316 err = b.abs() + abx*err;
00317 }
00318
00319 err *= EPSS;
00320
00321 if( b.abs() <= err) return;
00322
00323 g = d/b;
00324 g2 = g*g;
00325 h = g2-((f/b)*2.0);
00326 sq = (((h*(double)m)-g2)*(double)(m-1)).squareroot();
00327 gp = g+sq;
00328 gm = g-sq;
00329 abp = gp.abs();
00330 abm = gm.abs();
00331
00332 if (abp < abm) gp=gm;
00333
00334 dx=( (abp>abm?abp:abm) > 0.0 ? (Complex(m,0.0)/gp)
00335 : (Complex(cos((double)iter),sin((double)iter)) * (1+abx)) );
00336
00337 x1 = x-dx;
00338
00339 if (x.real() == x1.real() && x.imaginary() == x1.imaginary()) return;
00340
00341 if (iter % MT) x = x1;
00342 else x = x-(dx*frac[iter/MT]);
00343 }
00344
00345 *calcOK = false;
00346 return;
00347 }
00348
00349 #undef EPSS
00350 #undef MR
00351 #undef MT
00352 #undef MAXIT
00353
00354
00355
00356 #define EPS 2.0e-13 // 2.0e-6 default in float implementation
00357
00358 Array1D<Complex> Polynomial::zroots(Array1D<Complex> & a, bool polish,
00359 bool *calcOK)
00360 {
00361 *calcOK = true;
00362
00363 int m = a.dim1() - 1;
00364
00365 Array1D<Complex> roots(m);
00366
00367 int its;
00368 Complex x,b,c;
00369 Array1D<Complex> ad(m+1);
00370
00371 for(int j=0;j<=m;j++)
00372 {
00373 ad(j) = a(j);
00374 }
00375
00376 for(int j=m;j>=1;j--)
00377 {
00378 x = 0.0;
00379
00380 laguer(ad,j,x,&its,calcOK);
00381
00382 if (fabs(x.imaginary()) <= 2.0*EPS*fabs(x.real()))
00383 {
00384 x = Complex(x.real(),0.0);
00385 }
00386
00387 roots(j-1) = x;
00388 b = ad(j);
00389
00390 for (int jj=j-1;jj>=0;jj--)
00391 {
00392 c = ad(jj);
00393 ad(jj) = b;
00394 b = (x*b)+c;
00395 }
00396 }
00397 if(polish)
00398 {
00399 for(int j=1;j<=m;j++)
00400 {
00401 laguer(a,m,roots(j-1),&its,calcOK);
00402 }
00403 }
00404
00405 for (int j=2;j<=m;j++)
00406 {
00407 x = roots(j-1);
00408
00409 int i;
00410 for (i=j-1;i>=1;i--)
00411 {
00412 if ( roots(i-1).real() <= x.real() ) break;
00413 roots(i) = roots(i-1);
00414 }
00415 roots(i) = x;
00416 }
00417
00418 return roots;
00419 }
00420 #undef EPS
00421
00422
00423
00424
00425