예제 #1
0
        /* ------------------------
         * Constructor
         * ------------------------ */


        ///<summary>QR Decomposition, computed by Householder reflections.</summary>
        ///<param name="A">Rectangular matrix</param>
        ///<returns>Structure to access R and the Householder vectors and compute Q.</returns>
        public QRDecomposition(Matrix3 A)
        {
            // Initialize.
            QR    = A.ToFloatArray();
            m     = A.RowLength();
            n     = A.ColumnLength();
            Rdiag = new float[n];

            // Main loop.
            for (int k = 0; k < n; k++)
            {
                // Compute 2-norm of k-th column without under/overflow.
                float nrm = 0;
                for (int i = k; i < m; i++)
                {
                    nrm = Convert.ToSingle(Maths.Hypot(nrm, QR[i, k]));
                }

                if (nrm != 0)
                {
                    // Form k-th Householder vector.
                    if (QR[k, k] < 0)
                    {
                        nrm = -nrm;
                    }
                    for (int i = k; i < m; i++)
                    {
                        QR[i, k] /= nrm;
                    }
                    QR[k, k] += 1.0f;

                    // Apply transformation to remaining columns.
                    for (int j = k + 1; j < n; j++)
                    {
                        float s = 0.0f;
                        for (int i = k; i < m; i++)
                        {
                            s += QR[i, k] * QR[i, j];
                        }
                        s = -s / QR[k, k];
                        for (int i = k; i < m; i++)
                        {
                            QR[i, j] += s * QR[i, k];
                        }
                    }
                }
                Rdiag[k] = -nrm;
            }
        }
예제 #2
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;
                    }
                }
            }
        }