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
391 anrm = dlange(
'M', m, n, a, lda, work )
393 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
397 CALL dlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
399 ELSE IF( anrm.GT.bignum )
THEN
403 CALL dlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
405 ELSE IF( anrm.EQ.zero )
THEN
409 CALL dlaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
410 CALL dlaset(
'F', minmn, 1, zero, zero, s, minmn )
417 bnrm = dlange(
'M', m, nrhs, b, ldb, work )
419 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
423 CALL dlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
425 ELSE IF( bnrm.GT.bignum )
THEN
429 CALL dlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
440 IF( m.GE.mnthr )
THEN
451 CALL dgeqrf( m, n, a, lda, work( itau ), work( iwork ),
452 $ lwork-iwork+1, info )
457 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ), b,
458 $ ldb, work( iwork ), lwork-iwork+1, info )
463 $
CALL dlaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), lda )
474 CALL dgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
475 $ work( itaup ), work( iwork ), lwork-iwork+1,
481 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, work( itauq ),
482 $ b, ldb, work( iwork ), lwork-iwork+1, info )
487 CALL dorgbr(
'P', n, n, n, a, lda, work( itaup ),
488 $ work( iwork ), lwork-iwork+1, info )
496 CALL dbdsqr(
'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
497 $ 1, b, ldb, work( iwork ), info )
503 thr = max( rcond*s( 1 ), sfmin )
505 $ thr = max( eps*s( 1 ), sfmin )
508 IF( s( i ).GT.thr )
THEN
509 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
512 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
519 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
520 CALL dgemm(
'T',
'N', n, nrhs, n, one, a, lda, b, ldb, zero,
522 CALL dlacpy(
'G', n, nrhs, work, ldb, b, ldb )
523 ELSE IF( nrhs.GT.1 )
THEN
525 DO 20 i = 1, nrhs, chunk
526 bl = min( nrhs-i+1, chunk )
527 CALL dgemm(
'T',
'N', n, bl, n, one, a, lda, b( 1, i ),
528 $ ldb, zero, work, n )
529 CALL dlacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
531 ELSE IF( nrhs.EQ.1 )
THEN
532 CALL dgemv(
'T', n, n, one, a, lda, b, 1, zero, work, 1 )
533 CALL dcopy( n, work, 1, b, 1 )
536 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
537 $ max( m, 2*m-4, nrhs, n-3*m ) )
THEN
543 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
544 $ m*lda+m+m*nrhs ) )ldwork = lda
551 CALL dgelqf( m, n, a, lda, work( itau ), work( iwork ),
552 $ lwork-iwork+1, info )
557 CALL dlacpy(
'L', m, m, a, lda, work( il ), ldwork )
558 CALL dlaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
568 CALL dgebrd( m, m, work( il ), ldwork, s, work( ie ),
569 $ work( itauq ), work( itaup ), work( iwork ),
570 $ lwork-iwork+1, info )
575 CALL dormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
576 $ work( itauq ), b, ldb, work( iwork ),
577 $ lwork-iwork+1, info )
582 CALL dorgbr(
'P', m, m, m, work( il ), ldwork, work( itaup ),
583 $ work( iwork ), lwork-iwork+1, info )
591 CALL dbdsqr(
'U', m, m, 0, nrhs, s, work( ie ), work( il ),
592 $ ldwork, a, lda, b, ldb, work( iwork ), info )
598 thr = max( rcond*s( 1 ), sfmin )
600 $ thr = max( eps*s( 1 ), sfmin )
603 IF( s( i ).GT.thr )
THEN
604 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
607 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
615 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 )
THEN
616 CALL dgemm(
'T',
'N', m, nrhs, m, one, work( il ), ldwork,
617 $ b, ldb, zero, work( iwork ), ldb )
618 CALL dlacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
619 ELSE IF( nrhs.GT.1 )
THEN
620 chunk = ( lwork-iwork+1 ) / m
621 DO 40 i = 1, nrhs, chunk
622 bl = min( nrhs-i+1, chunk )
623 CALL dgemm(
'T',
'N', m, bl, m, one, work( il ), ldwork,
624 $ b( 1, i ), ldb, zero, work( iwork ), m )
625 CALL dlacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
628 ELSE IF( nrhs.EQ.1 )
THEN
629 CALL dgemv(
'T', m, m, one, work( il ), ldwork, b( 1, 1 ),
630 $ 1, zero, work( iwork ), 1 )
631 CALL dcopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
636 CALL dlaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
642 CALL dormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
643 $ ldb, work( iwork ), lwork-iwork+1, info )
657 CALL dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
658 $ work( itaup ), work( iwork ), lwork-iwork+1,
664 CALL dormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda, work( itauq ),
665 $ b, ldb, work( iwork ), lwork-iwork+1, info )
670 CALL dorgbr(
'P', m, n, m, a, lda, work( itaup ),
671 $ work( iwork ), lwork-iwork+1, info )
679 CALL dbdsqr(
'L', m, n, 0, nrhs, s, work( ie ), a, lda, dum,
680 $ 1, b, ldb, work( iwork ), info )
686 thr = max( rcond*s( 1 ), sfmin )
688 $ thr = max( eps*s( 1 ), sfmin )
691 IF( s( i ).GT.thr )
THEN
692 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
695 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
702 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
703 CALL dgemm(
'T',
'N', n, nrhs, m, one, a, lda, b, ldb, zero,
705 CALL dlacpy(
'F', n, nrhs, work, ldb, b, ldb )
706 ELSE IF( nrhs.GT.1 )
THEN
708 DO 60 i = 1, nrhs, chunk
709 bl = min( nrhs-i+1, chunk )
710 CALL dgemm(
'T',
'N', n, bl, m, one, a, lda, b( 1, i ),
711 $ ldb, zero, work, n )
712 CALL dlacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
714 ELSE IF( nrhs.EQ.1 )
THEN
715 CALL dgemv(
'T', m, n, one, a, lda, b, 1, zero, work, 1 )
716 CALL dcopy( n, work, 1, b, 1 )
722 IF( iascl.EQ.1 )
THEN
723 CALL dlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
724 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
726 ELSE IF( iascl.EQ.2 )
THEN
727 CALL dlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
728 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
731 IF( ibscl.EQ.1 )
THEN
732 CALL dlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
733 ELSE IF( ibscl.EQ.2 )
THEN
734 CALL dlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
subroutine xerbla(srname, info)
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 dgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
DGEBRD
subroutine dgelqf(m, n, a, lda, tau, work, lwork, info)
DGELQF
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 dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
subroutine dgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
DGEMV
subroutine dgeqrf(m, n, a, lda, tau, work, lwork, info)
DGEQRF
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
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 drscl(n, sa, sx, incx)
DRSCL multiplies a vector by the reciprocal of a real scalar.
subroutine dorgbr(vect, m, n, k, a, lda, tau, work, lwork, info)
DORGBR
subroutine dormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
DORMBR
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