Beispiel #1
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,
                                                FSubmatrixD1 A,
                                                FSubmatrixD1 V,
                                                int row)
        {
            int height = Math.Min(blockLength, A.row1 - A.row0);

            float[] dataA = A.original.data;
            float[] 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;

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

                // take in account the leading one
                float 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_FDRB.add_row(blockLength, A, row, 1, V, i, u_row, A, row, row, A.col1 - A.col0);
                VectorOps_FDRB.add_row(blockLength, A, row, 1, A, i, v_row, A, row, row, A.col1 - A.col0);

                A.set(i, i + 1, before);
            }
        }
Beispiel #2
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,
                                    FSubmatrixD1 A,
                                    FSubmatrixD1 V,
                                    int row,
                                    float 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
                float dot_v_u = BlockHouseHolder_FDRB.innerProdRow(blockLength, A, row, V, i, 1);

                // u_i^t*u
                float dot_u_u = BlockHouseHolder_FDRB.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_FDRB.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_FDRB.add_row(blockLength, V, row, 1, V, i, dot_u_u, V, row, row + 1, A.col1 - A.col0);
            }

            // y = -gamma*y
            VectorOps_FDRB.scale_row(blockLength, V, row, -gamma, V, row, row + 1, V.col1 - V.col0);
        }
Beispiel #3
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,
                                                FSubmatrixD1 A,
                                                float[] gammas,
                                                FSubmatrixD1 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++)
            {
                float gamma = gammas[A.row0 + i];

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

                // compute v from y
                computeRowOfV(blockLength, A, V, i, gamma);
            }
        }
