public virtual /**/ double quality() { return(SpecializedOps_FDRM.qualityTriangular(decomposer.getT(null))); } /** * If X == null then the solution is written into B. Otherwise the solution is copied * from B into X. */ public virtual void solve(FMatrixRBlock B, FMatrixRBlock X) { if (B.blockLength != blockLength) { throw new ArgumentException("Unexpected blocklength in B."); } FSubmatrixD1 L = new FSubmatrixD1(decomposer.getT(null)); if (X != null) { if (X.blockLength != blockLength) { throw new ArgumentException("Unexpected blocklength in X."); } if (X.numRows != L.col1) { throw new ArgumentException("Not enough rows in X"); } } if (B.numRows != L.col1) { throw new ArgumentException("Not enough rows in B"); } // L * L^T*X = B // Solve for Y: L*Y = B TriangularSolver_FDRB.solve(blockLength, false, L, new FSubmatrixD1(B), false); // L^T * X = Y TriangularSolver_FDRB.solve(blockLength, false, L, new FSubmatrixD1(B), true); if (X != null) { // copy the solution from B into X MatrixOps_FDRB.extractAligned(B, X); } }
public virtual /**/ double quality() { return(SpecializedOps_FDRM.qualityTriangular(decomposer.getQR())); } public virtual void solve(FMatrixRBlock B, FMatrixRBlock X) { if (B.numCols != X.numCols) { throw new ArgumentException("Columns of B and X do not match"); } if (QR.numCols != X.numRows) { throw new ArgumentException("Rows in X do not match the columns in A"); } if (QR.numRows != B.numRows) { throw new ArgumentException("Rows in B do not match the rows in A."); } if (B.blockLength != QR.blockLength || X.blockLength != QR.blockLength) { throw new ArgumentException("All matrices must have the same block length."); } // The system being solved for can be described as: // Q*R*X = B // First apply householder reflectors to B // Y = Q^T*B decomposer.applyQTran(B); // Second solve for Y using the upper triangle matrix R and the just computed Y // X = R^-1 * Y MatrixOps_FDRB.extractAligned(B, X); // extract a block aligned matrix int M = Math.Min(QR.numRows, QR.numCols); TriangularSolver_FDRB.solve(QR.blockLength, true, new FSubmatrixD1(QR, 0, M, 0, M), new FSubmatrixD1(X), false); } /** * Invert by solving for against an identity matrix. * * @param A_inv Where the inverted matrix saved. Modified. */ public virtual void invert(FMatrixRBlock A_inv) { int M = Math.Min(QR.numRows, QR.numCols); if (A_inv.numRows != M || A_inv.numCols != M) { throw new ArgumentException("A_inv must be square an have dimension " + M); } // Solve for A^-1 // Q*R*A^-1 = I // Apply householder reflectors to the identity matrix // y = Q^T*I = Q^T MatrixOps_FDRB.setIdentity(A_inv); decomposer.applyQTran(A_inv); // Solve using upper triangular R matrix // R*A^-1 = y // A^-1 = R^-1*y TriangularSolver_FDRB.solve(QR.blockLength, true, new FSubmatrixD1(QR, 0, M, 0, M), new FSubmatrixD1(A_inv), false); }