public override /**/ double quality() { return(SpecializedOps_CDRM.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 override void solve(CMatrixRMaj B, CMatrixRMaj X) { if (X.numRows != numCols) { throw new ArgumentException("Unexpected dimensions for X: X rows = " + X.numRows + " expected = " + numCols); } else if (B.numRows != numRows || B.numCols != X.numCols) { throw new ArgumentException("Unexpected dimensions for B"); } 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++) { float[] u = QR[n]; float realVV = u[n * 2]; float imagVV = u[n * 2 + 1]; u[n * 2] = 1; u[n * 2 + 1] = 0; QrHelperFunctions_CDRM.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_CDRM.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]; } } }
/** * Internal function for computing the decomposition. */ private bool _decompose() { float[] h = QH.data; for (int k = 0; k < N - 2; k++) { // k = column u[k * 2] = 0; u[k * 2 + 1] = 0; float max = QrHelperFunctions_CDRM.extractColumnAndMax(QH, k + 1, N, k, u, 0); if (max > 0) { // -------- set up the reflector Q_k float gamma = QrHelperFunctions_CDRM.computeTauGammaAndDivide(k + 1, N, u, max, tau); gammas[k] = gamma; // divide u by u_0 float real_u_0 = u[(k + 1) * 2] + tau.real; float imag_u_0 = u[(k + 1) * 2 + 1] + tau.imaginary; QrHelperFunctions_CDRM.divideElements(k + 2, N, u, 0, real_u_0, imag_u_0); // write the reflector into the lower left column of the matrix for (int i = k + 2; i < N; i++) { h[(i * N + k) * 2] = u[i * 2]; h[(i * N + k) * 2 + 1] = u[i * 2 + 1]; } u[(k + 1) * 2] = 1; u[(k + 1) * 2 + 1] = 0; // ---------- multiply on the left by Q_k QrHelperFunctions_CDRM.rank1UpdateMultR(QH, u, 0, gamma, k + 1, k + 1, N, b); // ---------- multiply on the right by Q_k QrHelperFunctions_CDRM.rank1UpdateMultL(QH, u, 0, 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) * 2] = -tau.real * max; h[((k + 1) * N + k) * 2 + 1] = -tau.imaginary * max; } else { gammas[k] = 0; } } return(true); }
/** * An orthogonal matrix that has the following property: H = 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. */ public CMatrixRMaj getQ(CMatrixRMaj Q) { Q = UtilDecompositons_CDRM.checkIdentity(Q, N, N); //Arrays.fill(u,0,N*2,0); Array.Clear(u, 0, N * 2); for (int j = N - 2; j >= 0; j--) { QrHelperFunctions_CDRM.extractHouseholderColumn(QH, j + 1, N, j, u, 0); QrHelperFunctions_CDRM.rank1UpdateMultR(Q, u, 0, gammas[j], j + 1, j + 1, N, b); } return(Q); }
/** * An orthogonal matrix that has the following property: T = Q<sup>H</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 CMatrixRMaj getQ(CMatrixRMaj Q, bool transposed) { Q = UtilDecompositons_CDRM.checkIdentity(Q, N, N); Array.Clear(w, 0, N * 2); if (transposed) { for (int j = N - 2; j >= 0; j--) { QrHelperFunctions_CDRM.extractHouseholderRow(QT, j, j + 1, N, w, 0); QrHelperFunctions_CDRM.rank1UpdateMultL(Q, w, 0, gammas[j], j + 1, j + 1, N); } } else { for (int j = N - 2; j >= 0; j--) { QrHelperFunctions_CDRM.extractHouseholderRow(QT, j, j + 1, N, w, 0); QrHelperFunctions_CDRM.rank1UpdateMultR(Q, w, 0, gammas[j], j + 1, j + 1, N, b); } } return(Q); }