Exemple #1
0
        /**
         * <p>
         * Performs a matrix multiplication with a transpose on {@link DMatrixRBlock} submatrices.<br>
         * <br>
         * c = a * b <sup>T</sup> <br>
         * <br>
         * </p>
         *
         * <p>
         * It is assumed that all submatrices start at the beginning of a block and end at the end of a block.
         * </p>
         *
         * @param blockLength Length of the blocks in the submatrix.
         * @param A A submatrix.  Not modified.
         * @param B A submatrix.  Not modified.
         * @param C Result of the operation.  Modified,
         */
        public static void multTransB(int blockLength, DSubmatrixD1 A, DSubmatrixD1 B, DSubmatrixD1 C)
        {
            for (int i = A.row0; i < A.row1; i += blockLength)
            {
                int heightA = Math.Min(blockLength, A.row1 - i);

                for (int j = B.row0; j < B.row1; j += blockLength)
                {
                    int widthC = Math.Min(blockLength, B.row1 - j);

                    int indexC = (i - A.row0 + C.row0) * C.original.numCols + (j - B.row0 + C.col0) * heightA;

                    for (int k = A.col0; k < A.col1; k += blockLength)
                    {
                        int widthA = Math.Min(blockLength, A.col1 - k);

                        int indexA = i * A.original.numCols + k * heightA;
                        int indexB = j * B.original.numCols + (k - A.col0 + B.col0) * widthC;

                        if (k == A.col0)
                        {
                            InnerMultiplication_DDRB.blockMultSetTransB(A.original.data, B.original.data, C.original.data,
                                                                        indexA, indexB, indexC, heightA, widthA, widthC);
                        }
                        else
                        {
                            InnerMultiplication_DDRB.blockMultPlusTransB(A.original.data, B.original.data, C.original.data,
                                                                         indexA, indexB, indexC, heightA, widthA, widthC);
                        }
                    }
                }
            }
        }
Exemple #2
0
        public static void multTransB(DMatrixRBlock A, DMatrixRBlock B, DMatrixRBlock 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;

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

            MatrixMult_DDRB.multTransB(blockLength, Asub, Bsub, Csub);
        }
Exemple #3
0
        /**
         * <p>
         * Performs a matrix multiplication on {@link DMatrixRBlock} submatrices.<br>
         * <br>
         * c = c + a * b <br>
         * <br>
         * </p>
         *
         * <p>
         * It is assumed that all submatrices start at the beginning of a block and end at the end of a block.
         * </p>
         *
         * @param blockLength Size of the blocks in the submatrix.
         * @param A A submatrix.  Not modified.
         * @param B A submatrix.  Not modified.
         * @param C Result of the operation.  Modified,
         */
        public static void multPlus(int blockLength, DSubmatrixD1 A, DSubmatrixD1 B, DSubmatrixD1 C)
        {
//        checkInput( blockLength,A,B,C);

            for (int i = A.row0; i < A.row1; i += blockLength)
            {
                int heightA = Math.Min(blockLength, A.row1 - i);

                for (int j = B.col0; j < B.col1; j += blockLength)
                {
                    int widthB = Math.Min(blockLength, B.col1 - j);

                    int indexC = (i - A.row0 + C.row0) * C.original.numCols + (j - B.col0 + C.col0) * heightA;

                    for (int k = A.col0; k < A.col1; k += blockLength)
                    {
                        int widthA = Math.Min(blockLength, A.col1 - k);

                        int indexA = i * A.original.numCols + k * heightA;
                        int indexB = (k - A.col0 + B.row0) * B.original.numCols + j * widthA;

                        InnerMultiplication_DDRB.blockMultPlus(A.original.data, B.original.data, C.original.data,
                                                               indexA, indexB, indexC, heightA, widthA, widthB);
                    }
                }
            }
        }
