/**
         * 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);
            }
        }
Ejemplo n.º 2
0
        public virtual FMatrixRBlock getQ(FMatrixRBlock Q, bool transposed)
        {
            Q = QRDecompositionHouseholder_FDRB.initializeQ(Q, A.numRows, A.numCols, A.blockLength, false);

            int height = Math.Min(A.blockLength, A.numRows);

            V.reshape(height, A.numCols, false);
            this.tmp.reshape(height, A.numCols, false);

            FSubmatrixD1 subQ = new FSubmatrixD1(Q);
            FSubmatrixD1 subU = new FSubmatrixD1(A);
            FSubmatrixD1 subW = new FSubmatrixD1(V);
            FSubmatrixD1 tmp  = new FSubmatrixD1(this.tmp);


            int N = A.numRows;

            int start = N - N % A.blockLength;

            if (start == N)
            {
                start -= A.blockLength;
            }
            if (start < 0)
            {
                start = 0;
            }

            // (Q1^T * (Q2^T * (Q3^t * A)))
            for (int i = start; i >= 0; i -= A.blockLength)
            {
                int blockSize = Math.Min(A.blockLength, N - i);

                subW.col0 = i;
                subW.row1 = blockSize;
                subW.original.reshape(subW.row1, subW.col1, false);

                if (transposed)
                {
                    tmp.row0 = i;
                    tmp.row1 = A.numCols;
                    tmp.col0 = 0;
                    tmp.col1 = blockSize;
                }
                else
                {
                    tmp.col0 = i;
                    tmp.row1 = blockSize;
                }
                tmp.original.reshape(tmp.row1, tmp.col1, false);

                subU.col0 = i;
                subU.row0 = i;
                subU.row1 = subU.row0 + blockSize;

                // zeros and ones are saved and overwritten in U so that standard matrix multiplication can be used
                copyZeros(subU);

                // compute W for Q(i) = ( I + W*Y^T)
                TridiagonalHelper_FDRB.computeW_row(A.blockLength, subU, subW, gammas, i);

                subQ.col0 = i;
                subQ.row0 = i;

                // Apply the Qi to Q
                // Qi = I + W*U^T

                // Note that U and V are really row vectors.  but standard notation assumed they are column vectors.
                // which is why the functions called don't match the math above

                // (I + W*U^T)*Q
                // F=U^T*Q(i)
                if (transposed)
                {
                    MatrixMult_FDRB.multTransB(A.blockLength, subQ, subU, tmp);
                }
                else
                {
                    MatrixMult_FDRB.mult(A.blockLength, subU, subQ, tmp);
                }
                // Q(i+1) = Q(i) + W*F
                if (transposed)
                {
                    MatrixMult_FDRB.multPlus(A.blockLength, tmp, subW, subQ);
                }
                else
                {
                    MatrixMult_FDRB.multPlusTransA(A.blockLength, subW, tmp, subQ);
                }

                replaceZeros(subU);
            }

            return(Q);
        }