예제 #1
0
        /**
         * <p>
         * Computes the householder vector "u" for the first column of submatrix j.  Note this is
         * a specialized householder for this problem.  There is some protection against
         * overflow and underflow.
         * </p>
         * <p>
         * Q = I - &gamma;uu<sup>T</sup>
         * </p>
         * <p>
         * This function finds the values of 'u' and '&gamma;'.
         * </p>
         *
         * @param j Which submatrix to work off of.
         */
        protected void householder(int j)
        {
            int startQR = j * numRows;
            int endQR   = startQR + numRows;

            startQR += j;

            float max = QrHelperFunctions_FDRM.findMax(QR.data, startQR, numRows - j);

            if (max == 0.0f)
            {
                gamma = 0;
                error = true;
            }
            else
            {
                // computes tau and normalizes u by max
                tau = QrHelperFunctions_FDRM.computeTauAndDivide(startQR, endQR, QR.data, max);

                // divide u by u_0
                float u_0 = QR.data[startQR] + tau;
                QrHelperFunctions_FDRM.divideElements(startQR + 1, endQR, QR.data, u_0);

                gamma = u_0 / tau;
                tau  *= max;

                QR.data[startQR] = -tau;
            }

            gammas[j] = gamma;
        }
        /**
         * <p>
         * Computes the householder vector "u" for the first column of submatrix j.  Note this is
         * a specialized householder for this problem.  There is some protection against
         * overfloaw and underflow.
         * </p>
         * <p>
         * Q = I - &gamma;uu<sup>T</sup>
         * </p>
         * <p>
         * This function finds the values of 'u' and '&gamma;'.
         * </p>
         *
         * @param j Which submatrix to work off of.
         */
        protected void householder(int j)
        {
            float[] u = dataQR[j];

            // find the largest value in this column
            // this is used to normalize the column and mitigate overflow/underflow
            float max = QrHelperFunctions_FDRM.findMax(u, j, numRows - j);

            if (max == 0.0f)
            {
                gamma = 0;
                error = true;
            }
            else
            {
                // computes tau and normalizes u by max
                tau = QrHelperFunctions_FDRM.computeTauAndDivide(j, numRows, u, max);

                // divide u by u_0
                float u_0 = u[j] + tau;
                QrHelperFunctions_FDRM.divideElements(j + 1, numRows, u, u_0);

                gamma = u_0 / tau;
                tau  *= max;

                u[j] = -tau;
            }

            gammas[j] = gamma;
        }
예제 #3
0
 /**
  * A = Q<sup>T</sup>*A
  *
  * @param A Matrix that is being multiplied by Q<sup>T</sup>.  Is modified.
  */
 public void applyTranQ(FMatrixRMaj A)
 {
     for (int j = 0; j < minLength; j++)
     {
         int   diagIndex = j * numRows + j;
         float before    = QR.data[diagIndex];
         QR.data[diagIndex] = 1;
         QrHelperFunctions_FDRM.rank1UpdateMultR(A, QR.data, j * numRows, gammas[j], 0, j, numRows, v);
         QR.data[diagIndex] = before;
     }
 }
예제 #4
0
        /**
         * Computes the Q matrix from the information stored in the QR matrix.  This
         * operation requires about 4(m<sup>2</sup>n-mn<sup>2</sup>+n<sup>3</sup>/3) flops.
         *
         * @param Q The orthogonal Q matrix.
         */
        public virtual FMatrixRMaj getQ(FMatrixRMaj Q, bool compact)
        {
            if (compact)
            {
                if (Q == null)
                {
                    Q = CommonOps_FDRM.identity(numRows, minLength);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != minLength)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_FDRM.setIdentity(Q);
                    }
                }
            }
            else
            {
                if (Q == null)
                {
                    Q = CommonOps_FDRM.identity(numRows);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != numRows)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_FDRM.setIdentity(Q);
                    }
                }
            }

            // Unlike applyQ() this takes advantage of zeros in the identity matrix
            // by not multiplying across all rows.
            for (int j = minLength - 1; j >= 0; j--)
            {
                int   diagIndex = j * numRows + j;
                float before    = QR.data[diagIndex];
                QR.data[diagIndex] = 1;
                QrHelperFunctions_FDRM.rank1UpdateMultR(Q, QR.data, j * numRows, gammas[j], j, j, numRows, v);
                QR.data[diagIndex] = before;
            }

            return(Q);
        }
        /**
         * Computes the Q matrix from the imformation stored in the QR matrix.  This
         * operation requires about 4(m<sup>2</sup>n-mn<sup>2</sup>+n<sup>3</sup>/3) flops.
         *
         * @param Q The orthogonal Q matrix.
         */
        //@Override
        public FMatrixRMaj getQ(FMatrixRMaj Q, bool compact)
        {
            if (compact)
            {
                if (Q == null)
                {
                    Q = CommonOps_FDRM.identity(numRows, minLength);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != minLength)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_FDRM.setIdentity(Q);
                    }
                }
            }
            else
            {
                if (Q == null)
                {
                    Q = CommonOps_FDRM.identity(numRows);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != numRows)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_FDRM.setIdentity(Q);
                    }
                }
            }

            for (int j = minLength - 1; j >= 0; j--)
            {
                u[j] = 1;
                for (int i = j + 1; i < numRows; i++)
                {
                    u[i] = QR.get(i, j);
                }
                QrHelperFunctions_FDRM.rank1UpdateMultR(Q, u, gammas[j], j, j, numRows, v);
            }

            return(Q);
        }
