/** * <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) { double[] u = dataQR[j]; // find the largest value in this column // this is used to normalize the column and mitigate overflow/underflow double max = QrHelperFunctions_ZDRM.findMax(u, j, numRows - j); if (max == 0.0) { gamma = 0; error = true; } else { // computes tau and gamma, and normalizes u by max gamma = QrHelperFunctions_ZDRM.computeTauGammaAndDivide(j, numRows, u, max, tau); // divide u by u_0 // double u_0 = u[j] + tau; 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); tau.real *= max; tau.imaginary *= max; u[j * 2] = -tau.real; u[j * 2 + 1] = -tau.imaginary; } gammas[j] = gamma; }
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); }
override public /**/ double quality() { return(SpecializedOps_ZDRM.qualityTriangular(R)); } /** * Solves for X using the QR decomposition. * * @param B A matrix that is n by m. Not modified. * @param X An n by m matrix where the solution is written to. Modified. */ override public void solve(ZMatrixRMaj B, ZMatrixRMaj X) { UtilEjml.checkReshapeSolve(numRows, numCols, B, X); int BnumCols = B.numCols; // solve each column one by one for (int colB = 0; colB < BnumCols; colB++) { // make a copy of this column in the vector for (int i = 0; i < numRows; i++) { int indexB = (i * BnumCols + colB) * 2; a.data[i * 2] = B.data[indexB]; a.data[i * 2 + 1] = B.data[indexB + 1]; } // Solve Qa=b // a = Q'b // a = Q_{n-1}...Q_2*Q_1*b // // Q_n*b = (I-gamma*u*u^T)*b = b - u*(gamma*U^T*b) for (int n = 0; n < numCols; n++) { double[] u = QR[n]; double realVV = u[n * 2]; double imagVV = u[n * 2 + 1]; u[n * 2] = 1; u[n * 2 + 1] = 0; QrHelperFunctions_ZDRM.rank1UpdateMultR(a, u, 0, gammas[n], 0, n, numRows, temp.data); u[n * 2] = realVV; u[n * 2 + 1] = imagVV; } // solve for Rx = b using the standard upper triangular solver TriangularSolver_ZDRM.solveU(R.data, a.data, numCols); // save the results for (int i = 0; i < numCols; i++) { int indexB = (i * BnumCols + colB) * 2; X.data[indexB] = a.data[i * 2]; X.data[indexB + 1] = a.data[i * 2 + 1]; } } }