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 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 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 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 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 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 dormbr(VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMBR