muller.h

Go to the documentation of this file.
00001 #ifndef MULLER_H
00002 #define MULLER_H
00003 
00029 #include "polyzero.h"
00030 
00054 template < class T, class U >
00055 int mullerZeros(const Polynomial < T > & P,
00056                 std::vector < std::complex < U > > & zeros,
00057                 bool polish)
00058 {
00059 
00060     typedef U Float;
00061     typedef std::complex < Float > Complex;
00062     typedef Polynomial < Complex > ComplexPolynomial;
00063     typedef Polynomial < Float > FloatPolynomial;
00064 
00065     const bool ADAPTIVE = false;
00066     static FloatSpecs < Float > fpSpecs;
00067     const int MAXIT          = 128;
00068     static const Float SHIFT = acos(Float(-1)) * Float(7 / 180.);
00069     const Float GROW         = Float(1.05);
00070 
00071     Polynomial < T > p = P, f;
00072     ComplexPolynomial q, q2;
00073     FloatPolynomial mp;
00074 
00075     Complex z0, zx, z, z1, z2, pz, pz1, pz2, bestZ, zE, shift;
00076     Complex h, h1, h2, d, d1, d2, ac, sq, b, D, E, x, sm, df, px;
00077     Float e, a = 0, da = 1, r, mpz, mpx, g;
00078     int i, j = 0, conv = 0, n;
00079     bool started;
00080 
00081     zeros.clear();
00082 
00083     modulus(p, mp);
00084     scalePoly(p, mp);
00085     f = p;
00086     i = removeNullZeros(p);
00087     zeros.assign(i, Complex(0));
00088 
00089     while (p.degree() > 0) {
00090 
00091         if (p.degree() == 1) {
00092             z = solveDegree1(p[1], p[0]);
00093             zeros.push_back(z);
00094             break;
00095         }
00096         if (p.degree() == 2) {
00097             solveDegree2(p[2], p[1], p[0], z, z1);
00098             if (polish) {
00099                 newtonZero(P, z, pz, mpz, ADAPTIVE);
00100                 newtonZero(P, z1, pz, mpz, ADAPTIVE);
00101             }
00102             zeros.push_back(z);
00103             zeros.push_back(z1);
00104             break;
00105         }
00106 
00107         modulus(p, mp);
00108         mp[0] = -mp[0];
00109         Float c = cauchyLowerBound(mp, Float(0));
00110         r = c;
00111         g = zerosGeometricMean(p);
00112         g = (g - c) / MAXIT;
00113         for (i = 1; i <= MAXIT; ++i) {
00114 
00115             shift = exp(Complex(0, a));
00116             z2 = Complex(0, -r) * shift;
00117             z1 = 0;
00118             z = (r) * shift;
00119             pz = eval(p, z);
00120             pz1 = eval(p, z1);
00121             pz2 = eval(p, z2);
00122             if (abs(pz2) < abs(pz)) {
00123                 std::swap(pz, pz2);
00124                 std::swap(z, z2);
00125             }
00126 
00127             a += SHIFT;
00128             r += g;
00129 
00130             e = abs(pz) * (1 + fpSpecs.MRE), mpx, mpz;
00131             started = false;
00132 
00133             h1 = z1 - z2;
00134             h2 = z - z1;
00135 
00136             if (h1 == Complex(0) && h2 == Complex(0) || (h1 + h2) == Complex(0))
00137                 continue;
00138             d1 = (pz1 - pz2) / h1;
00139             d2 = (pz - pz1) / h2;
00140             d = (d2 - d1) / (h2 + h1);
00141 
00142             px = pz;
00143             mpx = mpz = abs(pz);
00144 
00145             j = 0;
00146             conv = 0;
00147             while (1) {
00148                 if (++j > 3)
00149                     started = true;
00150 
00151                 if (!started || conv == 0) {
00152                     b = d2 + (h2 * d);
00153                     ac = pz * d;
00154                     ac = ac + ac;
00155                     ac = ac + ac;
00156                     D = sqrt((b * b) - ac);
00157 
00158                     sm = b + D;
00159                     df = b - D;
00160                     E = (abs(df) > abs(sm)) ? df : sm;
00161                     if (E == Complex(0)) {
00162                         //printf("e");
00163                         break;
00164                     }
00165                     h = (pz + pz) / E;
00166                 }
00167                 else {
00168                     //  if we've lost convergence, reduce step by half until we converge again
00169                     //printf("h");
00170                     h = h * Float(.5);
00171                 }
00172 
00173                 x = z - h;
00174 
00175                 if (x == z) {
00176                     if (j == 1)
00177                         evalAndDeflate(p, z, q);
00178                     //printf("a");
00179                     break;
00180                 }
00181 
00182                 px = evalAndDeflate(p, x, q, e);
00183                 mpx = abs(px);
00184 
00185                 if (_isnan(mpx)) {
00186                     //printf("b");
00187                     break;
00188                 }
00189                 else if (mpx <= (mpz + mpz))
00190                     conv = 0;
00191                 else
00192                     ++conv;
00193                 if (conv > 5) {
00194                     //printf("g");
00195                     conv = 0;
00196                     break;
00197                 }
00198 
00199                 if (!started || conv == 0) {
00200                     conv = 0;
00201 
00202                     mpz = mpx;
00203 
00204                     z2 = z1;
00205                     z1 = z;
00206                     z = x;
00207 
00208                     if (mpz < e)
00209                         break;
00210 
00211                     pz2 = pz1;
00212                     pz1 = pz;
00213                     pz = px;
00214 
00215                     h1 = h2;
00216                     d1 = d2;
00217                     h2 = z - z1;
00218                     if (h2 == Complex(0)) {
00219                         //printf("c");
00220                         break;
00221                     }
00222                     d2 = (pz - pz1) / h2;
00223                     if ((h2 + h1) == Complex(0)) {
00224                         //printf("d");
00225                         break;
00226                     }
00227                     d = (d2 - d1) / (h2 + h1);
00228                 }
00229             }
00230 
00231             //printf("j:%d%s", j, (mpz < e) ? "\n" : "f ");
00232             if (mpz < e || mpz == 0) {
00233                 if (sizeof(T) == sizeof(U)) {
00234                     z1 = conj(z);
00235                     pz1 = eval(q, conj(z), e);
00236                     if (abs(pz1) < e) {
00237                         //if (abs(z.imag()) > abs(z.real()) * 20 * fpSpecs.MRE) {
00238                         if (polish) {
00239                             newtonZero(P, z, pz, mpz, ADAPTIVE);
00240                             evalAndDeflate(p, z, q);
00241                         }
00242                         zeros.push_back(z);
00243                         z = conj(z);
00244                         if (polish) {
00245                             newtonZero(P, z, pz, mpz, ADAPTIVE);
00246                         }
00247                         evalAndDeflate(q, z, q2);
00248                         zeros.push_back(z);
00249                         n = q2.degree();
00250                         for (int i = 0; i <= n; ++i)
00251                             * (Float *) & (p[i]) = q2[i].real();
00252                         p.resize(n + 1);
00253                     }
00254                     else {
00255                         if (polish) {
00256                             newtonZero(P, z, pz, mpz, ADAPTIVE);
00257                             evalAndDeflate(p, z, q);
00258                         }
00259                         zeros.push_back(z);
00260                         n = q.degree();
00261                         for (int i = 0; i <= n; ++i)
00262                             * (Float *) & (p[i]) = q[i].real();
00263                         p.resize(n + 1);
00264                     }
00265                     break;
00266                 }
00267                 else {
00268                     if (polish) {
00269                         newtonZero(P, z, pz, mpz, ADAPTIVE);
00270                         evalAndDeflate(p, z, q);
00271                     }
00272                     zeros.push_back(z);
00273                     * (ComplexPolynomial *) & p = q;
00274                     break;
00275                 }
00276             }
00277         }
00278         if (i >= MAXIT)
00279             break;
00280     }
00281     sortZeros(zeros);
00282     return (int)zeros.size();
00283 }
00284 
00285 #endif //MUELLER_H

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