Ejemplo n.º 1
0
        /**
         * <p>
         * Given an already computed tridiagonal decomposition, compute the V row block vector.<br>
         * <br>
         * y(:) = A*u<br>
         * v(i) = y - (1/2)*&gamma;*(y^T*u)*u
         * </p>
         */
        public static void computeV_blockVector(int blockLength,
                                                DSubmatrixD1 A,
                                                double[] gammas,
                                                DSubmatrixD1 V)
        {
            int blockHeight = Math.Min(blockLength, A.row1 - A.row0);

            if (blockHeight <= 1)
            {
                return;
            }
            int width = A.col1 - A.col0;
            int num   = Math.Min(width - 1, blockHeight);

            for (int i = 0; i < num; i++)
            {
                double gamma = gammas[A.row0 + i];

                // compute y
                computeY(blockLength, A, V, i, gamma);

                // compute v from y
                computeRowOfV(blockLength, A, V, i, gamma);
            }
        }
Ejemplo n.º 2
0
        /**
         * <p>
         * Applies the reflectors that have been computed previously to the specified row.
         * <br>
         * A = A + u*v^T + v*u^T only along the specified row in A.
         * </p>
         *
         * @param blockLength
         * @param A Contains the reflectors and the row being updated.
         * @param V Contains previously computed 'v' vectors.
         * @param row The row of 'A' that is to be updated.
         */
        public static void applyReflectorsToRow(int blockLength,
                                                DSubmatrixD1 A,
                                                DSubmatrixD1 V,
                                                int row)
        {
            int height = Math.Min(blockLength, A.row1 - A.row0);

            double[] dataA = A.original.data;
            double[] dataV = V.original.data;

            int indexU, indexV;

            // for each previously computed reflector
            for (int i = 0; i < row; i++)
            {
                int width = Math.Min(blockLength, A.col1 - A.col0);

                indexU = A.original.numCols * A.row0 + height * A.col0 + i * width + row;
                indexV = V.original.numCols * V.row0 + height * V.col0 + i * width + row;

                double u_row = (i + 1 == row) ? 1.0 : dataA[indexU];
                double v_row = dataV[indexV];

                // take in account the leading one
                double before = A.get(i, i + 1);
                A.set(i, i + 1, 1);

                // grab only the relevant row from A = A + u*v^T + v*u^T
                VectorOps_DDRB.add_row(blockLength, A, row, 1, V, i, u_row, A, row, row, A.col1 - A.col0);
                VectorOps_DDRB.add_row(blockLength, A, row, 1, A, i, v_row, A, row, row, A.col1 - A.col0);

                A.set(i, i + 1, before);
            }
        }
Ejemplo n.º 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)
        {
            //        checkShapeMult( blockLength,A,B,C);

            //CONCURRENT_BELOW EjmlConcurrency.loopFor(A.row0,A.row1,blockLength,i->{
            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);
                    }
                }
            }
            //CONCURRENT_ABOVE });
        }
        virtual public void solve(DMatrixRBlock B, DMatrixRBlock X)
        {
            if (B.blockLength != blockLength)
            {
                throw new ArgumentException("Unexpected blocklength in B.");
            }

            DSubmatrixD1 L = new DSubmatrixD1(decomposer.getT(null));

            if (X == null)
            {
                //X = B.create<DMatrixRBlock>(L.col1, B.numCols);
                X = new DMatrixRBlock(L.col1, B.numCols);
            }
            else
            {
                X.reshape(L.col1, B.numCols, blockLength, false);
            }

            //  L * L^T*X = B

            // Solve for Y:  L*Y = B
            TriangularSolver_DDRB.solve(blockLength, false, L, new DSubmatrixD1(B), false);

            // L^T * X = Y
            TriangularSolver_DDRB.solve(blockLength, false, L, new DSubmatrixD1(B), true);

            if (X != null)
            {
                // copy the solution from B into X
                MatrixOps_DDRB.extractAligned(B, X);
            }
        }
        public static bool lower(DSubmatrixD1 T)
        {
            int n      = T.row1 - T.row0;
            int indexT = T.row0 * T.original.numCols + T.col0 * n;

            return(lower(T.original.data, indexT, n));
        }
