/** * Inverts an upper or lower triangular block submatrix. * * @param blockLength * @param upper Is it upper or lower triangular. * @param T Triangular matrix that is to be inverted. Overwritten with solution. Modified. * @param temp Work space variable that is size blockLength*blockLength. */ public static void invert(int blockLength, bool upper, DSubmatrixD1 T, double[] temp) { if (upper) { throw new ArgumentException("Upper triangular matrices not supported yet"); } if (temp.Length < blockLength * blockLength) { throw new ArgumentException("Temp must be at least blockLength*blockLength long."); } int M = T.row1 - T.row0; double[] dataT = T.original.data; int offsetT = T.row0 * T.original.numCols + M * T.col0; for (int i = 0; i < M; i += blockLength) { int heightT = Math.Min(T.row1 - (i + T.row0), blockLength); int indexII = offsetT + T.original.numCols * (i + T.row0) + heightT * (i + T.col0); for (int j = 0; j < i; j += blockLength) { int widthX = Math.Min(T.col1 - (j + T.col0), blockLength); for (int w = 0; w < temp.Length; w++) { temp[w] = 0; } for (int k = j; k < i; k += blockLength) { int widthT = Math.Min(T.col1 - (k + T.col0), blockLength); int indL = offsetT + T.original.numCols * (i + T.row0) + heightT * (k + T.col0); int indX = offsetT + T.original.numCols * (k + T.row0) + widthT * (j + T.col0); InnerMultiplication_DDRB.blockMultMinus(dataT, dataT, temp, indL, indX, 0, heightT, widthT, widthX); } int indexX = offsetT + T.original.numCols * (i + T.row0) + heightT * (j + T.col0); InnerTriangularSolver_DDRB.solveL(dataT, temp, heightT, widthX, heightT, indexII, 0); Array.Copy(temp, 0, dataT, indexX, widthX * heightT); } InnerTriangularSolver_DDRB.invertLower(dataT, heightT, indexII); } }
/** * <p> * Performs an in-place solve operation where T is contained in a single block.<br> * <br> * B = T<sup>-1</sup> B<br> * <br> * where T is a triangular matrix contained in an inner block. T or B can be transposed. T must be a single complete inner block * and B is either a column block vector or row block vector. * </p> * * @param blockLength Size of the inner blocks in the block matrix. * @param upper If T is upper or lower triangular. * @param T An upper or lower triangular matrix that is contained in an inner block. Not modified. * @param B A block aligned row or column submatrix. Modified. * @param transT If T is transposed or not. * @param transB If B is transposed or not. */ public static void solveBlock(int blockLength, bool upper, DSubmatrixD1 T, DSubmatrixD1 B, bool transT, bool transB) { int Trows = T.row1 - T.row0; if (Trows > blockLength) { throw new ArgumentException("T can be at most the size of a block"); } // number of rows in a block. The submatrix can be smaller than a block int blockT_rows = Math.Min(blockLength, T.original.numRows - T.row0); int blockT_cols = Math.Min(blockLength, T.original.numCols - T.col0); int offsetT = T.row0 * T.original.numCols + blockT_rows * T.col0; double[] dataT = T.original.data; double[] dataB = B.original.data; if (transB) { if (upper) { if (transT) { throw new ArgumentException("Operation not yet supported"); } else { throw new ArgumentException("Operation not yet supported"); } } else { if (transT) { throw new ArgumentException("Operation not yet supported"); } else { for (int i = B.row0; i < B.row1; i += blockLength) { int N = Math.Min(B.row1, i + blockLength) - i; int offsetB = i * B.original.numCols + N * B.col0; InnerTriangularSolver_DDRB.solveLTransB(dataT, dataB, blockT_rows, N, blockT_rows, offsetT, offsetB); } } } } else { if (Trows != B.row1 - B.row0) { throw new ArgumentException("T and B must have the same number of rows."); } if (upper) { if (transT) { for (int i = B.col0; i < B.col1; i += blockLength) { int offsetB = B.row0 * B.original.numCols + Trows * i; int N = Math.Min(B.col1, i + blockLength) - i; InnerTriangularSolver_DDRB.solveTransU(dataT, dataB, Trows, N, Trows, offsetT, offsetB); } } else { for (int i = B.col0; i < B.col1; i += blockLength) { int offsetB = B.row0 * B.original.numCols + Trows * i; int N = Math.Min(B.col1, i + blockLength) - i; InnerTriangularSolver_DDRB.solveU(dataT, dataB, Trows, N, Trows, offsetT, offsetB); } } } else { if (transT) { for (int i = B.col0; i < B.col1; i += blockLength) { int offsetB = B.row0 * B.original.numCols + Trows * i; int N = Math.Min(B.col1, i + blockLength) - i; InnerTriangularSolver_DDRB.solveTransL(dataT, dataB, Trows, N, blockT_cols, offsetT, offsetB); } } else { for (int i = B.col0; i < B.col1; i += blockLength) { int offsetB = B.row0 * B.original.numCols + Trows * i; int N = Math.Min(B.col1, i + blockLength) - i; InnerTriangularSolver_DDRB.solveL(dataT, dataB, Trows, N, blockT_cols, offsetT, offsetB); } } } } }