polyzero.h

Go to the documentation of this file.
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     //printf("j:%d, mpz:%le\n", j, mpz);
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 

Generated on Mon Aug 21 21:00:38 2006 for The Polynomials Templates Library by  doxygen 1.4.5