Routine: PZLARZB()  File: SRC\pzlarzb.f

 
 
# lines: 626
  # code: 626
  # comment: 0
  # blank:0
# Variables:86
# Callers:2
# Callings:0
# Words:333
# Keywords:190
 

 

..
     .. Array Arguments ..
     ..
  Purpose
  =======
  PZLARZB applies a complex block reflector Q or its conjugate
  transpose Q**H to a complex M-by-N distributed matrix sub( C )
  denoting C(IC:IC+M-1,JC:JC+N-1), from the left or the right.
  Q is a product of k elementary reflectors as returned by PZTZRZF.
  Currently, only STOREV = 'R' and DIRECT = 'B' are supported.
  Notes
  =====
  Each global data object is described by an associated description
  vector.  This vector stores the information required to establish
  the mapping between an object element and its corresponding process
  and memory location.
  Let A be a generic term for any 2D block cyclicly distributed array.
  Such a global array has an associated description vector DESCA.
  In the following comments, the character _ should be read as
  "of the global array".
  NOTATION        STORED IN      EXPLANATION
  --------------- -------------- --------------------------------------
  DTYPE_A(global) DESCA( DTYPE_ )The descriptor type.  In this case,
                                 DTYPE_A = 1.
  CTXT_A (global) DESCA( CTXT_ ) The BLACS context handle, indicating
                                 the BLACS process grid A is distribu-
                                 ted over. The context itself is glo-
                                 bal, but the handle (the integer
                                 value) may vary.
  M_A    (global) DESCA( M_ )    The number of rows in the global
                                 array A.
  N_A    (global) DESCA( N_ )    The number of columns in the global
                                 array A.
  MB_A   (global) DESCA( MB_ )   The blocking factor used to distribute
                                 the rows of the array.
  NB_A   (global) DESCA( NB_ )   The blocking factor used to distribute
                                 the columns of the array.
  RSRC_A (global) DESCA( RSRC_ ) The process row over which the first
                                 row of the array A is distributed.
  CSRC_A (global) DESCA( CSRC_ ) The process column over which the
                                 first column of the array A is
                                 distributed.
  LLD_A  (local)  DESCA( LLD_ )  The leading dimension of the local
                                 array.  LLD_A >= MAX(1,LOCr(M_A)).
  Let K be the number of rows or columns of a distributed matrix,
  and assume that its process grid has dimension p x q.
  LOCr( K ) denotes the number of elements of K that a process
  would receive if K were distributed over the p processes of its
  process column.
  Similarly, LOCc( K ) denotes the number of elements of K that a
  process would receive if K were distributed over the q processes of
  its process row.
  The values of LOCr() and LOCc() may be determined via a call to the
  ScaLAPACK tool function, NUMROC:
          LOCr( M ) = NUMROC( M, MB_A, MYROW, RSRC_A, NPROW ),
          LOCc( N ) = NUMROC( N, NB_A, MYCOL, CSRC_A, NPCOL ).
  An upper bound for these quantities may be computed by:
          LOCr( M ) <= ceil( ceil(M/MB_A)/NPROW )*MB_A
          LOCc( N ) <= ceil( ceil(N/NB_A)/NPCOL )*NB_A
  Arguments
  =========
  SIDE    (global input) CHARACTER
          = 'L': apply Q or Q**H from the Left;
          = 'R': apply Q or Q**H from the Right.
  TRANS   (global input) CHARACTER
          = 'N':  No transpose, apply Q;
          = 'C':  Conjugate transpose, apply Q**H.
  DIRECT  (global input) CHARACTER
          Indicates how H is formed from a product of elementary
          reflectors
          = 'F': H = H(1) H(2) . . . H(k) (Forward, not supported yet)
          = 'B': H = H(k) . . . H(2) H(1) (Backward)
  STOREV  (global input) CHARACTER
          Indicates how the vectors which define the elementary
          reflectors are stored:
          = 'C': Columnwise                        (not supported yet)
          = 'R': Rowwise
  M       (global input) INTEGER
          The number of rows to be operated on i.e the number of rows
          of the distributed submatrix sub( C ). M >= 0.
  N       (global input) INTEGER
          The number of columns to be operated on i.e the number of
          columns of the distributed submatrix sub( C ). N >= 0.
  K       (global input) INTEGER
          The order of the matrix T (= the number of elementary
          reflectors whose product defines the block reflector).
  L       (global input) INTEGER
          The columns of the distributed submatrix sub( A ) containing
          the meaningful part of the Householder reflectors.
          If SIDE = 'L', M >= L >= 0, if SIDE = 'R', N >= L >= 0.
  V       (local input) COMPLEX*16 pointer into the local memory
          to an array of dimension (LLD_V, LOCc(JV+M-1)) if SIDE = 'L',
          (LLD_V, LOCc(JV+N-1)) if SIDE = 'R'. It contains the local
          pieces of the distributed vectors V representing the
          Householder transformation as returned by PZTZRZF.
          LLD_V >= LOCr(IV+K-1).
  IV      (global input) INTEGER
          The row index in the global array V indicating the first
          row of sub( V ).
  JV      (global input) INTEGER
          The column index in the global array V indicating the
          first column of sub( V ).
  DESCV   (global and local input) INTEGER array of dimension DLEN_.
          The array descriptor for the distributed matrix V.
  T       (local input) COMPLEX*16 array, dimension MB_V by MB_V
          The lower triangular matrix T in the representation of the
          block reflector.
  C       (local input/local output) COMPLEX*16 pointer into the
          local memory to an array of dimension (LLD_C,LOCc(JC+N-1)).
          On entry, the M-by-N distributed matrix sub( C ). On exit,
          sub( C ) is overwritten by Q*sub( C ) or Q'*sub( C ) or
          sub( C )*Q or sub( C )*Q'.
  IC      (global input) INTEGER
          The row index in the global array C indicating the first
          row of sub( C ).
  JC      (global input) INTEGER
          The column index in the global array C indicating the
          first column of sub( C ).
  DESCC   (global and local input) INTEGER array of dimension DLEN_.
          The array descriptor for the distributed matrix C.
  WORK    (local workspace) COMPLEX*16 array, dimension (LWORK)
          If STOREV = 'C',
            if SIDE = 'L',
              LWORK >= ( NqC0 + MpC0 ) * K
            else if SIDE = 'R',
              LWORK >= ( NqC0 + MAX( NpV0 + NUMROC( NUMROC( N+ICOFFC,
                         NB_V, 0, 0, NPCOL ), NB_V, 0, 0, LCMQ ),
                         MpC0 ) ) * K
            end if
          else if STOREV = 'R',
            if SIDE = 'L',
              LWORK >= ( MpC0 + MAX( MqV0 + NUMROC( NUMROC( M+IROFFC,
                         MB_V, 0, 0, NPROW ), MB_V, 0, 0, LCMP ),
                         NqC0 ) ) * K
            else if SIDE = 'R',
              LWORK >= ( MpC0 + NqC0 ) * K
            end if
          end if
          where LCMQ = LCM / NPCOL with LCM = ICLM( NPROW, NPCOL ),
          IROFFV = MOD( IV-1, MB_V ), ICOFFV = MOD( JV-1, NB_V ),
          IVROW = INDXG2P( IV, MB_V, MYROW, RSRC_V, NPROW ),
          IVCOL = INDXG2P( JV, NB_V, MYCOL, CSRC_V, NPCOL ),
          MqV0 = NUMROC( M+ICOFFV, NB_V, MYCOL, IVCOL, NPCOL ),
          NpV0 = NUMROC( N+IROFFV, MB_V, MYROW, IVROW, NPROW ),
          IROFFC = MOD( IC-1, MB_C ), ICOFFC = MOD( JC-1, NB_C ),
          ICROW = INDXG2P( IC, MB_C, MYROW, RSRC_C, NPROW ),
          ICCOL = INDXG2P( JC, NB_C, MYCOL, CSRC_C, NPCOL ),
          MpC0 = NUMROC( M+IROFFC, MB_C, MYROW, ICROW, NPROW ),
          NpC0 = NUMROC( N+ICOFFC, MB_C, MYROW, ICROW, NPROW ),
          NqC0 = NUMROC( N+ICOFFC, NB_C, MYCOL, ICCOL, NPCOL ),
          ILCM, INDXG2P and NUMROC are ScaLAPACK tool functions;
          MYROW, MYCOL, NPROW and NPCOL can be determined by calling
          the subroutine BLACS_GRIDINFO.
  Alignment requirements
  ======================
  The distributed submatrices V(IV:*, JV:*) and C(IC:IC+M-1,JC:JC+N-1)
  must verify some alignment properties, namely the following
  expressions should be true:
  If STOREV = 'Columnwise'
    If SIDE = 'Left',
      ( MB_V.EQ.MB_C .AND. IROFFV.EQ.IROFFC .AND. IVROW.EQ.ICROW )
    If SIDE = 'Right',
      ( MB_V.EQ.NB_C .AND. IROFFV.EQ.ICOFFC )
  else if STOREV = 'Rowwise'
    If SIDE = 'Left',
      ( NB_V.EQ.MB_C .AND. ICOFFV.EQ.IROFFC )
    If SIDE = 'Right',
      ( NB_V.EQ.NB_C .AND. ICOFFV.EQ.ICOFFC .AND. IVCOL.EQ.ICCOL )
  end if
  =====================================================================
     .. Parameters ..

 
