Accord.Math.Decompositions.JaggedGeneralizedEigenvalueDecomposition.qzval C# (CSharp) Method

qzval() private static method

Adaptation of the original Fortran QZVAL routine from EISPACK.
This subroutine is the third step of the qz algorithm for solving generalized matrix eigenvalue problems, Siam J. Numer. anal. 10, 241-256(1973) by Moler and Stewart. This subroutine accepts a pair of real matrices, one of them in quasi-triangular form and the other in upper triangular form. it reduces the quasi-triangular matrix further, so that any remaining 2-by-2 blocks correspond to pairs of complex Eigenvalues, and returns quantities whose ratios give the generalized eigenvalues. it is usually preceded by qzhes and qzit and may be followed by qzvec. For the full documentation, please check the original function.
private static qzval ( int n, double a, double b, double alfr, double alfi, double beta, bool matz, double z ) : int
n int
a double
b double
alfr double
alfi double
beta double
matz bool
z double
return int
        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;
        }