zschur.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /**************************************************************************
  2. **
  3. ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
  4. **
  5. ** Meschach Library
  6. **
  7. ** This Meschach Library is provided "as is" without any express
  8. ** or implied warranty of any kind with respect to this software.
  9. ** In particular the authors shall not be liable for any direct,
  10. ** indirect, special, incidental or consequential damages arising
  11. ** in any way from use of the software.
  12. **
  13. ** Everyone is granted permission to copy, modify and redistribute this
  14. ** Meschach Library, provided:
  15. ** 1. All copies contain this copyright notice.
  16. ** 2. All modified copies shall carry a notice stating who
  17. ** made the last modification and the date of such modification.
  18. ** 3. No charge is made for this software or works derived from it.
  19. ** This clause shall not be construed as constraining other software
  20. ** distributed on the same medium as this software, nor is a
  21. ** distribution fee considered a charge.
  22. **
  23. ***************************************************************************/
  24. /*
  25. File containing routines for computing the Schur decomposition
  26. of a complex non-symmetric matrix
  27. See also: hessen.c
  28. Complex version
  29. */
  30. #include <stdio.h>
  31. #include <math.h>
  32. #include "zmatrix.h"
  33. #include "zmatrix2.h"
  34. static char rcsid[] = "$Id: zschur.c,v 1.4 1995/04/07 16:28:58 des Exp $";
  35. #define is_zero(z) ((z).re == 0.0 && (z).im == 0.0)
  36. #define b2s(t_or_f) ((t_or_f) ? "TRUE" : "FALSE")
  37. /* zschur -- computes the Schur decomposition of the matrix A in situ
  38. -- optionally, gives Q matrix such that Q^*.A.Q is upper triangular
  39. -- returns upper triangular Schur matrix */
  40. ZMAT *zschur(A,Q)
  41. ZMAT *A, *Q;
  42. {
  43. int i, j, iter, k, k_min, k_max, k_tmp, n, split;
  44. Real c;
  45. complex det, discrim, lambda, lambda0, lambda1, s, sum, ztmp;
  46. complex x, y; /* for chasing algorithm */
  47. complex **A_me;
  48. STATIC ZVEC *diag=ZVNULL;
  49. if ( ! A )
  50. error(E_NULL,"zschur");
  51. if ( A->m != A->n || ( Q && Q->m != Q->n ) )
  52. error(E_SQUARE,"zschur");
  53. if ( Q != ZMNULL && Q->m != A->m )
  54. error(E_SIZES,"zschur");
  55. n = A->n;
  56. diag = zv_resize(diag,A->n);
  57. MEM_STAT_REG(diag,TYPE_ZVEC);
  58. /* compute Hessenberg form */
  59. zHfactor(A,diag);
  60. /* save Q if necessary, and make A explicitly Hessenberg */
  61. zHQunpack(A,diag,Q,A);
  62. k_min = 0; A_me = A->me;
  63. while ( k_min < n )
  64. {
  65. /* find k_max to suit:
  66. submatrix k_min..k_max should be irreducible */
  67. k_max = n-1;
  68. for ( k = k_min; k < k_max; k++ )
  69. if ( is_zero(A_me[k+1][k]) )
  70. { k_max = k; break; }
  71. if ( k_max <= k_min )
  72. {
  73. k_min = k_max + 1;
  74. continue; /* outer loop */
  75. }
  76. /* now have r x r block with r >= 2:
  77. apply Francis QR step until block splits */
  78. split = FALSE; iter = 0;
  79. while ( ! split )
  80. {
  81. complex a00, a01, a10, a11;
  82. iter++;
  83. /* set up Wilkinson/Francis complex shift */
  84. /* use the smallest eigenvalue of the bottom 2 x 2 submatrix */
  85. k_tmp = k_max - 1;
  86. a00 = A_me[k_tmp][k_tmp];
  87. a01 = A_me[k_tmp][k_max];
  88. a10 = A_me[k_max][k_tmp];
  89. a11 = A_me[k_max][k_max];
  90. ztmp.re = 0.5*(a00.re - a11.re);
  91. ztmp.im = 0.5*(a00.im - a11.im);
  92. discrim = zsqrt(zadd(zmlt(ztmp,ztmp),zmlt(a01,a10)));
  93. sum.re = 0.5*(a00.re + a11.re);
  94. sum.im = 0.5*(a00.im + a11.im);
  95. lambda0 = zadd(sum,discrim);
  96. lambda1 = zsub(sum,discrim);
  97. det = zsub(zmlt(a00,a11),zmlt(a01,a10));
  98. if ( is_zero(lambda0) && is_zero(lambda1) )
  99. {
  100. lambda.re = lambda.im = 0.0;
  101. }
  102. else if ( zabs(lambda0) > zabs(lambda1) )
  103. lambda = zdiv(det,lambda0);
  104. else
  105. lambda = zdiv(det,lambda1);
  106. /* perturb shift if convergence is slow */
  107. if ( (iter % 10) == 0 )
  108. {
  109. lambda.re += iter*0.02;
  110. lambda.im += iter*0.02;
  111. }
  112. /* set up Householder transformations */
  113. k_tmp = k_min + 1;
  114. x = zsub(A->me[k_min][k_min],lambda);
  115. y = A->me[k_min+1][k_min];
  116. /* use Givens' rotations to "chase" off-Hessenberg entry */
  117. for ( k = k_min; k <= k_max-1; k++ )
  118. {
  119. zgivens(x,y,&c,&s);
  120. zrot_cols(A,k,k+1,c,s,A);
  121. zrot_rows(A,k,k+1,c,s,A);
  122. if ( Q != ZMNULL )
  123. zrot_cols(Q,k,k+1,c,s,Q);
  124. /* zero things that should be zero */
  125. if ( k > k_min )
  126. A->me[k+1][k-1].re = A->me[k+1][k-1].im = 0.0;
  127. /* get next entry to chase along sub-diagonal */
  128. x = A->me[k+1][k];
  129. if ( k <= k_max - 2 )
  130. y = A->me[k+2][k];
  131. else
  132. y.re = y.im = 0.0;
  133. }
  134. for ( k = k_min; k <= k_max-2; k++ )
  135. {
  136. /* zero appropriate sub-diagonals */
  137. A->me[k+2][k].re = A->me[k+2][k].im = 0.0;
  138. }
  139. /* test to see if matrix should split */
  140. for ( k = k_min; k < k_max; k++ )
  141. if ( zabs(A_me[k+1][k]) < MACHEPS*
  142. (zabs(A_me[k][k])+zabs(A_me[k+1][k+1])) )
  143. {
  144. A_me[k+1][k].re = A_me[k+1][k].im = 0.0;
  145. split = TRUE;
  146. }
  147. }
  148. }
  149. /* polish up A by zeroing strictly lower triangular elements
  150. and small sub-diagonal elements */
  151. for ( i = 0; i < A->m; i++ )
  152. for ( j = 0; j < i-1; j++ )
  153. A_me[i][j].re = A_me[i][j].im = 0.0;
  154. for ( i = 0; i < A->m - 1; i++ )
  155. if ( zabs(A_me[i+1][i]) < MACHEPS*
  156. (zabs(A_me[i][i])+zabs(A_me[i+1][i+1])) )
  157. A_me[i+1][i].re = A_me[i+1][i].im = 0.0;
  158. #ifdef THREADSAFE
  159. ZV_FREE(diag);
  160. #endif
  161. return A;
  162. }
  163. #if 0
  164. /* schur_vecs -- returns eigenvectors computed from the real Schur
  165. decomposition of a matrix
  166. -- T is the block upper triangular Schur matrix
  167. -- Q is the orthognal matrix where A = Q.T.Q^T
  168. -- if Q is null, the eigenvectors of T are returned
  169. -- X_re is the real part of the matrix of eigenvectors,
  170. and X_im is the imaginary part of the matrix.
  171. -- X_re is returned */
  172. MAT *schur_vecs(T,Q,X_re,X_im)
  173. MAT *T, *Q, *X_re, *X_im;
  174. {
  175. int i, j, limit;
  176. Real t11_re, t11_im, t12, t21, t22_re, t22_im;
  177. Real l_re, l_im, det_re, det_im, invdet_re, invdet_im,
  178. val1_re, val1_im, val2_re, val2_im,
  179. tmp_val1_re, tmp_val1_im, tmp_val2_re, tmp_val2_im, **T_me;
  180. Real sum, diff, discrim, magdet, norm, scale;
  181. STATIC VEC *tmp1_re=VNULL, *tmp1_im=VNULL,
  182. *tmp2_re=VNULL, *tmp2_im=VNULL;
  183. if ( ! T || ! X_re )
  184. error(E_NULL,"schur_vecs");
  185. if ( T->m != T->n || X_re->m != X_re->n ||
  186. ( Q != MNULL && Q->m != Q->n ) ||
  187. ( X_im != MNULL && X_im->m != X_im->n ) )
  188. error(E_SQUARE,"schur_vecs");
  189. if ( T->m != X_re->m ||
  190. ( Q != MNULL && T->m != Q->m ) ||
  191. ( X_im != MNULL && T->m != X_im->m ) )
  192. error(E_SIZES,"schur_vecs");
  193. tmp1_re = v_resize(tmp1_re,T->m);
  194. tmp1_im = v_resize(tmp1_im,T->m);
  195. tmp2_re = v_resize(tmp2_re,T->m);
  196. tmp2_im = v_resize(tmp2_im,T->m);
  197. MEM_STAT_REG(tmp1_re,TYPE_VEC);
  198. MEM_STAT_REG(tmp1_im,TYPE_VEC);
  199. MEM_STAT_REG(tmp2_re,TYPE_VEC);
  200. MEM_STAT_REG(tmp2_im,TYPE_VEC);
  201. T_me = T->me;
  202. i = 0;
  203. while ( i < T->m )
  204. {
  205. if ( i+1 < T->m && T->me[i+1][i] != 0.0 )
  206. { /* complex eigenvalue */
  207. sum = 0.5*(T_me[i][i]+T_me[i+1][i+1]);
  208. diff = 0.5*(T_me[i][i]-T_me[i+1][i+1]);
  209. discrim = diff*diff + T_me[i][i+1]*T_me[i+1][i];
  210. l_re = l_im = 0.0;
  211. if ( discrim < 0.0 )
  212. { /* yes -- complex e-vals */
  213. l_re = sum;
  214. l_im = sqrt(-discrim);
  215. }
  216. else /* not correct Real Schur form */
  217. error(E_RANGE,"schur_vecs");
  218. }
  219. else
  220. {
  221. l_re = T_me[i][i];
  222. l_im = 0.0;
  223. }
  224. v_zero(tmp1_im);
  225. v_rand(tmp1_re);
  226. sv_mlt(MACHEPS,tmp1_re,tmp1_re);
  227. /* solve (T-l.I)x = tmp1 */
  228. limit = ( l_im != 0.0 ) ? i+1 : i;
  229. /* printf("limit = %d\n",limit); */
  230. for ( j = limit+1; j < T->m; j++ )
  231. tmp1_re->ve[j] = 0.0;
  232. j = limit;
  233. while ( j >= 0 )
  234. {
  235. if ( j > 0 && T->me[j][j-1] != 0.0 )
  236. { /* 2 x 2 diagonal block */
  237. /* printf("checkpoint A\n"); */
  238. val1_re = tmp1_re->ve[j-1] -
  239. __ip__(&(tmp1_re->ve[j+1]),&(T->me[j-1][j+1]),limit-j);
  240. /* printf("checkpoint B\n"); */
  241. val1_im = tmp1_im->ve[j-1] -
  242. __ip__(&(tmp1_im->ve[j+1]),&(T->me[j-1][j+1]),limit-j);
  243. /* printf("checkpoint C\n"); */
  244. val2_re = tmp1_re->ve[j] -
  245. __ip__(&(tmp1_re->ve[j+1]),&(T->me[j][j+1]),limit-j);
  246. /* printf("checkpoint D\n"); */
  247. val2_im = tmp1_im->ve[j] -
  248. __ip__(&(tmp1_im->ve[j+1]),&(T->me[j][j+1]),limit-j);
  249. /* printf("checkpoint E\n"); */
  250. t11_re = T_me[j-1][j-1] - l_re;
  251. t11_im = - l_im;
  252. t22_re = T_me[j][j] - l_re;
  253. t22_im = - l_im;
  254. t12 = T_me[j-1][j];
  255. t21 = T_me[j][j-1];
  256. scale = fabs(T_me[j-1][j-1]) + fabs(T_me[j][j]) +
  257. fabs(t12) + fabs(t21) + fabs(l_re) + fabs(l_im);
  258. det_re = t11_re*t22_re - t11_im*t22_im - t12*t21;
  259. det_im = t11_re*t22_im + t11_im*t22_re;
  260. magdet = det_re*det_re+det_im*det_im;
  261. if ( sqrt(magdet) < MACHEPS*scale )
  262. {
  263. det_re = MACHEPS*scale;
  264. magdet = det_re*det_re+det_im*det_im;
  265. }
  266. invdet_re = det_re/magdet;
  267. invdet_im = - det_im/magdet;
  268. tmp_val1_re = t22_re*val1_re-t22_im*val1_im-t12*val2_re;
  269. tmp_val1_im = t22_im*val1_re+t22_re*val1_im-t12*val2_im;
  270. tmp_val2_re = t11_re*val2_re-t11_im*val2_im-t21*val1_re;
  271. tmp_val2_im = t11_im*val2_re+t11_re*val2_im-t21*val1_im;
  272. tmp1_re->ve[j-1] = invdet_re*tmp_val1_re -
  273. invdet_im*tmp_val1_im;
  274. tmp1_im->ve[j-1] = invdet_im*tmp_val1_re +
  275. invdet_re*tmp_val1_im;
  276. tmp1_re->ve[j] = invdet_re*tmp_val2_re -
  277. invdet_im*tmp_val2_im;
  278. tmp1_im->ve[j] = invdet_im*tmp_val2_re +
  279. invdet_re*tmp_val2_im;
  280. j -= 2;
  281. }
  282. else
  283. {
  284. t11_re = T_me[j][j] - l_re;
  285. t11_im = - l_im;
  286. magdet = t11_re*t11_re + t11_im*t11_im;
  287. scale = fabs(T_me[j][j]) + fabs(l_re);
  288. if ( sqrt(magdet) < MACHEPS*scale )
  289. {
  290. t11_re = MACHEPS*scale;
  291. magdet = t11_re*t11_re + t11_im*t11_im;
  292. }
  293. invdet_re = t11_re/magdet;
  294. invdet_im = - t11_im/magdet;
  295. /* printf("checkpoint F\n"); */
  296. val1_re = tmp1_re->ve[j] -
  297. __ip__(&(tmp1_re->ve[j+1]),&(T->me[j][j+1]),limit-j);
  298. /* printf("checkpoint G\n"); */
  299. val1_im = tmp1_im->ve[j] -
  300. __ip__(&(tmp1_im->ve[j+1]),&(T->me[j][j+1]),limit-j);
  301. /* printf("checkpoint H\n"); */
  302. tmp1_re->ve[j] = invdet_re*val1_re - invdet_im*val1_im;
  303. tmp1_im->ve[j] = invdet_im*val1_re + invdet_re*val1_im;
  304. j -= 1;
  305. }
  306. }
  307. norm = v_norm_inf(tmp1_re) + v_norm_inf(tmp1_im);
  308. sv_mlt(1/norm,tmp1_re,tmp1_re);
  309. if ( l_im != 0.0 )
  310. sv_mlt(1/norm,tmp1_im,tmp1_im);
  311. mv_mlt(Q,tmp1_re,tmp2_re);
  312. if ( l_im != 0.0 )
  313. mv_mlt(Q,tmp1_im,tmp2_im);
  314. if ( l_im != 0.0 )
  315. norm = sqrt(in_prod(tmp2_re,tmp2_re)+in_prod(tmp2_im,tmp2_im));
  316. else
  317. norm = v_norm2(tmp2_re);
  318. sv_mlt(1/norm,tmp2_re,tmp2_re);
  319. if ( l_im != 0.0 )
  320. sv_mlt(1/norm,tmp2_im,tmp2_im);
  321. if ( l_im != 0.0 )
  322. {
  323. if ( ! X_im )
  324. error(E_NULL,"schur_vecs");
  325. set_col(X_re,i,tmp2_re);
  326. set_col(X_im,i,tmp2_im);
  327. sv_mlt(-1.0,tmp2_im,tmp2_im);
  328. set_col(X_re,i+1,tmp2_re);
  329. set_col(X_im,i+1,tmp2_im);
  330. i += 2;
  331. }
  332. else
  333. {
  334. set_col(X_re,i,tmp2_re);
  335. if ( X_im != MNULL )
  336. set_col(X_im,i,tmp1_im); /* zero vector */
  337. i += 1;
  338. }
  339. }
  340. return X_re;
  341. }
  342. #endif