207 SUBROUTINE dgelsd( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
208 $ WORK, LWORK, IWORK, INFO )
215 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
216 DOUBLE PRECISION RCOND
220 DOUBLE PRECISION A( lda, * ), B( ldb, * ), S( * ), WORK( * )
226 DOUBLE PRECISION ZERO, ONE, TWO
227 parameter( zero = 0.0d0, one = 1.0d0, two = 2.0d0 )
231 INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,
232 $ ldwork, liwork, maxmn, maxwrk, minmn, minwrk,
233 $ mm, mnthr, nlvl, nwork, smlsiz, wlalsd
234 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM
242 DOUBLE PRECISION DLAMCH, DLANGE
243 EXTERNAL ilaenv, dlamch, dlange
246 INTRINSIC dble, int, log, max, min
255 mnthr = ilaenv( 6,
'DGELSD',
' ', m, n, nrhs, -1 )
256 lquery = ( lwork.EQ.-1 )
259 ELSE IF( n.LT.0 )
THEN 261 ELSE IF( nrhs.LT.0 )
THEN 263 ELSE IF( lda.LT.max( 1, m ) )
THEN 265 ELSE IF( ldb.LT.max( 1, maxmn ) )
THEN 269 smlsiz = ilaenv( 9,
'DGELSD',
' ', 0, 0, 0, 0 )
280 minmn = max( 1, minmn )
281 nlvl = max( int( log( dble( minmn ) / dble( smlsiz+1 ) ) /
282 $ log( two ) ) + 1, 0 )
286 liwork = 3*minmn*nlvl + 11*minmn
288 IF( m.GE.n .AND. m.GE.mnthr )
THEN 293 maxwrk = max( maxwrk, n+n*ilaenv( 1,
'DGEQRF',
' ', m, n,
295 maxwrk = max( maxwrk, n+nrhs*
296 $ ilaenv( 1,
'DORMQR',
'LT', m, nrhs, n, -1 ) )
302 maxwrk = max( maxwrk, 3*n+( mm+n )*
303 $ ilaenv( 1,
'DGEBRD',
' ', mm, n, -1, -1 ) )
304 maxwrk = max( maxwrk, 3*n+nrhs*
305 $ ilaenv( 1,
'DORMBR',
'QLT', mm, nrhs, n, -1 ) )
306 maxwrk = max( maxwrk, 3*n+( n-1 )*
307 $ ilaenv( 1,
'DORMBR',
'PLN', n, nrhs, n, -1 ) )
308 wlalsd = 9*n+2*n*smlsiz+8*n*nlvl+n*nrhs+(smlsiz+1)**2
309 maxwrk = max( maxwrk, 3*n+wlalsd )
310 minwrk = max( 3*n+mm, 3*n+nrhs, 3*n+wlalsd )
313 wlalsd = 9*m+2*m*smlsiz+8*m*nlvl+m*nrhs+(smlsiz+1)**2
314 IF( n.GE.mnthr )
THEN 319 maxwrk = m + m*ilaenv( 1,
'DGELQF',
' ', m, n, -1, -1 )
320 maxwrk = max( maxwrk, m*m+4*m+2*m*
321 $ ilaenv( 1,
'DGEBRD',
' ', m, m, -1, -1 ) )
322 maxwrk = max( maxwrk, m*m+4*m+nrhs*
323 $ ilaenv( 1,
'DORMBR',
'QLT', m, nrhs, m, -1 ) )
324 maxwrk = max( maxwrk, m*m+4*m+( m-1 )*
325 $ ilaenv( 1,
'DORMBR',
'PLN', m, nrhs, m, -1 ) )
327 maxwrk = max( maxwrk, m*m+m+m*nrhs )
329 maxwrk = max( maxwrk, m*m+2*m )
331 maxwrk = max( maxwrk, m+nrhs*
332 $ ilaenv( 1,
'DORMLQ',
'LT', n, nrhs, m, -1 ) )
333 maxwrk = max( maxwrk, m*m+4*m+wlalsd )
336 maxwrk = max( maxwrk,
337 $ 4*m+m*m+max( m, 2*m-4, nrhs, n-3*m ) )
342 maxwrk = 3*m + ( n+m )*ilaenv( 1,
'DGEBRD',
' ', m, n,
344 maxwrk = max( maxwrk, 3*m+nrhs*
345 $ ilaenv( 1,
'DORMBR',
'QLT', m, nrhs, n, -1 ) )
346 maxwrk = max( maxwrk, 3*m+m*
347 $ ilaenv( 1,
'DORMBR',
'PLN', n, nrhs, m, -1 ) )
348 maxwrk = max( maxwrk, 3*m+wlalsd )
350 minwrk = max( 3*m+nrhs, 3*m+m, 3*m+wlalsd )
352 minwrk = min( minwrk, maxwrk )
356 IF( lwork.LT.minwrk .AND. .NOT.lquery )
THEN 362 CALL xerbla(
'DGELSD', -info )
364 ELSE IF( lquery )
THEN 370 IF( m.EQ.0 .OR. n.EQ.0 )
THEN 378 sfmin = dlamch(
'S' )
380 bignum = one / smlnum
381 CALL dlabad( smlnum, bignum )
385 anrm = dlange(
'M', m, n, a, lda, work )
387 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN 391 CALL dlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
393 ELSE IF( anrm.GT.bignum )
THEN 397 CALL dlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
399 ELSE IF( anrm.EQ.zero )
THEN 403 CALL dlaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
404 CALL dlaset(
'F', minmn, 1, zero, zero, s, 1 )
411 bnrm = dlange(
'M', m, nrhs, b, ldb, work )
413 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN 417 CALL dlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
419 ELSE IF( bnrm.GT.bignum )
THEN 423 CALL dlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
430 $
CALL dlaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
439 IF( m.GE.mnthr )
THEN 450 CALL dgeqrf( m, n, a, lda, work( itau ), work( nwork ),
451 $ lwork-nwork+1, info )
456 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ), b,
457 $ ldb, work( nwork ), lwork-nwork+1, info )
462 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( nwork ), lwork-nwork+1,
481 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, work( itauq ),
482 $ b, ldb, work( nwork ), lwork-nwork+1, info )
486 CALL dlalsd(
'U', smlsiz, n, nrhs, s, work( ie ), b, ldb,
487 $ rcond, rank, work( nwork ), iwork, info )
494 CALL dormbr(
'P',
'L',
'N', n, nrhs, n, a, lda, work( itaup ),
495 $ b, ldb, work( nwork ), lwork-nwork+1, info )
497 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
498 $ max( m, 2*m-4, nrhs, n-3*m, wlalsd ) )
THEN 504 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
505 $ m*lda+m+m*nrhs, 4*m+m*lda+wlalsd ) )ldwork = lda
512 CALL dgelqf( m, n, a, lda, work( itau ), work( nwork ),
513 $ lwork-nwork+1, info )
518 CALL dlacpy(
'L', m, m, a, lda, work( il ), ldwork )
519 CALL dlaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
529 CALL dgebrd( m, m, work( il ), ldwork, s, work( ie ),
530 $ work( itauq ), work( itaup ), work( nwork ),
531 $ lwork-nwork+1, info )
536 CALL dormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
537 $ work( itauq ), b, ldb, work( nwork ),
538 $ lwork-nwork+1, info )
542 CALL dlalsd(
'U', smlsiz, m, nrhs, s, work( ie ), b, ldb,
543 $ rcond, rank, work( nwork ), iwork, info )
550 CALL dormbr(
'P',
'L',
'N', m, nrhs, m, work( il ), ldwork,
551 $ work( itaup ), b, ldb, work( nwork ),
552 $ lwork-nwork+1, info )
556 CALL dlaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
562 CALL dormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
563 $ ldb, work( nwork ), lwork-nwork+1, info )
577 CALL dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
578 $ work( itaup ), work( nwork ), lwork-nwork+1,
584 CALL dormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda, work( itauq ),
585 $ b, ldb, work( nwork ), lwork-nwork+1, info )
589 CALL dlalsd(
'L', smlsiz, m, nrhs, s, work( ie ), b, ldb,
590 $ rcond, rank, work( nwork ), iwork, info )
597 CALL dormbr(
'P',
'L',
'N', n, nrhs, m, a, lda, work( itaup ),
598 $ b, ldb, work( nwork ), lwork-nwork+1, info )
604 IF( iascl.EQ.1 )
THEN 605 CALL dlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
606 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
608 ELSE IF( iascl.EQ.2 )
THEN 609 CALL dlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
610 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
613 IF( ibscl.EQ.1 )
THEN 614 CALL dlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
615 ELSE IF( ibscl.EQ.2 )
THEN 616 CALL dlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
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 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 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 dgelsd(M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, WORK, LWORK, IWORK, INFO)
DGELSD computes the minimum-norm solution to a linear least squares problem for GE matrices ...
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 dlalsd(UPLO, SMLSIZ, N, NRHS, D, E, B, LDB, RCOND, RANK, WORK, IWORK, INFO)
DLALSD uses the singular value decomposition of A to solve the least squares problem.
subroutine dgeqrf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
DGEQRF
subroutine dlabad(SMALL, LARGE)
DLABAD