Exemple #4
0
        /**
         * <p>
         * Row vector scale:<br>
         * scale: b<sub>i</sub> = &alpha;*a<sub>i</sub><br>
         * where 'a' and 'b' are row vectors within the row block vector A and B.
         * </p>
         *
         * @param A submatrix. Not modified.
         * @param rowA which row in A the vector is contained in.
         * @param alpha scale factor.
         * @param B submatrix that the results are written to.  Modified.
         * @param offset Index at which the vectors start at.
         * @param end Index at which the vectors end at.
         */
        public static void scale_row(int blockLength,
                                     DSubmatrixD1 A, int rowA,
                                     double alpha, DSubmatrixD1 B, int rowB,
                                     int offset, int end)
        {
            double[] dataA = A.original.data;
            double[] dataB = B.original.data;

            // handle the case where offset is more than a block
            int startI = offset - offset % blockLength;

            offset = offset % blockLength;

            // handle rows in any block
            int rowBlockA = A.row0 + rowA - rowA % blockLength;

            rowA = rowA % blockLength;
            int rowBlockB = B.row0 + rowB - rowB % blockLength;

            rowB = rowB % blockLength;

            int heightA = Math.Min(blockLength, A.row1 - rowBlockA);
            int heightB = Math.Min(blockLength, B.row1 - rowBlockB);

            for (int i = startI; i < end; i += blockLength)
            {
                int segment = Math.Min(blockLength, end - i);

                int widthA = Math.Min(blockLength, A.col1 - A.col0 - i);
                int widthB = Math.Min(blockLength, B.col1 - B.col0 - i);

                int indexA = rowBlockA * A.original.numCols + (A.col0 + i) * heightA + rowA * widthA;
                int indexB = rowBlockB * B.original.numCols + (B.col0 + i) * heightB + rowB * widthB;

                if (i == startI)
                {
                    indexA += offset;
                    indexB += offset;

                    for (int j = offset; j < segment; j++)
                    {
                        dataB[indexB++] = alpha * dataA[indexA++];
                    }
                }
                else
                {
                    for (int j = 0; j < segment; j++)
                    {
                        dataB[indexB++] = alpha * dataA[indexA++];
                    }
                }
            }
        }
Exemple #5
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,
                                  DSubmatrixD1 T,
                                  double[] 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;

            double[] 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_DDRB.blockMultMinus(dataT, dataT, temp, indL, indX, 0, heightT, widthT, widthX);
                    }

                    int indexX = offsetT + T.original.numCols * (i + T.row0) + heightT * (j + T.col0);

                    InnerTriangularSolver_DDRB.solveL(dataT, temp, heightT, widthX, heightT, indexII, 0);
                    Array.Copy(temp, 0, dataT, indexX, widthX * heightT);
                }
                InnerTriangularSolver_DDRB.invertLower(dataT, heightT, indexII);
            }
        }
