PageRenderTime 58ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/mesch/schur.c

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