private static int qzval(int n, double[][] a, double[][] b, double[] alfr, double[] alfi, double[] beta, bool matz, double[][] z)
{
int i, j;
int na, en, nn;
double c, d, e = 0;
double r, s, t;
double a1, a2, u1, u2, v1, v2;
double a11, a12, a21, a22;
double b11, b12, b22;
double di, ei;
double an = 0, bn;
double cq, dr;
double cz, ti, tr;
double a1i, a2i, a11i, a12i, a22i, a11r, a12r, a22r;
double sqi, ssi, sqr, szi, ssr, szr;
double epsb = b[n - 1][0];
int isw = 1;
// Find eigenvalues of quasi-triangular matrices.
for (nn = 0; nn < n; ++nn)
{
en = n - nn - 1;
na = en - 1;
if (isw == 2) goto L505;
if (en == 0) goto L410;
if (a[en][na] != 0.0) goto L420;
// 1-by-1 block][one real root
L410:
alfr[en] = a[en][en];
if (b[en][en] < 0.0)
{
alfr[en] = -alfr[en];
}
beta[en] = (Math.Abs(b[en][en]));
alfi[en] = 0.0;
goto L510;
// 2-by-2 block
L420:
if (Math.Abs(b[na][na]) <= epsb) goto L455;
if (Math.Abs(b[en][en]) > epsb) goto L430;
a1 = a[en][en];
a2 = a[en][na];
bn = 0.0;
goto L435;
L430:
an = Math.Abs(a[na][na]) + Math.Abs(a[na][en]) + Math.Abs(a[en][na]) + Math.Abs(a[en][en]);
bn = Math.Abs(b[na][na]) + Math.Abs(b[na][en]) + Math.Abs(b[en][en]);
a11 = a[na][na] / an;
a12 = a[na][en] / an;
a21 = a[en][na] / an;
a22 = a[en][en] / an;
b11 = b[na][na] / bn;
b12 = b[na][en] / bn;
b22 = b[en][en] / bn;
e = a11 / b11;
ei = a22 / b22;
s = a21 / (b11 * b22);
t = (a22 - e * b22) / b22;
if (Math.Abs(e) <= Math.Abs(ei))
goto L431;
e = ei;
t = (a11 - e * b11) / b11;
L431:
c = (t - s * b12) * .5;
d = c * c + s * (a12 - e * b12);
if (d < 0.0) goto L480;
// Two real roots. Zero both a(en,na) and b(en,na)
e += c + Special.Sign(Math.Sqrt(d), c);
a11 -= e * b11;
a12 -= e * b12;
a22 -= e * b22;
if (Math.Abs(a11) + Math.Abs(a12) < Math.Abs(a21) + Math.Abs(a22))
goto L432;
a1 = a12;
a2 = a11;
goto L435;
L432:
a1 = a22;
a2 = a21;
// Choose and apply real z
L435:
s = Math.Abs(a1) + Math.Abs(a2);
u1 = a1 / s;
u2 = a2 / s;
r = Special.Sign(Math.Sqrt(u1 * u1 + u2 * u2), u1);
v1 = -(u1 + r) / r;
v2 = -u2 / r;
u2 = v2 / v1;
for (i = 0; i <= en; ++i)
{
t = a[i][en] + u2 * a[i][na];
a[i][en] += t * v1;
a[i][na] += t * v2;
t = b[i][en] + u2 * b[i][na];
b[i][en] += t * v1;
b[i][na] += t * v2;
}
if (matz)
{
for (i = 0; i < n; ++i)
{
t = z[i][en] + u2 * z[i][na];
z[i][en] += t * v1;
z[i][na] += t * v2;
}
}
if (bn == 0.0) goto L475;
if (an < System.Math.Abs(e) * bn) goto L455;
a1 = b[na][na];
a2 = b[en][na];
goto L460;
L455:
a1 = a[na][na];
a2 = a[en][na];
// Choose and apply real q
L460:
s = System.Math.Abs(a1) + System.Math.Abs(a2);
if (s == 0.0) goto L475;
u1 = a1 / s;
u2 = a2 / s;
r = Special.Sign(Math.Sqrt(u1 * u1 + u2 * u2), u1);
v1 = -(u1 + r) / r;
v2 = -u2 / r;
u2 = v2 / v1;
for (j = na; j < n; ++j)
{
t = a[na][j] + u2 * a[en][j];
a[na][j] += t * v1;
a[en][j] += t * v2;
t = b[na][j] + u2 * b[en][j];
b[na][j] += t * v1;
b[en][j] += t * v2;
}
L475:
a[en][na] = 0.0;
b[en][na] = 0.0;
alfr[na] = a[na][na];
alfr[en] = a[en][en];
if (b[na][na] < 0.0)
alfr[na] = -alfr[na];
if (b[en][en] < 0.0)
alfr[en] = -alfr[en];
beta[na] = (System.Math.Abs(b[na][na]));
beta[en] = (System.Math.Abs(b[en][en]));
alfi[en] = 0.0;
alfi[na] = 0.0;
goto L505;
// Two complex roots
L480:
e += c;
ei = System.Math.Sqrt(-d);
a11r = a11 - e * b11;
a11i = ei * b11;
a12r = a12 - e * b12;
a12i = ei * b12;
a22r = a22 - e * b22;
a22i = ei * b22;
if (System.Math.Abs(a11r) + System.Math.Abs(a11i) +
System.Math.Abs(a12r) + System.Math.Abs(a12i) <
System.Math.Abs(a21) + System.Math.Abs(a22r)
+ System.Math.Abs(a22i))
goto L482;
a1 = a12r;
a1i = a12i;
a2 = -a11r;
a2i = -a11i;
goto L485;
L482:
a1 = a22r;
a1i = a22i;
a2 = -a21;
a2i = 0.0;
// Choose complex z
L485:
cz = System.Math.Sqrt(a1 * a1 + a1i * a1i);
if (cz == 0.0) goto L487;
szr = (a1 * a2 + a1i * a2i) / cz;
szi = (a1 * a2i - a1i * a2) / cz;
r = System.Math.Sqrt(cz * cz + szr * szr + szi * szi);
cz /= r;
szr /= r;
szi /= r;
goto L490;
L487:
szr = 1.0;
szi = 0.0;
L490:
if (an < (System.Math.Abs(e) + ei) * bn) goto L492;
a1 = cz * b11 + szr * b12;
a1i = szi * b12;
a2 = szr * b22;
a2i = szi * b22;
goto L495;
L492:
a1 = cz * a11 + szr * a12;
a1i = szi * a12;
a2 = cz * a21 + szr * a22;
a2i = szi * a22;
// Choose complex q
L495:
cq = System.Math.Sqrt(a1 * a1 + a1i * a1i);
if (cq == 0.0) goto L497;
sqr = (a1 * a2 + a1i * a2i) / cq;
sqi = (a1 * a2i - a1i * a2) / cq;
r = System.Math.Sqrt(cq * cq + sqr * sqr + sqi * sqi);
cq /= r;
sqr /= r;
sqi /= r;
goto L500;
L497:
sqr = 1.0;
sqi = 0.0;
// Compute diagonal elements that would result if transformations were applied
L500:
ssr = sqr * szr + sqi * szi;
ssi = sqr * szi - sqi * szr;
i = 0;
tr = cq * cz * a11 + cq * szr * a12 + sqr * cz * a21 + ssr * a22;
ti = cq * szi * a12 - sqi * cz * a21 + ssi * a22;
dr = cq * cz * b11 + cq * szr * b12 + ssr * b22;
di = cq * szi * b12 + ssi * b22;
goto L503;
L502:
i = 1;
tr = ssr * a11 - sqr * cz * a12 - cq * szr * a21 + cq * cz * a22;
ti = -ssi * a11 - sqi * cz * a12 + cq * szi * a21;
dr = ssr * b11 - sqr * cz * b12 + cq * cz * b22;
di = -ssi * b11 - sqi * cz * b12;
L503:
t = ti * dr - tr * di;
j = na;
if (t < 0.0)
j = en;
r = Math.Sqrt(dr * dr + di * di);
beta[j] = bn * r;
alfr[j] = an * (tr * dr + ti * di) / r;
alfi[j] = an * t / r;
if (i == 0) goto L502;
L505:
isw = 3 - isw;
L510:
;
}
b[n - 1][0] = epsb;
return 0;
}