1*> \brief \b CGERQF
2*
3*  =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6*            http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download CGERQF + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cgerqf.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cgerqf.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgerqf.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18*  Definition:
19*  ===========
20*
21*       SUBROUTINE CGERQF( M, N, A, LDA, TAU, WORK, LWORK, INFO )
22*
23*       .. Scalar Arguments ..
24*       INTEGER            INFO, LDA, LWORK, M, N
25*       ..
26*       .. Array Arguments ..
27*       COMPLEX            A( LDA, * ), TAU( * ), WORK( * )
28*       ..
29*
30*
31*> \par Purpose:
32*  =============
33*>
34*> \verbatim
35*>
36*> CGERQF computes an RQ factorization of a complex M-by-N matrix A:
37*> A = R * Q.
38*> \endverbatim
39*
40*  Arguments:
41*  ==========
42*
43*> \param[in] M
44*> \verbatim
45*>          M is INTEGER
46*>          The number of rows of the matrix A.  M >= 0.
47*> \endverbatim
48*>
49*> \param[in] N
50*> \verbatim
51*>          N is INTEGER
52*>          The number of columns of the matrix A.  N >= 0.
53*> \endverbatim
54*>
55*> \param[in,out] A
56*> \verbatim
57*>          A is COMPLEX array, dimension (LDA,N)
58*>          On entry, the M-by-N matrix A.
59*>          On exit,
60*>          if m <= n, the upper triangle of the subarray
61*>          A(1:m,n-m+1:n) contains the M-by-M upper triangular matrix R;
62*>          if m >= n, the elements on and above the (m-n)-th subdiagonal
63*>          contain the M-by-N upper trapezoidal matrix R;
64*>          the remaining elements, with the array TAU, represent the
65*>          unitary matrix Q as a product of min(m,n) elementary
66*>          reflectors (see Further Details).
67*> \endverbatim
68*>
69*> \param[in] LDA
70*> \verbatim
71*>          LDA is INTEGER
72*>          The leading dimension of the array A.  LDA >= max(1,M).
73*> \endverbatim
74*>
75*> \param[out] TAU
76*> \verbatim
77*>          TAU is COMPLEX array, dimension (min(M,N))
78*>          The scalar factors of the elementary reflectors (see Further
79*>          Details).
80*> \endverbatim
81*>
82*> \param[out] WORK
83*> \verbatim
84*>          WORK is COMPLEX array, dimension (MAX(1,LWORK))
85*>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
86*> \endverbatim
87*>
88*> \param[in] LWORK
89*> \verbatim
90*>          LWORK is INTEGER
91*>          The dimension of the array WORK.  LWORK >= max(1,M).
92*>          For optimum performance LWORK >= M*NB, where NB is
93*>          the optimal blocksize.
94*>
95*>          If LWORK = -1, then a workspace query is assumed; the routine
96*>          only calculates the optimal size of the WORK array, returns
97*>          this value as the first entry of the WORK array, and no error
98*>          message related to LWORK is issued by XERBLA.
99*> \endverbatim
100*>
101*> \param[out] INFO
102*> \verbatim
103*>          INFO is INTEGER
104*>          = 0:  successful exit
105*>          < 0:  if INFO = -i, the i-th argument had an illegal value
106*> \endverbatim
107*
108*  Authors:
109*  ========
110*
111*> \author Univ. of Tennessee
112*> \author Univ. of California Berkeley
113*> \author Univ. of Colorado Denver
114*> \author NAG Ltd.
115*
116*> \date November 2011
117*
118*> \ingroup complexGEcomputational
119*
120*> \par Further Details:
121*  =====================
122*>
123*> \verbatim
124*>
125*>  The matrix Q is represented as a product of elementary reflectors
126*>
127*>     Q = H(1)**H H(2)**H . . . H(k)**H, where k = min(m,n).
128*>
129*>  Each H(i) has the form
130*>
131*>     H(i) = I - tau * v * v**H
132*>
133*>  where tau is a complex scalar, and v is a complex vector with
134*>  v(n-k+i+1:n) = 0 and v(n-k+i) = 1; conjg(v(1:n-k+i-1)) is stored on
135*>  exit in A(m-k+i,1:n-k+i-1), and tau in TAU(i).
136*> \endverbatim
137*>
138*  =====================================================================
139      SUBROUTINE CGERQF( M, N, A, LDA, TAU, WORK, LWORK, INFO )
140*
141*  -- LAPACK computational routine (version 3.4.0) --
142*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
143*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
144*     November 2011
145*
146*     .. Scalar Arguments ..
147      INTEGER            INFO, LDA, LWORK, M, N
148*     ..
149*     .. Array Arguments ..
150      COMPLEX            A( LDA, * ), TAU( * ), WORK( * )
151*     ..
152*
153*  =====================================================================
154*
155*     .. Local Scalars ..
156      LOGICAL            LQUERY
157      INTEGER            I, IB, IINFO, IWS, K, KI, KK, LDWORK, LWKOPT,
158     $                   MU, NB, NBMIN, NU, NX
159*     ..
160*     .. External Subroutines ..
161      EXTERNAL           CGERQ2, CLARFB, CLARFT, XERBLA
162*     ..
163*     .. Intrinsic Functions ..
164      INTRINSIC          MAX, MIN
165*     ..
166*     .. External Functions ..
167      INTEGER            ILAENV
168      EXTERNAL           ILAENV
169*     ..
170*     .. Executable Statements ..
171*
172*     Test the input arguments
173*
174      INFO = 0
175      LQUERY = ( LWORK.EQ.-1 )
176      IF( M.LT.0 ) THEN
177         INFO = -1
178      ELSE IF( N.LT.0 ) THEN
179         INFO = -2
180      ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
181         INFO = -4
182      END IF
183*
184      IF( INFO.EQ.0 ) THEN
185         K = MIN( M, N )
186         IF( K.EQ.0 ) THEN
187            LWKOPT = 1
188         ELSE
189            NB = ILAENV( 1, 'CGERQF', ' ', M, N, -1, -1 )
190            LWKOPT = M*NB
191         END IF
192         WORK( 1 ) = LWKOPT
193*
194         IF( LWORK.LT.MAX( 1, M ) .AND. .NOT.LQUERY ) THEN
195            INFO = -7
196         END IF
197      END IF
198*
199      IF( INFO.NE.0 ) THEN
200         CALL XERBLA( 'CGERQF', -INFO )
201         RETURN
202      ELSE IF( LQUERY ) THEN
203         RETURN
204      END IF
205*
206*     Quick return if possible
207*
208      IF( K.EQ.0 ) THEN
209         RETURN
210      END IF
211*
212      NBMIN = 2
213      NX = 1
214      IWS = M
215      IF( NB.GT.1 .AND. NB.LT.K ) THEN
216*
217*        Determine when to cross over from blocked to unblocked code.
218*
219         NX = MAX( 0, ILAENV( 3, 'CGERQF', ' ', M, N, -1, -1 ) )
220         IF( NX.LT.K ) THEN
221*
222*           Determine if workspace is large enough for blocked code.
223*
224            LDWORK = M
225            IWS = LDWORK*NB
226            IF( LWORK.LT.IWS ) THEN
227*
228*              Not enough workspace to use optimal NB:  reduce NB and
229*              determine the minimum value of NB.
230*
231               NB = LWORK / LDWORK
232               NBMIN = MAX( 2, ILAENV( 2, 'CGERQF', ' ', M, N, -1,
233     $                 -1 ) )
234            END IF
235         END IF
236      END IF
237*
238      IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN
239*
240*        Use blocked code initially.
241*        The last kk rows are handled by the block method.
242*
243         KI = ( ( K-NX-1 ) / NB )*NB
244         KK = MIN( K, KI+NB )
245*
246         DO 10 I = K - KK + KI + 1, K - KK + 1, -NB
247            IB = MIN( K-I+1, NB )
248*
249*           Compute the RQ factorization of the current block
250*           A(m-k+i:m-k+i+ib-1,1:n-k+i+ib-1)
251*
252            CALL CGERQ2( IB, N-K+I+IB-1, A( M-K+I, 1 ), LDA, TAU( I ),
253     $                   WORK, IINFO )
254            IF( M-K+I.GT.1 ) THEN
255*
256*              Form the triangular factor of the block reflector
257*              H = H(i+ib-1) . . . H(i+1) H(i)
258*
259               CALL CLARFT( 'Backward', 'Rowwise', N-K+I+IB-1, IB,
260     $                      A( M-K+I, 1 ), LDA, TAU( I ), WORK, LDWORK )
261*
262*              Apply H to A(1:m-k+i-1,1:n-k+i+ib-1) from the right
263*
264               CALL CLARFB( 'Right', 'No transpose', 'Backward',
265     $                      'Rowwise', M-K+I-1, N-K+I+IB-1, IB,
266     $                      A( M-K+I, 1 ), LDA, WORK, LDWORK, A, LDA,
267     $                      WORK( IB+1 ), LDWORK )
268            END IF
269   10    CONTINUE
270         MU = M - K + I + NB - 1
271         NU = N - K + I + NB - 1
272      ELSE
273         MU = M
274         NU = N
275      END IF
276*
277*     Use unblocked code to factor the last or only block
278*
279      IF( MU.GT.0 .AND. NU.GT.0 )
280     $   CALL CGERQ2( MU, NU, A, LDA, TAU, WORK, IINFO )
281*
282      WORK( 1 ) = IWS
283      RETURN
284*
285*     End of CGERQF
286*
287      END
288