Esempio n. 1
0
        /**
         * Computes and performs the similar a transform for submatrix k.
         */
        private void similarTransform(int k)
        {
            double[] t = QT.data;

            // find the largest value in this column
            // this is used to normalize the column and mitigate overflow/underflow
            double max = 0;

            int rowU = (k - 1) * N;

            for (int i = k; i < N; i++)
            {
                double val = Math.Abs(t[rowU + i]);
                if (val > max)
                {
                    max = val;
                }
            }

            if (max > 0)
            {
                // -------- set up the reflector Q_k

                double tau = QrHelperFunctions_DDRM.computeTauAndDivide(k, N, t, rowU, max);

                // write the reflector into the lower left column of the matrix
                double nu = t[rowU + k] + tau;
                QrHelperFunctions_DDRM.divideElements(k + 1, N, t, rowU, nu);
                t[rowU + k] = 1.0;

                double gamma = nu / tau;
                gammas[k] = gamma;

                // ---------- Specialized householder that takes advantage of the symmetry
                householderSymmetric(k, gamma);

                // since the first element in the householder vector is known to be 1
                // store the full upper hessenberg
                t[rowU + k] = -tau * max;
            }
            else
            {
                gammas[k] = 0;
            }
        }
        protected void computeU(int k)
        {
            double[] b = UBV.data;

            // find the largest value in this column
            // this is used to normalize the column and mitigate overflow/underflow
            double max = 0;

            for (int i = k; i < m; i++)
            {
                // copy the householder vector to vector outside of the matrix to reduce caching issues
                // big improvement on larger matrices and a relatively small performance hit on small matrices.
                double val = u[i] = b[i * n + k];
                val = Math.Abs(val);
                if (val > max)
                {
                    max = val;
                }
            }

            if (max > 0)
            {
                // -------- set up the reflector Q_k
                double tau = QrHelperFunctions_DDRM.computeTauAndDivide(k, m, u, max);

                // write the reflector into the lower left column of the matrix
                // while dividing u by nu
                double nu = u[k] + tau;
                QrHelperFunctions_DDRM.divideElements_Bcol(k + 1, m, n, u, b, k, nu);
                u[k] = 1.0;

                double gamma = nu / tau;
                gammasU[k] = gamma;

                // ---------- multiply on the left by Q_k
                QrHelperFunctions_DDRM.rank1UpdateMultR(UBV, u, gamma, k + 1, k, m, this.b);

                b[k * n + k] = -tau * max;
            }
            else
            {
                gammasU[k] = 0;
            }
        }
        protected void computeV(int k)
        {
            double[] b = UBV.data;

            int row = k * n;

            // find the largest value in this column
            // this is used to normalize the column and mitigate overflow/underflow
            double max = QrHelperFunctions_DDRM.findMax(b, row + k + 1, n - k - 1);

            if (max > 0)
            {
                // -------- set up the reflector Q_k

                double tau = QrHelperFunctions_DDRM.computeTauAndDivide(k + 1, n, b, row, max);

                // write the reflector into the lower left column of the matrix
                double nu = b[row + k + 1] + tau;
                QrHelperFunctions_DDRM.divideElements_Brow(k + 2, n, u, b, row, nu);

                u[k + 1] = 1.0;

                double gamma = nu / tau;
                gammasV[k] = gamma;

                // writing to u could be avoided by working directly with b.
                // requires writing a custom rank1Update function
                // ---------- multiply on the left by Q_k
                QrHelperFunctions_DDRM.rank1UpdateMultL(UBV, u, gamma, k + 1, k + 1, n);

                b[row + k + 1] = -tau * max;
            }
            else
            {
                gammasV[k] = 0;
            }
        }