Ejemplo n.º 6
0
        /**
         * <p>
         * Computes the 'y' vector and stores the result in 'v'<br>
         * <br>
         * y = -&gamma;(A + U*V^T + V*U^T)u
         * </p>
         *
         * @param blockLength
         * @param A Contains the reflectors and the row being updated.
         * @param V Contains previously computed 'v' vectors.
         * @param row The row of 'A' that is to be updated.
         */
        public static void computeY(int blockLength,
                                    DSubmatrixD1 A,
                                    DSubmatrixD1 V,
                                    int row,
                                    double gamma)
        {
            // Elements in 'y' before 'row' are known to be zero and the element at 'row'
            // is not used. Thus only elements after row and after are computed.
            // y = A*u
            multA_u(blockLength, A, V, row);

            for (int i = 0; i < row; i++)
            {
                // y = y + u_i*v_i^t*u + v_i*u_i^t*u

                // v_i^t*u
                double dot_v_u = BlockHouseHolder_DDRB.innerProdRow(blockLength, A, row, V, i, 1);

                // u_i^t*u
                double dot_u_u = BlockHouseHolder_DDRB.innerProdRow(blockLength, A, row, A, i, 1);

                // y = y + u_i*(v_i^t*u)
                // the ones in these 'u' are skipped over since the next submatrix of A
                // is only updated
                VectorOps_DDRB.add_row(blockLength, V, row, 1, A, i, dot_v_u, V, row, row + 1, A.col1 - A.col0);

                // y = y + v_i*(u_i^t*u)
                // the 1 in U is taken account above
                VectorOps_DDRB.add_row(blockLength, V, row, 1, V, i, dot_u_u, V, row, row + 1, A.col1 - A.col0);
            }

            // y = -gamma*y
            VectorOps_DDRB.scale_row(blockLength, V, row, -gamma, V, row, row + 1, V.col1 - V.col0);
        }
Ejemplo n.º 7
0
        /**
         * <p>
         * Computes W from the householder reflectors stored in the columns of the row block
         * submatrix Y.
         * </p>
         *
         * <p>
         * Y = v<sup>(1)</sup><br>
         * W = -&beta;<sub>1</sub>v<sup>(1)</sup><br>
         * for j=2:r<br>
         * &nbsp;&nbsp;z = -&beta;(I +WY<sup>T</sup>)v<sup>(j)</sup> <br>
         * &nbsp;&nbsp;W = [W z]<br>
         * &nbsp;&nbsp;Y = [Y v<sup>(j)</sup>]<br>
         * end<br>
         * <br>
         * where v<sup>(.)</sup> are the house holder vectors, and r is the block length.  Note that
         * Y already contains the householder vectors so it does not need to be modified.
         * </p>
         *
         * <p>
         * Y and W are assumed to have the same number of rows and columns.
         * </p>
         */
        public static void computeW_row(int blockLength,
                                        DSubmatrixD1 Y, DSubmatrixD1 W,
                                        double[] beta, int betaIndex)
        {
            int heightY = Y.row1 - Y.row0;

            CommonOps_DDRM.fill(W.original, 0);

            // W = -beta*v(1)
            BlockHouseHolder_DDRB.scale_row(blockLength, Y, W, 0, 1, -beta[betaIndex++]);

            int min = Math.Min(heightY, W.col1 - W.col0);

            // set up rest of the rows
            for (int i = 1; i < min; i++)
            {
                // w=-beta*(I + W*Y^T)*u
                double b = -beta[betaIndex++];

                // w = w -beta*W*(Y^T*u)
                for (int j = 0; j < i; j++)
                {
                    double yv = BlockHouseHolder_DDRB.innerProdRow(blockLength, Y, i, Y, j, 1);
                    VectorOps_DDRB.add_row(blockLength, W, i, 1, W, j, b * yv, W, i, 1, Y.col1 - Y.col0);
                }

                //w=w -beta*u + stuff above
                BlockHouseHolder_DDRB.add_row(blockLength, Y, i, b, W, i, 1, W, i, 1, Y.col1 - Y.col0);
            }
        }
