3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 static int qr_companion (double *h, size_t nc, gsl_complex_packed_ptr z);
23 qr_companion (double *h, size_t nc, gsl_complex_packed_ptr zroot)
27 size_t iterations, e, i, j, k, m;
31 double p = 0, q = 0, r = 0;
33 /* FIXME: if p,q,r, are not set to zero then the compiler complains
34 that they ``might be used uninitialized in this
35 function''. Looking at the code this does seem possible, so this
51 for (e = n; e >= 2; e--)
53 double a1 = fabs (FMAT (h, e, e - 1, nc));
54 double a2 = fabs (FMAT (h, e - 1, e - 1, nc));
55 double a3 = fabs (FMAT (h, e, e, nc));
57 if (a1 <= GSL_DBL_EPSILON * (a2 + a3))
61 x = FMAT (h, n, n, nc);
65 GSL_SET_COMPLEX_PACKED (zroot, n-1, x + t, 0); /* one real root */
71 y = FMAT (h, n - 1, n - 1, nc);
72 w = FMAT (h, n - 1, n, nc) * FMAT (h, n, n - 1, nc);
82 if (q > 0) /* two real roots */
88 GSL_SET_COMPLEX_PACKED (zroot, n-1, x - w / y, 0);
89 GSL_SET_COMPLEX_PACKED (zroot, n-2, x + y, 0);
93 GSL_SET_COMPLEX_PACKED (zroot, n-1, x + p, -y);
94 GSL_SET_COMPLEX_PACKED (zroot, n-2, x + p, y);
102 /* No more roots found yet, do another iteration */
104 if (iterations == 60) /* increased from 30 to 60 */
106 /* too many iterations - give up! */
111 if (iterations % 10 == 0 && iterations > 0)
113 /* use an exceptional shift */
117 for (i = 1; i <= n; i++)
119 FMAT (h, i, i, nc) -= x;
122 s = fabs (FMAT (h, n, n - 1, nc)) + fabs (FMAT (h, n - 1, n - 2, nc));
130 for (m = n - 2; m >= e; m--)
134 z = FMAT (h, m, m, nc);
137 p = FMAT (h, m, m + 1, nc) + (r * s - w) / FMAT (h, m + 1, m, nc);
138 q = FMAT (h, m + 1, m + 1, nc) - z - r - s;
139 r = FMAT (h, m + 2, m + 1, nc);
140 s = fabs (p) + fabs (q) + fabs (r);
148 a1 = fabs (FMAT (h, m, m - 1, nc));
149 a2 = fabs (FMAT (h, m - 1, m - 1, nc));
150 a3 = fabs (FMAT (h, m + 1, m + 1, nc));
152 if (a1 * (fabs (q) + fabs (r)) <= GSL_DBL_EPSILON * fabs (p) * (a2 + a3))
156 for (i = m + 2; i <= n; i++)
158 FMAT (h, i, i - 2, nc) = 0;
161 for (i = m + 3; i <= n; i++)
163 FMAT (h, i, i - 3, nc) = 0;
168 for (k = m; k <= n - 1; k++)
170 notlast = (k != n - 1);
174 p = FMAT (h, k, k - 1, nc);
175 q = FMAT (h, k + 1, k - 1, nc);
176 r = notlast ? FMAT (h, k + 2, k - 1, nc) : 0.0;
178 x = fabs (p) + fabs (q) + fabs (r);
181 continue; /* FIXME????? */
188 s = sqrt (p * p + q * q + r * r);
195 FMAT (h, k, k - 1, nc) = -s * x;
199 FMAT (h, k, k - 1, nc) *= -1;
209 /* do row modifications */
211 for (j = k; j <= n; j++)
213 p = FMAT (h, k, j, nc) + q * FMAT (h, k + 1, j, nc);
217 p += r * FMAT (h, k + 2, j, nc);
218 FMAT (h, k + 2, j, nc) -= p * z;
221 FMAT (h, k + 1, j, nc) -= p * y;
222 FMAT (h, k, j, nc) -= p * x;
225 j = (k + 3 < n) ? (k + 3) : n;
227 /* do column modifications */
229 for (i = e; i <= j; i++)
231 p = x * FMAT (h, i, k, nc) + y * FMAT (h, i, k + 1, nc);
235 p += z * FMAT (h, i, k + 2, nc);
236 FMAT (h, i, k + 2, nc) -= p * r;
238 FMAT (h, i, k + 1, nc) -= p * q;
239 FMAT (h, i, k, nc) -= p;