Example #1
0
        public static void multTransB(FMatrixRBlock A, FMatrixRBlock B, FMatrixRBlock C)
        {
            if (A.numCols != B.numCols)
            {
                throw new ArgumentException("Columns in A are incompatible with columns in B");
            }
            if (A.numRows != C.numRows)
            {
                throw new ArgumentException("Rows in A are incompatible with rows in C");
            }
            if (B.numRows != C.numCols)
            {
                throw new ArgumentException("Rows in B are incompatible with columns in C");
            }
            if (A.blockLength != B.blockLength || A.blockLength != C.blockLength)
            {
                throw new ArgumentException("Block lengths are not all the same.");
            }

            int blockLength = A.blockLength;

            FSubmatrixD1 Asub = new FSubmatrixD1(A, 0, A.numRows, 0, A.numCols);
            FSubmatrixD1 Bsub = new FSubmatrixD1(B, 0, B.numRows, 0, B.numCols);
            FSubmatrixD1 Csub = new FSubmatrixD1(C, 0, C.numRows, 0, C.numCols);

            MatrixMult_FDRB.multTransB(blockLength, Asub, Bsub, Csub);
        }
        /**
         * <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);
                        }
                    }
                }
            }
        }
        /**
         * <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,
                                  FSubmatrixD1 L,
                                  FSubmatrixD1 B,
                                  bool transL)
        {
            FSubmatrixD1 Y = new FSubmatrixD1(B.original);

            FSubmatrixD1 Linner = new FSubmatrixD1(L.original);
            FSubmatrixD1 Binner = new FSubmatrixD1(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_FDRB.multMinusTransA(blockLength, Linner, Binner, Y);
                        }
                        else
                        {
                            // Y = Y - T * B
                            MatrixMult_FDRB.multMinus(blockLength, Linner, Binner, Y);
                        }
                    }
                }
            }
        }