/** * 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 ZMatrixRMaj getQ(ZMatrixRMaj Q, bool compact) { if (compact) { Q = UtilDecompositons_ZDRM.checkIdentity(Q, numRows, minLength); } else { Q = UtilDecompositons_ZDRM.checkIdentity(Q, numRows, numRows); } for (int j = minLength - 1; j >= 0; j--) { double[] u = dataQR[j]; double vvReal = u[j * 2]; double vvImag = u[j * 2 + 1]; u[j * 2] = 1; u[j * 2 + 1] = 0; double gammaReal = gammas[j]; QrHelperFunctions_ZDRM.rank1UpdateMultR(Q, u, 0, gammaReal, j, j, numRows, v); u[j * 2] = vvReal; u[j * 2 + 1] = vvImag; } 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. */ //@Override public ZMatrixRMaj getQ(ZMatrixRMaj Q, bool compact) { if (compact) { Q = UtilDecompositons_ZDRM.checkIdentity(Q, numRows, minLength); } else { Q = UtilDecompositons_ZDRM.checkIdentity(Q, numRows, numRows); } // 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) * 2; double realBefore = QR.data[diagIndex]; double imagBefore = QR.data[diagIndex + 1]; QR.data[diagIndex] = 1; QR.data[diagIndex + 1] = 0; QrHelperFunctions_ZDRM.rank1UpdateMultR(Q, QR.data, j * numRows, gammas[j], j, j, numRows, v); QR.data[diagIndex] = realBefore; QR.data[diagIndex + 1] = imagBefore; } return(Q); }
/** * A = Q<sup>H</sup>*A * * @param A Matrix that is being multiplied by Q<sup>T</sup>. Is modified. */ public void applyTranQ(ZMatrixRMaj A) { for (int j = 0; j < minLength; j++) { int diagIndex = (j * numRows + j) * 2; double realBefore = QR.data[diagIndex]; double imagBefore = QR.data[diagIndex + 1]; QR.data[diagIndex] = 1; QR.data[diagIndex + 1] = 0; QrHelperFunctions_ZDRM.rank1UpdateMultR(A, QR.data, j * numRows, gammas[j], 0, j, numRows, v); QR.data[diagIndex] = realBefore; QR.data[diagIndex + 1] = imagBefore; } }
/** * 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. */ //@Override public ZMatrixRMaj getQ(ZMatrixRMaj Q, bool compact) { if (compact) { Q = UtilDecompositons_ZDRM.checkIdentity(Q, numRows, minLength); } else { Q = UtilDecompositons_ZDRM.checkIdentity(Q, numRows, numRows); } for (int j = minLength - 1; j >= 0; j--) { QrHelperFunctions_ZDRM.extractHouseholderColumn(QR, j, numRows, j, u, 0); QrHelperFunctions_ZDRM.rank1UpdateMultR(Q, u, 0, gammas[j], j, j, numRows, v); } return(Q); }
/** * <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>H</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) { // find the element with the largest absolute value in the column and make a copy double max = QrHelperFunctions_ZDRM.extractColumnAndMax(QR, j, numRows, j, u, 0); if (max <= 0.0) { gammas[j] = 0; error = true; } else { double gamma = QrHelperFunctions_ZDRM.computeTauGammaAndDivide(j, numRows, u, max, tau); gammas[j] = gamma; // divide u by u_0 double real_u_0 = u[j * 2] + tau.real; double imag_u_0 = u[j * 2 + 1] + tau.imaginary; QrHelperFunctions_ZDRM.divideElements(j + 1, numRows, u, 0, real_u_0, imag_u_0); // write the reflector into the lower left column of the matrix for (int i = j + 1; i < numRows; i++) { dataQR[(i * numCols + j) * 2] = u[i * 2]; dataQR[(i * numCols + j) * 2 + 1] = u[i * 2 + 1]; } u[j * 2] = 1; u[j * 2 + 1] = 0; QrHelperFunctions_ZDRM.rank1UpdateMultR(QR, u, 0, gamma, j + 1, j, numRows, v); // since the first element in the householder vector is known to be 1 // store the full upper hessenberg if (j < numCols) { dataQR[(j * numCols + j) * 2] = -tau.real * max; dataQR[(j * numCols + j) * 2 + 1] = -tau.imaginary * max; } } }
/** * A = Q*A * * @param A Matrix that is being multiplied by Q. Is modified. */ public void applyQ(ZMatrixRMaj 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) * 2; double realBefore = QR.data[diagIndex]; double imagBefore = QR.data[diagIndex + 1]; QR.data[diagIndex] = 1; QR.data[diagIndex + 1] = 0; QrHelperFunctions_ZDRM.rank1UpdateMultR(A, QR.data, j * numRows, gammas[j], 0, j, numRows, v); QR.data[diagIndex] = realBefore; QR.data[diagIndex + 1] = imagBefore; } }