1 #include <../../nrnconf.h>
40 static char rcsid[] =
"schur.c,v 1.1 1997/12/04 17:55:46 hines Exp";
45 static void hhldr3(x,y,z,nu1,beta,newval)
47 Real *nu1, *beta, *newval;
49 static void hhldr3(
double x,
double y,
double z,
60 *beta = 1.0/(
alpha*(*nu1));
68 double beta, nu1, nu2, nu3;
71 double nu1,
double nu2,
double nu3)
74 Real **A_me, ip, prod;
77 if ( k < 0 || k+3 >
A->m || j0 < 0 )
79 A_me =
A->me;
n =
A->n;
85 for (
j = j0;
j <
n;
j++ )
117 double beta, nu1, nu2, nu3;
120 double nu1,
double nu2,
double nu3)
123 Real **A_me, ip, prod;
128 if ( k < 0 || k+3 >
A->n )
130 A_me =
A->me; m =
A->m;
133 for (
i = 0;
i <= i0;
i++ )
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;
166 if (
A->m !=
A->n || ( Q && Q->m != Q->n ) )
168 if ( Q !=
MNULL && Q->m !=
A->m )
185 k_min = 0; A_me =
A->me;
189 Real a00, a01, a10, a11;
190 double scale,
t, numer, denom;
195 for (
k = k_min;
k < k_max;
k++ )
198 { k_max =
k;
break; }
200 if ( k_max <= k_min )
208 if ( k_max == k_min + 1 )
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);
250 numer = ( tmp >= 0.0 ) ?
251 - tmp -
sqrt(discrim) : - tmp +
sqrt(discrim);
259 else if ( numer != 0.0 )
264 s = (
t >= 0.0 ) ? scale : -scale;
283 split =
FALSE; iter = 0;
316 t = a00*a11 - a01*a10;
319 if ( k_max == k_min + 1 && s*s < 4.0*
t )
326 if ( (iter % 10) == 0 )
327 { s += iter*0.02;
t += iter*0.02;
355 x = a00*a00 + a01*a10 - s*a00 +
t;
357 if ( k_min + 2 <= k_max )
358 z = a10*
A->me[k_min+2][k_tmp];
362 for (
k = k_min;
k <= k_max-1;
k++ )
384 if (
k <= k_max - 2 )
389 if (
k <= k_max - 3 )
399 for (
k = k_min;
k <= k_max-2;
k++ )
408 for (
k = k_min;
k < k_max;
k++ )
411 { A_me[
k+1][
k] = 0.0; split =
TRUE; }
417 for (
i = 0;
i <
A->m;
i++ )
418 for (
j = 0;
j <
i-1;
j++ )
420 for (
i = 0;
i <
A->m - 1;
i++ )
434 VEC *real_pt, *imag_pt;
437 Real discrim, **T_me;
440 if ( !
T || ! real_pt || ! imag_pt )
444 n =
T->n; T_me =
T->me;
451 if (
i <
n-1 && T_me[
i+1][
i] != 0.0 )
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];
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];
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;
473 real_pt->
ve[
i] = T_me[
i][
i];
474 imag_pt->
ve[
i] = 0.0;
489 MAT *
T, *Q, *X_re, *X_im;
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;
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 ) )
506 if (
T->m != X_re->m ||
507 ( Q !=
MNULL &&
T->m != Q->m ) ||
508 ( X_im !=
MNULL &&
T->m != X_im->m ) )
524 if (
i+1 <
T->m &&
T->me[
i+1][
i] != 0.0 )
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];
533 l_im =
sqrt(-discrim);
549 limit = ( l_im != 0.0 ) ?
i+1 :
i;
551 for (
j = limit+1;
j <
T->m;
j++ )
552 tmp1_re->
ve[
j] = 0.0;
556 if (
j > 0 &&
T->me[
j][
j-1] != 0.0 )
559 val1_re = tmp1_re->
ve[
j-1] -
562 val1_im = tmp1_im->ve[
j-1] -
563 __ip__(&(tmp1_im->ve[
j+1]),&(
T->me[
j-1][
j+1]),limit-
j);
565 val2_re = tmp1_re->
ve[
j] -
568 val2_im = tmp1_im->ve[
j] -
569 __ip__(&(tmp1_im->ve[
j+1]),&(
T->me[
j][
j+1]),limit-
j);
572 t11_re = T_me[
j-1][
j-1] - l_re;
574 t22_re = T_me[
j][
j] - l_re;
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;
588 magdet = det_re*det_re+det_im*det_im;
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;
608 t11_re = T_me[
j][
j] - l_re;
610 magdet = t11_re*t11_re + t11_im*t11_im;
615 magdet = t11_re*t11_re + t11_im*t11_im;
617 invdet_re = t11_re/magdet;
618 invdet_im = - t11_im/magdet;
620 val1_re = tmp1_re->
ve[
j] -
623 val1_im = tmp1_im->ve[
j] -
624 __ip__(&(tmp1_im->ve[
j+1]),&(
T->me[
j][
j+1]),limit-
j);
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;
633 sv_mlt(1/norm,tmp1_re,tmp1_re);
635 sv_mlt(1/norm,tmp1_im,tmp1_im);
636 mv_mlt(Q,tmp1_re,tmp2_re);
638 mv_mlt(Q,tmp1_im,tmp2_im);
643 sv_mlt(1/norm,tmp2_re,tmp2_re);
645 sv_mlt(1/norm,tmp2_im,tmp2_im);
653 sv_mlt(-1.0,tmp2_im,tmp2_im);
#define error(err_num, fn_name)
#define tracecatch(ok_part, function)
void givens(double x, double y, Real *c, Real *s)
MAT * rot_cols(MAT *mat, u_int i, u_int k, double c, double s, MAT *out)
MAT * rot_rows(MAT *mat, u_int i, u_int k, double c, double s, MAT *out)
MAT * makeH(MAT *H, MAT *Hout)
MAT * makeHQ(MAT *H, VEC *diag, VEC *beta, MAT *Qout)
MAT * Hfactor(MAT *A, VEC *diag, VEC *beta)
static Object ** v_resize(void *v)
double __ip__(Real *dp1, Real *dp2, int len)
VEC * mv_mlt(MAT *A, VEC *b, VEC *out)
#define m_set_val(A, i, j, val)
#define m_add_val(A, i, j, val)
#define set_col(mat, col, vec)
VEC * sv_mlt(double, VEC *, VEC *)
#define MEM_STAT_REG(var, type)
int const size_t const size_t n
static philox4x32_key_t k
static void hhldr3(double x, double y, double z, Real *nu1, Real *beta, Real *newval)
void schur_evals(MAT *T, VEC *real_pt, VEC *imag_pt)
MAT * schur_vecs(MAT *T, MAT *Q, MAT *X_re, MAT *X_im)
static void hhldr3rows(MAT *A, int k, int i0, double beta, double nu1, double nu2, double nu3)
static void hhldr3cols(MAT *A, int k, int j0, double beta, double nu1, double nu2, double nu3)
MAT * schur(MAT *A, MAT *Q)