コード例 #1
0
        /// <summary>
        /// Symmetric tridiagonal QL algorithm.
        /// </summary>
        private void tql2()
        {
            //  This is derived from the Algol procedures tql2, by
            //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
            //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
            //  Fortran subroutine in EISPACK.

            for (int i = 1; i < n; i++)
            {
                e[i - 1] = e[i];
            }
            e[n - 1] = 0.0f;

            float f    = 0.0f;
            float tst1 = 0.0f;
            float eps  = Convert.ToSingle(Math.Pow(2.0, -52));

            for (int l = 0; l < n; l++)
            {
                // Find small subdiagonal element

                tst1 = Convert.ToSingle(Math.Max(tst1, Math.Abs(d[l]) + Math.Abs(e[l])));
                int m = l;
                while (m < n)
                {
                    if (Math.Abs(e[m]) <= eps * tst1)
                    {
                        break;
                    }
                    m++;
                }

                // If m == l, d[l] is an eigenvalue,
                // otherwise, iterate.

                if (m > l)
                {
                    int iter = 0;
                    do
                    {
                        iter = iter + 1;  // (Could check iteration count here.)

                        // Compute implicit shift

                        float g = d[l];
                        float p = (d[l + 1] - g) / (2 * e[l]);
                        float r = Convert.ToSingle(Maths.Hypot(p, 1));
                        if (p < 0)
                        {
                            r = -r;
                        }
                        d[l]     = e[l] / (p + r);
                        d[l + 1] = e[l] * (p + r);
                        float dl1 = d[l + 1];
                        float h   = g - d[l];
                        for (int i = l + 2; i < n; i++)
                        {
                            d[i] -= h;
                        }
                        f = f + h;

                        // Implicit QL transformation.

                        p = d[m];
                        float c   = 1.0f;
                        float c2  = c;
                        float c3  = c;
                        float el1 = e[l + 1];
                        float s   = 0.0f;
                        float s2  = 0.0f;
                        for (int i = m - 1; i >= l; i--)
                        {
                            c3       = c2;
                            c2       = c;
                            s2       = s;
                            g        = c * e[i];
                            h        = c * p;
                            r        = Convert.ToSingle(Maths.Hypot(p, e[i]));
                            e[i + 1] = s * r;
                            s        = e[i] / r;
                            c        = p / r;
                            p        = c * d[i] - s * g;
                            d[i + 1] = h + s * (c * g + s * d[i]);

                            // Accumulate transformation.

                            for (int k = 0; k < n; k++)
                            {
                                h = Varray[k, i + 1];
                                Varray[k, i + 1] = s * Varray[k, i] + c * h;
                                Varray[k, i]     = c * Varray[k, i] - s * h;
                            }
                        }
                        p    = -s * s2 * c3 * el1 * e[l] / dl1;
                        e[l] = s * p;
                        d[l] = c * p;

                        // Check for convergence.
                    } while (Math.Abs(e[l]) > eps * tst1);
                }
                d[l] = d[l] + f;
                e[l] = 0.0f;
            }

            // Sort eigenvalues and corresponding vectors.

            for (int i = 0; i < n - 1; i++)
            {
                int   k = i;
                float p = d[i];
                for (int j = i + 1; j < n; j++)
                {
                    if (d[j] < p)
                    {
                        k = j;
                        p = d[j];
                    }
                }
                if (k != i)
                {
                    d[k] = d[i];
                    d[i] = p;
                    for (int j = 0; j < n; j++)
                    {
                        p            = Varray[j, i];
                        Varray[j, i] = Varray[j, k];
                        Varray[j, k] = p;
                    }
                }
            }
        }