Exemple #6
0
        /**
         * <p>
         * Row vector add:<br>
         * add: c<sub>i</sub> = &alpha;*a<sub>i</sub> + &beta;B<sub>i</sub><br>
         * where 'a', 'b', and 'c' are row vectors within the row block vectors of A, B, and C respectively.
         * </p>
         *
         * @param blockLength Length of each inner matrix block.
         * @param A submatrix. Not modified.
         * @param rowA which row in A the vector is contained in.
         * @param alpha scale factor of A
         * @param B submatrix. Not modified.
         * @param rowB which row in B the vector is contained in.
         * @param beta scale factor of B
         * @param C submatrix where the results are written to. Modified.
         * @param rowC which row in C is the vector contained.
         * @param offset Index at which the vectors start at.
         * @param end Index at which the vectors end at.
         */
        public static void add_row(int blockLength,
                                   DSubmatrixD1 A, int rowA, double alpha,
                                   DSubmatrixD1 B, int rowB, double beta,
                                   DSubmatrixD1 C, int rowC,
                                   int offset, int end)
        {
            int heightA = Math.Min(blockLength, A.row1 - A.row0);
            int heightB = Math.Min(blockLength, B.row1 - B.row0);
            int heightC = Math.Min(blockLength, C.row1 - C.row0);

            // handle the case where offset is more than a block
            int startI = offset - offset % blockLength;

            offset = offset % blockLength;

            double[] dataA = A.original.data;
            double[] dataB = B.original.data;
            double[] dataC = C.original.data;

            for (int i = startI; i < end; i += blockLength)
            {
                int segment = Math.Min(blockLength, end - i);

                int widthA = Math.Min(blockLength, A.col1 - A.col0 - i);
                int widthB = Math.Min(blockLength, B.col1 - B.col0 - i);
                int widthC = Math.Min(blockLength, C.col1 - C.col0 - i);

                int indexA = A.row0 * A.original.numCols + (A.col0 + i) * heightA + rowA * widthA;
                int indexB = B.row0 * B.original.numCols + (B.col0 + i) * heightB + rowB * widthB;
                int indexC = C.row0 * C.original.numCols + (C.col0 + i) * heightC + rowC * widthC;

                if (i == startI)
                {
                    indexA += offset;
                    indexB += offset;
                    indexC += offset;

                    for (int j = offset; j < segment; j++)
                    {
                        dataC[indexC++] = alpha * dataA[indexA++] + beta * dataB[indexB++];
                    }
                }
                else
                {
                    for (int j = 0; j < segment; j++)
                    {
                        dataC[indexC++] = alpha * dataA[indexA++] + beta * dataB[indexB++];
                    }
                }
            }
        }
        /**
         * <p>
         * Rank N update function for a symmetric inner submatrix and only operates on the upper
         * triangular portion of the submatrix.<br>
         * <br>
         * A = A - B <sup>T</sup>B
         * </p>
         */
        public static void symmRankNMinus_U(int blockLength,
                                            DSubmatrixD1 A, DSubmatrixD1 B)
        {
            int heightB = B.row1 - B.row0;

            if (heightB > blockLength)
            {
                throw new ArgumentException("Height of B cannot be greater than the block length");
            }

            int N = B.col1 - B.col0;

            if (A.col1 - A.col0 != N)
            {
                throw new ArgumentException("A does not have the expected number of columns based on B's width");
            }
            if (A.row1 - A.row0 != N)
            {
                throw new ArgumentException("A does not have the expected number of rows based on B's width");
            }


            for (int i = B.col0; i < B.col1; i += blockLength)
            {
                int indexB_i = B.row0 * B.original.numCols + i * heightB;
                int widthB_i = Math.Min(blockLength, B.col1 - i);

                int rowA    = i - B.col0 + A.row0;
                int heightA = Math.Min(blockLength, A.row1 - rowA);

                for (int j = i; j < B.col1; j += blockLength)
                {
                    int widthB_j = Math.Min(blockLength, B.col1 - j);

                    int indexA   = rowA * A.original.numCols + (j - B.col0 + A.col0) * heightA;
                    int indexB_j = B.row0 * B.original.numCols + j * heightB;

                    if (i == j)
                    {
                        // only the upper portion of this block needs to be modified since it is along a diagonal
                        multTransABlockMinus_U(B.original.data, A.original.data,
                                               indexB_i, indexB_j, indexA, heightB, widthB_i, widthB_j);
                    }
                    else
                    {
                        multTransABlockMinus(B.original.data, A.original.data,
                                             indexB_i, indexB_j, indexA, heightB, widthB_i, widthB_j);
                    }
                }
            }
        }