Beispiel #4
0
        /**
         * <p>
         * Performs a matrix multiplication on {@link FMatrixRBlock} 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,
                                    FSubmatrixD1 A, FSubmatrixD1 B,
                                    FSubmatrixD1 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_FDRB.blockMultPlus(A.original.data, B.original.data, C.original.data,
                                                               indexA, indexB, indexC, heightA, widthA, widthB);
                    }
                }
            }
        }
Beispiel #5
0
        public static bool lower(FSubmatrixD1 T)
        {
            int n      = T.row1 - T.row0;
            int indexT = T.row0 * T.original.numCols + T.col0 * n;

            return(lower(T.original.data, indexT, n));
        }
Beispiel #6
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,
                                        FSubmatrixD1 Y, FSubmatrixD1 W,
                                        float[] beta, int betaIndex)
        {
            int heightY = Y.row1 - Y.row0;

            CommonOps_FDRM.fill(W.original, 0);

            // W = -beta*v(1)
            BlockHouseHolder_FDRB.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
                float b = -beta[betaIndex++];

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

                //w=w -beta*u + stuff above
                BlockHouseHolder_FDRB.add_row(blockLength, Y, i, b, W, i, 1, W, i, 1, Y.col1 - Y.col0);
            }
        }
Beispiel #7
0
        public static void multTransB(FMatrixRBlock A, FMatrixRBlock B, FMatrixRBlock C)
        {
            if (A.numCols != B.numCols)
            {
                throw new ArgumentException("Columns in A are incompatible with columns in B");
            }
            if (A.numRows != C.numRows)
            {
                throw new ArgumentException("Rows in A are incompatible with rows in C");
            }
            if (B.numRows != C.numCols)
            {
                throw new ArgumentException("Rows in B are incompatible with columns in C");
            }
            if (A.blockLength != B.blockLength || A.blockLength != C.blockLength)
            {
                throw new ArgumentException("Block lengths are not all the same.");
            }

            int blockLength = A.blockLength;

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

            MatrixMult_FDRB.multTransB(blockLength, Asub, Bsub, Csub);
        }
Beispiel #8
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,
                                           FSubmatrixD1 A,
                                           float[] gammas,
                                           FSubmatrixD1 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_FDRB.computeHouseHolderRow(blockLength, A, gammas, i);
                float 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);
                }
            }
        }
        public virtual void invert(FMatrixRBlock A_inv)
        {
            FMatrixRBlock 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 float[blockLength * blockLength];
            }

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

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

            // invert L from cholesky decomposition and write the solution into the lower
            // triangular portion of A_inv
            // B = inv(L)
            TriangularSolver_FDRB.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_FDRB.solveL(blockLength, L, B, true);
        }
        /**
         * <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, FSubmatrixD1 Y,
                                                 float[] gamma, int i)
        {
            float max = BlockHouseHolder_FDRB.findMaxRow(blockLength, Y, i, i + 1);

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

                // divide u by u_0
                float u_0 = Y.get(i, i + 1) + tau;
                VectorOps_FDRB.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);
        }
        /**
         * Divides the elements at the specified column by 'val'.  Takes in account
         * leading zeros and one.
         */
        public static void divideElementsCol(int blockLength,
                                             FSubmatrixD1 Y, int col, float val)
        {
            int width = Math.Min(blockLength, Y.col1 - Y.col0);

            float[] 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;
                    }
                }
            }
        }
        /**
         * <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,
                                       FSubmatrixD1 W, FSubmatrixD1 Y,
                                       int widthB, float b)
        {
            float[] dataW = W.original.data;
            float[] 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];
                    }
                }
            }
        }
Beispiel #13
0
        public static float innerProdRowSymm(int blockLength,
                                             FSubmatrixD1 A,
                                             int rowA,
                                             FSubmatrixD1 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'
                float total = B.get(offset, rowB);

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

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

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

                return(total);
            }
        }
Beispiel #14
0
        /**
         * <p>
         * Performs a matrix multiplication with a transpose on {@link FMatrixRBlock} 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,
                                      FSubmatrixD1 A, FSubmatrixD1 B,
                                      FSubmatrixD1 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_FDRB.blockMultSetTransB(A.original.data, B.original.data, C.original.data,
                                                                        indexA, indexB, indexC, heightA, widthA, widthC);
                        }
                        else
                        {
                            InnerMultiplication_FDRB.blockMultPlusTransB(A.original.data, B.original.data, C.original.data,
                                                                         indexA, indexB, indexC, heightA, widthA, widthC);
                        }
                    }
                }
            }
        }
        /**
         * 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,
                                         FSubmatrixD1 Y, FSubmatrixD1 B,
                                         FSubmatrixD1 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_FDRB.blockMultPlus(Y.original.data, B.original.data, C.original.data,
                                                                   indexY, indexB, indexC, heightY, widthY, widthB);
                        }
                    }
                }
            }
        }
        /**
         * <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, FSubmatrixD1 Y,
                                                 float[] gamma, int i)
        {
            float max = BlockHouseHolder_FDRB.findMaxCol(blockLength, Y, i);

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

                // divide u by u_0
                float 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);
        }
        /**
         * <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(FSubmatrixD1 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_FDRB.computeW_Column(blockLength, Y, W, temp, gammas, Y.col0);

                MatrixMult_FDRB.multTransA(blockLength, W, A, WTA);
                BlockHouseHolder_FDRB.multAdd_zeros(blockLength, Y, WTA, A);
            }
            else if (saveW)
            {
                BlockHouseHolder_FDRB.computeW_Column(blockLength, Y, W, temp, gammas, Y.col0);
            }
        }
        /**
         * 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, FSubmatrixD1 Y,
                                        int col, float[] temp)
        {
            int widthB = Y.col1 - Y.col0;

            for (int j = 0; j < col; j++)
            {
                temp[j] = innerProdCol(blockLength, Y, col, widthB, j, widthB);
            }
        }
        /**
         * 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,
                                             FSubmatrixD1 A,
                                             float[] gammasU,
                                             float[] 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_FDRB.computeHouseHolderCol(blockLength, A, gammasU, i))
                {
                    return(false);
                }

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

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

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

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

                // apply to rest of the rows in the row block
                BlockHouseHolder_FDRB.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);
        }
        /**
         * <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 float computeTauAndDivideRow(int blockLength,
                                                   FSubmatrixD1 Y,
                                                   int row, int colStart, float max)
        {
            int height = Math.Min(blockLength, Y.row1 - Y.row0);

            float[] dataY = Y.original.data;

            float top   = 0;
            float 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++)
                    {
                        float val = dataY[index++] /= max;
                        norm2 += val * val;
                    }
                }
                else
                {
                    for (int k = 0; k < width; k++)
                    {
                        float val = dataY[index++] /= max;
                        norm2 += val * val;
                    }
                }
            }

            norm2 = (float)Math.Sqrt(norm2);

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

            return(norm2);
        }
        /**
         * <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 float innerProdCol(int blockLength, FSubmatrixD1 A,
                                         int colA, int widthA,
                                         int colB, int widthB)
        {
            float total = 0;

            float[] 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);
        }
        /**
         * Inverts an upper or lower triangular block submatrix.
         *
         * @param blockLength
         * @param upper Is it upper or lower triangular.
         * @param T Triangular matrix that is to be inverted.  Overwritten with solution.  Modified.
         * @param temp Work space variable that is size blockLength*blockLength.
         */
        public static void invert(int blockLength,
                                  bool upper,
                                  FSubmatrixD1 T,
                                  float[] temp)
        {
            if (upper)
            {
                throw new ArgumentException("Upper triangular matrices not supported yet");
            }

            if (temp.Length < blockLength * blockLength)
            {
                throw new ArgumentException("Temp must be at least blockLength*blockLength long.");
            }

            int M = T.row1 - T.row0;

            float[] dataT   = T.original.data;
            int     offsetT = T.row0 * T.original.numCols + M * T.col0;

            for (int i = 0; i < M; i += blockLength)
            {
                int heightT = Math.Min(T.row1 - (i + T.row0), blockLength);

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

                for (int j = 0; j < i; j += blockLength)
                {
                    int widthX = Math.Min(T.col1 - (j + T.col0), blockLength);

                    for (int w = 0; w < temp.Length; w++)
                    {
                        temp[w] = 0;
                    }

                    for (int k = j; k < i; k += blockLength)
                    {
                        int widthT = Math.Min(T.col1 - (k + T.col0), blockLength);

                        int indL = offsetT + T.original.numCols * (i + T.row0) + heightT * (k + T.col0);
                        int indX = offsetT + T.original.numCols * (k + T.row0) + widthT * (j + T.col0);

                        InnerMultiplication_FDRB.blockMultMinus(dataT, dataT, temp, indL, indX, 0, heightT, widthT, widthX);
                    }

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

                    InnerTriangularSolver_FDRB.solveL(dataT, temp, heightT, widthX, heightT, indexII, 0);
                    Array.Copy(temp, 0, dataT, indexX, widthX * heightT);
                }
                InnerTriangularSolver_FDRB.invertLower(dataT, heightT, indexII);
            }
        }
