/** * <p> * Performs a matrix multiplication on {@link FMatrixRBlock} submatrices.<br> * <br> * c = c - a * b <br> * <br> * </p> * * <p> * It is assumed that all submatrices start at the beginning of a block and end at the end of a block. * </p> * * @param blockLength Size of the blocks in the submatrix. * @param A A submatrix. Not modified. * @param B A submatrix. Not modified. * @param C Result of the operation. Modified, */ public static void multMinus(int blockLength, FSubmatrixD1 A, FSubmatrixD1 B, FSubmatrixD1 C) { checkInput(blockLength, A, B, C); for (int i = A.row0; i < A.row1; i += blockLength) { int heightA = Math.Min(blockLength, A.row1 - i); for (int j = B.col0; j < B.col1; j += blockLength) { int widthB = Math.Min(blockLength, B.col1 - j); int indexC = (i - A.row0 + C.row0) * C.original.numCols + (j - B.col0 + C.col0) * heightA; for (int k = A.col0; k < A.col1; k += blockLength) { int widthA = Math.Min(blockLength, A.col1 - k); int indexA = i * A.original.numCols + k * heightA; int indexB = (k - A.col0 + B.row0) * B.original.numCols + j * widthA; InnerMultiplication_FDRB.blockMultMinus(A.original.data, B.original.data, C.original.data, indexA, indexB, indexC, heightA, widthA, widthB); } } } }
/** * 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, FSubmatrixD1 T, float[] 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; float[] 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_FDRB.blockMultMinus(dataT, dataT, temp, indL, indX, 0, heightT, widthT, widthX); } int indexX = offsetT + T.original.numCols * (i + T.row0) + heightT * (j + T.col0); InnerTriangularSolver_FDRB.solveL(dataT, temp, heightT, widthX, heightT, indexII, 0); Array.Copy(temp, 0, dataT, indexX, widthX * heightT); } InnerTriangularSolver_FDRB.invertLower(dataT, heightT, indexII); } }