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 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 dlacpy(UPLO, M, N, A, LDA, B, LDB)
DLACPY copies all or part of one two-dimensional array to another.
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 dbdsqr(UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U, LDU, C, LDC, WORK, INFO)
DBDSQR
subroutine dcopy(N, DX, INCX, DY, INCY)
DCOPY
subroutine dgemv(TRANS, M, N, ALPHA, A, LDA, X, INCX, BETA, Y, INCY)
DGEMV
subroutine dgemm(TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC)
DGEMM
subroutine dorgbr(VECT, M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
DORGBR
subroutine dgeqrf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
DGEQRF
subroutine dgelqf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
DGELQF
subroutine dgebrd(M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, INFO)
DGEBRD
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 drscl(N, SA, SX, INCX)
DRSCL multiplies a vector by the reciprocal of a real scalar.
subroutine dormqr(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMQR
subroutine dormlq(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMLQ
subroutine dormbr(VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMBR