Ejemplo n.º 1
0
            /// <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));
            }