00001 #ifndef __polynomial_hpp__
00002 #define __polynomial_hpp__
00003
00004 #include <math.h>
00005
00006 #define RADIX 2.0
00007
00008 #define SIGN(a,b) (((b)>0)?fabs(a):-fabs(a))
00009
00010
00011
00012
00013
00014
00015 inline void balance (float* a, int n) {
00016 int last, j, i;
00017 float s ,r, g, f, c, sqrdx;
00018
00019 sqrdx = RADIX * RADIX;
00020 last = 0;
00021
00022 while(last == 0) {
00023 last = 1;
00024
00025
00026 for(i=0; i<n; i++) {
00027 r = c = 0.0;
00028
00029 for(j=0; j<n; ++j) {
00030 if(j!=i) {
00031 c += fabs(a[(j*n) + i]);
00032 r += fabs(a[(i*n) + j]);
00033 }
00034 }
00035
00036
00037 if(c && r) {
00038 g = r / RADIX;
00039 f = 1.0;
00040 s = c + r;
00041
00042
00043
00044 while(c < g) {
00045 f *= RADIX;
00046 g *= sqrdx;
00047 }
00048
00049 g = r * RADIX;
00050
00051 while(c > g) {
00052 f /= RADIX;
00053 c /= sqrdx;
00054 }
00055
00056 if( ((c + r) / f) < (0.95 + s)) {
00057 last = 0;
00058 g = 1.0 / f;
00059
00060
00061 for(j=0; j<= n; ++j) a[(i*n) + j] *= g;
00062 for(j=0; j<= n; ++j) a[(j*n) + i] *= f;
00063 }
00064 }
00065 }
00066 }
00067 }
00068
00069
00070
00071
00072
00073 void hqr(float* a, int n, float* wr, float* wi) {
00074 int nn, m, l, k, j, its, i, mmin;
00075 float z, y, x, w, v, u, t, s, r, q, p, anorm;
00076
00077
00078
00079 anorm = 0.0;
00080 for(i=0; i<n; ++i) {
00081 for(j=(i>1)?(i-1):0; j<n;++j) {
00082 anorm += fabs(a[(j*n) + i]);
00083 }
00084 }
00085
00086 nn = n-1;
00087
00088
00089 t = 0.0;
00090
00091 while(nn >= 0) {
00092 its = 0;
00093
00094 do {
00095
00096
00097 for(l=nn; l>0; l--) {
00098 s = fabs(a[((l-1)*n) + l-1]) + fabs(a[(l*n) + l]);
00099
00100 if(s == 0) s = anorm;
00101
00102 if((float)(fabs(a[(l*n) + l-1]) + s) == s) {
00103 a[(l*n) + l-1] = 0.0;
00104 break;
00105 }
00106 }
00107
00108 x = a[(nn * n) + nn];
00109
00110
00111 if (l == nn) {
00112 wr[nn] = x + t;
00113 wi[nn] = 0.0;
00114 --nn;
00115 }
00116 else {
00117 y = a[((nn - 1) * n) + nn-1];
00118 w = a[(nn * n) + nn-1] * a[((nn - 1) * n) + nn];
00119
00120
00121 if(l == (nn - 1)) {
00122 p = 0.5 * (y - x);
00123 q = (p * p) + w;
00124 z = sqrt(fabs(q));
00125 x+= t;
00126
00127
00128 if(q >= 0.0) {
00129 z = p + SIGN(z,p);
00130 wr[nn-1] = wr[nn] = x + z;
00131 if(z) wr[nn] = x - (w / z);
00132 wi[nn-1] = wi[nn] = 0.0;
00133 }
00134
00135 else {
00136 wr[nn - 1] = wr[nn] = x + p;
00137 wi[nn - 1] = -z;
00138 wi[nn] = z;
00139 }
00140
00141 nn -= 2;
00142 }
00143
00144 else {
00145 if (its == 30) return;
00146
00147 if ((its == 10) || (its == 20)) {
00148 t += x;
00149 for(i=0; i<=nn; ++i) a[(i * n) + i] -= x;
00150 s = fabs(a[(nn * n) + nn-1]) + fabs(a[((nn-1) * n) + nn-2]);
00151 y = x = 0.75 * s;
00152 w = -0.4375 * s * s;
00153 }
00154
00155 ++its;
00156
00157
00158
00159 for(m=(nn-2); m>=l; m--) {
00160 z = a[(m * n) + m];
00161 r = x - z;
00162 s = y - z;
00163 p = ((r * s) - w) / a[((m + 1) * n) + m] + a[(m * n) + m+1];
00164 q = a[((m + 1) * n) + m+1] - z - r - s;
00165 r = a[((m + 2) * n) + m+1];
00166
00167
00168 s = fabs(p) + fabs(q) + fabs(r);
00169 p /= s;
00170 q /= s;
00171 r /= s;
00172
00173 if(m == 1) break;
00174
00175 u = fabs(a[(m * n) + m-1]) * (fabs(q) + fabs(r));
00176 v = fabs(p) * (fabs(a[((m-1) * n) + m-1]) + fabs(z) +
00177 fabs(a[((m+1) * n) + m+1]));
00178 if((float)(u + v) == v) break;
00179 }
00180
00181 for(i=m+2; i<=nn; ++i) {
00182 a[(i * n) + i-2] = 0.0;
00183 if(i != (m+2)) a[(i * n) + i-3] = 0.0;
00184 }
00185
00186 for(k=m; k<= nn-1; ++k) {
00187
00188 if(k != m) {
00189
00190 p = a[(k * n) + k-1];
00191 q = a[((k+1) * n) + k-1];
00192 r = 0.0;
00193 if(k != (nn-1)) r = a[((k+2) * n) + k-1];
00194
00195 x = fabs(p) + fabs(q) + fabs(r);
00196
00197
00198 if(x != 0.0) {
00199 p /= x;
00200 q /= x;
00201 r /= x;
00202 }
00203 }
00204
00205 s = SIGN(sqrt((p*p) + (q*q) + (r*r)), p);
00206 if(s != 0.0) {
00207 if( k == m) {
00208 if(l != m) a[(k * n) + k-1] = -a[(k * n) + k-1];
00209 }
00210 else {
00211 a[(k * n) + k-1] = - s * x;
00212 }
00213
00214 p += s;
00215 x = p / s;
00216 y = q / s;
00217 z = r / s;
00218 q /= p;
00219 r /= p;
00220
00221
00222 for(j=k; j<=nn; ++j) {
00223 p = a[(k * n) + j] + (q * a[((k+1) * n) + j]);
00224
00225 if(k != (nn-1)) {
00226 p += r * a[((k+2) * n) + j];
00227 a[((k+2) * n) + j] -= p * z;
00228 }
00229
00230 a[((k+1) * n) + j] -= p * y;
00231 a[(k * n) + j] -= p * x;
00232 }
00233
00234 mmin = (nn < (k+3))?nn:(k+3);
00235
00236
00237 for(i=l; i<= mmin; ++i) {
00238 p = (x * a[(i*n) + k]) + (y * a[(i*n) + k+1]);
00239
00240 if(k != (nn-1)) {
00241 p += z * a[(i*n) + k+2];
00242 a[(i*n) + k+2] -= p * r;
00243 }
00244
00245 a[(i*n) + k+1] -= p * q;
00246 a[(i*n) + k] -= p;
00247 }
00248 }
00249 }
00250 }
00251 }
00252 } while(l < (nn - 1));
00253 }
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263 void polynomial(float* a, int n, float* rtr, float* rti) {
00264 int j, k;
00265 float xr, xi;
00266 float *hess;
00267
00268 hess = new float[n * n];
00269
00270
00271 for(k=0; k<n; ++k) {
00272 hess[k] = -a[((n-1-k) * n) + k] / a[n-1];
00273 for(j=1; j<n; ++k) hess[(j*n) + k] = 0.0;
00274 if(k != (n-1)) hess[((k+1) * n) + k] = 1.0;
00275 }
00276
00277 balance(hess, n);
00278
00279 hqr(hess, n, rtr, rti);
00280
00281
00282 for(j=1; j<n; ++j) {
00283 xr = rtr[j];
00284 xi = rti[j];
00285
00286 for(k=j-1; k>=0; --k) {
00287 if(rtr[k] <= xr) break;
00288 rtr[k+1] = rtr[k];
00289 rti[k+1] = rti[k];
00290 }
00291
00292 rtr[k+1] = xr;
00293 rtr[k+1] = xi;
00294 }
00295
00296 delete [] hess;
00297 }
00298
00299 #endif