/** * <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 - γuu<sup>T</sup> * </p> * <p> * This function finds the values of 'u' and 'γ'. * </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 - γuu<sup>T</sup> * </p> * <p> * This function finds the values of 'u' and 'γ'. * </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; }
/** * 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; } }
/** * 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); }
/** * 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); }
/** * 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); }
/** * <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 - γuu<sup>T</sup> * </p> * <p> * This function finds the values of 'u' and 'γ'. * </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); }