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
00163 break;
00164 }
00165 h = (pz + pz) / E;
00166 }
00167 else {
00168
00169
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
00179 break;
00180 }
00181
00182 px = evalAndDeflate(p, x, q, e);
00183 mpx = abs(px);
00184
00185 if (_isnan(mpx)) {
00186
00187 break;
00188 }
00189 else if (mpx <= (mpz + mpz))
00190 conv = 0;
00191 else
00192 ++conv;
00193 if (conv > 5) {
00194
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
00220 break;
00221 }
00222 d2 = (pz - pz1) / h2;
00223 if ((h2 + h1) == Complex(0)) {
00224
00225 break;
00226 }
00227 d = (d2 - d1) / (h2 + h1);
00228 }
00229 }
00230
00231
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
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