gsl_poly__qr.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /* poly/qr.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
  4. *
  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.
  9. *
  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.
  14. *
  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.
  18. */
  19. static int qr_companion (double *h, size_t nc, gsl_complex_packed_ptr z);
  20. static int
  21. qr_companion (double *h, size_t nc, gsl_complex_packed_ptr zroot)
  22. {
  23. double t = 0.0;
  24. size_t iterations, e, i, j, k, m;
  25. double w, x, y, s, z;
  26. double p = 0, q = 0, r = 0;
  27. /* FIXME: if p,q,r, are not set to zero then the compiler complains
  28. that they ``might be used uninitialized in this
  29. function''. Looking at the code this does seem possible, so this
  30. should be checked. */
  31. int notlast;
  32. size_t n = nc;
  33. next_root:
  34. if (n == 0)
  35. return GSL_SUCCESS ;
  36. iterations = 0;
  37. next_iteration:
  38. for (e = n; e >= 2; e--)
  39. {
  40. double a1 = fabs (FMAT (h, e, e - 1, nc));
  41. double a2 = fabs (FMAT (h, e - 1, e - 1, nc));
  42. double a3 = fabs (FMAT (h, e, e, nc));
  43. if (a1 <= GSL_DBL_EPSILON * (a2 + a3))
  44. break;
  45. }
  46. x = FMAT (h, n, n, nc);
  47. if (e == n)
  48. {
  49. GSL_SET_COMPLEX_PACKED (zroot, n-1, x + t, 0); /* one real root */
  50. n--;
  51. goto next_root;
  52. /*continue;*/
  53. }
  54. y = FMAT (h, n - 1, n - 1, nc);
  55. w = FMAT (h, n - 1, n, nc) * FMAT (h, n, n - 1, nc);
  56. if (e == n - 1)
  57. {
  58. p = (y - x) / 2;
  59. q = p * p + w;
  60. y = sqrt (fabs (q));
  61. x += t;
  62. if (q > 0) /* two real roots */
  63. {
  64. if (p < 0)
  65. y = -y;
  66. y += p;
  67. GSL_SET_COMPLEX_PACKED (zroot, n-1, x - w / y, 0);
  68. GSL_SET_COMPLEX_PACKED (zroot, n-2, x + y, 0);
  69. }
  70. else
  71. {
  72. GSL_SET_COMPLEX_PACKED (zroot, n-1, x + p, -y);
  73. GSL_SET_COMPLEX_PACKED (zroot, n-2, x + p, y);
  74. }
  75. n -= 2;
  76. goto next_root;
  77. /*continue;*/
  78. }
  79. /* No more roots found yet, do another iteration */
  80. if (iterations == 60) /* increased from 30 to 60 */
  81. {
  82. /* too many iterations - give up! */
  83. return GSL_FAILURE ;
  84. }
  85. if (iterations % 10 == 0 && iterations > 0)
  86. {
  87. /* use an exceptional shift */
  88. t += x;
  89. for (i = 1; i <= n; i++)
  90. {
  91. FMAT (h, i, i, nc) -= x;
  92. }
  93. s = fabs (FMAT (h, n, n - 1, nc)) + fabs (FMAT (h, n - 1, n - 2, nc));
  94. y = 0.75 * s;
  95. x = y;
  96. w = -0.4375 * s * s;
  97. }
  98. iterations++;
  99. for (m = n - 2; m >= e; m--)
  100. {
  101. double a1, a2, a3;
  102. z = FMAT (h, m, m, nc);
  103. r = x - z;
  104. s = y - z;
  105. p = FMAT (h, m, m + 1, nc) + (r * s - w) / FMAT (h, m + 1, m, nc);
  106. q = FMAT (h, m + 1, m + 1, nc) - z - r - s;
  107. r = FMAT (h, m + 2, m + 1, nc);
  108. s = fabs (p) + fabs (q) + fabs (r);
  109. p /= s;
  110. q /= s;
  111. r /= s;
  112. if (m == e)
  113. break;
  114. a1 = fabs (FMAT (h, m, m - 1, nc));
  115. a2 = fabs (FMAT (h, m - 1, m - 1, nc));
  116. a3 = fabs (FMAT (h, m + 1, m + 1, nc));
  117. if (a1 * (fabs (q) + fabs (r)) <= GSL_DBL_EPSILON * fabs (p) * (a2 + a3))
  118. break;
  119. }
  120. for (i = m + 2; i <= n; i++)
  121. {
  122. FMAT (h, i, i - 2, nc) = 0;
  123. }
  124. for (i = m + 3; i <= n; i++)
  125. {
  126. FMAT (h, i, i - 3, nc) = 0;
  127. }
  128. /* double QR step */
  129. for (k = m; k <= n - 1; k++)
  130. {
  131. notlast = (k != n - 1);
  132. if (k != m)
  133. {
  134. p = FMAT (h, k, k - 1, nc);
  135. q = FMAT (h, k + 1, k - 1, nc);
  136. r = notlast ? FMAT (h, k + 2, k - 1, nc) : 0.0;
  137. x = fabs (p) + fabs (q) + fabs (r);
  138. if (x == 0)
  139. continue; /* FIXME????? */
  140. p /= x;
  141. q /= x;
  142. r /= x;
  143. }
  144. s = sqrt (p * p + q * q + r * r);
  145. if (p < 0)
  146. s = -s;
  147. if (k != m)
  148. {
  149. FMAT (h, k, k - 1, nc) = -s * x;
  150. }
  151. else if (e != m)
  152. {
  153. FMAT (h, k, k - 1, nc) *= -1;
  154. }
  155. p += s;
  156. x = p / s;
  157. y = q / s;
  158. z = r / s;
  159. q /= p;
  160. r /= p;
  161. /* do row modifications */
  162. for (j = k; j <= n; j++)
  163. {
  164. p = FMAT (h, k, j, nc) + q * FMAT (h, k + 1, j, nc);
  165. if (notlast)
  166. {
  167. p += r * FMAT (h, k + 2, j, nc);
  168. FMAT (h, k + 2, j, nc) -= p * z;
  169. }
  170. FMAT (h, k + 1, j, nc) -= p * y;
  171. FMAT (h, k, j, nc) -= p * x;
  172. }
  173. j = (k + 3 < n) ? (k + 3) : n;
  174. /* do column modifications */
  175. for (i = e; i <= j; i++)
  176. {
  177. p = x * FMAT (h, i, k, nc) + y * FMAT (h, i, k + 1, nc);
  178. if (notlast)
  179. {
  180. p += z * FMAT (h, i, k + 2, nc);
  181. FMAT (h, i, k + 2, nc) -= p * r;
  182. }
  183. FMAT (h, i, k + 1, nc) -= p * q;
  184. FMAT (h, i, k, nc) -= p;
  185. }
  186. }
  187. goto next_iteration;
  188. }