1*> \brief <b> CGELSS solves overdetermined or underdetermined systems for GE matrices</b>
2*
3*  =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6*            http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download CGELSS + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cgelss.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cgelss.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgelss.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18*  Definition:
19*  ===========
20*
21*       SUBROUTINE CGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
22*                          WORK, LWORK, RWORK, INFO )
23*
24*       .. Scalar Arguments ..
25*       INTEGER            INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
26*       REAL               RCOND
27*       ..
28*       .. Array Arguments ..
29*       REAL               RWORK( * ), S( * )
30*       COMPLEX            A( LDA, * ), B( LDB, * ), WORK( * )
31*       ..
32*
33*
34*> \par Purpose:
35*  =============
36*>
37*> \verbatim
38*>
39*> CGELSS computes the minimum norm solution to a complex linear
40*> least squares problem:
41*>
42*> Minimize 2-norm(| b - A*x |).
43*>
44*> using the singular value decomposition (SVD) of A. A is an M-by-N
45*> matrix which may be rank-deficient.
46*>
47*> Several right hand side vectors b and solution vectors x can be
48*> handled in a single call; they are stored as the columns of the
49*> M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix
50*> X.
51*>
52*> The effective rank of A is determined by treating as zero those
53*> singular values which are less than RCOND times the largest singular
54*> value.
55*> \endverbatim
56*
57*  Arguments:
58*  ==========
59*
60*> \param[in] M
61*> \verbatim
62*>          M is INTEGER
63*>          The number of rows of the matrix A. M >= 0.
64*> \endverbatim
65*>
66*> \param[in] N
67*> \verbatim
68*>          N is INTEGER
69*>          The number of columns of the matrix A. N >= 0.
70*> \endverbatim
71*>
72*> \param[in] NRHS
73*> \verbatim
74*>          NRHS is INTEGER
75*>          The number of right hand sides, i.e., the number of columns
76*>          of the matrices B and X. NRHS >= 0.
77*> \endverbatim
78*>
79*> \param[in,out] A
80*> \verbatim
81*>          A is COMPLEX array, dimension (LDA,N)
82*>          On entry, the M-by-N matrix A.
83*>          On exit, the first min(m,n) rows of A are overwritten with
84*>          its right singular vectors, stored rowwise.
85*> \endverbatim
86*>
87*> \param[in] LDA
88*> \verbatim
89*>          LDA is INTEGER
90*>          The leading dimension of the array A. LDA >= max(1,M).
91*> \endverbatim
92*>
93*> \param[in,out] B
94*> \verbatim
95*>          B is COMPLEX array, dimension (LDB,NRHS)
96*>          On entry, the M-by-NRHS right hand side matrix B.
97*>          On exit, B is overwritten by the N-by-NRHS solution matrix X.
98*>          If m >= n and RANK = n, the residual sum-of-squares for
99*>          the solution in the i-th column is given by the sum of
100*>          squares of the modulus of elements n+1:m in that column.
101*> \endverbatim
102*>
103*> \param[in] LDB
104*> \verbatim
105*>          LDB is INTEGER
106*>          The leading dimension of the array B.  LDB >= max(1,M,N).
107*> \endverbatim
108*>
109*> \param[out] S
110*> \verbatim
111*>          S is REAL array, dimension (min(M,N))
112*>          The singular values of A in decreasing order.
113*>          The condition number of A in the 2-norm = S(1)/S(min(m,n)).
114*> \endverbatim
115*>
116*> \param[in] RCOND
117*> \verbatim
118*>          RCOND is REAL
119*>          RCOND is used to determine the effective rank of A.
120*>          Singular values S(i) <= RCOND*S(1) are treated as zero.
121*>          If RCOND < 0, machine precision is used instead.
122*> \endverbatim
123*>
124*> \param[out] RANK
125*> \verbatim
126*>          RANK is INTEGER
127*>          The effective rank of A, i.e., the number of singular values
128*>          which are greater than RCOND*S(1).
129*> \endverbatim
130*>
131*> \param[out] WORK
132*> \verbatim
133*>          WORK is COMPLEX array, dimension (MAX(1,LWORK))
134*>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
135*> \endverbatim
136*>
137*> \param[in] LWORK
138*> \verbatim
139*>          LWORK is INTEGER
140*>          The dimension of the array WORK. LWORK >= 1, and also:
141*>          LWORK >=  2*min(M,N) + max(M,N,NRHS)
142*>          For good performance, LWORK should generally be larger.
143*>
144*>          If LWORK = -1, then a workspace query is assumed; the routine
145*>          only calculates the optimal size of the WORK array, returns
146*>          this value as the first entry of the WORK array, and no error
147*>          message related to LWORK is issued by XERBLA.
148*> \endverbatim
149*>
150*> \param[out] RWORK
151*> \verbatim
152*>          RWORK is REAL array, dimension (5*min(M,N))
153*> \endverbatim
154*>
155*> \param[out] INFO
156*> \verbatim
157*>          INFO is INTEGER
158*>          = 0:  successful exit
159*>          < 0:  if INFO = -i, the i-th argument had an illegal value.
160*>          > 0:  the algorithm for computing the SVD failed to converge;
161*>                if INFO = i, i off-diagonal elements of an intermediate
162*>                bidiagonal form did not converge to zero.
163*> \endverbatim
164*
165*  Authors:
166*  ========
167*
168*> \author Univ. of Tennessee
169*> \author Univ. of California Berkeley
170*> \author Univ. of Colorado Denver
171*> \author NAG Ltd.
172*
173*> \date November 2011
174*
175*> \ingroup complexGEsolve
176*
177*  =====================================================================
178      SUBROUTINE CGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
179     $                   WORK, LWORK, RWORK, INFO )
180*
181*  -- LAPACK driver routine (version 3.4.0) --
182*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
183*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
184*     November 2011
185*
186*     .. Scalar Arguments ..
187      INTEGER            INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
188      REAL               RCOND
189*     ..
190*     .. Array Arguments ..
191      REAL               RWORK( * ), S( * )
192      COMPLEX            A( LDA, * ), B( LDB, * ), WORK( * )
193*     ..
194*
195*  =====================================================================
196*
197*     .. Parameters ..
198      REAL               ZERO, ONE
199      PARAMETER          ( ZERO = 0.0E+0, ONE = 1.0E+0 )
200      COMPLEX            CZERO, CONE
201      PARAMETER          ( CZERO = ( 0.0E+0, 0.0E+0 ),
202     $                   CONE = ( 1.0E+0, 0.0E+0 ) )
203*     ..
204*     .. Local Scalars ..
205      LOGICAL            LQUERY
206      INTEGER            BL, CHUNK, I, IASCL, IBSCL, IE, IL, IRWORK,
207     $                   ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,
208     $                   MAXWRK, MINMN, MINWRK, MM, MNTHR
209      INTEGER            LWORK_CGEQRF, LWORK_CUNMQR, LWORK_CGEBRD,
210     $                   LWORK_CUNMBR, LWORK_CUNGBR, LWORK_CUNMLQ,
211     $                   LWORK_CGELQF
212      REAL               ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
213*     ..
214*     .. Local Arrays ..
215      COMPLEX            DUM( 1 )
216*     ..
217*     .. External Subroutines ..
218      EXTERNAL           CBDSQR, CCOPY, CGEBRD, CGELQF, CGEMM, CGEMV,
219     $                   CGEQRF, CLACPY, CLASCL, CLASET, CSRSCL, CUNGBR,
220     $                   CUNMBR, CUNMLQ, CUNMQR, SLABAD, SLASCL, SLASET,
221     $                   XERBLA
222*     ..
223*     .. External Functions ..
224      INTEGER            ILAENV
225      REAL               CLANGE, SLAMCH
226      EXTERNAL           ILAENV, CLANGE, SLAMCH
227*     ..
228*     .. Intrinsic Functions ..
229      INTRINSIC          MAX, MIN
230*     ..
231*     .. Executable Statements ..
232*
233*     Test the input arguments
234*
235      INFO = 0
236      MINMN = MIN( M, N )
237      MAXMN = MAX( M, N )
238      LQUERY = ( LWORK.EQ.-1 )
239      IF( M.LT.0 ) THEN
240         INFO = -1
241      ELSE IF( N.LT.0 ) THEN
242         INFO = -2
243      ELSE IF( NRHS.LT.0 ) THEN
244         INFO = -3
245      ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
246         INFO = -5
247      ELSE IF( LDB.LT.MAX( 1, MAXMN ) ) THEN
248         INFO = -7
249      END IF
250*
251*     Compute workspace
252*      (Note: Comments in the code beginning "Workspace:" describe the
253*       minimal amount of workspace needed at that point in the code,
254*       as well as the preferred amount for good performance.
255*       CWorkspace refers to complex workspace, and RWorkspace refers
256*       to real workspace. NB refers to the optimal block size for the
257*       immediately following subroutine, as returned by ILAENV.)
258*
259      IF( INFO.EQ.0 ) THEN
260         MINWRK = 1
261         MAXWRK = 1
262         IF( MINMN.GT.0 ) THEN
263            MM = M
264            MNTHR = ILAENV( 6, 'CGELSS', ' ', M, N, NRHS, -1 )
265            IF( M.GE.N .AND. M.GE.MNTHR ) THEN
266*
267*              Path 1a - overdetermined, with many more rows than
268*                        columns
269*
270*              Compute space needed for CGEQRF
271               CALL CGEQRF( M, N, A, LDA, DUM(1), DUM(1), -1, INFO )
272               LWORK_CGEQRF=DUM(1)
273*              Compute space needed for CUNMQR
274               CALL CUNMQR( 'L', 'C', M, NRHS, N, A, LDA, DUM(1), B,
275     $                   LDB, DUM(1), -1, INFO )
276               LWORK_CUNMQR=DUM(1)
277               MM = N
278               MAXWRK = MAX( MAXWRK, N + N*ILAENV( 1, 'CGEQRF', ' ', M,
279     $                       N, -1, -1 ) )
280               MAXWRK = MAX( MAXWRK, N + NRHS*ILAENV( 1, 'CUNMQR', 'LC',
281     $                       M, NRHS, N, -1 ) )
282            END IF
283            IF( M.GE.N ) THEN
284*
285*              Path 1 - overdetermined or exactly determined
286*
287*              Compute space needed for CGEBRD
288               CALL CGEBRD( MM, N, A, LDA, S, DUM(1), DUM(1),
289     $                      DUM(1), DUM(1), -1, INFO )
290               LWORK_CGEBRD=DUM(1)
291*              Compute space needed for CUNMBR
292               CALL CUNMBR( 'Q', 'L', 'C', MM, NRHS, N, A, LDA, DUM(1),
293     $                B, LDB, DUM(1), -1, INFO )
294               LWORK_CUNMBR=DUM(1)
295*              Compute space needed for CUNGBR
296               CALL CUNGBR( 'P', N, N, N, A, LDA, DUM(1),
297     $                   DUM(1), -1, INFO )
298               LWORK_CUNGBR=DUM(1)
299*              Compute total workspace needed
300               MAXWRK = MAX( MAXWRK, 2*N + LWORK_CGEBRD )
301               MAXWRK = MAX( MAXWRK, 2*N + LWORK_CUNMBR )
302               MAXWRK = MAX( MAXWRK, 2*N + LWORK_CUNGBR )
303               MAXWRK = MAX( MAXWRK, N*NRHS )
304               MINWRK = 2*N + MAX( NRHS, M )
305            END IF
306            IF( N.GT.M ) THEN
307               MINWRK = 2*M + MAX( NRHS, N )
308               IF( N.GE.MNTHR ) THEN
309*
310*                 Path 2a - underdetermined, with many more columns
311*                 than rows
312*
313*                 Compute space needed for CGELQF
314                  CALL CGELQF( M, N, A, LDA, DUM(1), DUM(1),
315     $                -1, INFO )
316                  LWORK_CGELQF=DUM(1)
317*                 Compute space needed for CGEBRD
318                  CALL CGEBRD( M, M, A, LDA, S, DUM(1), DUM(1),
319     $                      DUM(1), DUM(1), -1, INFO )
320                  LWORK_CGEBRD=DUM(1)
321*                 Compute space needed for CUNMBR
322                  CALL CUNMBR( 'Q', 'L', 'C', M, NRHS, N, A, LDA,
323     $                DUM(1), B, LDB, DUM(1), -1, INFO )
324                  LWORK_CUNMBR=DUM(1)
325*                 Compute space needed for CUNGBR
326                  CALL CUNGBR( 'P', M, M, M, A, LDA, DUM(1),
327     $                   DUM(1), -1, INFO )
328                  LWORK_CUNGBR=DUM(1)
329*                 Compute space needed for CUNMLQ
330                  CALL CUNMLQ( 'L', 'C', N, NRHS, M, A, LDA, DUM(1),
331     $                 B, LDB, DUM(1), -1, INFO )
332                  LWORK_CUNMLQ=DUM(1)
333*                 Compute total workspace needed
334                  MAXWRK = M + LWORK_CGELQF
335                  MAXWRK = MAX( MAXWRK, 3*M + M*M + LWORK_CGEBRD )
336                  MAXWRK = MAX( MAXWRK, 3*M + M*M + LWORK_CUNMBR )
337                  MAXWRK = MAX( MAXWRK, 3*M + M*M + LWORK_CUNGBR )
338                  IF( NRHS.GT.1 ) THEN
339                     MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS )
340                  ELSE
341                     MAXWRK = MAX( MAXWRK, M*M + 2*M )
342                  END IF
343                  MAXWRK = MAX( MAXWRK, M + LWORK_CUNMLQ )
344               ELSE
345*
346*                 Path 2 - underdetermined
347*
348*                 Compute space needed for CGEBRD
349                  CALL CGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
350     $                      DUM(1), DUM(1), -1, INFO )
351                  LWORK_CGEBRD=DUM(1)
352*                 Compute space needed for CUNMBR
353                  CALL CUNMBR( 'Q', 'L', 'C', M, NRHS, M, A, LDA,
354     $                DUM(1), B, LDB, DUM(1), -1, INFO )
355                  LWORK_CUNMBR=DUM(1)
356*                 Compute space needed for CUNGBR
357                  CALL CUNGBR( 'P', M, N, M, A, LDA, DUM(1),
358     $                   DUM(1), -1, INFO )
359                  LWORK_CUNGBR=DUM(1)
360                  MAXWRK = 2*M + LWORK_CGEBRD
361                  MAXWRK = MAX( MAXWRK, 2*M + LWORK_CUNMBR )
362                  MAXWRK = MAX( MAXWRK, 2*M + LWORK_CUNGBR )
363                  MAXWRK = MAX( MAXWRK, N*NRHS )
364               END IF
365            END IF
366            MAXWRK = MAX( MINWRK, MAXWRK )
367         END IF
368         WORK( 1 ) = MAXWRK
369*
370         IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY )
371     $      INFO = -12
372      END IF
373*
374      IF( INFO.NE.0 ) THEN
375         CALL XERBLA( 'CGELSS', -INFO )
376         RETURN
377      ELSE IF( LQUERY ) THEN
378         RETURN
379      END IF
380*
381*     Quick return if possible
382*
383      IF( M.EQ.0 .OR. N.EQ.0 ) THEN
384         RANK = 0
385         RETURN
386      END IF
387*
388*     Get machine parameters
389*
390      EPS = SLAMCH( 'P' )
391      SFMIN = SLAMCH( 'S' )
392      SMLNUM = SFMIN / EPS
393      BIGNUM = ONE / SMLNUM
394      CALL SLABAD( SMLNUM, BIGNUM )
395*
396*     Scale A if max element outside range [SMLNUM,BIGNUM]
397*
398      ANRM = CLANGE( 'M', M, N, A, LDA, RWORK )
399      IASCL = 0
400      IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
401*
402*        Scale matrix norm up to SMLNUM
403*
404         CALL CLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
405         IASCL = 1
406      ELSE IF( ANRM.GT.BIGNUM ) THEN
407*
408*        Scale matrix norm down to BIGNUM
409*
410         CALL CLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
411         IASCL = 2
412      ELSE IF( ANRM.EQ.ZERO ) THEN
413*
414*        Matrix all zero. Return zero solution.
415*
416         CALL CLASET( 'F', MAX( M, N ), NRHS, CZERO, CZERO, B, LDB )
417         CALL SLASET( 'F', MINMN, 1, ZERO, ZERO, S, MINMN )
418         RANK = 0
419         GO TO 70
420      END IF
421*
422*     Scale B if max element outside range [SMLNUM,BIGNUM]
423*
424      BNRM = CLANGE( 'M', M, NRHS, B, LDB, RWORK )
425      IBSCL = 0
426      IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
427*
428*        Scale matrix norm up to SMLNUM
429*
430         CALL CLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
431         IBSCL = 1
432      ELSE IF( BNRM.GT.BIGNUM ) THEN
433*
434*        Scale matrix norm down to BIGNUM
435*
436         CALL CLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )
437         IBSCL = 2
438      END IF
439*
440*     Overdetermined case
441*
442      IF( M.GE.N ) THEN
443*
444*        Path 1 - overdetermined or exactly determined
445*
446         MM = M
447         IF( M.GE.MNTHR ) THEN
448*
449*           Path 1a - overdetermined, with many more rows than columns
450*
451            MM = N
452            ITAU = 1
453            IWORK = ITAU + N
454*
455*           Compute A=Q*R
456*           (CWorkspace: need 2*N, prefer N+N*NB)
457*           (RWorkspace: none)
458*
459            CALL CGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
460     $                   LWORK-IWORK+1, INFO )
461*
462*           Multiply B by transpose(Q)
463*           (CWorkspace: need N+NRHS, prefer N+NRHS*NB)
464*           (RWorkspace: none)
465*
466            CALL CUNMQR( 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAU ), B,
467     $                   LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
468*
469*           Zero out below R
470*
471            IF( N.GT.1 )
472     $         CALL CLASET( 'L', N-1, N-1, CZERO, CZERO, A( 2, 1 ),
473     $                      LDA )
474         END IF
475*
476         IE = 1
477         ITAUQ = 1
478         ITAUP = ITAUQ + N
479         IWORK = ITAUP + N
480*
481*        Bidiagonalize R in A
482*        (CWorkspace: need 2*N+MM, prefer 2*N+(MM+N)*NB)
483*        (RWorkspace: need N)
484*
485         CALL CGEBRD( MM, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ),
486     $                WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
487     $                INFO )
488*
489*        Multiply B by transpose of left bidiagonalizing vectors of R
490*        (CWorkspace: need 2*N+NRHS, prefer 2*N+NRHS*NB)
491*        (RWorkspace: none)
492*
493         CALL CUNMBR( 'Q', 'L', 'C', MM, NRHS, N, A, LDA, WORK( ITAUQ ),
494     $                B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
495*
496*        Generate right bidiagonalizing vectors of R in A
497*        (CWorkspace: need 3*N-1, prefer 2*N+(N-1)*NB)
498*        (RWorkspace: none)
499*
500         CALL CUNGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
501     $                WORK( IWORK ), LWORK-IWORK+1, INFO )
502         IRWORK = IE + N
503*
504*        Perform bidiagonal QR iteration
505*          multiply B by transpose of left singular vectors
506*          compute right singular vectors in A
507*        (CWorkspace: none)
508*        (RWorkspace: need BDSPAC)
509*
510         CALL CBDSQR( 'U', N, N, 0, NRHS, S, RWORK( IE ), A, LDA, DUM,
511     $                1, B, LDB, RWORK( IRWORK ), INFO )
512         IF( INFO.NE.0 )
513     $      GO TO 70
514*
515*        Multiply B by reciprocals of singular values
516*
517         THR = MAX( RCOND*S( 1 ), SFMIN )
518         IF( RCOND.LT.ZERO )
519     $      THR = MAX( EPS*S( 1 ), SFMIN )
520         RANK = 0
521         DO 10 I = 1, N
522            IF( S( I ).GT.THR ) THEN
523               CALL CSRSCL( NRHS, S( I ), B( I, 1 ), LDB )
524               RANK = RANK + 1
525            ELSE
526               CALL CLASET( 'F', 1, NRHS, CZERO, CZERO, B( I, 1 ), LDB )
527            END IF
528   10    CONTINUE
529*
530*        Multiply B by right singular vectors
531*        (CWorkspace: need N, prefer N*NRHS)
532*        (RWorkspace: none)
533*
534         IF( LWORK.GE.LDB*NRHS .AND. NRHS.GT.1 ) THEN
535            CALL CGEMM( 'C', 'N', N, NRHS, N, CONE, A, LDA, B, LDB,
536     $                  CZERO, WORK, LDB )
537            CALL CLACPY( 'G', N, NRHS, WORK, LDB, B, LDB )
538         ELSE IF( NRHS.GT.1 ) THEN
539            CHUNK = LWORK / N
540            DO 20 I = 1, NRHS, CHUNK
541               BL = MIN( NRHS-I+1, CHUNK )
542               CALL CGEMM( 'C', 'N', N, BL, N, CONE, A, LDA, B( 1, I ),
543     $                     LDB, CZERO, WORK, N )
544               CALL CLACPY( 'G', N, BL, WORK, N, B( 1, I ), LDB )
545   20       CONTINUE
546         ELSE
547            CALL CGEMV( 'C', N, N, CONE, A, LDA, B, 1, CZERO, WORK, 1 )
548            CALL CCOPY( N, WORK, 1, B, 1 )
549         END IF
550*
551      ELSE IF( N.GE.MNTHR .AND. LWORK.GE.3*M+M*M+MAX( M, NRHS, N-2*M ) )
552     $          THEN
553*
554*        Underdetermined case, M much less than N
555*
556*        Path 2a - underdetermined, with many more columns than rows
557*        and sufficient workspace for an efficient algorithm
558*
559         LDWORK = M
560         IF( LWORK.GE.3*M+M*LDA+MAX( M, NRHS, N-2*M ) )
561     $      LDWORK = LDA
562         ITAU = 1
563         IWORK = M + 1
564*
565*        Compute A=L*Q
566*        (CWorkspace: need 2*M, prefer M+M*NB)
567*        (RWorkspace: none)
568*
569         CALL CGELQF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
570     $                LWORK-IWORK+1, INFO )
571         IL = IWORK
572*
573*        Copy L to WORK(IL), zeroing out above it
574*
575         CALL CLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWORK )
576         CALL CLASET( 'U', M-1, M-1, CZERO, CZERO, WORK( IL+LDWORK ),
577     $                LDWORK )
578         IE = 1
579         ITAUQ = IL + LDWORK*M
580         ITAUP = ITAUQ + M
581         IWORK = ITAUP + M
582*
583*        Bidiagonalize L in WORK(IL)
584*        (CWorkspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
585*        (RWorkspace: need M)
586*
587         CALL CGEBRD( M, M, WORK( IL ), LDWORK, S, RWORK( IE ),
588     $                WORK( ITAUQ ), WORK( ITAUP ), WORK( IWORK ),
589     $                LWORK-IWORK+1, INFO )
590*
591*        Multiply B by transpose of left bidiagonalizing vectors of L
592*        (CWorkspace: need M*M+3*M+NRHS, prefer M*M+3*M+NRHS*NB)
593*        (RWorkspace: none)
594*
595         CALL CUNMBR( 'Q', 'L', 'C', M, NRHS, M, WORK( IL ), LDWORK,
596     $                WORK( ITAUQ ), B, LDB, WORK( IWORK ),
597     $                LWORK-IWORK+1, INFO )
598*
599*        Generate right bidiagonalizing vectors of R in WORK(IL)
600*        (CWorkspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB)
601*        (RWorkspace: none)
602*
603         CALL CUNGBR( 'P', M, M, M, WORK( IL ), LDWORK, WORK( ITAUP ),
604     $                WORK( IWORK ), LWORK-IWORK+1, INFO )
605         IRWORK = IE + M
606*
607*        Perform bidiagonal QR iteration, computing right singular
608*        vectors of L in WORK(IL) and multiplying B by transpose of
609*        left singular vectors
610*        (CWorkspace: need M*M)
611*        (RWorkspace: need BDSPAC)
612*
613         CALL CBDSQR( 'U', M, M, 0, NRHS, S, RWORK( IE ), WORK( IL ),
614     $                LDWORK, A, LDA, B, LDB, RWORK( IRWORK ), INFO )
615         IF( INFO.NE.0 )
616     $      GO TO 70
617*
618*        Multiply B by reciprocals of singular values
619*
620         THR = MAX( RCOND*S( 1 ), SFMIN )
621         IF( RCOND.LT.ZERO )
622     $      THR = MAX( EPS*S( 1 ), SFMIN )
623         RANK = 0
624         DO 30 I = 1, M
625            IF( S( I ).GT.THR ) THEN
626               CALL CSRSCL( NRHS, S( I ), B( I, 1 ), LDB )
627               RANK = RANK + 1
628            ELSE
629               CALL CLASET( 'F', 1, NRHS, CZERO, CZERO, B( I, 1 ), LDB )
630            END IF
631   30    CONTINUE
632         IWORK = IL + M*LDWORK
633*
634*        Multiply B by right singular vectors of L in WORK(IL)
635*        (CWorkspace: need M*M+2*M, prefer M*M+M+M*NRHS)
636*        (RWorkspace: none)
637*
638         IF( LWORK.GE.LDB*NRHS+IWORK-1 .AND. NRHS.GT.1 ) THEN
639            CALL CGEMM( 'C', 'N', M, NRHS, M, CONE, WORK( IL ), LDWORK,
640     $                  B, LDB, CZERO, WORK( IWORK ), LDB )
641            CALL CLACPY( 'G', M, NRHS, WORK( IWORK ), LDB, B, LDB )
642         ELSE IF( NRHS.GT.1 ) THEN
643            CHUNK = ( LWORK-IWORK+1 ) / M
644            DO 40 I = 1, NRHS, CHUNK
645               BL = MIN( NRHS-I+1, CHUNK )
646               CALL CGEMM( 'C', 'N', M, BL, M, CONE, WORK( IL ), LDWORK,
647     $                     B( 1, I ), LDB, CZERO, WORK( IWORK ), M )
648               CALL CLACPY( 'G', M, BL, WORK( IWORK ), M, B( 1, I ),
649     $                      LDB )
650   40       CONTINUE
651         ELSE
652            CALL CGEMV( 'C', M, M, CONE, WORK( IL ), LDWORK, B( 1, 1 ),
653     $                  1, CZERO, WORK( IWORK ), 1 )
654            CALL CCOPY( M, WORK( IWORK ), 1, B( 1, 1 ), 1 )
655         END IF
656*
657*        Zero out below first M rows of B
658*
659         CALL CLASET( 'F', N-M, NRHS, CZERO, CZERO, B( M+1, 1 ), LDB )
660         IWORK = ITAU + M
661*
662*        Multiply transpose(Q) by B
663*        (CWorkspace: need M+NRHS, prefer M+NHRS*NB)
664*        (RWorkspace: none)
665*
666         CALL CUNMLQ( 'L', 'C', N, NRHS, M, A, LDA, WORK( ITAU ), B,
667     $                LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
668*
669      ELSE
670*
671*        Path 2 - remaining underdetermined cases
672*
673         IE = 1
674         ITAUQ = 1
675         ITAUP = ITAUQ + M
676         IWORK = ITAUP + M
677*
678*        Bidiagonalize A
679*        (CWorkspace: need 3*M, prefer 2*M+(M+N)*NB)
680*        (RWorkspace: need N)
681*
682         CALL CGEBRD( M, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ),
683     $                WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
684     $                INFO )
685*
686*        Multiply B by transpose of left bidiagonalizing vectors
687*        (CWorkspace: need 2*M+NRHS, prefer 2*M+NRHS*NB)
688*        (RWorkspace: none)
689*
690         CALL CUNMBR( 'Q', 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAUQ ),
691     $                B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
692*
693*        Generate right bidiagonalizing vectors in A
694*        (CWorkspace: need 3*M, prefer 2*M+M*NB)
695*        (RWorkspace: none)
696*
697         CALL CUNGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
698     $                WORK( IWORK ), LWORK-IWORK+1, INFO )
699         IRWORK = IE + M
700*
701*        Perform bidiagonal QR iteration,
702*           computing right singular vectors of A in A and
703*           multiplying B by transpose of left singular vectors
704*        (CWorkspace: none)
705*        (RWorkspace: need BDSPAC)
706*
707         CALL CBDSQR( 'L', M, N, 0, NRHS, S, RWORK( IE ), A, LDA, DUM,
708     $                1, B, LDB, RWORK( IRWORK ), INFO )
709         IF( INFO.NE.0 )
710     $      GO TO 70
711*
712*        Multiply B by reciprocals of singular values
713*
714         THR = MAX( RCOND*S( 1 ), SFMIN )
715         IF( RCOND.LT.ZERO )
716     $      THR = MAX( EPS*S( 1 ), SFMIN )
717         RANK = 0
718         DO 50 I = 1, M
719            IF( S( I ).GT.THR ) THEN
720               CALL CSRSCL( NRHS, S( I ), B( I, 1 ), LDB )
721               RANK = RANK + 1
722            ELSE
723               CALL CLASET( 'F', 1, NRHS, CZERO, CZERO, B( I, 1 ), LDB )
724            END IF
725   50    CONTINUE
726*
727*        Multiply B by right singular vectors of A
728*        (CWorkspace: need N, prefer N*NRHS)
729*        (RWorkspace: none)
730*
731         IF( LWORK.GE.LDB*NRHS .AND. NRHS.GT.1 ) THEN
732            CALL CGEMM( 'C', 'N', N, NRHS, M, CONE, A, LDA, B, LDB,
733     $                  CZERO, WORK, LDB )
734            CALL CLACPY( 'G', N, NRHS, WORK, LDB, B, LDB )
735         ELSE IF( NRHS.GT.1 ) THEN
736            CHUNK = LWORK / N
737            DO 60 I = 1, NRHS, CHUNK
738               BL = MIN( NRHS-I+1, CHUNK )
739               CALL CGEMM( 'C', 'N', N, BL, M, CONE, A, LDA, B( 1, I ),
740     $                     LDB, CZERO, WORK, N )
741               CALL CLACPY( 'F', N, BL, WORK, N, B( 1, I ), LDB )
742   60       CONTINUE
743         ELSE
744            CALL CGEMV( 'C', M, N, CONE, A, LDA, B, 1, CZERO, WORK, 1 )
745            CALL CCOPY( N, WORK, 1, B, 1 )
746         END IF
747      END IF
748*
749*     Undo scaling
750*
751      IF( IASCL.EQ.1 ) THEN
752         CALL CLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )
753         CALL SLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
754     $                INFO )
755      ELSE IF( IASCL.EQ.2 ) THEN
756         CALL CLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )
757         CALL SLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
758     $                INFO )
759      END IF
760      IF( IBSCL.EQ.1 ) THEN
761         CALL CLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )
762      ELSE IF( IBSCL.EQ.2 ) THEN
763         CALL CLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )
764      END IF
765   70 CONTINUE
766      WORK( 1 ) = MAXWRK
767      RETURN
768*
769*     End of CGELSS
770*
771      END
772