Ejemplo n.º 8
0
        /**
         * Divides the elements at the specified column by 'val'.  Takes in account
         * leading zeros and one.
         */
        public static void divideElementsCol(int blockLength,
                                             DSubmatrixD1 Y, int col, double val)
        {
            int width = Math.Min(blockLength, Y.col1 - Y.col0);

            double[] dataY = Y.original.data;

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

                int index = i * Y.original.numCols + height * Y.col0 + col;

                if (i == Y.row0)
                {
                    index += width * (col + 1);

                    for (int k = col + 1; k < height; k++, index += width)
                    {
                        dataY[index] /= val;
                    }
                }
                else
                {
                    int endIndex = index + width * height;
                    //for( int k = 0; k < height; k++
                    for (; index != endIndex; index += width)
                    {
                        dataY[index] /= val;
                    }
                }
            }
        }
Ejemplo n.º 9
0
        /**
         * Special multiplication that takes in account the zeros and one in Y, which
         * is the matrix that stores the householder vectors.
         *
         */
        public static void multAdd_zeros(int blockLength,
                                         DSubmatrixD1 Y, DSubmatrixD1 B,
                                         DSubmatrixD1 C)
        {
            int widthY = Y.col1 - Y.col0;

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

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

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

                    for (int k = Y.col0; k < Y.col1; k += blockLength)
                    {
                        int indexY = i * Y.original.numCols + k * heightY;
                        int indexB = (k - Y.col0 + B.row0) * B.original.numCols + j * widthY;

                        if (i == Y.row0)
                        {
                            multBlockAdd_zerosone(Y.original.data, B.original.data, C.original.data,
                                                  indexY, indexB, indexC, heightY, widthY, widthB);
                        }
                        else
                        {
                            InnerMultiplication_DDRB.blockMultPlus(Y.original.data, B.original.data, C.original.data,
                                                                   indexY, indexB, indexC, heightY, widthY, widthB);
                        }
                    }
                }
            }
        }
Ejemplo n.º 10
0
        public virtual void invert(DMatrixRBlock A_inv)
        {
            DMatrixRBlock T = decomposer.getT(null);

            if (A_inv.numRows != T.numRows || A_inv.numCols != T.numCols)
            {
                throw new ArgumentException("Unexpected number or rows and/or columns");
            }


            if (temp == null || temp.Length < blockLength * blockLength)
            {
                temp = new double[blockLength * blockLength];
            }

            // zero the upper triangular portion of A_inv
            MatrixOps_DDRB.zeroTriangle(true, A_inv);

            DSubmatrixD1 L = new DSubmatrixD1(T);
            DSubmatrixD1 B = new DSubmatrixD1(A_inv);

            // invert L from cholesky decomposition and write the solution into the lower
            // triangular portion of A_inv
            // B = inv(L)
            TriangularSolver_DDRB.invert(blockLength, false, L, B, temp);

            // B = L^-T * B
            // todo could speed up by taking advantage of B being lower triangular
            // todo take advantage of symmetry
            TriangularSolver_DDRB.solveL(blockLength, L, B, true);
        }
Ejemplo n.º 11
0
        /**
         * <p>
         * Computes the householder vector from the specified row
         * </p>
         *
         * <p>
         * The householder vector 'u' is computed as follows:<br>
         * <br>
         * u(1) = 1 <br>
         * u(i) = x(i)/(&tau; + x(1))<br>
         * </p>
         *
         * The first element is implicitly assumed to be one and not written.
         *
         * @return If there was any problems or not. true = no problem.
         */
        public static bool computeHouseHolderRow(int blockLength, DSubmatrixD1 Y,
                                                 double[] gamma, int i)
        {
            double max = BlockHouseHolder_DDRB.findMaxRow(blockLength, Y, i, i + 1);

            if (max == 0.0)
            {
                return(false);
            }
            else
            {
                // computes tau and normalizes u by max
                double tau = computeTauAndDivideRow(blockLength, Y, i, i + 1, max);

                // divide u by u_0
                double u_0 = Y.get(i, i + 1) + tau;
                VectorOps_DDRB.div_row(blockLength, Y, i, u_0, Y, i, i + 1, Y.col1 - Y.col0);

                gamma[Y.row0 + i] = u_0 / tau;

                // after the reflector is applied the column would be all zeros but be -tau in the first element
                Y.set(i, i + 1, -tau * max);
            }
            return(true);
        }
