/**
         * Returns the orthogonal V matrix.
         *
         * @param V If not null then the results will be stored here.  Otherwise a new matrix will be created.
         * @return The extracted Q matrix.
         */
        public virtual DMatrixRMaj getV(DMatrixRMaj V, bool transpose, bool compact)
        {
            V = handleV(V, transpose, compact, m, n, min);
            CommonOps_DDRM.setIdentity(V);

//        UBV.print();

            // todo the very first multiplication can be avoided by setting to the rank1update output
            for (int j = min - 1; j >= 0; j--)
            {
                u[j + 1] = 1;
                for (int i = j + 2; i < n; i++)
                {
                    u[i] = UBV.get(j, i);
                }
                if (transpose)
                {
                    QrHelperFunctions_DDRM.rank1UpdateMultL(V, u, gammasV[j], j + 1, j + 1, n);
                }
                else
                {
                    QrHelperFunctions_DDRM.rank1UpdateMultR(V, u, gammasV[j], j + 1, j + 1, n, this.b);
                }
            }

            return(V);
        }
        /**
         * Returns the orthogonal U matrix.
         *
         * @param U If not null then the results will be stored here.  Otherwise a new matrix will be created.
         * @return The extracted Q matrix.
         */
        public virtual DMatrixRMaj getU(DMatrixRMaj U, bool transpose, bool compact)
        {
            U = handleU(U, transpose, compact, m, n, min);
            CommonOps_DDRM.setIdentity(U);

            for (int i = 0; i < m; i++)
            {
                u[i] = 0;
            }

            for (int j = min - 1; j >= 0; j--)
            {
                u[j] = 1;
                for (int i = j + 1; i < m; i++)
                {
                    u[i] = UBV.get(i, j);
                }
                if (transpose)
                {
                    QrHelperFunctions_DDRM.rank1UpdateMultL(U, u, gammasU[j], j, j, m);
                }
                else
                {
                    QrHelperFunctions_DDRM.rank1UpdateMultR(U, u, gammasU[j], j, j, m, this.b);
                }
            }

            return(U);
        }
        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;
            }
        }
Ejemplo n.º 4
0
        /**
         * An orthogonal matrix that has the following property: T = Q<sup>T</sup>AQ
         *
         * @param Q If not null then the results will be stored here.  Otherwise a new matrix will be created.
         * @return The extracted Q matrix.
         */
        //@Override
        public DMatrixRMaj getQ(DMatrixRMaj Q, bool transposed)
        {
            Q = UtilDecompositons_DDRM.checkIdentity(Q, N, N);

            for (int i = 0; i < N; i++)
            {
                w[i] = 0;
            }

            if (transposed)
            {
                for (int j = N - 2; j >= 0; j--)
                {
                    w[j + 1] = 1;
                    for (int i = j + 2; i < N; i++)
                    {
                        w[i] = QT.data[j * N + i];
                    }
                    QrHelperFunctions_DDRM.rank1UpdateMultL(Q, w, gammas[j + 1], j + 1, j + 1, N);
                }
            }
            else
            {
                for (int j = N - 2; j >= 0; j--)
                {
                    w[j + 1] = 1;
                    for (int i = j + 2; i < N; i++)
                    {
                        w[i] = QT.get(j, i);
                    }
                    QrHelperFunctions_DDRM.rank1UpdateMultR(Q, w, gammas[j + 1], j + 1, j + 1, N, b);
                }
            }

            return(Q);
        }
        /**
         * Internal function for computing the decomposition.
         */
        private bool _decompose()
        {
            double[] h = QH.data;

            for (int k = 0; k < N - 2; k++)
            {
                // 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 + 1; i < N; 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] = h[i * N + k];
                    val = Math.Abs(val);
                    if (val > max)
                    {
                        max = val;
                    }
                }

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

                    double tau = 0;
                    // normalize to reduce overflow/underflow
                    // and compute tau for the reflector
                    for (int i = k + 1; i < N; i++)
                    {
                        double val = u[i] /= max;
                        tau += val * val;
                    }

                    tau = Math.Sqrt(tau);

                    if (u[k + 1] < 0)
                    {
                        tau = -tau;
                    }

                    // write the reflector into the lower left column of the matrix
                    double nu = u[k + 1] + tau;
                    u[k + 1] = 1.0;

                    for (int i = k + 2; i < N; i++)
                    {
                        h[i * N + k] = u[i] /= nu;
                    }

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

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

                    // ---------- multiply on the right by Q_k
                    QrHelperFunctions_DDRM.rank1UpdateMultL(QH, u, gamma, 0, k + 1, N);

                    // since the first element in the householder vector is known to be 1
                    // store the full upper hessenberg
                    h[(k + 1) * N + k] = -tau * max;
                }
                else
                {
                    gammas[k] = 0;
                }
            }

            return(true);
        }
Ejemplo n.º 6
0
        public bool bulgeSingleStepQn(int i,
                                      double a11, double a21,
                                      double threshold, bool set)
        {
            double max;

            if (normalize)
            {
                max = Math.Abs(a11);
                if (max < Math.Abs(a21))
                {
                    max = Math.Abs(a21);
                }

//            if( max <= Math.Abs(A.get(i,i))*UtilEjml.EPS ) {
                if (max <= threshold)
                {
//                Console.WriteLine("i = "+i);
//                A.print();
                    if (set)
                    {
                        A.set(i, i - 1, 0);
                        A.set(i + 1, i - 1, 0);
                    }
                    return(false);
                }

                a11 /= max;
                a21 /= max;
            }
            else
            {
                max = 1;
            }

            // compute the reflector using the b's above

            double tau = Math.Sqrt(a11 * a11 + a21 * a21);

            if (a11 < 0)
            {
                tau = -tau;
            }

            double div = a11 + tau;

            u.set(i, 0, 1);
            u.set(i + 1, 0, a21 / div);

            gamma = div / tau;

            // compute A_1 = Q_1^T * A * Q_1

            // apply Q*A  - just do the 3 rows
            QrHelperFunctions_DDRM.rank1UpdateMultR(A, u.data, gamma, 0, i, i + 2, _temp.data);

            if (set)
            {
                A.set(i, i - 1, -max * tau);
                A.set(i + 1, i - 1, 0);
            }

            // apply A*Q - just the three things
            QrHelperFunctions_DDRM.rank1UpdateMultL(A, u.data, gamma, 0, i, i + 2);

            if (checkUncountable && MatrixFeatures_DDRM.hasUncountable(A))
            {
                throw new InvalidOperationException("bad matrix");
            }

            return(true);
        }