Exemple #8
0
 /**
  * <p>
  * Performs an in-place solve operation on the provided block aligned sub-matrices.<br>
  * <br>
  * B = T<sup>-1</sup> B<br>
  * <br>
  * where T is a triangular matrix. T or B can be transposed.  T is a square matrix of arbitrary
  * size and B has the same number of rows as T and an arbitrary number of columns.
  * </p>
  *
  * @param blockLength Size of the inner blocks.
  * @param upper If T is upper or lower triangular.
  * @param T An upper or lower triangular matrix. Not modified.
  * @param B A matrix whose height is the same as T's width. Solution is written here. Modified.
  */
 public static void solve(int blockLength,
                          bool upper,
                          DSubmatrixD1 T,
                          DSubmatrixD1 B,
                          bool transT)
 {
     if (upper)
     {
         solveR(blockLength, T, B, transT);
     }
     else
     {
         solveL(blockLength, T, B, transT);
     }
 }
        /**
         * <p>
         * Rank N update function for a symmetric inner submatrix and only operates on the lower
         * triangular portion of the submatrix.<br>
         * <br>
         * A = A - B*B<sup>T</sup><br>
         * </p>
         */
        public static void symmRankNMinus_L(int blockLength, DSubmatrixD1 A, DSubmatrixD1 B)
        {
            int widthB = B.col1 - B.col0;

            if (widthB > blockLength)
            {
                throw new ArgumentException("Width of B cannot be greater than the block length");
            }

            int N = B.row1 - B.row0;

            if (A.col1 - A.col0 != N)
            {
                throw new ArgumentException("A does not have the expected number of columns based on B's height");
            }
            if (A.row1 - A.row0 != N)
            {
                throw new ArgumentException("A does not have the expected number of rows based on B's height");
            }

            for (int i = B.row0; i < B.row1; i += blockLength)
            {
                int heightB_i = Math.Min(blockLength, B.row1 - i);
                int indexB_i  = i * B.original.numCols + heightB_i * B.col0;

                int rowA    = i - B.row0 + A.row0;
                int heightA = Math.Min(blockLength, A.row1 - rowA);

                for (int j = B.row0; j <= i; j += blockLength)
                {
                    int widthB_j = Math.Min(blockLength, B.row1 - j);

                    int indexA   = rowA * A.original.numCols + (j - B.row0 + A.col0) * heightA;
                    int indexB_j = j * B.original.numCols + widthB_j * B.col0;

                    if (i == j)
                    {
                        multTransBBlockMinus_L(B.original.data, A.original.data,
                                               indexB_i, indexB_j, indexA, widthB, heightB_i, widthB_j);
                    }
                    else
                    {
                        multTransBBlockMinus(B.original.data, A.original.data,
                                             indexB_i, indexB_j, indexA, widthB, heightB_i, widthB_j);
                    }
                }
            }
        }
        /**
         * <p>
         * Performs:<br>
         * <br>
         * A = A + &alpha; B <sup>T</sup>B
         * </p>
         *
         * @param blockLength Size of the block in the block matrix.
         * @param alpha scaling factor for right hand side.
         * @param A Block aligned submatrix.
         * @param B Block aligned submatrix.
         */
        public static void rankNUpdate(int blockLength, double alpha,
                                       DSubmatrixD1 A, DSubmatrixD1 B)
        {
            int heightB = B.row1 - B.row0;

            if (heightB > blockLength)
            {
                throw new ArgumentException("Height of B cannot be greater than the block length");
            }

            int N = B.col1 - B.col0;

            if (A.col1 - A.col0 != N)
            {
                throw new ArgumentException("A does not have the expected number of columns based on B's width");
            }
            if (A.row1 - A.row0 != N)
            {
                throw new ArgumentException("A does not have the expected number of rows based on B's width");
            }

            for (int i = B.col0; i < B.col1; i += blockLength)
            {
                int indexB_i = B.row0 * B.original.numCols + i * heightB;
                int widthB_i = Math.Min(blockLength, B.col1 - i);

                int rowA    = i - B.col0 + A.row0;
                int heightA = Math.Min(blockLength, A.row1 - rowA);

                for (int j = B.col0; j < B.col1; j += blockLength)
                {
                    int widthB_j = Math.Min(blockLength, B.col1 - j);

                    int indexA   = rowA * A.original.numCols + (j - B.col0 + A.col0) * heightA;
                    int indexB_j = B.row0 * B.original.numCols + j * heightB;

                    InnerMultiplication_DDRB.blockMultPlusTransA(alpha,
                                                                 B.original.data, B.original.data, A.original.data,
                                                                 indexB_i, indexB_j, indexA, heightB, widthB_i, widthB_j);
                }
            }
        }
Exemple #11
0
        /**
         * Checks to see if the submatrix has its boundaries along inner blocks.
         *
         * @param blockLength Size of an inner block.
         * @param A Submatrix.
         * @return If it is block aligned or not.
         */
        public static bool blockAligned(int blockLength, DSubmatrixD1 A)
        {
            if (A.col0 % blockLength != 0)
            {
                return(false);
            }
            if (A.row0 % blockLength != 0)
            {
                return(false);
            }

            if (A.col1 % blockLength != 0 && A.col1 != A.original.numCols)
            {
                return(false);
            }

            if (A.row1 % blockLength != 0 && A.row1 != A.original.numRows)
            {
                return(false);
            }

            return(true);
        }