Ejemplo n.º 12
0
        /**
         * <p>
         * Computes the householder vector that is used to create reflector for the column.
         * The results are stored in the original matrix.
         * </p>
         *
         * <p>
         * The householder vector 'u' is computed as follows:<br>
         * <br>
         * u(1) = 1 <br>
         * u(i) = x(i)/(&tau; + x(1))<br>
         * </p>
         *
         * The first element is implicitly assumed to be one and not written.
         *
         * @return If there was any problems or not. true = no problem.
         */
        public static bool computeHouseHolderCol(int blockLength, DSubmatrixD1 Y,
                                                 double[] gamma, int i)
        {
            double max = BlockHouseHolder_DDRB.findMaxCol(blockLength, Y, i);

            if (max == 0.0)
            {
                return(false);
            }
            else
            {
                // computes tau and normalizes u by max
                double tau = computeTauAndDivideCol(blockLength, Y, i, max);

                // divide u by u_0
                double u_0 = Y.get(i, i) + tau;
                divideElementsCol(blockLength, Y, i, u_0);

                gamma[Y.col0 + i] = u_0 / tau;
                tau *= max;

                // after the reflector is applied the column would be all zeros but be -tau in the first element
                Y.set(i, i, -tau);
            }
            return(true);
        }
Ejemplo n.º 13
0
        /**
         * <p>
         * A = (I + W Y<sup>T</sup>)<sup>T</sup>A<BR>
         * A = A + Y (W<sup>T</sup>A)<BR>
         * <br>
         * where A is a submatrix of the input matrix.
         * </p>
         */
        protected void updateA(DSubmatrixD1 A)
        {
            setW();

            A.row0 = Y.row0;
            A.row1 = Y.row1;
            A.col0 = Y.col1;
            A.col1 = Y.original.numCols;

            WTA.row0 = 0;
            WTA.col0 = 0;
            WTA.row1 = W.col1 - W.col0;
            WTA.col1 = A.col1 - A.col0;
            WTA.original.reshape(WTA.row1, WTA.col1, false);

            if (A.col1 > A.col0)
            {
                BlockHouseHolder_DDRB.computeW_Column(blockLength, Y, W, temp, gammas, Y.col0);

                MatrixMult_DDRB.multTransA(blockLength, W, A, WTA);
                BlockHouseHolder_DDRB.multAdd_zeros(blockLength, Y, WTA, A);
            }
            else if (saveW)
            {
                BlockHouseHolder_DDRB.computeW_Column(blockLength, Y, W, temp, gammas, Y.col0);
            }
        }
Ejemplo n.º 14
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);
        }
Ejemplo n.º 15
0
        /**
         * <p>
         * Sets W to its initial value using the first column of 'y' and the value of 'b':
         * <br>
         * W = -&beta;v<br>
         * <br>
         * where v = Y(:,0).
         * </p>
         *
         * @param blockLength size of the inner block
         * @param W Submatrix being initialized.
         * @param Y Contains householder vector
         * @param widthB How wide the W block matrix is.
         * @param b beta
         */
        public static void initializeW(int blockLength,
                                       DSubmatrixD1 W, DSubmatrixD1 Y,
                                       int widthB, double b)
        {
            double[] dataW = W.original.data;
            double[] dataY = Y.original.data;

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

                int indexW = i * W.original.numCols + heightW * W.col0;
                int indexY = i * Y.original.numCols + heightW * Y.col0;

                // take in account the first element in V being 1
                if (i == W.row0)
                {
                    dataW[indexW] = -b;
                    indexW       += widthB;
                    indexY       += widthB;
                    for (int k = 1; k < heightW; k++, indexW += widthB, indexY += widthB)
                    {
                        dataW[indexW] = -b * dataY[indexY];
                    }
                }
                else
                {
                    for (int k = 0; k < heightW; k++, indexW += widthB, indexY += widthB)
                    {
                        dataW[indexW] = -b * dataY[indexY];
                    }
                }
            }
        }