예제 #6
0
        /**
         * Computes the Q matrix from the information stored in the QR matrix.  This
         * operation requires about 4(m<sup>2</sup>n-mn<sup>2</sup>+n<sup>3</sup>/3) flops.
         *
         * @param Q The orthogonal Q matrix.
         */
        public override FMatrixRMaj getQ(FMatrixRMaj Q, bool compact)
        {
            if (compact)
            {
                if (Q == null)
                {
                    Q = CommonOps_FDRM.identity(numRows, minLength);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != minLength)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_FDRM.setIdentity(Q);
                    }
                }
            }
            else
            {
                if (Q == null)
                {
                    Q = CommonOps_FDRM.identity(numRows);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != numRows)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_FDRM.setIdentity(Q);
                    }
                }
            }

            for (int j = rank - 1; j >= 0; j--)
            {
                float[] u = dataQR[j];

                float vv = u[j];
                u[j] = 1;
                QrHelperFunctions_FDRM.rank1UpdateMultR(Q, u, gammas[j], j, j, numRows, v);
                u[j] = vv;
            }

            return(Q);
        }
예제 #7
0
        /**
         * A = Q*A
         *
         * @param A Matrix that is being multiplied by Q.  Is modified.
         */
        public void applyQ(FMatrixRMaj A)
        {
            if (A.numRows != numRows)
            {
                throw new ArgumentException("A must have at least " + numRows + " rows.");
            }

            for (int j = minLength - 1; j >= 0; j--)
            {
                int   diagIndex = j * numRows + j;
                float before    = QR.data[diagIndex];
                QR.data[diagIndex] = 1;
                QrHelperFunctions_FDRM.rank1UpdateMultR(A, QR.data, j * numRows, gammas[j], 0, j, numRows, v);
                QR.data[diagIndex] = before;
            }
        }
        /**
         * Computes the Q matrix from the imformation stored in the QR matrix.  This
         * operation requires about 4(m<sup>2</sup>n-mn<sup>2</sup>+n<sup>3</sup>/3) flops.
         *
         * @param Q The orthogonal Q matrix.
         */
        public virtual FMatrixRMaj getQ(FMatrixRMaj Q, bool compact)
        {
            if (compact)
            {
                Q = UtilDecompositons_FDRM.checkIdentity(Q, numRows, minLength);
            }
            else
            {
                Q = UtilDecompositons_FDRM.checkIdentity(Q, numRows, numRows);
            }

            for (int j = minLength - 1; j >= 0; j--)
            {
                float[] u = dataQR[j];

                float vv = u[j];
                u[j] = 1;
                QrHelperFunctions_FDRM.rank1UpdateMultR(Q, u, gammas[j], j, j, numRows, v);
                u[j] = vv;
            }

            return(Q);
        }
예제 #9
0
        /**
         * <p>
         * Computes the householder vector "u" for the first column of submatrix j. The already computed
         * norm is used and checks to see if the matrix is singular at this point.
         * </p>
         * <p>
         * Q = I - &gamma;uu<sup>T</sup>
         * </p>
         * <p>
         * This function finds the values of 'u' and '&gamma;'.
         * </p>
         *
         * @param j Which submatrix to work off of.
         * @return false if it is degenerate
         */
        protected bool householderPivot(int j)
        {
            float[] u = dataQR[j];

            // find the largest value in this column
            // this is used to normalize the column and mitigate overflow/underflow
            float max = QrHelperFunctions_FDRM.findMax(u, j, numRows - j);

            if (max <= 0)
            {
                return(false);
            }
            else
            {
                // computes tau and normalizes u by max
                tau = QrHelperFunctions_FDRM.computeTauAndDivide(j, numRows, u, max);

                // divide u by u_0
                float u_0 = u[j] + tau;
                QrHelperFunctions_FDRM.divideElements(j + 1, numRows, u, u_0);

                gamma = u_0 / tau;
                tau  *= max;

                u[j] = -tau;

                if (Math.Abs(tau) <= singularThreshold)
                {
                    return(false);
                }
            }

            gammas[j] = gamma;

            return(true);
        }