1*> \brief \b ZGEMQR
2*
3*  Definition:
4*  ===========
5*
6*      SUBROUTINE ZGEMQR( SIDE, TRANS, M, N, K, A, LDA, T,
7*     $                   TSIZE, C, LDC, WORK, LWORK, INFO )
8*
9*
10*     .. Scalar Arguments ..
11*     CHARACTER         SIDE, TRANS
12*     INTEGER           INFO, LDA, M, N, K, LDT, TSIZE, LWORK, LDC
13*     ..
14*     .. Array Arguments ..
15*     COMPLEX*16        A( LDA, * ), T( * ), C( LDC, * ), WORK( * )
16*     ..
17*
18*> \par Purpose:
19*  =============
20*>
21*> \verbatim
22*>
23*> ZGEMQR overwrites the general real M-by-N matrix C with
24*>
25*>                      SIDE = 'L'     SIDE = 'R'
26*>      TRANS = 'N':      Q * C          C * Q
27*>      TRANS = 'T':      Q**H * C       C * Q**H
28*>
29*> where Q is a complex unitary matrix defined as the product
30*> of blocked elementary reflectors computed by tall skinny
31*> QR factorization (ZGEQR)
32*>
33*> \endverbatim
34*
35*  Arguments:
36*  ==========
37*
38*> \param[in] SIDE
39*> \verbatim
40*>          SIDE is CHARACTER*1
41*>          = 'L': apply Q or Q**H from the Left;
42*>          = 'R': apply Q or Q**H from the Right.
43*> \endverbatim
44*>
45*> \param[in] TRANS
46*> \verbatim
47*>          TRANS is CHARACTER*1
48*>          = 'N':  No transpose, apply Q;
49*>          = 'C':  Conjugate transpose, apply Q**H.
50*> \endverbatim
51*>
52*> \param[in] M
53*> \verbatim
54*>          M is INTEGER
55*>          The number of rows of the matrix A.  M >=0.
56*> \endverbatim
57*>
58*> \param[in] N
59*> \verbatim
60*>          N is INTEGER
61*>          The number of columns of the matrix C. N >= 0.
62*> \endverbatim
63*>
64*> \param[in] K
65*> \verbatim
66*>          K is INTEGER
67*>          The number of elementary reflectors whose product defines
68*>          the matrix Q.
69*>          If SIDE = 'L', M >= K >= 0;
70*>          if SIDE = 'R', N >= K >= 0.
71*> \endverbatim
72*>
73*> \param[in] A
74*> \verbatim
75*>          A is COMPLEX*16 array, dimension (LDA,K)
76*>          Part of the data structure to represent Q as returned by ZGEQR.
77*> \endverbatim
78*>
79*> \param[in] LDA
80*> \verbatim
81*>          LDA is INTEGER
82*>          The leading dimension of the array A.
83*>          If SIDE = 'L', LDA >= max(1,M);
84*>          if SIDE = 'R', LDA >= max(1,N).
85*> \endverbatim
86*>
87*> \param[in] T
88*> \verbatim
89*>          T is COMPLEX*16 array, dimension (MAX(5,TSIZE)).
90*>          Part of the data structure to represent Q as returned by ZGEQR.
91*> \endverbatim
92*>
93*> \param[in] TSIZE
94*> \verbatim
95*>          TSIZE is INTEGER
96*>          The dimension of the array T. TSIZE >= 5.
97*> \endverbatim
98*>
99*> \param[in,out] C
100*> \verbatim
101*>          C is COMPLEX*16 array, dimension (LDC,N)
102*>          On entry, the M-by-N matrix C.
103*>          On exit, C is overwritten by Q*C or Q**H*C or C*Q**H or C*Q.
104*> \endverbatim
105*>
106*> \param[in] LDC
107*> \verbatim
108*>          LDC is INTEGER
109*>          The leading dimension of the array C. LDC >= max(1,M).
110*> \endverbatim
111*>
112*> \param[out] WORK
113*> \verbatim
114*>         (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK))
115*> \endverbatim
116*>
117*> \param[in] LWORK
118*> \verbatim
119*>          LWORK is INTEGER
120*>          The dimension of the array WORK.
121*>          If LWORK = -1, then a workspace query is assumed. The routine
122*>          only calculates the size of the WORK array, returns this
123*>          value as WORK(1), and no error message related to WORK
124*>          is issued by XERBLA.
125*> \endverbatim
126*>
127*> \param[out] INFO
128*> \verbatim
129*>          INFO is INTEGER
130*>          = 0:  successful exit
131*>          < 0:  if INFO = -i, the i-th argument had an illegal value
132*> \endverbatim
133*
134*  Authors:
135*  ========
136*
137*> \author Univ. of Tennessee
138*> \author Univ. of California Berkeley
139*> \author Univ. of Colorado Denver
140*> \author NAG Ltd.
141*
142*> \par Further Details
143*  ====================
144*>
145*> \verbatim
146*>
147*> These details are particular for this LAPACK implementation. Users should not
148*> take them for granted. These details may change in the future, and are not likely
149*> true for another LAPACK implementation. These details are relevant if one wants
150*> to try to understand the code. They are not part of the interface.
151*>
152*> In this version,
153*>
154*>          T(2): row block size (MB)
155*>          T(3): column block size (NB)
156*>          T(6:TSIZE): data structure needed for Q, computed by
157*>                           ZLATSQR or ZGEQRT
158*>
159*>  Depending on the matrix dimensions M and N, and row and column
160*>  block sizes MB and NB returned by ILAENV, ZGEQR will use either
161*>  ZLATSQR (if the matrix is tall-and-skinny) or ZGEQRT to compute
162*>  the QR factorization.
163*>  This version of ZGEMQR will use either ZLAMTSQR or ZGEMQRT to
164*>  multiply matrix Q by another matrix.
165*>  Further Details in ZLAMTSQR or ZGEMQRT.
166*>
167*> \endverbatim
168*>
169*  =====================================================================
170      SUBROUTINE ZGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE,
171     $                   C, LDC, WORK, LWORK, INFO )
172*
173*  -- LAPACK computational routine --
174*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
175*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
176*
177*     .. Scalar Arguments ..
178      CHARACTER          SIDE, TRANS
179      INTEGER            INFO, LDA, M, N, K, TSIZE, LWORK, LDC
180*     ..
181*     .. Array Arguments ..
182      COMPLEX*16         A( LDA, * ), T( * ), C( LDC, * ), WORK( * )
183*     ..
184*
185* =====================================================================
186*
187*     ..
188*     .. Local Scalars ..
189      LOGICAL            LEFT, RIGHT, TRAN, NOTRAN, LQUERY
190      INTEGER            MB, NB, LW, NBLCKS, MN
191*     ..
192*     .. External Functions ..
193      LOGICAL            LSAME
194      EXTERNAL           LSAME
195*     ..
196*     .. External Subroutines ..
197      EXTERNAL           ZGEMQRT, ZLAMTSQR, XERBLA
198*     ..
199*     .. Intrinsic Functions ..
200      INTRINSIC          INT, MAX, MIN, MOD
201*     ..
202*     .. Executable Statements ..
203*
204*     Test the input arguments
205*
206      LQUERY  = LWORK.EQ.-1
207      NOTRAN  = LSAME( TRANS, 'N' )
208      TRAN    = LSAME( TRANS, 'C' )
209      LEFT    = LSAME( SIDE, 'L' )
210      RIGHT   = LSAME( SIDE, 'R' )
211*
212      MB = INT( T( 2 ) )
213      NB = INT( T( 3 ) )
214      IF( LEFT ) THEN
215        LW = N * NB
216        MN = M
217      ELSE
218        LW = MB * NB
219        MN = N
220      END IF
221*
222      IF( ( MB.GT.K ) .AND. ( MN.GT.K ) ) THEN
223        IF( MOD( MN - K, MB - K ).EQ.0 ) THEN
224          NBLCKS = ( MN - K ) / ( MB - K )
225        ELSE
226          NBLCKS = ( MN - K ) / ( MB - K ) + 1
227        END IF
228      ELSE
229        NBLCKS = 1
230      END IF
231*
232      INFO = 0
233      IF( .NOT.LEFT .AND. .NOT.RIGHT ) THEN
234        INFO = -1
235      ELSE IF( .NOT.TRAN .AND. .NOT.NOTRAN ) THEN
236        INFO = -2
237      ELSE IF( M.LT.0 ) THEN
238        INFO = -3
239      ELSE IF( N.LT.0 ) THEN
240        INFO = -4
241      ELSE IF( K.LT.0 .OR. K.GT.MN ) THEN
242        INFO = -5
243      ELSE IF( LDA.LT.MAX( 1, MN ) ) THEN
244        INFO = -7
245      ELSE IF( TSIZE.LT.5 ) THEN
246        INFO = -9
247      ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
248        INFO = -11
249      ELSE IF( ( LWORK.LT.MAX( 1, LW ) ) .AND. ( .NOT.LQUERY ) ) THEN
250        INFO = -13
251      END IF
252*
253      IF( INFO.EQ.0 ) THEN
254        WORK( 1 ) = LW
255      END IF
256*
257      IF( INFO.NE.0 ) THEN
258        CALL XERBLA( 'ZGEMQR', -INFO )
259        RETURN
260      ELSE IF( LQUERY ) THEN
261        RETURN
262      END IF
263*
264*     Quick return if possible
265*
266      IF( MIN( M, N, K ).EQ.0 ) THEN
267        RETURN
268      END IF
269*
270      IF( ( LEFT .AND. M.LE.K ) .OR. ( RIGHT .AND. N.LE.K )
271     $     .OR. ( MB.LE.K ) .OR. ( MB.GE.MAX( M, N, K ) ) ) THEN
272        CALL ZGEMQRT( SIDE, TRANS, M, N, K, NB, A, LDA, T( 6 ),
273     $                NB, C, LDC, WORK, INFO )
274      ELSE
275        CALL ZLAMTSQR( SIDE, TRANS, M, N, K, MB, NB, A, LDA, T( 6 ),
276     $                 NB, C, LDC, WORK, LWORK, INFO )
277      END IF
278*
279      WORK( 1 ) = LW
280*
281      RETURN
282*
283*     End of ZGEMQR
284*
285      END
286