Ejemplo n.º 16
0
        /**
         * <p>
         * Performs a tridiagonal decomposition on the upper row only.
         * </p>
         *
         * <p>
         * For each row 'a' in 'A':
         * Compute 'u' the householder reflector.
         * y(:) = A*u
         * v(i) = y - (1/2)*(y^T*u)*u
         * a(i+1) = a(i) - u*&gamma;*v^T - v*u^t
         * </p>
         *
         * @param blockLength Size of a block
         * @param A is the row block being decomposed.  Modified.
         * @param gammas Householder gammas.
         * @param V Where computed 'v' are stored in a row block.  Modified.
         */
        public static void tridiagUpperRow(int blockLength,
                                           DSubmatrixD1 A,
                                           double[] gammas,
                                           DSubmatrixD1 V)
        {
            int blockHeight = Math.Min(blockLength, A.row1 - A.row0);

            if (blockHeight <= 1)
            {
                return;
            }
            int width      = A.col1 - A.col0;
            int num        = Math.Min(width - 1, blockHeight);
            int applyIndex = Math.Min(width, blockHeight);

            // step through rows in the block
            for (int i = 0; i < num; i++)
            {
                // compute the new reflector and save it in a row in 'A'
                BlockHouseHolder_DDRB.computeHouseHolderRow(blockLength, A, gammas, i);
                double gamma = gammas[A.row0 + i];

                // compute y
                computeY(blockLength, A, V, i, gamma);

                // compute v from y
                computeRowOfV(blockLength, A, V, i, gamma);

                // Apply the reflectors to the next row in 'A' only
                if (i + 1 < applyIndex)
                {
                    applyReflectorsToRow(blockLength, A, V, i + 1);
                }
            }
        }
Ejemplo n.º 17
0
        public static double innerProdRowSymm(int blockLength,
                                              DSubmatrixD1 A,
                                              int rowA,
                                              DSubmatrixD1 B,
                                              int rowB, int zeroOffset)
        {
            int offset = rowA + zeroOffset;

            if (offset + B.col0 >= B.col1)
            {
                return(0);
            }

            if (offset < rowB)
            {
                // take in account the one in 'A'
                double total = B.get(offset, rowB);

                total += VectorOps_DDRB.dot_row_col(blockLength, A, rowA, B, rowB, offset + 1, rowB);
                total += VectorOps_DDRB.dot_row(blockLength, A, rowA, B, rowB, rowB, A.col1 - A.col0);

                return(total);
            }
            else
            {
                // take in account the one in 'A'
                double total = B.get(rowB, offset);

                total += VectorOps_DDRB.dot_row(blockLength, A, rowA, B, rowB, offset + 1, A.col1 - A.col0);

                return(total);
            }
        }
Ejemplo n.º 18
0
        /**
         * Computes Y<sup>T</sup>v<sup>(j)</sup>.  Where Y are the columns before 'col' and v is the column
         * at 'col'.  The zeros and ones are taken in account.  The solution is a vector with 'col' elements.
         *
         * width of Y must be along the block of original matrix A
         *
         * @param temp Temporary storage of least length 'col'
         */
        public static void computeY_t_V(int blockLength, DSubmatrixD1 Y,
                                        int col, double[] temp)
        {
            int widthB = Y.col1 - Y.col0;

            for (int j = 0; j < col; j++)
            {
                temp[j] = innerProdCol(blockLength, Y, col, widthB, j, widthB);
            }
        }
Ejemplo n.º 19
0
        /**
         * Performs a standard bidiagonal decomposition just on the outer blocks of the provided matrix
         *
         * @param blockLength
         * @param A
         * @param gammasU
         */

        public static bool bidiagOuterBlocks(int blockLength,
                                             DSubmatrixD1 A,
                                             double[] gammasU,
                                             double[] gammasV)
        {
//        Console.WriteLine("---------- Orig");
//        A.original.print();

            int width  = Math.Min(blockLength, A.col1 - A.col0);
            int height = Math.Min(blockLength, A.row1 - A.row0);

            int min = Math.Min(width, height);

            for (int i = 0; i < min; i++)
            {
                //--- Apply reflector to the column

                // compute the householder vector
                if (!BlockHouseHolder_DDRB.computeHouseHolderCol(blockLength, A, gammasU, i))
                {
                    return(false);
                }

                // apply to rest of the columns in the column block
                BlockHouseHolder_DDRB.rank1UpdateMultR_Col(blockLength, A, i, gammasU[A.col0 + i]);

                // apply to the top row block
                BlockHouseHolder_DDRB.rank1UpdateMultR_TopRow(blockLength, A, i, gammasU[A.col0 + i]);

                Console.WriteLine("After column stuff");
                A.original.print();

                //-- Apply reflector to the row
                if (!BlockHouseHolder_DDRB.computeHouseHolderRow(blockLength, A, gammasV, i))
                {
                    return(false);
                }

                // apply to rest of the rows in the row block
                BlockHouseHolder_DDRB.rank1UpdateMultL_Row(blockLength, A, i, i + 1, gammasV[A.row0 + i]);

                Console.WriteLine("After update row");
                A.original.print();

                // apply to the left column block
                // TODO THIS WON'T WORK!!!!!!!!!!!!!
                // Needs the whole matrix to have been updated by the left reflector to compute the correct solution
//            rank1UpdateMultL_LeftCol(blockLength,A,i,i+1,gammasV[A.row0+i]);

                Console.WriteLine("After row stuff");
                A.original.print();
            }

            return(true);
        }
Ejemplo n.º 20
0
        /**
         * <p>
         * Computes the inner product of column vector 'colA' against column vector 'colB' while taking account leading zeros and one.<br>
         * <br>
         * ret = a<sup>T</sup>*b
         * </p>
         *
         * <p>
         * Column A is assumed to be a householder vector.  Element at 'colA' is one and previous ones are zero.
         * </p>
         *
         * @param blockLength
         * @param A block aligned submatrix.
         * @param colA Column inside the block of first column vector.
         * @param widthA how wide the column block that colA is inside of.
         * @param colB Column inside the block of second column vector.
         * @param widthB how wide the column block that colB is inside of.
         * @return dot product of the two vectors.
         */
        public static double innerProdCol(int blockLength, DSubmatrixD1 A,
                                          int colA, int widthA,
                                          int colB, int widthB)
        {
            double total = 0;

            double[] data = A.original.data;
            // first column in the blocks
            int colBlockA = A.col0 + colA - colA % blockLength;
            int colBlockB = A.col0 + colB - colB % blockLength;

            colA = colA % blockLength;
            colB = colB % blockLength;

            // compute dot product down column vectors
            for (int i = A.row0; i < A.row1; i += blockLength)
            {
                int height = Math.Min(blockLength, A.row1 - i);

                int indexA = i * A.original.numCols + height * colBlockA + colA;
                int indexB = i * A.original.numCols + height * colBlockB + colB;

                if (i == A.row0)
                {
                    // handle leading zeros
                    indexA += widthA * (colA + 1);
                    indexB += widthB * colA;

                    // handle leading one
                    total = data[indexB];

                    indexB += widthB;

                    // standard vector dot product
                    int endA = indexA + (height - colA - 1) * widthA;
                    for (; indexA != endA; indexA += widthA, indexB += widthB)
                    {
//                    for( int k = col+1; k < height; k++ , indexU += width, indexA += width ) {
                        total += data[indexA] * data[indexB];
                    }
                }
                else
                {
                    // standard vector dot product
                    int endA = indexA + widthA * height;
//                    for( int k = 0; k < height; k++ ) {
                    for (; indexA != endA; indexA += widthA, indexB += widthB)
                    {
                        total += data[indexA] * data[indexB];
                    }
                }
            }
            return(total);
        }
Ejemplo n.º 21
0
        /**
         * <p>
         * From the specified row of Y tau is computed and each element is divided by 'max'.
         * See code below:
         * </p>
         *
         * <pre>
         * for j=row:Y.numCols
         *   Y[row][j] = u[row][j] / max
         *   tau = tau + u[row][j]*u[row][j]
         * end
         * tau = sqrt(tau)
         * if( Y[row][row] &lt; 0 )
         *    tau = -tau;
         * </pre>
         *
         * @param row Which row in the block will be processed
         * @param colStart The first column that computation of tau will start at
         * @param max used to normalize and prevent buffer over flow
         *
         */
        public static double computeTauAndDivideRow(int blockLength,
                                                    DSubmatrixD1 Y,
                                                    int row, int colStart, double max)
        {
            int height = Math.Min(blockLength, Y.row1 - Y.row0);

            double[] dataY = Y.original.data;

            double top   = 0;
            double norm2 = 0;

            int startJ = Y.col0 + colStart - colStart % blockLength;

            colStart = colStart % blockLength;

            for (int j = startJ; j < Y.col1; j += blockLength)
            {
                int width = Math.Min(blockLength, Y.col1 - j);

                int index = Y.row0 * Y.original.numCols + height * j + row * width;

                if (j == startJ)
                {
                    index += colStart;
                    // save this value so that the sign can be determined later on
                    top    = dataY[index] /= max;
                    norm2 += top * top;
                    index++;

                    for (int k = colStart + 1; k < width; k++)
                    {
                        double val = dataY[index++] /= max;
                        norm2 += val * val;
                    }
                }
                else
                {
                    for (int k = 0; k < width; k++)
                    {
                        double val = dataY[index++] /= max;
                        norm2 += val * val;
                    }
                }
            }

            norm2 = Math.Sqrt(norm2);

            if (top < 0)
            {
                norm2 = -norm2;
            }

            return(norm2);
        }
