174 SUBROUTINE cgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
175 $ WORK, LWORK, RWORK, INFO )
182 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
186 REAL RWORK( * ), S( * )
187 COMPLEX A( LDA, * ), B( LDB, * ), WORK( * )
194 parameter( zero = 0.0e+0, one = 1.0e+0 )
196 parameter( czero = ( 0.0e+0, 0.0e+0 ),
197 $ cone = ( 1.0e+0, 0.0e+0 ) )
201 INTEGER BL, CHUNK, I, IASCL, IBSCL, IE, IL, IRWORK,
202 $ itau, itaup, itauq, iwork, ldwork, maxmn,
203 $ maxwrk, minmn, minwrk, mm, mnthr
204 INTEGER LWORK_CGEQRF, LWORK_CUNMQR, LWORK_CGEBRD,
205 $ lwork_cunmbr, lwork_cungbr, lwork_cunmlq,
207 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
220 REAL CLANGE, SLAMCH, SROUNDUP_LWORK
221 EXTERNAL ilaenv, clange, slamch,
234 lquery = ( lwork.EQ.-1 )
237 ELSE IF( n.LT.0 )
THEN
239 ELSE IF( nrhs.LT.0 )
THEN
241 ELSE IF( lda.LT.max( 1, m ) )
THEN
243 ELSE IF( ldb.LT.max( 1, maxmn ) )
THEN
258 IF( minmn.GT.0 )
THEN
260 mnthr = ilaenv( 6,
'CGELSS',
' ', m, n, nrhs, -1 )
261 IF( m.GE.n .AND. m.GE.mnthr )
THEN
267 CALL cgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
268 lwork_cgeqrf = int( dum(1) )
270 CALL cunmqr(
'L',
'C', m, nrhs, n, a, lda, dum(1), b,
271 $ ldb, dum(1), -1, info )
272 lwork_cunmqr = int( dum(1) )
274 maxwrk = max( maxwrk, n + n*ilaenv( 1,
'CGEQRF',
' ',
277 maxwrk = max( maxwrk, n + nrhs*ilaenv( 1,
'CUNMQR',
286 CALL cgebrd( mm, n, a, lda, s, s, dum(1), dum(1),
289 lwork_cgebrd = int( dum(1) )
291 CALL cunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda,
293 $ b, ldb, dum(1), -1, info )
294 lwork_cunmbr = int( dum(1) )
296 CALL cungbr(
'P', n, n, n, a, lda, dum(1),
298 lwork_cungbr = int( dum(1) )
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 )
307 minwrk = 2*m + max( nrhs, n )
308 IF( n.GE.mnthr )
THEN
314 CALL cgelqf( m, n, a, lda, dum(1), dum(1),
316 lwork_cgelqf = int( dum(1) )
318 CALL cgebrd( m, m, a, lda, s, s, dum(1), dum(1),
320 lwork_cgebrd = int( dum(1) )
322 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda,
323 $ dum(1), b, ldb, dum(1), -1, info )
324 lwork_cunmbr = int( dum(1) )
326 CALL cungbr(
'P', m, m, m, a, lda, dum(1),
328 lwork_cungbr = int( dum(1) )
330 CALL cunmlq(
'L',
'C', n, nrhs, m, a, lda, dum(1),
331 $ b, ldb, dum(1), -1, info )
332 lwork_cunmlq = int( dum(1) )
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 )
339 maxwrk = max( maxwrk, m*m + m + m*nrhs )
341 maxwrk = max( maxwrk, m*m + 2*m )
343 maxwrk = max( maxwrk, m + lwork_cunmlq )
349 CALL cgebrd( m, n, a, lda, s, s, dum(1), dum(1),
351 lwork_cgebrd = int( dum(1) )
353 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, m, a, lda,
354 $ dum(1), b, ldb, dum(1), -1, info )
355 lwork_cunmbr = int( dum(1) )
357 CALL cungbr(
'P', m, n, m, a, lda, dum(1),
359 lwork_cungbr = int( 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 )
366 maxwrk = max( minwrk, maxwrk )
368 work( 1 ) = sroundup_lwork(maxwrk)
370 IF( lwork.LT.minwrk .AND. .NOT.lquery )
375 CALL xerbla(
'CGELSS', -info )
377 ELSE IF( lquery )
THEN
383 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
391 sfmin = slamch(
'S' )
393 bignum = one / smlnum
397 anrm = clange(
'M', m, n, a, lda, rwork )
399 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
403 CALL clascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
405 ELSE IF( anrm.GT.bignum )
THEN
409 CALL clascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
411 ELSE IF( anrm.EQ.zero )
THEN
415 CALL claset(
'F', max( m, n ), nrhs, czero, czero, b, ldb )
416 CALL slaset(
'F', minmn, 1, zero, zero, s, minmn )
423 bnrm = clange(
'M', m, nrhs, b, ldb, rwork )
425 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
429 CALL clascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
432 ELSE IF( bnrm.GT.bignum )
THEN
436 CALL clascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb,
448 IF( m.GE.mnthr )
THEN
460 CALL cgeqrf( m, n, a, lda, work( itau ), work( iwork ),
461 $ lwork-iwork+1, info )
467 CALL cunmqr(
'L',
'C', m, nrhs, n, a, lda, work( itau ),
469 $ ldb, work( iwork ), lwork-iwork+1, info )
474 $
CALL claset(
'L', n-1, n-1, czero, czero, a( 2, 1 ),
487 CALL cgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),
488 $ work( itaup ), work( iwork ), lwork-iwork+1,
495 CALL cunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda,
497 $ b, ldb, work( iwork ), lwork-iwork+1, info )
503 CALL cungbr(
'P', n, n, n, a, lda, work( itaup ),
504 $ work( iwork ), lwork-iwork+1, info )
513 CALL cbdsqr(
'U', n, n, 0, nrhs, s, rwork( ie ), a, lda,
515 $ 1, b, ldb, rwork( irwork ), info )
521 thr = max( rcond*s( 1 ), sfmin )
523 $ thr = max( eps*s( 1 ), sfmin )
526 IF( s( i ).GT.thr )
THEN
527 CALL csrscl( nrhs, s( i ), b( i, 1 ), ldb )
530 CALL claset(
'F', 1, nrhs, czero, czero, b( i, 1 ),
539 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
540 CALL cgemm(
'C',
'N', n, nrhs, n, cone, a, lda, b, ldb,
542 CALL clacpy(
'G', n, nrhs, work, ldb, b, ldb )
543 ELSE IF( nrhs.GT.1 )
THEN
545 DO 20 i = 1, nrhs, chunk
546 bl = min( nrhs-i+1, chunk )
547 CALL cgemm(
'C',
'N', n, bl, n, cone, a, lda, b( 1,
549 $ ldb, czero, work, n )
550 CALL clacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
552 ELSE IF( nrhs.EQ.1 )
THEN
553 CALL cgemv(
'C', n, n, cone, a, lda, b, 1, czero, work,
555 CALL ccopy( n, work, 1, b, 1 )
558 ELSE IF( n.GE.mnthr .AND. lwork.GE.3*m+m*m+max( m, nrhs, n-2*m ) )
567 IF( lwork.GE.3*m+m*lda+max( m, nrhs, n-2*m ) )
576 CALL cgelqf( m, n, a, lda, work( itau ), work( iwork ),
577 $ lwork-iwork+1, info )
582 CALL clacpy(
'L', m, m, a, lda, work( il ), ldwork )
583 CALL claset(
'U', m-1, m-1, czero, czero, work( il+ldwork ),
586 itauq = il + ldwork*m
594 CALL cgebrd( m, m, work( il ), ldwork, s, rwork( ie ),
595 $ work( itauq ), work( itaup ), work( iwork ),
596 $ lwork-iwork+1, info )
602 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, m, work( il ), ldwork,
603 $ work( itauq ), b, ldb, work( iwork ),
604 $ lwork-iwork+1, info )
610 CALL cungbr(
'P', m, m, m, work( il ), ldwork,
612 $ work( iwork ), lwork-iwork+1, info )
621 CALL cbdsqr(
'U', m, m, 0, nrhs, s, rwork( ie ), work( il ),
622 $ ldwork, a, lda, b, ldb, rwork( irwork ), info )
628 thr = max( rcond*s( 1 ), sfmin )
630 $ thr = max( eps*s( 1 ), sfmin )
633 IF( s( i ).GT.thr )
THEN
634 CALL csrscl( nrhs, s( i ), b( i, 1 ), ldb )
637 CALL claset(
'F', 1, nrhs, czero, czero, b( i, 1 ),
641 iwork = il + m*ldwork
647 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 )
THEN
648 CALL cgemm(
'C',
'N', m, nrhs, m, cone, work( il ),
650 $ b, ldb, czero, work( iwork ), ldb )
651 CALL clacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
652 ELSE IF( nrhs.GT.1 )
THEN
653 chunk = ( lwork-iwork+1 ) / m
654 DO 40 i = 1, nrhs, chunk
655 bl = min( nrhs-i+1, chunk )
656 CALL cgemm(
'C',
'N', m, bl, m, cone, work( il ),
658 $ b( 1, i ), ldb, czero, work( iwork ), m )
659 CALL clacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
662 ELSE IF( nrhs.EQ.1 )
THEN
663 CALL cgemv(
'C', m, m, cone, work( il ), ldwork, b( 1,
664 $ 1 ), 1, czero, work( iwork ), 1 )
665 CALL ccopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
670 CALL claset(
'F', n-m, nrhs, czero, czero, b( m+1, 1 ),
678 CALL cunmlq(
'L',
'C', n, nrhs, m, a, lda, work( itau ), b,
679 $ ldb, work( iwork ), lwork-iwork+1, info )
694 CALL cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),
695 $ work( itaup ), work( iwork ), lwork-iwork+1,
702 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda,
704 $ b, ldb, work( iwork ), lwork-iwork+1, info )
710 CALL cungbr(
'P', m, n, m, a, lda, work( itaup ),
711 $ work( iwork ), lwork-iwork+1, info )
720 CALL cbdsqr(
'L', m, n, 0, nrhs, s, rwork( ie ), a, lda,
722 $ 1, b, ldb, rwork( irwork ), info )
728 thr = max( rcond*s( 1 ), sfmin )
730 $ thr = max( eps*s( 1 ), sfmin )
733 IF( s( i ).GT.thr )
THEN
734 CALL csrscl( nrhs, s( i ), b( i, 1 ), ldb )
737 CALL claset(
'F', 1, nrhs, czero, czero, b( i, 1 ),
746 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
747 CALL cgemm(
'C',
'N', n, nrhs, m, cone, a, lda, b, ldb,
749 CALL clacpy(
'G', n, nrhs, work, ldb, b, ldb )
750 ELSE IF( nrhs.GT.1 )
THEN
752 DO 60 i = 1, nrhs, chunk
753 bl = min( nrhs-i+1, chunk )
754 CALL cgemm(
'C',
'N', n, bl, m, cone, a, lda, b( 1,
756 $ ldb, czero, work, n )
757 CALL clacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
759 ELSE IF( nrhs.EQ.1 )
THEN
760 CALL cgemv(
'C', m, n, cone, a, lda, b, 1, czero, work,
762 CALL ccopy( n, work, 1, b, 1 )
768 IF( iascl.EQ.1 )
THEN
769 CALL clascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
771 CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
773 ELSE IF( iascl.EQ.2 )
THEN
774 CALL clascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
776 CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
779 IF( ibscl.EQ.1 )
THEN
780 CALL clascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
782 ELSE IF( ibscl.EQ.2 )
THEN
783 CALL clascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,
787 work( 1 ) = sroundup_lwork(maxwrk)