170 SUBROUTINE dgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
171 $ WORK, LWORK, INFO )
178 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
179 DOUBLE PRECISION RCOND
182 DOUBLE PRECISION A( lda, * ), B( ldb, * ), S( * ), WORK( * )
188 DOUBLE PRECISION ZERO, ONE
189 parameter( zero = 0.0d+0, one = 1.0d+0 )
193 INTEGER BDSPAC, BL, CHUNK, I, IASCL, IBSCL, IE, IL,
194 $ itau, itaup, itauq, iwork, ldwork, maxmn,
195 $ maxwrk, minmn, minwrk, mm, mnthr
196 INTEGER LWORK_DGEQRF, LWORK_DORMQR, LWORK_DGEBRD,
197 $ lwork_dormbr, lwork_dorgbr, lwork_dormlq,
199 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
202 DOUBLE PRECISION DUM( 1 )
211 DOUBLE PRECISION DLAMCH, DLANGE
212 EXTERNAL ilaenv, dlamch, dlange
224 lquery = ( lwork.EQ.-1 )
227 ELSE IF( n.LT.0 )
THEN 229 ELSE IF( nrhs.LT.0 )
THEN 231 ELSE IF( lda.LT.max( 1, m ) )
THEN 233 ELSE IF( ldb.LT.max( 1, maxmn ) )
THEN 247 IF( minmn.GT.0 )
THEN 249 mnthr = ilaenv( 6,
'DGELSS',
' ', m, n, nrhs, -1 )
250 IF( m.GE.n .AND. m.GE.mnthr )
THEN 256 CALL dgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
257 lwork_dgeqrf = int( dum(1) )
259 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, dum(1), b,
260 $ ldb, dum(1), -1, info )
261 lwork_dormqr = int( dum(1) )
263 maxwrk = max( maxwrk, n + lwork_dgeqrf )
264 maxwrk = max( maxwrk, n + lwork_dormqr )
272 bdspac = max( 1, 5*n )
274 CALL dgebrd( mm, n, a, lda, s, dum(1), dum(1),
275 $ dum(1), dum(1), -1, info )
276 lwork_dgebrd = int( dum(1) )
278 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, dum(1),
279 $ b, ldb, dum(1), -1, info )
280 lwork_dormbr = int( dum(1) )
282 CALL dorgbr(
'P', n, n, n, a, lda, dum(1),
284 lwork_dorgbr = int( dum(1) )
286 maxwrk = max( maxwrk, 3*n + lwork_dgebrd )
287 maxwrk = max( maxwrk, 3*n + lwork_dormbr )
288 maxwrk = max( maxwrk, 3*n + lwork_dorgbr )
289 maxwrk = max( maxwrk, bdspac )
290 maxwrk = max( maxwrk, n*nrhs )
291 minwrk = max( 3*n + mm, 3*n + nrhs, bdspac )
292 maxwrk = max( minwrk, maxwrk )
298 bdspac = max( 1, 5*m )
299 minwrk = max( 3*m+nrhs, 3*m+n, bdspac )
300 IF( n.GE.mnthr )
THEN 306 CALL dgelqf( m, n, a, lda, dum(1), dum(1),
308 lwork_dgelqf = int( dum(1) )
310 CALL dgebrd( m, m, a, lda, s, dum(1), dum(1),
311 $ dum(1), dum(1), -1, info )
312 lwork_dgebrd = int( dum(1) )
314 CALL dormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda,
315 $ dum(1), b, ldb, dum(1), -1, info )
316 lwork_dormbr = int( dum(1) )
318 CALL dorgbr(
'P', m, m, m, a, lda, dum(1),
320 lwork_dorgbr = int( dum(1) )
322 CALL dormlq(
'L',
'T', n, nrhs, m, a, lda, dum(1),
323 $ b, ldb, dum(1), -1, info )
324 lwork_dormlq = int( dum(1) )
326 maxwrk = m + lwork_dgelqf
327 maxwrk = max( maxwrk, m*m + 4*m + lwork_dgebrd )
328 maxwrk = max( maxwrk, m*m + 4*m + lwork_dormbr )
329 maxwrk = max( maxwrk, m*m + 4*m + lwork_dorgbr )
330 maxwrk = max( maxwrk, m*m + m + bdspac )
332 maxwrk = max( maxwrk, m*m + m + m*nrhs )
334 maxwrk = max( maxwrk, m*m + 2*m )
336 maxwrk = max( maxwrk, m + lwork_dormlq )
342 CALL dgebrd( m, n, a, lda, s, dum(1), dum(1),
343 $ dum(1), dum(1), -1, info )
344 lwork_dgebrd = int( dum(1) )
346 CALL dormbr(
'Q',
'L',
'T', m, nrhs, m, a, lda,
347 $ dum(1), b, ldb, dum(1), -1, info )
348 lwork_dormbr = int( dum(1) )
350 CALL dorgbr(
'P', m, n, m, a, lda, dum(1),
352 lwork_dorgbr = int( dum(1) )
353 maxwrk = 3*m + lwork_dgebrd
354 maxwrk = max( maxwrk, 3*m + lwork_dormbr )
355 maxwrk = max( maxwrk, 3*m + lwork_dorgbr )
356 maxwrk = max( maxwrk, bdspac )
357 maxwrk = max( maxwrk, n*nrhs )
360 maxwrk = max( minwrk, maxwrk )
364 IF( lwork.LT.minwrk .AND. .NOT.lquery )
369 CALL xerbla(
'DGELSS', -info )
371 ELSE IF( lquery )
THEN 377 IF( m.EQ.0 .OR. n.EQ.0 )
THEN 385 sfmin = dlamch(
'S' )
387 bignum = one / smlnum
388 CALL dlabad( smlnum, bignum )
392 anrm = dlange(
'M', m, n, a, lda, work )
394 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN 398 CALL dlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
400 ELSE IF( anrm.GT.bignum )
THEN 404 CALL dlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
406 ELSE IF( anrm.EQ.zero )
THEN 410 CALL dlaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
411 CALL dlaset(
'F', minmn, 1, zero, zero, s, minmn )
418 bnrm = dlange(
'M', m, nrhs, b, ldb, work )
420 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN 424 CALL dlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
426 ELSE IF( bnrm.GT.bignum )
THEN 430 CALL dlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
441 IF( m.GE.mnthr )
THEN 452 CALL dgeqrf( m, n, a, lda, work( itau ), work( iwork ),
453 $ lwork-iwork+1, info )
458 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ), b,
459 $ ldb, work( iwork ), lwork-iwork+1, info )
464 $
CALL dlaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), lda )
475 CALL dgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
476 $ work( itaup ), work( iwork ), lwork-iwork+1,
482 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, work( itauq ),
483 $ b, ldb, work( iwork ), lwork-iwork+1, info )
488 CALL dorgbr(
'P', n, n, n, a, lda, work( itaup ),
489 $ work( iwork ), lwork-iwork+1, info )
497 CALL dbdsqr(
'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
498 $ 1, b, ldb, work( iwork ), info )
504 thr = max( rcond*s( 1 ), sfmin )
506 $ thr = max( eps*s( 1 ), sfmin )
509 IF( s( i ).GT.thr )
THEN 510 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
513 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
520 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN 521 CALL dgemm(
'T',
'N', n, nrhs, n, one, a, lda, b, ldb, zero,
523 CALL dlacpy(
'G', n, nrhs, work, ldb, b, ldb )
524 ELSE IF( nrhs.GT.1 )
THEN 526 DO 20 i = 1, nrhs, chunk
527 bl = min( nrhs-i+1, chunk )
528 CALL dgemm(
'T',
'N', n, bl, n, one, a, lda, b( 1, i ),
529 $ ldb, zero, work, n )
530 CALL dlacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
533 CALL dgemv(
'T', n, n, one, a, lda, b, 1, zero, work, 1 )
534 CALL dcopy( n, work, 1, b, 1 )
537 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
538 $ max( m, 2*m-4, nrhs, n-3*m ) )
THEN 544 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
545 $ m*lda+m+m*nrhs ) )ldwork = lda
552 CALL dgelqf( m, n, a, lda, work( itau ), work( iwork ),
553 $ lwork-iwork+1, info )
558 CALL dlacpy(
'L', m, m, a, lda, work( il ), ldwork )
559 CALL dlaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
569 CALL dgebrd( m, m, work( il ), ldwork, s, work( ie ),
570 $ work( itauq ), work( itaup ), work( iwork ),
571 $ lwork-iwork+1, info )
576 CALL dormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
577 $ work( itauq ), b, ldb, work( iwork ),
578 $ lwork-iwork+1, info )
583 CALL dorgbr(
'P', m, m, m, work( il ), ldwork, work( itaup ),
584 $ work( iwork ), lwork-iwork+1, info )
592 CALL dbdsqr(
'U', m, m, 0, nrhs, s, work( ie ), work( il ),
593 $ ldwork, a, lda, b, ldb, work( iwork ), info )
599 thr = max( rcond*s( 1 ), sfmin )
601 $ thr = max( eps*s( 1 ), sfmin )
604 IF( s( i ).GT.thr )
THEN 605 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
608 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
616 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 )
THEN 617 CALL dgemm(
'T',
'N', m, nrhs, m, one, work( il ), ldwork,
618 $ b, ldb, zero, work( iwork ), ldb )
619 CALL dlacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
620 ELSE IF( nrhs.GT.1 )
THEN 621 chunk = ( lwork-iwork+1 ) / m
622 DO 40 i = 1, nrhs, chunk
623 bl = min( nrhs-i+1, chunk )
624 CALL dgemm(
'T',
'N', m, bl, m, one, work( il ), ldwork,
625 $ b( 1, i ), ldb, zero, work( iwork ), m )
626 CALL dlacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
630 CALL dgemv(
'T', m, m, one, work( il ), ldwork, b( 1, 1 ),
631 $ 1, zero, work( iwork ), 1 )
632 CALL dcopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
637 CALL dlaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
643 CALL dormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
644 $ ldb, work( iwork ), lwork-iwork+1, info )
658 CALL dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
659 $ work( itaup ), work( iwork ), lwork-iwork+1,
665 CALL dormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda, work( itauq ),
666 $ b, ldb, work( iwork ), lwork-iwork+1, info )
671 CALL dorgbr(
'P', m, n, m, a, lda, work( itaup ),
672 $ work( iwork ), lwork-iwork+1, info )
680 CALL dbdsqr(
'L', m, n, 0, nrhs, s, work( ie ), a, lda, dum,
681 $ 1, b, ldb, work( iwork ), info )
687 thr = max( rcond*s( 1 ), sfmin )
689 $ thr = max( eps*s( 1 ), sfmin )
692 IF( s( i ).GT.thr )
THEN 693 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
696 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
703 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN 704 CALL dgemm(
'T',
'N', n, nrhs, m, one, a, lda, b, ldb, zero,
706 CALL dlacpy(
'F', n, nrhs, work, ldb, b, ldb )
707 ELSE IF( nrhs.GT.1 )
THEN 709 DO 60 i = 1, nrhs, chunk
710 bl = min( nrhs-i+1, chunk )
711 CALL dgemm(
'T',
'N', n, bl, m, one, a, lda, b( 1, i ),
712 $ ldb, zero, work, n )
713 CALL dlacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
716 CALL dgemv(
'T', m, n, one, a, lda, b, 1, zero, work, 1 )
717 CALL dcopy( n, work, 1, b, 1 )
723 IF( iascl.EQ.1 )
THEN 724 CALL dlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
725 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
727 ELSE IF( iascl.EQ.2 )
THEN 728 CALL dlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
729 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
732 IF( ibscl.EQ.1 )
THEN 733 CALL dlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
734 ELSE IF( ibscl.EQ.2 )
THEN 735 CALL dlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
subroutine drscl(N, SA, SX, INCX)
DRSCL multiplies a vector by the reciprocal of a real scalar.
subroutine dgebrd(M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, INFO)
DGEBRD
subroutine xerbla(SRNAME, INFO)
XERBLA
subroutine dlacpy(UPLO, M, N, A, LDA, B, LDB)
DLACPY copies all or part of one two-dimensional array to another.
subroutine dgemm(TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC)
DGEMM
subroutine dgelss(M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, WORK, LWORK, INFO)
DGELSS solves overdetermined or underdetermined systems for GE matrices
subroutine dgemv(TRANS, M, N, ALPHA, A, LDA, X, INCX, BETA, Y, INCY)
DGEMV
subroutine dormlq(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMLQ
subroutine dormqr(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMQR
subroutine dormbr(VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMBR
subroutine dorgbr(VECT, M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
DORGBR
subroutine dgelqf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
DGELQF
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 dbdsqr(UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U, LDU, C, LDC, WORK, INFO)
DBDSQR
subroutine dgeqrf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
DGEQRF
subroutine dlabad(SMALL, LARGE)
DLABAD
subroutine dcopy(N, DX, INCX, DY, INCY)
DCOPY