/// <inheritdoc/> public RealMatrix solve(RealMatrix b) { int n = qrt.Length; int m = qrt[0].Length; if (b.getRowDimension() != m) { throw new DimensionMismatchException(b.getRowDimension(), m); } if (!isNonSingular()) { throw new SingularMatrixException(); } int columns = b.getColumnDimension(); int blockSize = BlockRealMatrix.BLOCK_SIZE; int cBlocks = (columns + blockSize - 1) / blockSize; double[][] xBlocks = BlockRealMatrix.createBlocksLayout(n, columns); double[][] y = new double[b.getRowDimension()][]; double[] alpha = new double[blockSize]; for (int kBlock = 0; kBlock < cBlocks; ++kBlock) { int kStart = kBlock * blockSize; int kEnd = FastMath.min(kStart + blockSize, columns); int kWidth = kEnd - kStart; // get the right hand side vector b.copySubMatrix(0, m - 1, kStart, kEnd - 1, y); // apply Householder transforms to solve Q.y = b for (int minor = 0; minor < FastMath.min(m, n); minor++) { double[] qrtMinor = qrt[minor]; double factor = 1.0 / (rDiag[minor] * qrtMinor[minor]); for (int i = 0; i < kWidth; ++i) { alpha[i] = 0.0d; } for (int row = minor; row < m; ++row) { double d = qrtMinor[row]; double[] yRow = y[row]; for (int k = 0; k < kWidth; ++k) { alpha[k] += d * yRow[k]; } } for (int k = 0; k < kWidth; ++k) { alpha[k] *= factor; } for (int row = minor; row < m; ++row) { double d = qrtMinor[row]; double[] yRow = y[row]; for (int k = 0; k < kWidth; ++k) { yRow[k] += alpha[k] * d; } } } // solve triangular system R.x = y for (int j = rDiag.Length - 1; j >= 0; --j) { int jBlock = j / blockSize; int jStart = jBlock * blockSize; double factor = 1.0 / rDiag[j]; double[] yJ = y[j]; double[] xBlock = xBlocks[jBlock * cBlocks + kBlock]; int index = (j - jStart) * kWidth; for (int k = 0; k < kWidth; ++k) { yJ[k] *= factor; xBlock[index++] = yJ[k]; } double[] qrtJ = qrt[j]; for (int i = 0; i < j; ++i) { double rIJ = qrtJ[i]; double[] yI = y[i]; for (int k = 0; k < kWidth; ++k) { yI[k] -= yJ[k] * rIJ; } } } } return(new BlockRealMatrix(n, columns, xBlocks, false)); }