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 )
231INTEGER 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, , 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
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
332 $ ilaenv
'DORMLQ', 'lt
', N, NRHS, M, -1 ) )
333 MAXWRK = MAX( MAXWRK, M*M+4*M+WLALSD )
334! XXX: Ensure the Path 2a case below is triggered. The workspace
335! calculation should use queries for all routines eventually.
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.LT..AND..NOT.
IF( LWORKMINWRK LQUERY ) THEN
362 CALL XERBLA( 'dgelsd', -INFO )
364 ELSE IF( LQUERY ) THEN
370.EQ..OR..EQ.
IF( M0 N0 ) THEN
378 SFMIN = DLAMCH( 's
' )
380 BIGNUM = ONE / SMLNUM
381 CALL DLABAD( SMLNUM, BIGNUM )
385 ANRM = DLANGE( 'm
', M, N, A, LDA, WORK )
387.GT..AND..LT.
IF( ANRMZERO ANRMSMLNUM ) THEN
391 CALL DLASCL( 'g
', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
393.GT.
ELSE IF( ANRMBIGNUM ) THEN
397 CALL DLASCL( 'g
', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
399.EQ.
ELSE IF( ANRMZERO ) 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.GT..AND..LT.
IF( BNRMZERO BNRMSMLNUM ) THEN
417 CALL DLASCL( 'g
', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
419.GT.
ELSE IF( BNRMBIGNUM ) 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.GE.
IF( MMNTHR ) 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.GE..AND..GE.
ELSE IF( NMNTHR LWORK4*M+M*M+
498 $ MAX( M, 2*M-4, NRHS, N-3*M, WLALSD ) ) THEN
504.GE.
IF( LWORKMAX( 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.EQ.
IF( IASCL1 ) 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.EQ.
ELSE IF( IASCL2 ) 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.EQ.
IF( IBSCL1 ) THEN
614 CALL DLASCL( 'g
', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )
615.EQ.
ELSE IF( IBSCL2 ) THEN
616 CALL DLASCL( 'g
', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )
subroutine dlabad(small, large)
DLABAD
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 xerbla(srname, info)
XERBLA
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 dgeqrf(m, n, a, lda, tau, work, lwork, info)
DGEQRF
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 dormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
DORMBR
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 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