Exemple #1
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);
        }
        /**
         * <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);
            }
        }
        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);
            }
        }
        /**
         * <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);
        }
        /**
         * <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);
            }
        }
Exemple #6
0
        public static void add_row(int blockLength,
                                   DSubmatrixD1 A, int rowA, double alpha,
                                   DSubmatrixD1 B, int rowB, double beta,
                                   DSubmatrixD1 C, int rowC,
                                   int zeroOffset, int end)
        {
            int offset = rowA + zeroOffset;

            if (C.col0 + offset >= C.col1)
            {
                return;
            }
            // handle leading one
            C.set(rowC, offset, alpha + B.get(rowB, offset) * beta);

            VectorOps_DDRB.add_row(blockLength, A, rowA, alpha, B, rowB, beta, C, rowC, offset + 1, end);
        }
Exemple #7
0
        /**
         * Scales the elements in the specified row starting at element colStart by 'val'.<br>
         * W = val*Y
         *
         * Takes in account zeros and leading one automatically.
         *
         * @param zeroOffset How far off the diagonal is the first element in the vector.
         */
        public static void scale_row(int blockLength,
                                     DSubmatrixD1 Y,
                                     DSubmatrixD1 W,
                                     int row,
                                     int zeroOffset,
                                     double val)
        {
            int offset = row + zeroOffset;

            if (offset >= W.col1 - W.col0)
            {
                return;
            }

            // handle the one
            W.set(row, offset, val);

            // scale rest of the vector
            VectorOps_DDRB.scale_row(blockLength, Y, row, val, W, row, offset + 1, Y.col1 - Y.col0);
        }
        /**
         * <p>
         * Final computation for a single row of 'v':<br>
         * <br>
         * v = y -(1/2)&gamma;(y^T*u)*u
         * </p>
         *
         * @param blockLength
         * @param A
         * @param V
         * @param row
         * @param gamma
         */
        public static void computeRowOfV(int blockLength,
                                         DSubmatrixD1 A,
                                         DSubmatrixD1 V,
                                         int row,
                                         double gamma)
        {
            // val=(y^T*u)
            double val = BlockHouseHolder_DDRB.innerProdRow(blockLength, A, row, V, row, 1);

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

            A.set(row, row + 1, 1);

            // v = y - (1/2)gamma*val * u
            VectorOps_DDRB.add_row(blockLength, V, row, 1, A, row, -0.5 * gamma * val, V, row, row + 1,
                                   A.col1 - A.col0);

            A.set(row, row + 1, before);
        }