Exemple #12
0
        private static void checkInput(int blockLength, DSubmatrixD1 A, DSubmatrixD1 B, DSubmatrixD1 C)
        {
            int Arow = A.getRows();
            int Acol = A.getCols();
            int Brow = B.getRows();
            int Bcol = B.getCols();
            int Crow = C.getRows();
            int Ccol = C.getCols();

            if (Arow != Crow)
            {
                throw new InvalidOperationException("Mismatch A and C rows");
            }
            if (Bcol != Ccol)
            {
                throw new InvalidOperationException("Mismatch B and C columns");
            }
            if (Acol != Brow)
            {
                throw new InvalidOperationException("Mismatch A columns and B rows");
            }

            if (!MatrixOps_DDRB.blockAligned(blockLength, A))
            {
                throw new InvalidOperationException("Sub-Matrix A is not block aligned");
            }

            if (!MatrixOps_DDRB.blockAligned(blockLength, B))
            {
                throw new InvalidOperationException("Sub-Matrix B is not block aligned");
            }

            if (!MatrixOps_DDRB.blockAligned(blockLength, C))
            {
                throw new InvalidOperationException("Sub-Matrix C is not block aligned");
            }
        }
Exemple #13
0
        /**
         * <p>
         * vector dot/inner product from one row vector and one column vector:<br>
         * dot: c = sum a<sub>i</sub>*b<sub>i</sub><br>
         * where 'a' is a row vector 'b' is a column vectors within the row block vector A and B, and 'c' is a scalar.
         * </p>
         *
         * @param A block row vector. Not modified.
         * @param rowA which row in A the vector is contained in.
         * @param B block column vector. Not modified.
         * @param colB which column in B is the vector contained in.
         * @param offset Index at which the vectors start at.
         * @param end Index at which the vectors end at.
         * @return Results of the dot product.
         */
        public static double dot_row_col(int blockLength,
                                         DSubmatrixD1 A, int rowA,
                                         DSubmatrixD1 B, int colB,
                                         int offset, int end)
        {
            // handle the case where offset is more than a block
            int startI = offset - offset % blockLength;

            offset = offset % blockLength;

            double[] dataA = A.original.data;
            double[] dataB = B.original.data;

            double total = 0;

            // handle rows in any block
            int rowBlockA = A.row0 + rowA - rowA % blockLength;

            rowA = rowA % blockLength;
            int colBlockB = B.col0 + colB - colB % blockLength;

            colB = colB % blockLength;

            int heightA = Math.Min(blockLength, A.row1 - rowBlockA);
            int widthB  = Math.Min(blockLength, B.col1 - colBlockB);

            if (A.col1 - A.col0 != B.col1 - B.col0)
            {
                throw new InvalidOperationException();
            }

            for (int i = startI; i < end; i += blockLength)
            {
                int segment = Math.Min(blockLength, end - i);

                int widthA  = Math.Min(blockLength, A.col1 - A.col0 - i);
                int heightB = Math.Min(blockLength, B.row1 - B.row0 - i);

                int indexA = rowBlockA * A.original.numCols + (A.col0 + i) * heightA + rowA * widthA;
                int indexB = (B.row0 + i) * B.original.numCols + colBlockB * heightB + colB;

                if (i == startI)
                {
                    indexA += offset;
                    indexB += offset * widthB;

                    for (int j = offset; j < segment; j++, indexB += widthB)
                    {
                        total += dataB[indexB] * dataA[indexA++];
                    }
                }
                else
                {
                    for (int j = 0; j < segment; j++, indexB += widthB)
                    {
                        total += dataB[indexB] * dataA[indexA++];
                    }
                }
            }

            return(total);
        }
Exemple #14
0
        /**
         * <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);
                        }
                    }
                }
            }
        }
Exemple #15
0
        /**
         * <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);
                        }
                    }
                }
            }
        }
Exemple #16
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, DSubmatrixD1 T,
                                      DSubmatrixD1 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;

            double[] dataT = T.original.data;
            double[] 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_DDRB.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_DDRB.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_DDRB.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_DDRB.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_DDRB.solveL(dataT, dataB, Trows, N, blockT_cols, offsetT, offsetB);
                        }
                    }
                }
            }
        }