201 SUBROUTINE dgelsd( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
202 $ WORK, LWORK, IWORK, INFO )
209 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
210 DOUBLE PRECISION RCOND
214 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
220 DOUBLE PRECISION ZERO, ONE, TWO
221 parameter( zero = 0.0d0, one = 1.0d0, two = 2.0d0 )
225 INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,
226 $ ldwork, liwork, maxmn, maxwrk, minmn, minwrk,
227 $ mm, mnthr, nlvl, nwork, smlsiz, wlalsd
228 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM
236 DOUBLE PRECISION DLAMCH, DLANGE
237 EXTERNAL ilaenv, dlamch, dlange
240 INTRINSIC dble, int, log, max, min
249 mnthr = ilaenv( 6,
'DGELSD',
' ', m, n, nrhs, -1 )
250 lquery = ( lwork.EQ.-1 )
253 ELSE IF( n.LT.0 )
THEN
255 ELSE IF( nrhs.LT.0 )
THEN
257 ELSE IF( lda.LT.max( 1, m ) )
THEN
259 ELSE IF( ldb.LT.max( 1, maxmn ) )
THEN
263 smlsiz = ilaenv( 9,
'DGELSD',
' ', 0, 0, 0, 0 )
274 minmn = max( 1, minmn )
275 nlvl = max( int( log( dble( minmn ) / dble( smlsiz+1 ) ) /
276 $ log( two ) ) + 1, 0 )
280 liwork = 3*minmn*nlvl + 11*minmn
282 IF( m.GE.n .AND. m.GE.mnthr )
THEN
287 maxwrk = max( maxwrk, n+n*ilaenv( 1,
'DGEQRF',
' ', m, n,
289 maxwrk = max( maxwrk, n+nrhs*
290 $ ilaenv( 1,
'DORMQR',
'LT', m, nrhs, n, -1 ) )
296 maxwrk = max( maxwrk, 3*n+( mm+n )*
297 $ ilaenv( 1,
'DGEBRD',
' ', mm, n, -1, -1 ) )
298 maxwrk = max( maxwrk, 3*n+nrhs*
299 $ ilaenv( 1,
'DORMBR',
'QLT', mm, nrhs, n, -1 ) )
300 maxwrk = max( maxwrk, 3*n+( n-1 )*
301 $ ilaenv( 1,
'DORMBR',
'PLN', n, nrhs, n, -1 ) )
302 wlalsd = 9*n+2*n*smlsiz+8*n*nlvl+n*nrhs+(smlsiz+1)**2
303 maxwrk = max( maxwrk, 3*n+wlalsd )
304 minwrk = max( 3*n+mm, 3*n+nrhs, 3*n+wlalsd )
307 wlalsd = 9*m+2*m*smlsiz+8*m*nlvl+m*nrhs+(smlsiz+1)**2
308 IF( n.GE.mnthr )
THEN
313 maxwrk = m + m*ilaenv( 1,
'DGELQF',
' ', m, n, -1, -1 )
314 maxwrk = max( maxwrk, m*m+4*m+2*m*
315 $ ilaenv( 1,
'DGEBRD',
' ', m, m, -1, -1 ) )
316 maxwrk = max( maxwrk, m*m+4*m+nrhs*
317 $ ilaenv( 1,
'DORMBR',
'QLT', m, nrhs, m, -1 ) )
318 maxwrk = max( maxwrk, m*m+4*m+( m-1 )*
319 $ ilaenv( 1,
'DORMBR',
'PLN', m, nrhs, m, -1 ) )
321 maxwrk = max( maxwrk, m*m+m+m*nrhs )
323 maxwrk = max( maxwrk, m*m+2*m )
325 maxwrk = max( maxwrk, m+nrhs*
326 $ ilaenv( 1,
'DORMLQ',
'LT', n, nrhs, m, -1 ) )
327 maxwrk = max( maxwrk, m*m+4*m+wlalsd )
330 maxwrk = max( maxwrk,
331 $ 4*m+m*m+max( m, 2*m-4, nrhs, n-3*m ) )
336 maxwrk = 3*m + ( n+m )*ilaenv( 1,
'DGEBRD',
' ', m, n,
338 maxwrk = max( maxwrk, 3*m+nrhs*
339 $ ilaenv( 1,
'DORMBR',
'QLT', m, nrhs, n, -1 ) )
340 maxwrk = max( maxwrk, 3*m+m*
341 $ ilaenv( 1,
'DORMBR',
'PLN', n, nrhs, m, -1 ) )
342 maxwrk = max( maxwrk, 3*m+wlalsd )
344 minwrk = max( 3*m+nrhs, 3*m+m, 3*m+wlalsd )
346 minwrk = min( minwrk, maxwrk )
350 IF( lwork.LT.minwrk .AND. .NOT.lquery )
THEN
356 CALL xerbla(
'DGELSD', -info )
358 ELSE IF( lquery )
THEN
364 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
372 sfmin = dlamch(
'S' )
374 bignum = one / smlnum
378 anrm = dlange(
'M', m, n, a, lda, work )
380 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
384 CALL dlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
386 ELSE IF( anrm.GT.bignum )
THEN
390 CALL dlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
392 ELSE IF( anrm.EQ.zero )
THEN
396 CALL dlaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
397 CALL dlaset(
'F', minmn, 1, zero, zero, s, 1 )
404 bnrm = dlange(
'M', m, nrhs, b, ldb, work )
406 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
410 CALL dlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
412 ELSE IF( bnrm.GT.bignum )
THEN
416 CALL dlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
423 $
CALL dlaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
432 IF( m.GE.mnthr )
THEN
443 CALL dgeqrf( m, n, a, lda, work( itau ), work( nwork ),
444 $ lwork-nwork+1, info )
449 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ), b,
450 $ ldb, work( nwork ), lwork-nwork+1, info )
455 CALL dlaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), lda )
467 CALL dgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
468 $ work( itaup ), work( nwork ), lwork-nwork+1,
474 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, work( itauq ),
475 $ b, ldb, work( nwork ), lwork-nwork+1, info )
479 CALL dlalsd(
'U', smlsiz, n, nrhs, s, work( ie ), b, ldb,
480 $ rcond, rank, work( nwork ), iwork, info )
487 CALL dormbr(
'P',
'L',
'N', n, nrhs, n, a, lda, work( itaup ),
488 $ b, ldb, work( nwork ), lwork-nwork+1, info )
490 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
491 $ max( m, 2*m-4, nrhs, n-3*m, wlalsd ) )
THEN
497 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
498 $ m*lda+m+m*nrhs, 4*m+m*lda+wlalsd ) )ldwork = lda
505 CALL dgelqf( m, n, a, lda, work( itau ), work( nwork ),
506 $ lwork-nwork+1, info )
511 CALL dlacpy(
'L', m, m, a, lda, work( il ), ldwork )
512 CALL dlaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
522 CALL dgebrd( m, m, work( il ), ldwork, s, work( ie ),
523 $ work( itauq ), work( itaup ), work( nwork ),
524 $ lwork-nwork+1, info )
529 CALL dormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
530 $ work( itauq ), b, ldb, work( nwork ),
531 $ lwork-nwork+1, info )
535 CALL dlalsd(
'U', smlsiz, m, nrhs, s, work( ie ), b, ldb,
536 $ rcond, rank, work( nwork ), iwork, info )
543 CALL dormbr(
'P',
'L',
'N', m, nrhs, m, work( il ), ldwork,
544 $ work( itaup ), b, ldb, work( nwork ),
545 $ lwork-nwork+1, info )
549 CALL dlaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
555 CALL dormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
556 $ ldb, work( nwork ), lwork-nwork+1, info )
570 CALL dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
571 $ work( itaup ), work( nwork ), lwork-nwork+1,
577 CALL dormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda, work( itauq ),
578 $ b, ldb, work( nwork ), lwork-nwork+1, info )
582 CALL dlalsd(
'L', smlsiz, m, nrhs, s, work( ie ), b, ldb,
583 $ rcond, rank, work( nwork ), iwork, info )
590 CALL dormbr(
'P',
'L',
'N', n, nrhs, m, a, lda, work( itaup ),
591 $ b, ldb, work( nwork ), lwork-nwork+1, info )
597 IF( iascl.EQ.1 )
THEN
598 CALL dlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
599 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
601 ELSE IF( iascl.EQ.2 )
THEN
602 CALL dlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
603 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
606 IF( ibscl.EQ.1 )
THEN
607 CALL dlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
608 ELSE IF( ibscl.EQ.2 )
THEN
609 CALL dlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
subroutine xerbla(srname, info)
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 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 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 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 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 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