Display dynamic version Find AutoScroll Reload FontSize: - + Hide Comments Hide Blanks Frame FullScreen MailPrint

 
001        SUBROUTINE PZLARZB( SIDE , TRANS , DIRECT , STOREV , M , N , K , L , V ,
002       $IV , JV , DESCV , T , C , IC , JC , DESCC , WORK )
003  
004  *     -- ScaLAPACK auxiliary routine(version 1.7) --
005  *     University of Tennessee , Knoxville , Oak Ridge National Laboratory ,
006  *     and University of California , Berkeley.
007  *     March 14 , 2000
008  
009  *     .. Scalar Arguments ..
010        CHARACTER DIRECT , SIDE , STOREV , TRANS
011        INTEGER IC , IV , JC , JV , K , L , M , N
012        INTEGER BLOCK_CYCLIC_2D , CSRC_ , CTXT_ , DLEN_ , DTYPE_ ,
013       $LLD_ , MB_ , M_ , NB_ , N_ , RSRC_
014        PARAMETER( BLOCK_CYCLIC_2D = 1 , DLEN_ = 9 , DTYPE_ = 1 ,
015       $CTXT_ = 2 , M_ = 3 , N_ = 4 , MB_ = 5 , NB_ = 6 ,
016       $RSRC_ = 7 , CSRC_ = 8 , LLD_ = 9 )
017        COMPLEX*16 ONE , ZERO
018        PARAMETER( ONE =( 1.0D + 0 , 0.0D + 0 ) ,
019       $ZERO =( 0.0D + 0 , 0.0D + 0 ) )
020  *     ..
021  *     .. Local Scalars ..
022        LOGICAL LEFT
023        CHARACTER COLBTOP , TRANST
024        INTEGER ICCOL1 , ICCOL2 , ICOFFC1 , ICOFFC2 , ICOFFV ,
025       $ICROW1 , ICROW2 , ICTXT , IIBEG , IIC1 , IIC2 ,
026       $IIEND , IINXT , IIV , ILEFT , INFO , IOFFC2 , IOFFV ,
027       $IPT , IPV , IPW , IROFFC1 , IROFFC2 , ITOP , IVCOL ,
028       $IVROW , J , JJBEG , JJEND , JJNXT , JJC1 , JJC2 , JJV ,
029       $LDC , LDV , LV , LW , MBC , MBV , MPC1 , MPC2 , MPC20 ,
030       $MQV , MQV0 , MYCOL , MYDIST , MYROW , NBC , NBV ,
031       $NPCOL , NPROW , NQC1 , NQC2 , NQCALL , NQV
032  *     ..
033  *     .. External Subroutines ..
034        EXTERNAL BLACS_ABORT , BLACS_GRIDINFO , INFOG2L ,
035       $PBZMATADD , PB_TOPGET , PXERBLA , PBZTRAN ,
036       $ZGEBR2D , ZGEBS2D , ZGEMM ,
037       $ZGSUM2D , ZLACGV , ZLACPY , ZLASET ,
038       $ZTRBR2D , ZTRBS2D , ZTRMM
039  *     ..
040  *     .. Intrinsic Functions ..
041        INTRINSIC MAX , MIN , MOD
042  *     ..
043  *     .. External Functions ..
044        LOGICAL LSAME
045        INTEGER ICEIL , NUMROC
046        EXTERNAL ICEIL , LSAME , NUMROC
047  *     ..
048  *     .. Executable Statements ..
049  
050  *     Quick return if possible
051  
052        IF( M.LE.0 .OR. N.LE.0 .OR. K.LE.0 )
053       $    RETURN
054  
055  *         Get grid parameters
056  
057            ICTXT = DESCC( CTXT_ )
058            CALL BLACS_GRIDINFO( ICTXT , NPROW , NPCOL , MYROW , MYCOL )
059  
060  *         Check for currently supported options
061  
062            INFO = 0
063            IF( .NOT.LSAME( DIRECT , 'B' ) ) THEN
064                INFO = - 3
065            ELSE IF( .NOT.LSAME( STOREV , 'R' ) ) THEN
066                INFO = - 4
067            END IF
068            IF( INFO.NE.0 ) THEN
069                CALL PXERBLA( ICTXT , 'PZLARZB' , - INFO )
070                CALL BLACS_ABORT( ICTXT , 1 )
071                RETURN
072            END IF
073  
074            LEFT = LSAME( SIDE , 'L' )
075            IF( LSAME( TRANS , 'N' ) ) THEN
076                TRANST = 'C'
077            ELSE
078                TRANST = 'N'
079            END IF
080  
081            CALL INFOG2L( IV , JV , DESCV , NPROW , NPCOL , MYROW , MYCOL , IIV , JJV ,
082       $    IVROW , IVCOL )
083            MBV = DESCV( MB_ )
084            NBV = DESCV( NB_ )
085            ICOFFV = MOD( JV - 1 , NBV )
086            NQV = NUMROC( L + ICOFFV , NBV , MYCOL , IVCOL , NPCOL )
087            IF( MYCOL.EQ.IVCOL )
088       $        NQV = NQV - ICOFFV
089                LDV = DESCV( LLD_ )
090                IIV = MIN( IIV , LDV )
091                JJV = MIN( JJV , MAX( 1 , NUMROC( DESCV( N_ ) , NBV , MYCOL ,
092       $        DESCV( CSRC_ ) , NPCOL ) ) )
093                IOFFV = IIV + ( JJV - 1 ) * LDV
094                MBC = DESCC( MB_ )
095                NBC = DESCC( NB_ )
096                NQCALL = NUMROC( DESCC( N_ ) , NBC , MYCOL , DESCC( CSRC_ ) , NPCOL )
097                CALL INFOG2L( IC , JC , DESCC , NPROW , NPCOL , MYROW , MYCOL , IIC1 ,
098       $        JJC1 , ICROW1 , ICCOL1 )
099                LDC = DESCC( LLD_ )
100                IIC1 = MIN( IIC1 , LDC )
101                JJC1 = MIN( JJC1 , MAX( 1 , NQCALL ) )
102  
103                IF( LEFT ) THEN
104                    IROFFC1 = MOD( IC - 1 , MBC )
105                    MPC1 = NUMROC( K + IROFFC1 , MBC , MYROW , ICROW1 , NPROW )
106                    IF( MYROW.EQ.ICROW1 )
107       $                MPC1 = MPC1 - IROFFC1
108                        ICOFFC1 = MOD( JC - 1 , NBC )
109                        NQC1 = NUMROC( N + ICOFFC1 , NBC , MYCOL , ICCOL1 , NPCOL )
110                        IF( MYCOL.EQ.ICCOL1 )
111       $                    NQC1 = NQC1 - ICOFFC1
112                            CALL INFOG2L( IC + M - L , JC , DESCC , NPROW , NPCOL , MYROW , MYCOL ,
113       $                    IIC2 , JJC2 , ICROW2 , ICCOL2 )
114                            IROFFC2 = MOD( IC + M - L - 1 , MBC )
115                            MPC2 = NUMROC( L + IROFFC2 , MBC , MYROW , ICROW2 , NPROW )
116                            IF( MYROW.EQ.ICROW2 )
117       $                        MPC2 = MPC2 - IROFFC2
118                                ICOFFC2 = ICOFFC1
119                                NQC2 = NQC1
120                            ELSE
121                                IROFFC1 = MOD( IC - 1 , MBC )
122                                MPC1 = NUMROC( M + IROFFC1 , MBC , MYROW , ICROW1 , NPROW )
123                                IF( MYROW.EQ.ICROW1 )
124       $                            MPC1 = MPC1 - IROFFC1
125                                    ICOFFC1 = MOD( JC - 1 , NBC )
126                                    NQC1 = NUMROC( K + ICOFFC1 , NBC , MYCOL , ICCOL1 , NPCOL )
127                                    IF( MYCOL.EQ.ICCOL1 )
128       $                                NQC1 = NQC1 - ICOFFC1
129                                        CALL INFOG2L( IC , JC + N - L , DESCC , NPROW , NPCOL , MYROW , MYCOL ,
130       $                                IIC2 , JJC2 , ICROW2 , ICCOL2 )
131                                        IROFFC2 = IROFFC1
132                                        MPC2 = MPC1
133                                        ICOFFC2 = MOD( JC + N - L - 1 , NBC )
134                                        NQC2 = NUMROC( L + ICOFFC2 , NBC , MYCOL , ICCOL2 , NPCOL )
135                                        IF( MYCOL.EQ.ICCOL2 )
136       $                                    NQC2 = NQC2 - ICOFFC2
137                                        END IF
138                                        IIC2 = MIN( IIC2 , LDC )
139                                        JJC2 = MIN( JJC2 , NQCALL )
140                                        IOFFC2 = IIC2 + ( JJC2 - 1 ) * LDC
141  
142                                        IF( LSAME( SIDE , 'L' ) ) THEN
143  
144  *                                         Form Q*sub( C ) or Q'*sub( C )
145  
146  *                                         IROFFC2 = ICOFFV is required by the current transposition
147  *                                         routine PBZTRAN
148  
149                                            MQV0 = NUMROC( M + ICOFFV , NBV , MYCOL , IVCOL , NPCOL )
150                                            IF( MYCOL.EQ.IVCOL ) THEN
151                                                MQV = MQV0 - ICOFFV
152                                            ELSE
153                                                MQV = MQV0
154                                            END IF
155                                            IF( MYROW.EQ.ICROW2 ) THEN
156                                                MPC20 = MPC2 + IROFFC2
157                                            ELSE
158                                                MPC20 = MPC2
159                                            END IF
160  
161  *                                         Locally V( IOFFV ) is K x MQV , C( IOFFC2 ) is MPC2 x NQC2
162  *                                         WORK( IPV ) is MPC20 x K =[ . V( IOFFV ) ]'
163  *                                         WORK( IPW ) is K x MQV0 =[ . V( IOFFV ) ]
164  *                                         WORK( IPT ) is the workspace for PBZTRAN
165  
166                                            IPV = 1
167                                            IPW = IPV + MPC20 * K
168                                            IPT = IPW + K * MQV0
169                                            LV = MAX( 1 , MPC20 )
170                                            LW = MAX( 1 , K )
171  
172                                            IF( MYROW.EQ.IVROW ) THEN
173                                                IF( MYCOL.EQ.IVCOL ) THEN
174                                                    CALL ZLACPY( 'All' , K , MQV , V( IOFFV ) , LDV ,
175       $                                            WORK( IPW + ICOFFV*LW ) , LW )
176                                                ELSE
177                                                    CALL ZLACPY( 'All' , K , MQV , V( IOFFV ) , LDV ,
178       $                                            WORK( IPW ) , LW )
179                                                END IF
180                                            END IF
181  
182  *                                         WORK( IPV ) = WORK( IPW )'(replicated) is MPC20 x K
183  
184                                            CALL PBZTRAN( ICTXT , 'Rowwise' , 'Conjugate transpose' , K ,
185       $                                    M + ICOFFV , DESCV( NB_ ) , WORK( IPW ) , LW , ZERO ,
186       $                                    WORK( IPV ) , LV , IVROW , IVCOL , ICROW2 , - 1 ,
187       $                                    WORK( IPT ) )
188  
189  *                                         WORK( IPV ) =( . V )' -> WORK( IPV ) = V' is MPC2 x K
190  
191                                            IF( MYROW.EQ.ICROW2 )
192       $                                        IPV = IPV + IROFFC2
193  
194  *                                             WORK( IPW ) becomes NQC2 x K = C( IOFFC2 )' * V'
195  *                                             WORK( IPW ) = C( IOFFC2 )' * V'(NQC2 x MPC2 x K) -> NQC2 x K
196  
197                                                LW = MAX( 1 , NQC2 )
198  
199                                                IF( MPC2.GT.0 ) THEN
200                                                    CALL ZGEMM( 'Transpose' , 'No transpose' , NQC2 , K , MPC2 ,
201       $                                            ONE , C( IOFFC2 ) , LDC , WORK( IPV ) , LV , ZERO ,
202       $                                            WORK( IPW ) , LW )
203                                                ELSE
204                                                    CALL ZLASET( 'All' , NQC2 , K , ZERO , ZERO , WORK( IPW ) , LW )
205                                                END IF
206  
207  *                                             WORK( IPW ) = WORK( IPW ) + C1( NQC1 = NQC2 )
208  
209                                                IF( MPC1.GT.0 ) THEN
210                                                    MYDIST = MOD( MYROW - ICROW1 + NPROW , NPROW )
211                                                    ITOP = MAX( 0 , MYDIST * MBC - IROFFC1 )
212                                                    IIBEG = IIC1
213                                                    IIEND = IIC1 + MPC1 - 1
214                                                    IINXT = MIN( ICEIL( IIBEG , MBC ) * MBC , IIEND )
215  
216     10 CONTINUE
217        IF( IIBEG.LE.IINXT ) THEN
218            CALL PBZMATADD( ICTXT , 'Transpose' , NQC2 , IINXT - IIBEG + 1 ,
219       $    ONE , C( IIBEG + (JJC1 - 1)*LDC ) , LDC , ONE ,
220       $    WORK( IPW + ITOP ) , LW )
221            MYDIST = MYDIST + NPROW
222            ITOP = MYDIST * MBC - IROFFC1
223            IIBEG = IINXT + 1
224            IINXT = MIN( IINXT + MBC , IIEND )
225            GO TO 10
226        END IF
227        END IF
228  
229        CALL ZGSUM2D( ICTXT , 'Columnwise' , ' ' , NQC2 , K , WORK( IPW ) ,
230       $LW , IVROW , MYCOL )
231  
232  *     WORK( IPW ) = WORK( IPW ) * T' or WORK( IPW ) * T
233  
234        IF( MYROW.EQ.IVROW ) THEN
235            IF( MYCOL.EQ.IVCOL ) THEN
236  
237  *             Broadcast the block reflector to the other columns.
238  
239                CALL ZTRBS2D( ICTXT , 'Rowwise' , ' ' , 'Lower' , 'Non unit' ,
240       $        K , K , T , MBV )
241            ELSE
242                CALL ZTRBR2D( ICTXT , 'Rowwise' , ' ' , 'Lower' , 'Non unit' ,
243       $        K , K , T , MBV , MYROW , IVCOL )
244            END IF
245            CALL ZTRMM( 'Right' , 'Lower' , TRANST , 'Non unit' , NQC2 , K ,
246       $    ONE , T , MBV , WORK( IPW ) , LW )
247  
248            CALL ZGEBS2D( ICTXT , 'Columnwise' , ' ' , NQC2 , K ,
249       $    WORK( IPW ) , LW )
250        ELSE
251            CALL ZGEBR2D( ICTXT , 'Columnwise' , ' ' , NQC2 , K ,
252       $    WORK( IPW ) , LW , IVROW , MYCOL )
253        END IF
254  
255  *     C1 = C1 - WORK( IPW )
256  
257        IF( MPC1.GT.0 ) THEN
258            MYDIST = MOD( MYROW - ICROW1 + NPROW , NPROW )
259            ITOP = MAX( 0 , MYDIST * MBC - IROFFC1 )
260            IIBEG = IIC1
261            IIEND = IIC1 + MPC1 - 1
262            IINXT = MIN( ICEIL( IIBEG , MBC ) * MBC , IIEND )
263  
264     20 CONTINUE
265        IF( IIBEG.LE.IINXT ) THEN
266            CALL PBZMATADD( ICTXT , 'Transpose' , IINXT - IIBEG + 1 , NQC2 ,
267       $    - ONE , WORK( IPW + ITOP ) , LW , ONE ,
268       $    C( IIBEG + (JJC1 - 1)*LDC ) , LDC )
269            MYDIST = MYDIST + NPROW
270            ITOP = MYDIST * MBC - IROFFC1
271            IIBEG = IINXT + 1
272            IINXT = MIN( IINXT + MBC , IIEND )
273            GO TO 20
274        END IF
275        END IF
276  
277  *     C2 C2 - V' * W'
278  *     C( IOFFC2 ) = C( IOFFC2 ) - WORK( IPV ) * WORK( IPW )'
279  *     MPC2 x NQC2 MPC2 x K K x NQC2
280  
281        DO 30 J = 1 , K
282            CALL ZLACGV( MPC2 , WORK( IPV + (J - 1)*LV ) , 1 )
283     30 CONTINUE
284        CALL ZGEMM( 'No transpose' , 'Transpose' , MPC2 , NQC2 , K , - ONE ,
285       $WORK( IPV ) , LV , WORK( IPW ) , LW , ONE ,
286       $C( IOFFC2 ) , LDC )
287  
288        ELSE
289  
290  *         Form sub( C ) * Q or sub( C ) * Q'
291  
292  *         Locally V( IOFFV ) is K x NQV , C( IOFFC2 ) is MPC2 x NQC2
293  *         WORK( IPV ) is K x NQV = V( IOFFV ) , NQV = NQC2
294  *         WORK( IPW ) is MPC2 x K = C( IOFFC2 ) * V( IOFFV )'
295  
296            IPV = 1
297            IPW = IPV + K * NQC2
298            LV = MAX( 1 , K )
299            LW = MAX( 1 , MPC2 )
300  
301  *         Broadcast V to the other process rows.
302  
303            CALL PB_TOPGET( ICTXT , 'Broadcast' , 'Columnwise' , COLBTOP )
304            IF( MYROW.EQ.IVROW ) THEN
305                CALL ZGEBS2D( ICTXT , 'Columnwise' , COLBTOP , K , NQC2 ,
306       $        V( IOFFV ) , LDV )
307                IF( MYCOL.EQ.IVCOL )
308       $            CALL ZTRBS2D( ICTXT , 'Columnwise' , COLBTOP , 'Lower' ,
309       $            'Non unit' , K , K , T , MBV )
310                    CALL ZLACPY( 'All' , K , NQC2 , V( IOFFV ) , LDV , WORK( IPV ) ,
311       $            LV )
312                ELSE
313                    CALL ZGEBR2D( ICTXT , 'Columnwise' , COLBTOP , K , NQC2 ,
314       $            WORK( IPV ) , LV , IVROW , MYCOL )
315                    IF( MYCOL.EQ.IVCOL )
316       $                CALL ZTRBR2D( ICTXT , 'Columnwise' , COLBTOP , 'Lower' ,
317       $                'Non unit' , K , K , T , MBV , IVROW , MYCOL )
318                    END IF
319  
320  *                 WORK( IPV ) is K x NQC2 = V = V( IOFFV )
321  *                 WORK( IPW ) = C( IOFFC2 ) * V'(MPC2 x NQC2 x K) -> MPC2 x K
322  
323                    IF( NQC2.GT.0 ) THEN
324                        CALL ZGEMM( 'No Transpose' , 'Transpose' , MPC2 , K , NQC2 ,
325       $                ONE , C( IOFFC2 ) , LDC , WORK( IPV ) , LV , ZERO ,
326       $                WORK( IPW ) , LW )
327                    ELSE
328                        CALL ZLASET( 'All' , MPC2 , K , ZERO , ZERO , WORK( IPW ) , LW )
329                    END IF
330  
331  *                 WORK( IPW ) = WORK( IPW ) + C1( MPC1 = MPC2 )
332  
333                    IF( NQC1.GT.0 ) THEN
334                        MYDIST = MOD( MYCOL - ICCOL1 + NPCOL , NPCOL )
335                        ILEFT = MAX( 0 , MYDIST * NBC - ICOFFC1 )
336                        JJBEG = JJC1
337                        JJEND = JJC1 + NQC1 - 1
338                        JJNXT = MIN( ICEIL( JJBEG , NBC ) * NBC , JJEND )
339  
340     40 CONTINUE
341        IF( JJBEG.LE.JJNXT ) THEN
342            CALL PBZMATADD( ICTXT , 'No transpose' , MPC2 ,
343       $    JJNXT - JJBEG + 1 , ONE ,
344       $    C( IIC1 + (JJBEG - 1)*LDC ) , LDC , ONE ,
345       $    WORK( IPW + ILEFT*LW ) , LW )
346            MYDIST = MYDIST + NPCOL
347            ILEFT = MYDIST * NBC - ICOFFC1
348            JJBEG = JJNXT + 1
349            JJNXT = MIN( JJNXT + NBC , JJEND )
350            GO TO 40
351        END IF
352        END IF
353  
354        CALL ZGSUM2D( ICTXT , 'Rowwise' , ' ' , MPC2 , K , WORK( IPW ) ,
355       $LW , MYROW , IVCOL )
356  
357  *     WORK( IPW ) = WORK( IPW ) * T' or WORK( IPW ) * T
358  
359        IF( MYCOL.EQ.IVCOL ) THEN
360            DO 50 J = 1 , K
361                CALL ZLACGV( K - J + 1 , T( J + (J - 1)*MBV ) , 1 )
362     50     CONTINUE
363            CALL ZTRMM( 'Right' , 'Lower' , TRANS , 'Non unit' , MPC2 , K ,
364       $    ONE , T , MBV , WORK( IPW ) , LW )
365            CALL ZGEBS2D( ICTXT , 'Rowwise' , ' ' , MPC2 , K , WORK( IPW ) ,
366       $    LW )
367            DO 60 J = 1 , K
368                CALL ZLACGV( K - J + 1 , T( J + (J - 1)*MBV ) , 1 )
369     60     CONTINUE
370        ELSE
371            CALL ZGEBR2D( ICTXT , 'Rowwise' , ' ' , MPC2 , K , WORK( IPW ) ,
372       $    LW , MYROW , IVCOL )
373        END IF
374  
375  *     C1 = C1 - WORK( IPW )
376  
377        IF( NQC1.GT.0 ) THEN
378            MYDIST = MOD( MYCOL - ICCOL1 + NPCOL , NPCOL )
379            ILEFT = MAX( 0 , MYDIST * NBC - ICOFFC1 )
380            JJBEG = JJC1
381            JJEND = JJC1 + NQC1 - 1
382            JJNXT = MIN( ICEIL( JJBEG , NBC ) * NBC , JJEND )
383  
384     70 CONTINUE
385        IF( JJBEG.LE.JJNXT ) THEN
386            CALL PBZMATADD( ICTXT , 'No transpose' , MPC2 ,
387       $    JJNXT - JJBEG + 1 , - ONE ,
388       $    WORK( IPW + ILEFT*LW ) , LW , ONE ,
389       $    C( IIC1 + (JJBEG - 1)*LDC ) , LDC )
390            MYDIST = MYDIST + NPCOL
391            ILEFT = MYDIST * NBC - ICOFFC1
392            JJBEG = JJNXT + 1
393            JJNXT = MIN( JJNXT + NBC , JJEND )
394            GO TO 70
395        END IF
396        END IF
397  
398  *     C2 C2 - W * conjg( V )
399  *     C( IOFFC ) = C( IOFFC ) - WORK( IPW ) * conjg( WORK( IPV ) )
400  *     MPC2 x NQC2 MPC2 x K K x NQC2
401  
402        DO 80 J = 1 , NQC2
403            CALL ZLACGV( K , WORK( IPV + (J - 1)*LV ) , 1 )
404     80 CONTINUE
405        IF( IOFFC2.GT.0 )
406       $    CALL ZGEMM( 'No transpose' , 'No transpose' , MPC2 , NQC2 , K ,
407       $    - ONE , WORK( IPW ) , LW , WORK( IPV ) , LV , ONE ,
408       $    C( IOFFC2 ) , LDC )
409  
410        END IF
411  
412        RETURN
413  
414  *     End of PZLARZB
415  
416        END