Пример #1
0
        /**
         * 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);
            }
        }
Пример #2
0
        /**
         * <p>
         * Performs an in-place solve operation where T is contained in a single block.<br>
         * <br>
         * B = T<sup>-1</sup> B<br>
         * <br>
         * where T is a triangular matrix contained in an inner block. T or B can be transposed.  T must be a single complete inner block
         * and B is either a column block vector or row block vector.
         * </p>
         *
         * @param blockLength Size of the inner blocks in the block matrix.
         * @param upper If T is upper or lower triangular.
         * @param T An upper or lower triangular matrix that is contained in an inner block. Not modified.
         * @param B A block aligned row or column submatrix. Modified.
         * @param transT If T is transposed or not.
         * @param transB If B is transposed or not.
         */
        public static void solveBlock(int blockLength,
                                      bool upper, FSubmatrixD1 T,
                                      FSubmatrixD1 B,
                                      bool transT, bool transB)
        {
            int Trows = T.row1 - T.row0;

            if (Trows > blockLength)
            {
                throw new ArgumentException("T can be at most the size of a block");
            }
            // number of rows in a block.  The submatrix can be smaller than a block
            int blockT_rows = Math.Min(blockLength, T.original.numRows - T.row0);
            int blockT_cols = Math.Min(blockLength, T.original.numCols - T.col0);

            int offsetT = T.row0 * T.original.numCols + blockT_rows * T.col0;

            float[] dataT = T.original.data;
            float[] dataB = B.original.data;

            if (transB)
            {
                if (upper)
                {
                    if (transT)
                    {
                        throw new ArgumentException("Operation not yet supported");
                    }
                    else
                    {
                        throw new ArgumentException("Operation not yet supported");
                    }
                }
                else
                {
                    if (transT)
                    {
                        throw new ArgumentException("Operation not yet supported");
                    }
                    else
                    {
                        for (int i = B.row0; i < B.row1; i += blockLength)
                        {
                            int N = Math.Min(B.row1, i + blockLength) - i;

                            int offsetB = i * B.original.numCols + N * B.col0;

                            InnerTriangularSolver_FDRB.solveLTransB(dataT, dataB, blockT_rows, N, blockT_rows, offsetT,
                                                                    offsetB);
                        }
                    }
                }
            }
            else
            {
                if (Trows != B.row1 - B.row0)
                {
                    throw new ArgumentException("T and B must have the same number of rows.");
                }

                if (upper)
                {
                    if (transT)
                    {
                        for (int i = B.col0; i < B.col1; i += blockLength)
                        {
                            int offsetB = B.row0 * B.original.numCols + Trows * i;

                            int N = Math.Min(B.col1, i + blockLength) - i;
                            InnerTriangularSolver_FDRB.solveTransU(dataT, dataB, Trows, N, Trows, offsetT, offsetB);
                        }
                    }
                    else
                    {
                        for (int i = B.col0; i < B.col1; i += blockLength)
                        {
                            int offsetB = B.row0 * B.original.numCols + Trows * i;

                            int N = Math.Min(B.col1, i + blockLength) - i;
                            InnerTriangularSolver_FDRB.solveU(dataT, dataB, Trows, N, Trows, offsetT, offsetB);
                        }
                    }
                }
                else
                {
                    if (transT)
                    {
                        for (int i = B.col0; i < B.col1; i += blockLength)
                        {
                            int offsetB = B.row0 * B.original.numCols + Trows * i;

                            int N = Math.Min(B.col1, i + blockLength) - i;
                            InnerTriangularSolver_FDRB.solveTransL(dataT, dataB, Trows, N, blockT_cols, offsetT,
                                                                   offsetB);
                        }
                    }
                    else
                    {
                        for (int i = B.col0; i < B.col1; i += blockLength)
                        {
                            int offsetB = B.row0 * B.original.numCols + Trows * i;

                            int N = Math.Min(B.col1, i + blockLength) - i;
                            InnerTriangularSolver_FDRB.solveL(dataT, dataB, Trows, N, blockT_cols, offsetT, offsetB);
                        }
                    }
                }
            }
        }