Ejemplo n.º 22
0
        /**
         * Computes Y<sup>T</sup>v<sup>(j)</sup>. Where Y are the columns before 'col' and v is the column
         * at 'col'. The zeros and ones are taken in account. The solution is a vector with 'col' elements.
         *
         * width of Y must be along the block of original matrix A
         *
         * @param temp Temporary storage of least length 'col'
         */
        public static void computeY_t_V(int blockLength, DSubmatrixD1 Y,
                                        int col, double[] temp)
        {
            int widthB = Y.col1 - Y.col0;

            //CONCURRENT_BELOW EjmlConcurrency.loopFor(0, col, j -> {
            for (int j = 0; j < col; j++)
            {
                temp[j] = innerProdCol(blockLength, Y, col, widthB, j, widthB);
            }
            //CONCURRENT_ABOVE });
        }
        /**
         * <p>
         * Row vector divide:<br>
         * div: b<sub>i</sub> = a<sub>i</sub>/&alpha;<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 div_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++] = dataA[indexA++] / alpha;
                    }
                }
                else
                {
                    for (int j = 0; j < segment; j++)
                    {
                        dataB[indexB++] = dataA[indexA++] / alpha;
                    }
                }
            }
        }
Ejemplo n.º 24
0
        /**
         * <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");
            }


            //CONCURRENT_BELOW EjmlConcurrency.loopFor(B.col0,B.col1,blockLength,i->{
            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);
                    }
                }
            }
            //CONCURRENT_ABOVE });
        }
        /**
         * <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++];
                    }
                }
            }
        }
Ejemplo n.º 26
0
        /**
         * <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");
            }

            //CONCURRENT_BELOW EjmlConcurrency.loopFor(B.row0,B.row1,blockLength,i->{
            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);
                    }
                }
            }
            //CONCURRENT_ABOVE });
        }
Ejemplo n.º 27
0
        /**
         * <p>
         * Multiples the appropriate submatrix of A by the specified reflector and stores
         * the result ('y') in V.<br>
         * <br>
         * y = A*u<br>
         * </p>
         *
         * @param blockLength
         * @param A Contains the 'A' matrix and 'u' vector.
         * @param V Where resulting 'y' row vectors are stored.
         * @param row row in matrix 'A' that 'u' vector and the row in 'V' that 'y' is stored in.
         */
        public static void multA_u(int blockLength,
                                   DSubmatrixD1 A,
                                   DSubmatrixD1 V,
                                   int row)
        {
            int heightMatA = A.row1 - A.row0;

            for (int i = row + 1; i < heightMatA; i++)
            {
                double val = innerProdRowSymm(blockLength, A, row, A, i, 1);

                V.set(row, i, val);
            }
        }
        public virtual bool decompose(DMatrixRBlock orig)
        {
            if (orig.numCols != orig.numRows)
            {
                throw new ArgumentException("Input matrix must be square.");
            }

            init(orig);

            DSubmatrixD1 subA = new DSubmatrixD1(A);
            DSubmatrixD1 subV = new DSubmatrixD1(V);
            DSubmatrixD1 subU = new DSubmatrixD1(A);

            int N = orig.numCols;

            for (int i = 0; i < N; i += A.blockLength)
            {
//            Console.WriteLine("-------- triag i "+i);
                int height = Math.Min(A.blockLength, A.numRows - i);

                subA.col0 = subU.col0 = i;
                subA.row0 = subU.row0 = i;

                subU.row1 = subU.row0 + height;

                subV.col0 = i;
                subV.row1 = height;
                subV.original.reshape(subV.row1, subV.col1, false);

                // bidiagonalize the top row
                TridiagonalHelper_DDRB.tridiagUpperRow(A.blockLength, subA, gammas, subV);

                // apply Householder reflectors to the lower portion using block multiplication

                if (subU.row1 < orig.numCols)
                {
                    // take in account the 1 in the last row.  The others are skipped over.
                    double before = subU.get(A.blockLength - 1, A.blockLength);
                    subU.set(A.blockLength - 1, A.blockLength, 1);

                    // A = A + U*V^T + V*U^T
                    multPlusTransA(A.blockLength, subU, subV, subA);
                    multPlusTransA(A.blockLength, subV, subU, subA);

                    subU.set(A.blockLength - 1, A.blockLength, before);
                }
            }

            return(true);
        }
