private static void checkInput(int blockLength, FSubmatrixD1 A, FSubmatrixD1 B, FSubmatrixD1 C) { int Arow = A.getRows(); int Acol = A.getCols(); int Brow = B.getRows(); int Bcol = B.getCols(); int Crow = C.getRows(); int Ccol = C.getCols(); if (Arow != Crow) { throw new InvalidOperationException("Mismatch A and C rows"); } if (Bcol != Ccol) { throw new InvalidOperationException("Mismatch B and C columns"); } if (Acol != Brow) { throw new InvalidOperationException("Mismatch A columns and B rows"); } if (!MatrixOps_FDRB.blockAligned(blockLength, A)) { throw new InvalidOperationException("Sub-Matrix A is not block aligned"); } if (!MatrixOps_FDRB.blockAligned(blockLength, B)) { throw new InvalidOperationException("Sub-Matrix B is not block aligned"); } if (!MatrixOps_FDRB.blockAligned(blockLength, C)) { throw new InvalidOperationException("Sub-Matrix C is not block aligned"); } }
/** * <p> * Solves upper triangular systems:<br> * <br> * B = R<sup>-1</sup> B<br> * <br> * </p> * * <p>Only the first B.numRows rows in R will be processed. Lower triangular elements are ignored.<p> * * <p> Reverse or forward substitution is used depending upon L being transposed or not. </p> * * @param blockLength * @param R Upper triangular with dimensions m by m. Not modified. * @param B A matrix with dimensions m by n. Solution is written into here. Modified. * @param transR Is the triangular matrix transposed? */ public static void solveR(int blockLength, FSubmatrixD1 R, FSubmatrixD1 B, bool transR) { int lengthR = B.row1 - B.row0; if (R.getCols() != lengthR) { throw new ArgumentException("Number of columns in R must be equal to the number of rows in B"); } else if (R.getRows() != lengthR) { throw new ArgumentException("Number of rows in R must be equal to the number of rows in B"); } FSubmatrixD1 Y = new FSubmatrixD1(B.original); FSubmatrixD1 Rinner = new FSubmatrixD1(R.original); FSubmatrixD1 Binner = new FSubmatrixD1(B.original); int startI, stepI; if (transR) { startI = 0; stepI = blockLength; } else { startI = lengthR - lengthR % blockLength; if (startI == lengthR && lengthR >= blockLength) { startI -= blockLength; } stepI = -blockLength; } for (int i = startI;; i += stepI) { if (transR) { if (i >= lengthR) { break; } } else { if (i < 0) { break; } } // width and height of the inner T(i,i) block int widthT = Math.Min(blockLength, lengthR - i); Rinner.col0 = R.col0 + i; Rinner.col1 = Rinner.col0 + widthT; Rinner.row0 = R.row0 + i; Rinner.row1 = Rinner.row0 + widthT; Binner.col0 = B.col0; Binner.col1 = B.col1; Binner.row0 = B.row0 + i; Binner.row1 = Binner.row0 + widthT; // solve the top row block // B(i,:) = T(i,i)^-1 Y(i,:) solveBlock(blockLength, true, Rinner, Binner, transR, false); bool updateY; if (transR) { updateY = Rinner.row1 < R.row1; } else { updateY = Rinner.row0 > 0; } if (updateY) { // Y[i,:] = Y[i,:] - sum j=1:i-1 { T[i,j] B[j,i] } // where i is the next block down // The summation is a block inner product if (transR) { Rinner.col0 = Rinner.col1; Rinner.col1 = Math.Min(Rinner.col0 + blockLength, R.col1); Rinner.row0 = R.row0; //Rinner.row1 = Rinner.row1; Binner.row0 = B.row0; //Binner.row1 = Binner.row1; Y.row0 = Binner.row1; Y.row1 = Math.Min(Y.row0 + blockLength, B.row1); } else { Rinner.row1 = Rinner.row0; Rinner.row0 = Rinner.row1 - blockLength; Rinner.col1 = R.col1; // Binner.row0 = Binner.row0; Binner.row1 = B.row1; Y.row0 = Binner.row0 - blockLength; Y.row1 = Binner.row0; } // step through each block column for (int k = B.col0; k < B.col1; k += blockLength) { Binner.col0 = k; Binner.col1 = Math.Min(k + blockLength, B.col1); Y.col0 = Binner.col0; Y.col1 = Binner.col1; if (transR) { // Y = Y - T^T * B MatrixMult_FDRB.multMinusTransA(blockLength, Rinner, Binner, Y); } else { // Y = Y - T * B MatrixMult_FDRB.multMinus(blockLength, Rinner, Binner, Y); } } } } }