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