/** * <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, DSubmatrixD1 R, DSubmatrixD1 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"); } DSubmatrixD1 Y = new DSubmatrixD1(B.original); DSubmatrixD1 Rinner = new DSubmatrixD1(R.original); DSubmatrixD1 Binner = new DSubmatrixD1(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_DDRB.multMinusTransA(blockLength, Rinner, Binner, Y); } else { // Y = Y - T * B MatrixMult_DDRB.multMinus(blockLength, Rinner, Binner, Y); } } } } }
/** * <p> * Solves lower triangular systems:<br> * <br> * B = L<sup>-1</sup> B<br> * <br> * </p> * * <p> Reverse or forward substitution is used depending upon L being transposed or not. </p> * * @param blockLength * @param L Lower triangular with dimensions m by m. Not modified. * @param B A matrix with dimensions m by n. Solution is written into here. Modified. * @param transL Is the triangular matrix transposed? */ public static void solveL(int blockLength, DSubmatrixD1 L, DSubmatrixD1 B, bool transL) { DSubmatrixD1 Y = new DSubmatrixD1(B.original); DSubmatrixD1 Linner = new DSubmatrixD1(L.original); DSubmatrixD1 Binner = new DSubmatrixD1(B.original); int lengthL = B.row1 - B.row0; int startI, stepI; if (transL) { startI = lengthL - lengthL % blockLength; if (startI == lengthL && lengthL >= blockLength) { startI -= blockLength; } stepI = -blockLength; } else { startI = 0; stepI = blockLength; } for (int i = startI;; i += stepI) { if (transL) { if (i < 0) { break; } } else { if (i >= lengthL) { break; } } // width and height of the inner T(i,i) block int widthT = Math.Min(blockLength, lengthL - i); Linner.col0 = L.col0 + i; Linner.col1 = Linner.col0 + widthT; Linner.row0 = L.row0 + i; Linner.row1 = Linner.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, false, Linner, Binner, transL, false); bool updateY; if (transL) { updateY = Linner.row0 > 0; } else { updateY = Linner.row1 < L.row1; } 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 (transL) { Linner.col1 = Linner.col0; Linner.col0 = Linner.col1 - blockLength; Linner.row1 = L.row1; //Tinner.col1 = Tinner.col1; // Binner.row0 = Binner.row0; Binner.row1 = B.row1; Y.row0 = Binner.row0 - blockLength; Y.row1 = Binner.row0; } else { Linner.row0 = Linner.row1; Linner.row1 = Math.Min(Linner.row0 + blockLength, L.row1); Linner.col0 = L.col0; //Tinner.col1 = Tinner.col1; Binner.row0 = B.row0; //Binner.row1 = Binner.row1; Y.row0 = Binner.row1; Y.row1 = Math.Min(Y.row0 + blockLength, B.row1); } // 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 (transL) { // Y = Y - T^T * B MatrixMult_DDRB.multMinusTransA(blockLength, Linner, Binner, Y); } else { // Y = Y - T * B MatrixMult_DDRB.multMinus(blockLength, Linner, Binner, Y); } } } } }