176 SUBROUTINE zgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
177 $ WORK, LWORK, RWORK, INFO )
184 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
185 DOUBLE PRECISION RCOND
188 DOUBLE PRECISION RWORK( * ), S( * )
189 COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * )
195 DOUBLE PRECISION ZERO, ONE
196 parameter( zero = 0.0d+0, one = 1.0d+0 )
197 COMPLEX*16 CZERO, CONE
198 parameter( czero = ( 0.0d+0, 0.0d+0 ),
199 $ cone = ( 1.0d+0, 0.0d+0 ) )
203 INTEGER BL, CHUNK, I, IASCL, IBSCL, IE, IL, IRWORK,
204 $ itau, itaup, itauq, iwork, ldwork, maxmn,
205 $ maxwrk, minmn, minwrk, mm, mnthr
206 INTEGER LWORK_ZGEQRF, LWORK_ZUNMQR, LWORK_ZGEBRD,
207 $ lwork_zunmbr, lwork_zungbr, lwork_zunmlq,
209 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
222 DOUBLE PRECISION DLAMCH, ZLANGE
223 EXTERNAL ilaenv, dlamch, zlange
235 lquery = ( lwork.EQ.-1 )
238 ELSE IF( n.LT.0 )
THEN
240 ELSE IF( nrhs.LT.0 )
THEN
242 ELSE IF( lda.LT.max( 1, m ) )
THEN
244 ELSE IF( ldb.LT.max( 1, maxmn ) )
THEN
259 IF( minmn.GT.0 )
THEN
261 mnthr = ilaenv( 6,
'ZGELSS',
' ', m, n, nrhs, -1 )
262 IF( m.GE.n .AND. m.GE.mnthr )
THEN
268 CALL zgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
269 lwork_zgeqrf = int( dum(1) )
271 CALL zunmqr(
'L',
'C', m, nrhs, n, a, lda, dum(1), b,
272 $ ldb, dum(1), -1, info )
273 lwork_zunmqr = int( dum(1) )
275 maxwrk = max( maxwrk, n + n*ilaenv( 1,
'ZGEQRF',
' ', m,
277 maxwrk = max( maxwrk, n + nrhs*ilaenv( 1,
'ZUNMQR',
'LC',
285 CALL zgebrd( mm, n, a, lda, s, s, dum(1), dum(1), dum(1),
287 lwork_zgebrd = int( dum(1) )
289 CALL zunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda, dum(1),
290 $ b, ldb, dum(1), -1, info )
291 lwork_zunmbr = int( dum(1) )
293 CALL zungbr(
'P', n, n, n, a, lda, dum(1),
295 lwork_zungbr = int( dum(1) )
297 maxwrk = max( maxwrk, 2*n + lwork_zgebrd )
298 maxwrk = max( maxwrk, 2*n + lwork_zunmbr )
299 maxwrk = max( maxwrk, 2*n + lwork_zungbr )
300 maxwrk = max( maxwrk, n*nrhs )
301 minwrk = 2*n + max( nrhs, m )
304 minwrk = 2*m + max( nrhs, n )
305 IF( n.GE.mnthr )
THEN
311 CALL zgelqf( m, n, a, lda, dum(1), dum(1),
313 lwork_zgelqf = int( dum(1) )
315 CALL zgebrd( m, m, a, lda, s, s, dum(1), dum(1),
317 lwork_zgebrd = int( dum(1) )
319 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda,
320 $ dum(1), b, ldb, dum(1), -1, info )
321 lwork_zunmbr = int( dum(1) )
323 CALL zungbr(
'P', m, m, m, a, lda, dum(1),
325 lwork_zungbr = int( dum(1) )
327 CALL zunmlq(
'L',
'C', n, nrhs, m, a, lda, dum(1),
328 $ b, ldb, dum(1), -1, info )
329 lwork_zunmlq = int( dum(1) )
331 maxwrk = m + lwork_zgelqf
332 maxwrk = max( maxwrk, 3*m + m*m + lwork_zgebrd )
333 maxwrk = max( maxwrk, 3*m + m*m + lwork_zunmbr )
334 maxwrk = max( maxwrk, 3*m + m*m + lwork_zungbr )
336 maxwrk = max( maxwrk, m*m + m + m*nrhs )
338 maxwrk = max( maxwrk, m*m + 2*m )
340 maxwrk = max( maxwrk, m + lwork_zunmlq )
346 CALL zgebrd( m, n, a, lda, s, s, dum(1), dum(1),
348 lwork_zgebrd = int( dum(1) )
350 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, m, a, lda,
351 $ dum(1), b, ldb, dum(1), -1, info )
352 lwork_zunmbr = int( dum(1) )
354 CALL zungbr(
'P', m, n, m, a, lda, dum(1),
356 lwork_zungbr = int( dum(1) )
357 maxwrk = 2*m + lwork_zgebrd
358 maxwrk = max( maxwrk, 2*m + lwork_zunmbr )
359 maxwrk = max( maxwrk, 2*m + lwork_zungbr )
360 maxwrk = max( maxwrk, n*nrhs )
363 maxwrk = max( minwrk, maxwrk )
367 IF( lwork.LT.minwrk .AND. .NOT.lquery )
372 CALL xerbla(
'ZGELSS', -info )
374 ELSE IF( lquery )
THEN
380 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
388 sfmin = dlamch(
'S' )
390 bignum = one / smlnum
391 CALL dlabad( smlnum, bignum )
395 anrm = zlange(
'M', m, n, a, lda, rwork )
397 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
401 CALL zlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
403 ELSE IF( anrm.GT.bignum )
THEN
407 CALL zlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
409 ELSE IF( anrm.EQ.zero )
THEN
413 CALL zlaset(
'F', max( m, n ), nrhs, czero, czero, b, ldb )
414 CALL dlaset(
'F', minmn, 1, zero, zero, s, minmn )
421 bnrm = zlange(
'M', m, nrhs, b, ldb, rwork )
423 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
427 CALL zlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
429 ELSE IF( bnrm.GT.bignum )
THEN
433 CALL zlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
444 IF( m.GE.mnthr )
THEN
456 CALL zgeqrf( m, n, a, lda, work( itau ), work( iwork ),
457 $ lwork-iwork+1, info )
463 CALL zunmqr(
'L',
'C', m, nrhs, n, a, lda, work( itau ), b,
464 $ ldb, work( iwork ), lwork-iwork+1, info )
469 $
CALL zlaset(
'L', n-1, n-1, czero, czero, a( 2, 1 ),
482 CALL zgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),
483 $ work( itaup ), work( iwork ), lwork-iwork+1,
490 CALL zunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda, work( itauq ),
491 $ b, ldb, work( iwork ), lwork-iwork+1, info )
497 CALL zungbr(
'P', n, n, n, a, lda, work( itaup ),
498 $ work( iwork ), lwork-iwork+1, info )
507 CALL zbdsqr(
'U', n, n, 0, nrhs, s, rwork( ie ), a, lda, dum,
508 $ 1, b, ldb, rwork( irwork ), info )
514 thr = max( rcond*s( 1 ), sfmin )
516 $ thr = max( eps*s( 1 ), sfmin )
519 IF( s( i ).GT.thr )
THEN
520 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
523 CALL zlaset(
'F', 1, nrhs, czero, czero, b( i, 1 ), ldb )
531 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
532 CALL zgemm(
'C',
'N', n, nrhs, n, cone, a, lda, b, ldb,
534 CALL zlacpy(
'G', n, nrhs, work, ldb, b, ldb )
535 ELSE IF( nrhs.GT.1 )
THEN
537 DO 20 i = 1, nrhs, chunk
538 bl = min( nrhs-i+1, chunk )
539 CALL zgemm(
'C',
'N', n, bl, n, cone, a, lda, b( 1, i ),
540 $ ldb, czero, work, n )
541 CALL zlacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
544 CALL zgemv(
'C', n, n, cone, a, lda, b, 1, czero, work, 1 )
545 CALL zcopy( n, work, 1, b, 1 )
548 ELSE IF( n.GE.mnthr .AND. lwork.GE.3*m+m*m+max( m, nrhs, n-2*m ) )
557 IF( lwork.GE.3*m+m*lda+max( m, nrhs, n-2*m ) )
566 CALL zgelqf( m, n, a, lda, work( itau ), work( iwork ),
567 $ lwork-iwork+1, info )
572 CALL zlacpy(
'L', m, m, a, lda, work( il ), ldwork )
573 CALL zlaset(
'U', m-1, m-1, czero, czero, work( il+ldwork ),
576 itauq = il + ldwork*m
584 CALL zgebrd( m, m, work( il ), ldwork, s, rwork( ie ),
585 $ work( itauq ), work( itaup ), work( iwork ),
586 $ lwork-iwork+1, info )
592 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, m, work( il ), ldwork,
593 $ work( itauq ), b, ldb, work( iwork ),
594 $ lwork-iwork+1, info )
600 CALL zungbr(
'P', m, m, m, work( il ), ldwork, work( itaup ),
601 $ work( iwork ), lwork-iwork+1, info )
610 CALL zbdsqr(
'U', m, m, 0, nrhs, s, rwork( ie ), work( il ),
611 $ ldwork, a, lda, b, ldb, rwork( irwork ), info )
617 thr = max( rcond*s( 1 ), sfmin )
619 $ thr = max( eps*s( 1 ), sfmin )
622 IF( s( i ).GT.thr )
THEN
623 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
626 CALL zlaset(
'F', 1, nrhs, czero, czero, b( i, 1 ), ldb )
629 iwork = il + m*ldwork
635 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 )
THEN
636 CALL zgemm(
'C',
'N', m, nrhs, m, cone, work( il ), ldwork,
637 $ b, ldb, czero, work( iwork ), ldb )
638 CALL zlacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
639 ELSE IF( nrhs.GT.1 )
THEN
640 chunk = ( lwork-iwork+1 ) / m
641 DO 40 i = 1, nrhs, chunk
642 bl = min( nrhs-i+1, chunk )
643 CALL zgemm(
'C',
'N', m, bl, m, cone, work( il ), ldwork,
644 $ b( 1, i ), ldb, czero, work( iwork ), m )
645 CALL zlacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
649 CALL zgemv(
'C', m, m, cone, work( il ), ldwork, b( 1, 1 ),
650 $ 1, czero, work( iwork ), 1 )
651 CALL zcopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
656 CALL zlaset(
'F', n-m, nrhs, czero, czero, b( m+1, 1 ), ldb )
663 CALL zunmlq(
'L',
'C', n, nrhs, m, a, lda, work( itau ), b,
664 $ ldb, work( iwork ), lwork-iwork+1, info )
679 CALL zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),
680 $ work( itaup ), work( iwork ), lwork-iwork+1,
687 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda, work( itauq ),
688 $ b, ldb, work( iwork ), lwork-iwork+1, info )
694 CALL zungbr(
'P', m, n, m, a, lda, work( itaup ),
695 $ work( iwork ), lwork-iwork+1, info )
704 CALL zbdsqr(
'L', m, n, 0, nrhs, s, rwork( ie ), a, lda, dum,
705 $ 1, b, ldb, rwork( irwork ), info )
711 thr = max( rcond*s( 1 ), sfmin )
713 $ thr = max( eps*s( 1 ), sfmin )
716 IF( s( i ).GT.thr )
THEN
717 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
720 CALL zlaset(
'F', 1, nrhs, czero, czero, b( i, 1 ), ldb )
728 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
729 CALL zgemm(
'C',
'N', n, nrhs, m, cone, a, lda, b, ldb,
731 CALL zlacpy(
'G', n, nrhs, work, ldb, b, ldb )
732 ELSE IF( nrhs.GT.1 )
THEN
734 DO 60 i = 1, nrhs, chunk
735 bl = min( nrhs-i+1, chunk )
736 CALL zgemm(
'C',
'N', n, bl, m, cone, a, lda, b( 1, i ),
737 $ ldb, czero, work, n )
738 CALL zlacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
741 CALL zgemv(
'C', m, n, cone, a, lda, b, 1, czero, work, 1 )
742 CALL zcopy( n, work, 1, b, 1 )
748 IF( iascl.EQ.1 )
THEN
749 CALL zlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
750 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
752 ELSE IF( iascl.EQ.2 )
THEN
753 CALL zlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
754 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
757 IF( ibscl.EQ.1 )
THEN
758 CALL zlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
759 ELSE IF( ibscl.EQ.2 )
THEN
760 CALL zlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
subroutine dlabad(SMALL, LARGE)
DLABAD
subroutine dlascl(TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine dlaset(UPLO, M, N, ALPHA, BETA, A, LDA)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine xerbla(SRNAME, INFO)
XERBLA
subroutine zcopy(N, ZX, INCX, ZY, INCY)
ZCOPY
subroutine zgemv(TRANS, M, N, ALPHA, A, LDA, X, INCX, BETA, Y, INCY)
ZGEMV
subroutine zgemm(TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC)
ZGEMM
subroutine zungbr(VECT, M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
ZUNGBR
subroutine zgelqf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
ZGELQF
subroutine zgebrd(M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, INFO)
ZGEBRD
subroutine zgelss(M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, WORK, LWORK, RWORK, INFO)
ZGELSS solves overdetermined or underdetermined systems for GE matrices
subroutine zlascl(TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO)
ZLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine zlacpy(UPLO, M, N, A, LDA, B, LDB)
ZLACPY copies all or part of one two-dimensional array to another.
subroutine zlaset(UPLO, M, N, ALPHA, BETA, A, LDA)
ZLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine zdrscl(N, SA, SX, INCX)
ZDRSCL multiplies a vector by the reciprocal of a real scalar.
subroutine zunmlq(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
ZUNMLQ
subroutine zunmqr(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
ZUNMQR
subroutine zbdsqr(UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U, LDU, C, LDC, RWORK, INFO)
ZBDSQR
subroutine zunmbr(VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
ZUNMBR
subroutine zgeqrf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
ZGEQRF VARIANT: left-looking Level 3 BLAS of the algorithm.