00001 #ifndef POLYZERO_H
00002 #define POLYZERO_H
00003
00037 #include "polynomial.h"
00038
00072 template <class T, class U, class V>
00073 bool newtonZero(const Polynomial<T>& p, U& z, U& pz, V& mpz, bool adaptive = false) {
00074 const int MAX_RATIO = 6;
00075 U ppz, z1, z2, dz, y, y1, y2;
00076 V my, my1, my2;
00077 int i, j = 0, m = p.degree();
00078
00079 if (m < 1)
00080 return false;
00081
00082 if (adaptive) {
00083 z1 = z;
00084 do {
00085 ++j;
00086 y = evalAndDerive(p, z1, ppz);
00087 my = abs(pz);
00088 if (ppz == U(0))
00089 break;
00090 z = z1;
00091 pz = y;
00092 mpz = my;
00093 dz = pz / ppz;
00094
00095 z1 = z - dz;
00096 ++j;
00097 y1 = eval(p, z1);
00098 my1 = abs(y1);
00099
00100 z2 = z1 - dz;
00101 ++j;
00102 y2 = eval(p, z2);
00103 my2 = abs(y2);
00104
00105 i = 3;
00106 while(my2 < my1 && i++ < MAX_RATIO) {
00107 z1 = z2;
00108 y1 = y2;
00109 my1 = my2;
00110 z2 = z2 - dz;
00111 ++j;
00112 y2 = eval(p, z2);
00113 my2 = abs(y2);
00114 }
00115 if (_isnan(my1))
00116 break;
00117 } while (my1 < my);
00118 }
00119 else {
00120 ++j;
00121 y = evalAndDerive(p, z, ppz);
00122 my = abs(y);
00123 z1 = z;
00124 do {
00125 z = z1;
00126 pz = y;
00127 mpz = my;
00128 if (ppz == U(0))
00129 break;
00130 z1 -= pz / ppz;
00131 if (z1 == z)
00132 break;
00133 ++j;
00134 y = evalAndDerive(p, z1, ppz);
00135 my = abs(y);
00136 if (_isnan(my))
00137 break;
00138 } while(my < mpz);
00139 }
00140
00141 return true;
00142 }
00143
00167 template<class T>
00168 int removeNullZeros(Polynomial<T>& p) {
00169 int i, m = p.degree();
00170 for (i = 0; i < m && p[i] == T(0); ++i)
00171 ;
00172 p.shift(-i);
00173 return i;
00174 }
00175
00232 template<class T>
00233 T cauchyLowerBound(const Polynomial<T>& p, const T& upperBound = T(0)) {
00234 static FloatSpecs<T> fpSpecs;
00235 T x, y, my;
00236 if (upperBound <= 0) {
00237 x = zerosGeometricMean(p);
00238 if (p[1] != 0)
00239 x = std::min(x, -p[0] / p[1]);
00240 }
00241 else
00242 x = upperBound;
00243
00244 newtonZero(p, x, y, my);
00245 return x;
00246 }
00247
00265 template<class T>
00266 T cauchyUpperBound(const Polynomial<T>& p) {
00267 int m = p.degree();
00268 T x = abs(p[0]);
00269 for (int i = 1; i <= m; ++i)
00270 x = std::max(x, abs(p[i]));
00271 return x + T(1);
00272 }
00273
00292 template<class T>
00293 T zerosGeometricMean(const Polynomial<T>& p) {
00294 const T SMALL = T(1.e-3);
00295 T m = Float(p.degree());
00296 return exp(log(abs(p[0]) - log(abs(p[p.degree()])))/m + SMALL);
00297 }
00298
00305 template<class T>
00306 T zerosGeometricMean(const Polynomial< std::complex <T> >& p) {
00307 const T SMALL = T(1.e-3);
00308 T m = Float(p.degree());
00309 return exp(log(abs(p[0]) - log(abs(p[p.degree()])))/m + SMALL);
00310 }
00311
00327 template<class T>
00328 inline void sortZeros(std::vector<std::complex<T> >& zeros) {
00329 class local {
00330 public:
00331 static inline bool zeroSortPred(const std::complex<T>& z1, const std::complex<T>& z2) {
00332 return z1.real() < z2.real();
00333 }
00334 };
00335 std::sort(zeros.begin(), zeros.end(), local::zeroSortPred);
00336 }
00337
00349 template <class T>
00350 inline T solveDegree1(const T& a, const T& b) {
00351 return -b / a;
00352 }
00353
00382 template <class T, class U>
00383 void solveDegree2(const T& a, const T& b, const T& c, U& z1, U& z2) {
00384 U sq, sum, dif, q;
00385 sq = sqrt(U((b * b) - (Float(4) * a * c)));
00386 sum = b + sq;
00387 dif = sq - b;
00388 if (abs(dif) > abs(sum))
00389 q = dif;
00390 else
00391 q = -sum;
00392
00393 z1 = (c + c) / q;
00394 z2 = q / (a + a);
00395
00396 if (z1 > z2)
00397 std::swap(z1, z2);
00398 }
00400 #endif // POLYZERO_H