Ejemplo n.º 29
0
        /**
         * <p>
         * Applies a householder reflector stored in column 'col' to the remainder of the columns
         * in the block after it. Takes in account leading zeros and one.<br>
         * <br>
         * A = (I - &gamma;*u*u<sup>T</sup>)*A<br>
         * </p>
         *
         * @param A submatrix that is at most one block wide and aligned along inner blocks
         * @param col The column in A containing 'u'
         */
        public static void rank1UpdateMultR_Col(int blockLength,
                                                DSubmatrixD1 A, int col, double gamma)
        {
            int width = Math.Min(blockLength, A.col1 - A.col0);

            double[] dataA = A.original.data;

            //CONCURRENT_BELOW EjmlConcurrency.loopFor(col + 1, width, j -> {
            for (int j = col + 1; j < width; j++)
            {
                // total = U^T * A(:,j)
                double total = innerProdCol(blockLength, A, col, width, j, width);

                total *= gamma;
                // A(:,j) - gamma*U*total

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

                    int indexU = i * A.original.numCols + height * A.col0 + col;
                    int indexA = i * A.original.numCols + height * A.col0 + j;

                    if (i == A.row0)
                    {
                        indexU += width * (col + 1);
                        indexA += width * col;

                        dataA[indexA] -= total;

                        indexA += width;

                        for (int k = col + 1; k < height; k++, indexU += width, indexA += width)
                        {
                            dataA[indexA] -= total * dataA[indexU];
                        }
                    }
                    else
                    {
                        int endU = indexU + width * height;
                        // for( int k = 0; k < height; k++
                        for (; indexU != endU; indexU += width, indexA += width)
                        {
                            dataA[indexA] -= total * dataA[indexU];
                        }
                    }
                }
            }
            //CONCURRENT_ABOVE });
        }
Ejemplo n.º 30
0
        /**
         * <p>
         * From the specified column of Y tau is computed and each element is divided by 'max'.
         * See code below:
         * </p>
         *
         * <pre>
         * for i=col:Y.numRows
         *   Y[i][col] = u[i][col] / max
         *   tau = tau + u[i][col]*u[i][col]
         * end
         * tau = sqrt(tau)
         * if( Y[col][col] &lt; 0 )
         *    tau = -tau;
         * </pre>
         *
         */
        public static double computeTauAndDivideCol(int blockLength,
                                                    DSubmatrixD1 Y,
                                                    int col, double max)
        {
            int width = Math.Min(blockLength, Y.col1 - Y.col0);

            double[] dataY = Y.original.data;

            double top   = 0;
            double norm2 = 0;

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

                int index = i * Y.original.numCols + height * Y.col0 + col;

                if (i == Y.row0)
                {
                    index += width * col;
                    // save this value so that the sign can be determined later on
                    top    = dataY[index] /= max;
                    norm2 += top * top;
                    index += width;

                    for (int k = col + 1; k < height; k++, index += width)
                    {
                        double val = dataY[index] /= max;
                        norm2 += val * val;
                    }
                }
                else
                {
                    for (int k = 0; k < height; k++, index += width)
                    {
                        double val = dataY[index] /= max;
                        norm2 += val * val;
                    }
                }
            }

            norm2 = Math.Sqrt(norm2);

            if (top < 0)
            {
                norm2 = -norm2;
            }

            return(norm2);
        }