Beispiel #23
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,
                                     FSubmatrixD1 A, int rowA,
                                     float alpha, FSubmatrixD1 B, int rowB,
                                     int offset, int end)
        {
            float[] dataA = A.original.data;
            float[] 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++];
                    }
                }
            }
        }
Beispiel #24
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,
                                   FSubmatrixD1 A, int rowA, float alpha,
                                   FSubmatrixD1 B, int rowB, float beta,
                                   FSubmatrixD1 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;

            float[] dataA = A.original.data;
            float[] dataB = B.original.data;
            float[] 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++];
                    }
                }
            }
        }
Beispiel #25
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,
                                            FSubmatrixD1 A, FSubmatrixD1 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);
                    }
                }
            }
        }
Beispiel #26
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,
                                   FSubmatrixD1 A,
                                   FSubmatrixD1 V,
                                   int row)
        {
            int heightMatA = A.row1 - A.row0;

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

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

            init(orig);

            FSubmatrixD1 subA = new FSubmatrixD1(A);
            FSubmatrixD1 subV = new FSubmatrixD1(V);
            FSubmatrixD1 subU = new FSubmatrixD1(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_FDRB.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.
                    float 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);
        }
        /**
         * <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 float computeTauAndDivideCol(int blockLength,
                                                   FSubmatrixD1 Y,
                                                   int col, float max)
        {
            int width = Math.Min(blockLength, Y.col1 - Y.col0);

            float[] dataY = Y.original.data;

            float top   = 0;
            float 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)
                    {
                        float val = dataY[index] /= max;
                        norm2 += val * val;
                    }
                }
                else
                {
                    for (int k = 0; k < height; k++, index += width)
                    {
                        float val = dataY[index] /= max;
                        norm2 += val * val;
                    }
                }
            }

            norm2 = (float)Math.Sqrt(norm2);

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

            return(norm2);
        }
Beispiel #29
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,
                                            FSubmatrixD1 A, FSubmatrixD1 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);
                    }
                }
            }
        }
        /**
         * Specialized version of applyQ() that allows the zeros in an identity matrix
         * to be taken advantage of depending on if isIdentity is true or not.
         *
         * @param B
         * @param isIdentity If B is an identity matrix.
         */
        public void applyQ(FMatrixRBlock B, bool isIdentity)
        {
            int minDimen = Math.Min(dataA.numCols, dataA.numRows);

            FSubmatrixD1 subB = new FSubmatrixD1(B);

            W.col0   = W.row0 = 0;
            Y.row1   = W.row1 = dataA.numRows;
            WTA.row0 = WTA.col0 = 0;

            int start = minDimen - minDimen % blockLength;

            if (start == minDimen)
            {
                start -= blockLength;
            }
            if (start < 0)
            {
                start = 0;
            }

            // (Q1^T * (Q2^T * (Q3^t * A)))
            for (int i = start; i >= 0; i -= blockLength)
            {
                Y.col0 = i;
                Y.col1 = Math.Min(Y.col0 + blockLength, dataA.numCols);
                Y.row0 = i;
                if (isIdentity)
                {
                    subB.col0 = i;
                }
                subB.row0 = i;

                setW();
                WTA.row1 = Y.col1 - Y.col0;
                WTA.col1 = subB.col1 - subB.col0;
                WTA.original.reshape(WTA.row1, WTA.col1, false);

                // Compute W matrix from reflectors stored in Y
                if (!saveW)
                {
                    BlockHouseHolder_FDRB.computeW_Column(blockLength, Y, W, temp, gammas, Y.col0);
                }

                // Apply the Qi to Q
                BlockHouseHolder_FDRB.multTransA_vecCol(blockLength, Y, subB, WTA);
                MatrixMult_FDRB.multPlus(blockLength, W, WTA, subB);
            }
        }