174 SUBROUTINE zgelss( 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
183 DOUBLE PRECISION RCOND
186 DOUBLE PRECISION RWORK( * ), S( * )
187 COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * )
193 DOUBLE PRECISION ZERO, ONE
194 parameter( zero = 0.0d+0, one = 1.0d+0 )
195 COMPLEX*16 CZERO, CONE
196 parameter( czero = ( 0.0d+0, 0.0d+0 ),
197 $ cone = ( 1.0d+0, 0.0d+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_ZGEQRF, LWORK_ZUNMQR, LWORK_ZGEBRD,
205 $ lwork_zunmbr, lwork_zungbr, lwork_zunmlq,
207 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
220 DOUBLE PRECISION DLAMCH, ZLANGE
221 EXTERNAL ilaenv, dlamch, zlange
233 lquery = ( lwork.EQ.-1 )
236 ELSE IF( n.LT.0 )
THEN
238 ELSE IF( nrhs.LT.0 )
THEN
240 ELSE IF( lda.LT.max( 1, m ) )
THEN
242 ELSE IF( ldb.LT.max( 1, maxmn ) )
THEN
257 IF( minmn.GT.0 )
THEN
259 mnthr = ilaenv( 6,
'ZGELSS',
' ', m, n, nrhs, -1 )
260 IF( m.GE.n .AND. m.GE.mnthr )
THEN
266 CALL zgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
267 lwork_zgeqrf = int( dum(1) )
269 CALL zunmqr(
'L',
'C', m, nrhs, n, a, lda, dum(1), b,
270 $ ldb, dum(1), -1, info )
271 lwork_zunmqr = int( dum(1) )
273 maxwrk = max( maxwrk, n + n*ilaenv( 1,
'ZGEQRF',
' ',
276 maxwrk = max( maxwrk, n + nrhs*ilaenv( 1,
'ZUNMQR',
285 CALL zgebrd( mm, n, a, lda, s, s, dum(1), dum(1),
288 lwork_zgebrd = int( dum(1) )
290 CALL zunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda,
292 $ b, ldb, dum(1), -1, info )
293 lwork_zunmbr = int( dum(1) )
295 CALL zungbr(
'P', n, n, n, a, lda, dum(1),
297 lwork_zungbr = int( dum(1) )
299 maxwrk = max( maxwrk, 2*n + lwork_zgebrd )
300 maxwrk = max( maxwrk, 2*n + lwork_zunmbr )
301 maxwrk = max( maxwrk, 2*n + lwork_zungbr )
302 maxwrk = max( maxwrk, n*nrhs )
303 minwrk = 2*n + max( nrhs, m )
306 minwrk = 2*m + max( nrhs, n )
307 IF( n.GE.mnthr )
THEN
313 CALL zgelqf( m, n, a, lda, dum(1), dum(1),
315 lwork_zgelqf = int( dum(1) )
317 CALL zgebrd( m, m, a, lda, s, s, dum(1), dum(1),
319 lwork_zgebrd = int( dum(1) )
321 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda,
322 $ dum(1), b, ldb, dum(1), -1, info )
323 lwork_zunmbr = int( dum(1) )
325 CALL zungbr(
'P', m, m, m, a, lda, dum(1),
327 lwork_zungbr = int( dum(1) )
329 CALL zunmlq(
'L',
'C', n, nrhs, m, a, lda, dum(1),
330 $ b, ldb, dum(1), -1, info )
331 lwork_zunmlq = int( dum(1) )
333 maxwrk = m + lwork_zgelqf
334 maxwrk = max( maxwrk, 3*m + m*m + lwork_zgebrd )
335 maxwrk = max( maxwrk, 3*m + m*m + lwork_zunmbr )
336 maxwrk = max( maxwrk, 3*m + m*m + lwork_zungbr )
338 maxwrk = max( maxwrk, m*m + m + m*nrhs )
340 maxwrk = max( maxwrk, m*m + 2*m )
342 maxwrk = max( maxwrk, m + lwork_zunmlq )
348 CALL zgebrd( m, n, a, lda, s, s, dum(1), dum(1),
350 lwork_zgebrd = int( dum(1) )
352 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, m, a, lda,
353 $ dum(1), b, ldb, dum(1), -1, info )
354 lwork_zunmbr = int( dum(1) )
356 CALL zungbr(
'P', m, n, m, a, lda, dum(1),
358 lwork_zungbr = int( dum(1) )
359 maxwrk = 2*m + lwork_zgebrd
360 maxwrk = max( maxwrk, 2*m + lwork_zunmbr )
361 maxwrk = max( maxwrk, 2*m + lwork_zungbr )
362 maxwrk = max( maxwrk, n*nrhs )
365 maxwrk = max( minwrk, maxwrk )
369 IF( lwork.LT.minwrk .AND. .NOT.lquery )
374 CALL xerbla(
'ZGELSS', -info )
376 ELSE IF( lquery )
THEN
382 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
390 sfmin = dlamch(
'S' )
392 bignum = one / smlnum
396 anrm = zlange(
'M', m, n, a, lda, rwork )
398 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
402 CALL zlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
404 ELSE IF( anrm.GT.bignum )
THEN
408 CALL zlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
410 ELSE IF( anrm.EQ.zero )
THEN
414 CALL zlaset(
'F', max( m, n ), nrhs, czero, czero, b, ldb )
415 CALL dlaset(
'F', minmn, 1, zero, zero, s, minmn )
422 bnrm = zlange(
'M', m, nrhs, b, ldb, rwork )
424 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
428 CALL zlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
431 ELSE IF( bnrm.GT.bignum )
THEN
435 CALL zlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb,
447 IF( m.GE.mnthr )
THEN
459 CALL zgeqrf( m, n, a, lda, work( itau ), work( iwork ),
460 $ lwork-iwork+1, info )
466 CALL zunmqr(
'L',
'C', m, nrhs, n, a, lda, work( itau ),
468 $ ldb, work( iwork ), lwork-iwork+1, info )
473 $
CALL zlaset(
'L', n-1, n-1, czero, czero, a( 2, 1 ),
486 CALL zgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),
487 $ work( itaup ), work( iwork ), lwork-iwork+1,
494 CALL zunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda,
496 $ b, ldb, work( iwork ), lwork-iwork+1, info )
502 CALL zungbr(
'P', n, n, n, a, lda, work( itaup ),
503 $ work( iwork ), lwork-iwork+1, info )
512 CALL zbdsqr(
'U', n, n, 0, nrhs, s, rwork( ie ), a, lda,
514 $ 1, b, ldb, rwork( irwork ), info )
520 thr = max( rcond*s( 1 ), sfmin )
522 $ thr = max( eps*s( 1 ), sfmin )
525 IF( s( i ).GT.thr )
THEN
526 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
529 CALL zlaset(
'F', 1, nrhs, czero, czero, b( i, 1 ),
538 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
539 CALL zgemm(
'C',
'N', n, nrhs, n, cone, a, lda, b, ldb,
541 CALL zlacpy(
'G', n, nrhs, work, ldb, b, ldb )
542 ELSE IF( nrhs.GT.1 )
THEN
544 DO 20 i = 1, nrhs, chunk
545 bl = min( nrhs-i+1, chunk )
546 CALL zgemm(
'C',
'N', n, bl, n, cone, a, lda, b( 1,
548 $ ldb, czero, work, n )
549 CALL zlacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
551 ELSE IF( nrhs.EQ.1 )
THEN
552 CALL zgemv(
'C', n, n, cone, a, lda, b, 1, czero, work,
554 CALL zcopy( n, work, 1, b, 1 )
557 ELSE IF( n.GE.mnthr .AND. lwork.GE.3*m+m*m+max( m, nrhs, n-2*m ) )
566 IF( lwork.GE.3*m+m*lda+max( m, nrhs, n-2*m ) )
575 CALL zgelqf( m, n, a, lda, work( itau ), work( iwork ),
576 $ lwork-iwork+1, info )
581 CALL zlacpy(
'L', m, m, a, lda, work( il ), ldwork )
582 CALL zlaset(
'U', m-1, m-1, czero, czero, work( il+ldwork ),
585 itauq = il + ldwork*m
593 CALL zgebrd( m, m, work( il ), ldwork, s, rwork( ie ),
594 $ work( itauq ), work( itaup ), work( iwork ),
595 $ lwork-iwork+1, info )
601 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, m, work( il ), ldwork,
602 $ work( itauq ), b, ldb, work( iwork ),
603 $ lwork-iwork+1, info )
609 CALL zungbr(
'P', m, m, m, work( il ), ldwork,
611 $ work( iwork ), lwork-iwork+1, info )
620 CALL zbdsqr(
'U', m, m, 0, nrhs, s, rwork( ie ), work( il ),
621 $ ldwork, a, lda, b, ldb, rwork( irwork ), info )
627 thr = max( rcond*s( 1 ), sfmin )
629 $ thr = max( eps*s( 1 ), sfmin )
632 IF( s( i ).GT.thr )
THEN
633 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
636 CALL zlaset(
'F', 1, nrhs, czero, czero, b( i, 1 ),
640 iwork = il + m*ldwork
646 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 )
THEN
647 CALL zgemm(
'C',
'N', m, nrhs, m, cone, work( il ),
649 $ b, ldb, czero, work( iwork ), ldb )
650 CALL zlacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
651 ELSE IF( nrhs.GT.1 )
THEN
652 chunk = ( lwork-iwork+1 ) / m
653 DO 40 i = 1, nrhs, chunk
654 bl = min( nrhs-i+1, chunk )
655 CALL zgemm(
'C',
'N', m, bl, m, cone, work( il ),
657 $ b( 1, i ), ldb, czero, work( iwork ), m )
658 CALL zlacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
661 ELSE IF( nrhs.EQ.1 )
THEN
662 CALL zgemv(
'C', m, m, cone, work( il ), ldwork, b( 1,
663 $ 1 ), 1, czero, work( iwork ), 1 )
664 CALL zcopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
669 CALL zlaset(
'F', n-m, nrhs, czero, czero, b( m+1, 1 ),
677 CALL zunmlq(
'L',
'C', n, nrhs, m, a, lda, work( itau ), b,
678 $ ldb, work( iwork ), lwork-iwork+1, info )
693 CALL zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),
694 $ work( itaup ), work( iwork ), lwork-iwork+1,
701 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda,
703 $ b, ldb, work( iwork ), lwork-iwork+1, info )
709 CALL zungbr(
'P', m, n, m, a, lda, work( itaup ),
710 $ work( iwork ), lwork-iwork+1, info )
719 CALL zbdsqr(
'L', m, n, 0, nrhs, s, rwork( ie ), a, lda,
721 $ 1, b, ldb, rwork( irwork ), info )
727 thr = max( rcond*s( 1 ), sfmin )
729 $ thr = max( eps*s( 1 ), sfmin )
732 IF( s( i ).GT.thr )
THEN
733 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
736 CALL zlaset(
'F', 1, nrhs, czero, czero, b( i, 1 ),
745 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
746 CALL zgemm(
'C',
'N', n, nrhs, m, cone, a, lda, b, ldb,
748 CALL zlacpy(
'G', n, nrhs, work, ldb, b, ldb )
749 ELSE IF( nrhs.GT.1 )
THEN
751 DO 60 i = 1, nrhs, chunk
752 bl = min( nrhs-i+1, chunk )
753 CALL zgemm(
'C',
'N', n, bl, m, cone, a, lda, b( 1,
755 $ ldb, czero, work, n )
756 CALL zlacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
758 ELSE IF( nrhs.EQ.1 )
THEN
759 CALL zgemv(
'C', m, n, cone, a, lda, b, 1, czero, work,
761 CALL zcopy( n, work, 1, b, 1 )
767 IF( iascl.EQ.1 )
THEN
768 CALL zlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
770 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
772 ELSE IF( iascl.EQ.2 )
THEN
773 CALL zlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
775 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
778 IF( ibscl.EQ.1 )
THEN
779 CALL zlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
781 ELSE IF( ibscl.EQ.2 )
THEN
782 CALL zlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,