public void convertBlockToRow(int numRows, int numCols, int blockLength, float[] data) { int tmpLength = Math.Min(blockLength, numRows) * numCols; if (tmp == null || tmp.Length < tmpLength) { tmp = new float[tmpLength]; } MatrixOps_FDRB.convertBlockToRow(numRows, numCols, Ablock.blockLength, data, tmp); }
public virtual FMatrixRMaj getT(FMatrixRMaj T) { FMatrixRBlock T_block = ((CholeskyOuterForm_FDRB)alg).getT(null); if (T == null) { T = new FMatrixRMaj(T_block.numRows, T_block.numCols); } MatrixOps_FDRB.convert(T_block, T); // todo set zeros return(T); }
//@Override public FMatrixRMaj getR(FMatrixRMaj R, bool compact) { FMatrixRBlock Rblock; Rblock = ((QRDecompositionHouseholder_FDRB)alg).getR(null, compact); if (R == null) { R = new FMatrixRMaj(Rblock.numRows, Rblock.numCols); } MatrixOps_FDRB.convert(Rblock, R); return(R); }
/** * Sanity checks the input or declares a new matrix. Return matrix is an identity matrix. */ public static FMatrixRBlock initializeQ(FMatrixRBlock Q, int numRows, int numCols, int blockLength, bool compact) { int minLength = Math.Min(numRows, numCols); if (compact) { if (Q == null) { Q = new FMatrixRBlock(numRows, minLength, blockLength); MatrixOps_FDRB.setIdentity(Q); } else { if (Q.numRows != numRows || Q.numCols != minLength) { throw new ArgumentException("Unexpected matrix dimension. Found " + Q.numRows + " " + Q.numCols); } else { MatrixOps_FDRB.setIdentity(Q); } } } else { if (Q == null) { Q = new FMatrixRBlock(numRows, numRows, blockLength); MatrixOps_FDRB.setIdentity(Q); } else { if (Q.numRows != numRows || Q.numCols != numRows) { throw new ArgumentException("Unexpected matrix dimension. Found " + Q.numRows + " " + Q.numCols); } else { MatrixOps_FDRB.setIdentity(Q); } } } return(Q); }
private bool decomposeLower() { int blockLength = T.blockLength; subA.set(T); subB.set(T); subC.set(T); for (int i = 0; i < T.numCols; i += blockLength) { int widthA = Math.Min(blockLength, T.numCols - i); subA.col0 = i; subA.col1 = i + widthA; subA.row0 = subA.col0; subA.row1 = subA.col1; subB.col0 = i; subB.col1 = i + widthA; subB.row0 = i + widthA; subB.row1 = T.numRows; subC.col0 = i + widthA; subC.col1 = T.numRows; subC.row0 = i + widthA; subC.row1 = T.numRows; // cholesky on inner block A if (!InnerCholesky_FDRB.lower(subA)) { return(false); } // on the last block these operations are not needed. if (widthA == blockLength) { // B = L^-1 B TriangularSolver_FDRB.solveBlock(blockLength, false, subA, subB, false, true); // C = C - B * B^T InnerRankUpdate_FDRB.symmRankNMinus_L(blockLength, subC, subB); } } MatrixOps_FDRB.zeroTriangle(true, T); return(true); }
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); }