schur.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. /**************************************************************************
  2. **
  3. ** Copyright (C) 1993 David E. Stewart & 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 real non-symmetric matrix
  27. See also: hessen.c
  28. */
  29. #include <stdio.h>
  30. #include <math.h>
  31. #include "matrix.h"
  32. #include "matrix2.h"
  33. static char rcsid[] = "$Id: schur.c,v 1.7 1994/03/17 05:36:53 des Exp $";
  34. #ifndef ANSI_C
  35. static void hhldr3(x,y,z,nu1,beta,newval)
  36. double x, y, z;
  37. Real *nu1, *beta, *newval;
  38. #else
  39. static void hhldr3(double x, double y, double z,
  40. Real *nu1, Real *beta, Real *newval)
  41. #endif
  42. {
  43. Real alpha;
  44. if ( x >= 0.0 )
  45. alpha = sqrt(x*x+y*y+z*z);
  46. else
  47. alpha = -sqrt(x*x+y*y+z*z);
  48. *nu1 = x + alpha;
  49. *beta = 1.0/(alpha*(*nu1));
  50. *newval = alpha;
  51. }
  52. #ifndef ANSI_C
  53. static void hhldr3cols(A,k,j0,beta,nu1,nu2,nu3)
  54. MAT *A;
  55. int k, j0;
  56. double beta, nu1, nu2, nu3;
  57. #else
  58. static void hhldr3cols(MAT *A, int k, int j0, double beta,
  59. double nu1, double nu2, double nu3)
  60. #endif
  61. {
  62. Real **A_me, ip, prod;
  63. int j, n;
  64. if ( k < 0 || k+3 > A->m || j0 < 0 )
  65. error(E_BOUNDS,"hhldr3cols");
  66. A_me = A->me; n = A->n;
  67. /* printf("hhldr3cols:(l.%d) j0 = %d, k = %d, A at 0x%lx, m = %d, n = %d\n",
  68. __LINE__, j0, k, (long)A, A->m, A->n); */
  69. /* printf("hhldr3cols: A (dumped) =\n"); m_dump(stdout,A); */
  70. for ( j = j0; j < n; j++ )
  71. {
  72. /*****
  73. ip = nu1*A_me[k][j] + nu2*A_me[k+1][j] + nu3*A_me[k+2][j];
  74. prod = ip*beta;
  75. A_me[k][j] -= prod*nu1;
  76. A_me[k+1][j] -= prod*nu2;
  77. A_me[k+2][j] -= prod*nu3;
  78. *****/
  79. /* printf("hhldr3cols: j = %d\n", j); */
  80. ip = nu1*m_entry(A,k,j)+nu2*m_entry(A,k+1,j)+nu3*m_entry(A,k+2,j);
  81. prod = ip*beta;
  82. /*****
  83. m_set_val(A,k ,j,m_entry(A,k ,j) - prod*nu1);
  84. m_set_val(A,k+1,j,m_entry(A,k+1,j) - prod*nu2);
  85. m_set_val(A,k+2,j,m_entry(A,k+2,j) - prod*nu3);
  86. *****/
  87. m_add_val(A,k ,j,-prod*nu1);
  88. m_add_val(A,k+1,j,-prod*nu2);
  89. m_add_val(A,k+2,j,-prod*nu3);
  90. }
  91. /* printf("hhldr3cols:(l.%d) j0 = %d, k = %d, m = %d, n = %d\n",
  92. __LINE__, j0, k, A->m, A->n); */
  93. /* putc('\n',stdout); */
  94. }
  95. #ifndef ANSI_C
  96. static void hhldr3rows(A,k,i0,beta,nu1,nu2,nu3)
  97. MAT *A;
  98. int k, i0;
  99. double beta, nu1, nu2, nu3;
  100. #else
  101. static void hhldr3rows(MAT *A, int k, int i0, double beta,
  102. double nu1, double nu2, double nu3)
  103. #endif
  104. {
  105. Real **A_me, ip, prod;
  106. int i, m;
  107. /* printf("hhldr3rows:(l.%d) A at 0x%lx\n", __LINE__, (long)A); */
  108. /* printf("hhldr3rows: k = %d\n", k); */
  109. if ( k < 0 || k+3 > A->n )
  110. error(E_BOUNDS,"hhldr3rows");
  111. A_me = A->me; m = A->m;
  112. i0 = min(i0,m-1);
  113. for ( i = 0; i <= i0; i++ )
  114. {
  115. /****
  116. ip = nu1*A_me[i][k] + nu2*A_me[i][k+1] + nu3*A_me[i][k+2];
  117. prod = ip*beta;
  118. A_me[i][k] -= prod*nu1;
  119. A_me[i][k+1] -= prod*nu2;
  120. A_me[i][k+2] -= prod*nu3;
  121. ****/
  122. ip = nu1*m_entry(A,i,k)+nu2*m_entry(A,i,k+1)+nu3*m_entry(A,i,k+2);
  123. prod = ip*beta;
  124. m_add_val(A,i,k , - prod*nu1);
  125. m_add_val(A,i,k+1, - prod*nu2);
  126. m_add_val(A,i,k+2, - prod*nu3);
  127. }
  128. }
  129. /* schur -- computes the Schur decomposition of the matrix A in situ
  130. -- optionally, gives Q matrix such that Q^T.A.Q is upper triangular
  131. -- returns upper triangular Schur matrix */
  132. #ifndef ANSI_C
  133. MAT *schur(A,Q)
  134. MAT *A, *Q;
  135. #else
  136. MAT *schur(MAT *A, MAT *Q)
  137. #endif
  138. {
  139. int i, j, iter, k, k_min, k_max, k_tmp, n, split;
  140. Real beta2, c, discrim, dummy, nu1, s, t, tmp, x, y, z;
  141. Real **A_me;
  142. Real sqrt_macheps;
  143. STATIC VEC *diag=VNULL, *beta=VNULL;
  144. if ( ! A )
  145. error(E_NULL,"schur");
  146. if ( A->m != A->n || ( Q && Q->m != Q->n ) )
  147. error(E_SQUARE,"schur");
  148. if ( Q != MNULL && Q->m != A->m )
  149. error(E_SIZES,"schur");
  150. n = A->n;
  151. diag = v_resize(diag,A->n);
  152. beta = v_resize(beta,A->n);
  153. MEM_STAT_REG(diag,TYPE_VEC);
  154. MEM_STAT_REG(beta,TYPE_VEC);
  155. /* compute Hessenberg form */
  156. Hfactor(A,diag,beta);
  157. /* save Q if necessary */
  158. if ( Q )
  159. Q = makeHQ(A,diag,beta,Q);
  160. makeH(A,A);
  161. sqrt_macheps = sqrt(MACHEPS);
  162. k_min = 0; A_me = A->me;
  163. while ( k_min < n )
  164. {
  165. Real a00, a01, a10, a11;
  166. double scale, t, numer, denom;
  167. /* find k_max to suit:
  168. submatrix k_min..k_max should be irreducible */
  169. k_max = n-1;
  170. for ( k = k_min; k < k_max; k++ )
  171. /* if ( A_me[k+1][k] == 0.0 ) */
  172. if ( m_entry(A,k+1,k) == 0.0 )
  173. { k_max = k; break; }
  174. if ( k_max <= k_min )
  175. {
  176. k_min = k_max + 1;
  177. continue; /* outer loop */
  178. }
  179. /* check to see if we have a 2 x 2 block
  180. with complex eigenvalues */
  181. if ( k_max == k_min + 1 )
  182. {
  183. /* tmp = A_me[k_min][k_min] - A_me[k_max][k_max]; */
  184. a00 = m_entry(A,k_min,k_min);
  185. a01 = m_entry(A,k_min,k_max);
  186. a10 = m_entry(A,k_max,k_min);
  187. a11 = m_entry(A,k_max,k_max);
  188. tmp = a00 - a11;
  189. /* discrim = tmp*tmp +
  190. 4*A_me[k_min][k_max]*A_me[k_max][k_min]; */
  191. discrim = tmp*tmp + 4*a01*a10;
  192. if ( discrim < 0.0 )
  193. { /* yes -- e-vals are complex
  194. -- put 2 x 2 block in form [a b; c a];
  195. then eigenvalues have real part a & imag part sqrt(|bc|) */
  196. numer = - tmp;
  197. denom = ( a01+a10 >= 0.0 ) ?
  198. (a01+a10) + sqrt((a01+a10)*(a01+a10)+tmp*tmp) :
  199. (a01+a10) - sqrt((a01+a10)*(a01+a10)+tmp*tmp);
  200. if ( denom != 0.0 )
  201. { /* t = s/c = numer/denom */
  202. t = numer/denom;
  203. scale = c = 1.0/sqrt(1+t*t);
  204. s = c*t;
  205. }
  206. else
  207. {
  208. c = 1.0;
  209. s = 0.0;
  210. }
  211. rot_cols(A,k_min,k_max,c,s,A);
  212. rot_rows(A,k_min,k_max,c,s,A);
  213. if ( Q != MNULL )
  214. rot_cols(Q,k_min,k_max,c,s,Q);
  215. k_min = k_max + 1;
  216. continue;
  217. }
  218. else /* discrim >= 0; i.e. block has two real eigenvalues */
  219. { /* no -- e-vals are not complex;
  220. split 2 x 2 block and continue */
  221. /* s/c = numer/denom */
  222. numer = ( tmp >= 0.0 ) ?
  223. - tmp - sqrt(discrim) : - tmp + sqrt(discrim);
  224. denom = 2*a01;
  225. if ( fabs(numer) < fabs(denom) )
  226. { /* t = s/c = numer/denom */
  227. t = numer/denom;
  228. scale = c = 1.0/sqrt(1+t*t);
  229. s = c*t;
  230. }
  231. else if ( numer != 0.0 )
  232. { /* t = c/s = denom/numer */
  233. t = denom/numer;
  234. scale = 1.0/sqrt(1+t*t);
  235. c = fabs(t)*scale;
  236. s = ( t >= 0.0 ) ? scale : -scale;
  237. }
  238. else /* numer == denom == 0 */
  239. {
  240. c = 0.0;
  241. s = 1.0;
  242. }
  243. rot_cols(A,k_min,k_max,c,s,A);
  244. rot_rows(A,k_min,k_max,c,s,A);
  245. /* A->me[k_max][k_min] = 0.0; */
  246. if ( Q != MNULL )
  247. rot_cols(Q,k_min,k_max,c,s,Q);
  248. k_min = k_max + 1; /* go to next block */
  249. continue;
  250. }
  251. }
  252. /* now have r x r block with r >= 2:
  253. apply Francis QR step until block splits */
  254. split = FALSE; iter = 0;
  255. while ( ! split )
  256. {
  257. iter++;
  258. /* set up Wilkinson/Francis complex shift */
  259. k_tmp = k_max - 1;
  260. a00 = m_entry(A,k_tmp,k_tmp);
  261. a01 = m_entry(A,k_tmp,k_max);
  262. a10 = m_entry(A,k_max,k_tmp);
  263. a11 = m_entry(A,k_max,k_max);
  264. /* treat degenerate cases differently
  265. -- if there are still no splits after five iterations
  266. and the bottom 2 x 2 looks degenerate, force it to
  267. split */
  268. #ifdef DEBUG
  269. printf("# schur: bottom 2 x 2 = [%lg, %lg; %lg, %lg]\n",
  270. a00, a01, a10, a11);
  271. #endif
  272. if ( iter >= 5 &&
  273. fabs(a00-a11) < sqrt_macheps*(fabs(a00)+fabs(a11)) &&
  274. (fabs(a01) < sqrt_macheps*(fabs(a00)+fabs(a11)) ||
  275. fabs(a10) < sqrt_macheps*(fabs(a00)+fabs(a11))) )
  276. {
  277. if ( fabs(a01) < sqrt_macheps*(fabs(a00)+fabs(a11)) )
  278. m_set_val(A,k_tmp,k_max,0.0);
  279. if ( fabs(a10) < sqrt_macheps*(fabs(a00)+fabs(a11)) )
  280. {
  281. m_set_val(A,k_max,k_tmp,0.0);
  282. split = TRUE;
  283. continue;
  284. }
  285. }
  286. s = a00 + a11;
  287. t = a00*a11 - a01*a10;
  288. /* break loop if a 2 x 2 complex block */
  289. if ( k_max == k_min + 1 && s*s < 4.0*t )
  290. {
  291. split = TRUE;
  292. continue;
  293. }
  294. /* perturb shift if convergence is slow */
  295. if ( (iter % 10) == 0 )
  296. { s += iter*0.02; t += iter*0.02;
  297. }
  298. /* set up Householder transformations */
  299. k_tmp = k_min + 1;
  300. /********************
  301. x = A_me[k_min][k_min]*A_me[k_min][k_min] +
  302. A_me[k_min][k_tmp]*A_me[k_tmp][k_min] -
  303. s*A_me[k_min][k_min] + t;
  304. y = A_me[k_tmp][k_min]*
  305. (A_me[k_min][k_min]+A_me[k_tmp][k_tmp]-s);
  306. if ( k_min + 2 <= k_max )
  307. z = A_me[k_tmp][k_min]*A_me[k_min+2][k_tmp];
  308. else
  309. z = 0.0;
  310. ********************/
  311. a00 = m_entry(A,k_min,k_min);
  312. a01 = m_entry(A,k_min,k_tmp);
  313. a10 = m_entry(A,k_tmp,k_min);
  314. a11 = m_entry(A,k_tmp,k_tmp);
  315. /********************
  316. a00 = A->me[k_min][k_min];
  317. a01 = A->me[k_min][k_tmp];
  318. a10 = A->me[k_tmp][k_min];
  319. a11 = A->me[k_tmp][k_tmp];
  320. ********************/
  321. x = a00*a00 + a01*a10 - s*a00 + t;
  322. y = a10*(a00+a11-s);
  323. if ( k_min + 2 <= k_max )
  324. z = a10* /* m_entry(A,k_min+2,k_tmp) */ A->me[k_min+2][k_tmp];
  325. else
  326. z = 0.0;
  327. for ( k = k_min; k <= k_max-1; k++ )
  328. {
  329. if ( k < k_max - 1 )
  330. {
  331. hhldr3(x,y,z,&nu1,&beta2,&dummy);
  332. tracecatch(hhldr3cols(A,k,max(k-1,0), beta2,nu1,y,z),"schur");
  333. tracecatch(hhldr3rows(A,k,min(n-1,k+3),beta2,nu1,y,z),"schur");
  334. if ( Q != MNULL )
  335. hhldr3rows(Q,k,n-1,beta2,nu1,y,z);
  336. }
  337. else
  338. {
  339. givens(x,y,&c,&s);
  340. rot_cols(A,k,k+1,c,s,A);
  341. rot_rows(A,k,k+1,c,s,A);
  342. if ( Q )
  343. rot_cols(Q,k,k+1,c,s,Q);
  344. }
  345. /* if ( k >= 2 )
  346. m_set_val(A,k,k-2,0.0); */
  347. /* x = A_me[k+1][k]; */
  348. x = m_entry(A,k+1,k);
  349. if ( k <= k_max - 2 )
  350. /* y = A_me[k+2][k];*/
  351. y = m_entry(A,k+2,k);
  352. else
  353. y = 0.0;
  354. if ( k <= k_max - 3 )
  355. /* z = A_me[k+3][k]; */
  356. z = m_entry(A,k+3,k);
  357. else
  358. z = 0.0;
  359. }
  360. /* if ( k_min > 0 )
  361. m_set_val(A,k_min,k_min-1,0.0);
  362. if ( k_max < n - 1 )
  363. m_set_val(A,k_max+1,k_max,0.0); */
  364. for ( k = k_min; k <= k_max-2; k++ )
  365. {
  366. /* zero appropriate sub-diagonals */
  367. m_set_val(A,k+2,k,0.0);
  368. if ( k < k_max-2 )
  369. m_set_val(A,k+3,k,0.0);
  370. }
  371. /* test to see if matrix should split */
  372. for ( k = k_min; k < k_max; k++ )
  373. if ( fabs(A_me[k+1][k]) < MACHEPS*
  374. (fabs(A_me[k][k])+fabs(A_me[k+1][k+1])) )
  375. { A_me[k+1][k] = 0.0; split = TRUE; }
  376. }
  377. }
  378. /* polish up A by zeroing strictly lower triangular elements
  379. and small sub-diagonal elements */
  380. for ( i = 0; i < A->m; i++ )
  381. for ( j = 0; j < i-1; j++ )
  382. A_me[i][j] = 0.0;
  383. for ( i = 0; i < A->m - 1; i++ )
  384. if ( fabs(A_me[i+1][i]) < MACHEPS*
  385. (fabs(A_me[i][i])+fabs(A_me[i+1][i+1])) )
  386. A_me[i+1][i] = 0.0;
  387. #ifdef THREADSAFE
  388. V_FREE(diag); V_FREE(beta);
  389. #endif
  390. return A;
  391. }
  392. /* schur_vals -- compute real & imaginary parts of eigenvalues
  393. -- assumes T contains a block upper triangular matrix
  394. as produced by schur()
  395. -- real parts stored in real_pt, imaginary parts in imag_pt */
  396. #ifndef ANSI_C
  397. void schur_evals(T,real_pt,imag_pt)
  398. MAT *T;
  399. VEC *real_pt, *imag_pt;
  400. #else
  401. void schur_evals(MAT *T, VEC *real_pt, VEC *imag_pt)
  402. #endif
  403. {
  404. int i, n;
  405. Real discrim, **T_me;
  406. Real diff, sum, tmp;
  407. if ( ! T || ! real_pt || ! imag_pt )
  408. error(E_NULL,"schur_evals");
  409. if ( T->m != T->n )
  410. error(E_SQUARE,"schur_evals");
  411. n = T->n; T_me = T->me;
  412. real_pt = v_resize(real_pt,(unsigned int)n);
  413. imag_pt = v_resize(imag_pt,(unsigned int)n);
  414. i = 0;
  415. while ( i < n )
  416. {
  417. if ( i < n-1 && T_me[i+1][i] != 0.0 )
  418. { /* should be a complex eigenvalue */
  419. sum = 0.5*(T_me[i][i]+T_me[i+1][i+1]);
  420. diff = 0.5*(T_me[i][i]-T_me[i+1][i+1]);
  421. discrim = diff*diff + T_me[i][i+1]*T_me[i+1][i];
  422. if ( discrim < 0.0 )
  423. { /* yes -- complex e-vals */
  424. real_pt->ve[i] = real_pt->ve[i+1] = sum;
  425. imag_pt->ve[i] = sqrt(-discrim);
  426. imag_pt->ve[i+1] = - imag_pt->ve[i];
  427. }
  428. else
  429. { /* no -- actually both real */
  430. tmp = sqrt(discrim);
  431. real_pt->ve[i] = sum + tmp;
  432. real_pt->ve[i+1] = sum - tmp;
  433. imag_pt->ve[i] = imag_pt->ve[i+1] = 0.0;
  434. }
  435. i += 2;
  436. }
  437. else
  438. { /* real eigenvalue */
  439. real_pt->ve[i] = T_me[i][i];
  440. imag_pt->ve[i] = 0.0;
  441. i++;
  442. }
  443. }
  444. }
  445. /* schur_vecs -- returns eigenvectors computed from the real Schur
  446. decomposition of a matrix
  447. -- T is the block upper triangular Schur matrix
  448. -- Q is the orthognal matrix where A = Q.T.Q^T
  449. -- if Q is null, the eigenvectors of T are returned
  450. -- X_re is the real part of the matrix of eigenvectors,
  451. and X_im is the imaginary part of the matrix.
  452. -- X_re is returned */
  453. #ifndef ANSI_C
  454. MAT *schur_vecs(T,Q,X_re,X_im)
  455. MAT *T, *Q, *X_re, *X_im;
  456. #else
  457. MAT *schur_vecs(MAT *T, MAT *Q, MAT *X_re, MAT *X_im)
  458. #endif
  459. {
  460. int i, j, limit;
  461. Real t11_re, t11_im, t12, t21, t22_re, t22_im;
  462. Real l_re, l_im, det_re, det_im, invdet_re, invdet_im,
  463. val1_re, val1_im, val2_re, val2_im,
  464. tmp_val1_re, tmp_val1_im, tmp_val2_re, tmp_val2_im, **T_me;
  465. Real sum, diff, discrim, magdet, norm, scale;
  466. STATIC VEC *tmp1_re=VNULL, *tmp1_im=VNULL,
  467. *tmp2_re=VNULL, *tmp2_im=VNULL;
  468. if ( ! T || ! X_re )
  469. error(E_NULL,"schur_vecs");
  470. if ( T->m != T->n || X_re->m != X_re->n ||
  471. ( Q != MNULL && Q->m != Q->n ) ||
  472. ( X_im != MNULL && X_im->m != X_im->n ) )
  473. error(E_SQUARE,"schur_vecs");
  474. if ( T->m != X_re->m ||
  475. ( Q != MNULL && T->m != Q->m ) ||
  476. ( X_im != MNULL && T->m != X_im->m ) )
  477. error(E_SIZES,"schur_vecs");
  478. tmp1_re = v_resize(tmp1_re,T->m);
  479. tmp1_im = v_resize(tmp1_im,T->m);
  480. tmp2_re = v_resize(tmp2_re,T->m);
  481. tmp2_im = v_resize(tmp2_im,T->m);
  482. MEM_STAT_REG(tmp1_re,TYPE_VEC);
  483. MEM_STAT_REG(tmp1_im,TYPE_VEC);
  484. MEM_STAT_REG(tmp2_re,TYPE_VEC);
  485. MEM_STAT_REG(tmp2_im,TYPE_VEC);
  486. T_me = T->me;
  487. i = 0;
  488. while ( i < T->m )
  489. {
  490. if ( i+1 < T->m && T->me[i+1][i] != 0.0 )
  491. { /* complex eigenvalue */
  492. sum = 0.5*(T_me[i][i]+T_me[i+1][i+1]);
  493. diff = 0.5*(T_me[i][i]-T_me[i+1][i+1]);
  494. discrim = diff*diff + T_me[i][i+1]*T_me[i+1][i];
  495. l_re = l_im = 0.0;
  496. if ( discrim < 0.0 )
  497. { /* yes -- complex e-vals */
  498. l_re = sum;
  499. l_im = sqrt(-discrim);
  500. }
  501. else /* not correct Real Schur form */
  502. error(E_RANGE,"schur_vecs");
  503. }
  504. else
  505. {
  506. l_re = T_me[i][i];
  507. l_im = 0.0;
  508. }
  509. v_zero(tmp1_im);
  510. v_rand(tmp1_re);
  511. sv_mlt(MACHEPS,tmp1_re,tmp1_re);
  512. /* solve (T-l.I)x = tmp1 */
  513. limit = ( l_im != 0.0 ) ? i+1 : i;
  514. /* printf("limit = %d\n",limit); */
  515. for ( j = limit+1; j < T->m; j++ )
  516. tmp1_re->ve[j] = 0.0;
  517. j = limit;
  518. while ( j >= 0 )
  519. {
  520. if ( j > 0 && T->me[j][j-1] != 0.0 )
  521. { /* 2 x 2 diagonal block */
  522. /* printf("checkpoint A\n"); */
  523. val1_re = tmp1_re->ve[j-1] -
  524. __ip__(&(tmp1_re->ve[j+1]),&(T->me[j-1][j+1]),limit-j);
  525. /* printf("checkpoint B\n"); */
  526. val1_im = tmp1_im->ve[j-1] -
  527. __ip__(&(tmp1_im->ve[j+1]),&(T->me[j-1][j+1]),limit-j);
  528. /* printf("checkpoint C\n"); */
  529. val2_re = tmp1_re->ve[j] -
  530. __ip__(&(tmp1_re->ve[j+1]),&(T->me[j][j+1]),limit-j);
  531. /* printf("checkpoint D\n"); */
  532. val2_im = tmp1_im->ve[j] -
  533. __ip__(&(tmp1_im->ve[j+1]),&(T->me[j][j+1]),limit-j);
  534. /* printf("checkpoint E\n"); */
  535. t11_re = T_me[j-1][j-1] - l_re;
  536. t11_im = - l_im;
  537. t22_re = T_me[j][j] - l_re;
  538. t22_im = - l_im;
  539. t12 = T_me[j-1][j];
  540. t21 = T_me[j][j-1];
  541. scale = fabs(T_me[j-1][j-1]) + fabs(T_me[j][j]) +
  542. fabs(t12) + fabs(t21) + fabs(l_re) + fabs(l_im);
  543. det_re = t11_re*t22_re - t11_im*t22_im - t12*t21;
  544. det_im = t11_re*t22_im + t11_im*t22_re;
  545. magdet = det_re*det_re+det_im*det_im;
  546. if ( sqrt(magdet) < MACHEPS*scale )
  547. {
  548. det_re = MACHEPS*scale;
  549. magdet = det_re*det_re+det_im*det_im;
  550. }
  551. invdet_re = det_re/magdet;
  552. invdet_im = - det_im/magdet;
  553. tmp_val1_re = t22_re*val1_re-t22_im*val1_im-t12*val2_re;
  554. tmp_val1_im = t22_im*val1_re+t22_re*val1_im-t12*val2_im;
  555. tmp_val2_re = t11_re*val2_re-t11_im*val2_im-t21*val1_re;
  556. tmp_val2_im = t11_im*val2_re+t11_re*val2_im-t21*val1_im;
  557. tmp1_re->ve[j-1] = invdet_re*tmp_val1_re -
  558. invdet_im*tmp_val1_im;
  559. tmp1_im->ve[j-1] = invdet_im*tmp_val1_re +
  560. invdet_re*tmp_val1_im;
  561. tmp1_re->ve[j] = invdet_re*tmp_val2_re -
  562. invdet_im*tmp_val2_im;
  563. tmp1_im->ve[j] = invdet_im*tmp_val2_re +
  564. invdet_re*tmp_val2_im;
  565. j -= 2;
  566. }
  567. else
  568. {
  569. t11_re = T_me[j][j] - l_re;
  570. t11_im = - l_im;
  571. magdet = t11_re*t11_re + t11_im*t11_im;
  572. scale = fabs(T_me[j][j]) + fabs(l_re);
  573. if ( sqrt(magdet) < MACHEPS*scale )
  574. {
  575. t11_re = MACHEPS*scale;
  576. magdet = t11_re*t11_re + t11_im*t11_im;
  577. }
  578. invdet_re = t11_re/magdet;
  579. invdet_im = - t11_im/magdet;
  580. /* printf("checkpoint F\n"); */
  581. val1_re = tmp1_re->ve[j] -
  582. __ip__(&(tmp1_re->ve[j+1]),&(T->me[j][j+1]),limit-j);
  583. /* printf("checkpoint G\n"); */
  584. val1_im = tmp1_im->ve[j] -
  585. __ip__(&(tmp1_im->ve[j+1]),&(T->me[j][j+1]),limit-j);
  586. /* printf("checkpoint H\n"); */
  587. tmp1_re->ve[j] = invdet_re*val1_re - invdet_im*val1_im;
  588. tmp1_im->ve[j] = invdet_im*val1_re + invdet_re*val1_im;
  589. j -= 1;
  590. }
  591. }
  592. norm = v_norm_inf(tmp1_re) + v_norm_inf(tmp1_im);
  593. sv_mlt(1/norm,tmp1_re,tmp1_re);
  594. if ( l_im != 0.0 )
  595. sv_mlt(1/norm,tmp1_im,tmp1_im);
  596. mv_mlt(Q,tmp1_re,tmp2_re);
  597. if ( l_im != 0.0 )
  598. mv_mlt(Q,tmp1_im,tmp2_im);
  599. if ( l_im != 0.0 )
  600. norm = sqrt(in_prod(tmp2_re,tmp2_re)+in_prod(tmp2_im,tmp2_im));
  601. else
  602. norm = v_norm2(tmp2_re);
  603. sv_mlt(1/norm,tmp2_re,tmp2_re);
  604. if ( l_im != 0.0 )
  605. sv_mlt(1/norm,tmp2_im,tmp2_im);
  606. if ( l_im != 0.0 )
  607. {
  608. if ( ! X_im )
  609. error(E_NULL,"schur_vecs");
  610. set_col(X_re,i,tmp2_re);
  611. set_col(X_im,i,tmp2_im);
  612. sv_mlt(-1.0,tmp2_im,tmp2_im);
  613. set_col(X_re,i+1,tmp2_re);
  614. set_col(X_im,i+1,tmp2_im);
  615. i += 2;
  616. }
  617. else
  618. {
  619. set_col(X_re,i,tmp2_re);
  620. if ( X_im != MNULL )
  621. set_col(X_im,i,tmp1_im); /* zero vector */
  622. i += 1;
  623. }
  624. }
  625. #ifdef THREADSAFE
  626. V_FREE(tmp1_re); V_FREE(tmp1_im);
  627. V_FREE(tmp2_re); V_FREE(tmp2_im);
  628. #endif
  629. return X_re;
  630. }