202 SUBROUTINE sgelsd( M, N, NRHS, A, LDA, B, LDB, S, RCOND,
203 $ RANK, WORK, LWORK, IWORK, INFO )
210 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
215 REAL A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
222 parameter( zero = 0.0e0, one = 1.0e0, two = 2.0e0 )
226 INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,
227 $ ldwork, liwork, maxmn, maxwrk, minmn, minwrk,
228 $ mm, mnthr, nlvl, nwork, smlsiz, wlalsd
229 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM
237 REAL SLAMCH, SLANGE, SROUNDUP_LWORK
238 EXTERNAL slamch, slange, ilaenv, sroundup_lwork
241 INTRINSIC int, log, max, min, real
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
274 IF( minmn.GT.0 )
THEN
275 smlsiz = ilaenv( 9,
'SGELSD',
' ', 0, 0, 0, 0 )
276 mnthr = ilaenv( 6,
'SGELSD',
' ', m, n, nrhs, -1 )
277 nlvl = max( int( log( real( minmn ) / real( smlsiz + 1 ) ) /
278 $ log( two ) ) + 1, 0 )
279 liwork = 3*minmn*nlvl + 11*minmn
281 IF( m.GE.n .AND. m.GE.mnthr )
THEN
287 maxwrk = max( maxwrk, n + n*ilaenv( 1,
'SGEQRF',
' ', m,
289 maxwrk = max( maxwrk, n + nrhs*ilaenv( 1,
'SORMQR',
'LT',
296 maxwrk = max( maxwrk, 3*n + ( mm + n )*ilaenv( 1,
297 $
'SGEBRD',
' ', mm, n, -1, -1 ) )
298 maxwrk = max( maxwrk, 3*n + nrhs*ilaenv( 1,
'SORMBR',
299 $
'QLT', mm, nrhs, n, -1 ) )
300 maxwrk = max( maxwrk, 3*n + ( n - 1 )*ilaenv( 1,
301 $
'SORMBR',
'PLN', n, nrhs, n, -1 ) )
302 wlalsd = 9*n + 2*n*smlsiz + 8*n*nlvl + n*nrhs +
304 maxwrk = max( maxwrk, 3*n + wlalsd )
305 minwrk = max( 3*n + mm, 3*n + nrhs, 3*n + wlalsd )
308 wlalsd = 9*m + 2*m*smlsiz + 8*m*nlvl + m*nrhs +
310 IF( n.GE.mnthr )
THEN
315 maxwrk = m + m*ilaenv( 1,
'SGELQF',
' ', m, n, -1,
317 maxwrk = max( maxwrk, m*m + 4*m + 2*m*ilaenv( 1,
318 $
'SGEBRD',
' ', m, m, -1, -1 ) )
319 maxwrk = max( maxwrk, m*m + 4*m + nrhs*ilaenv( 1,
320 $
'SORMBR',
'QLT', m, nrhs, m, -1 ) )
321 maxwrk = max( maxwrk, m*m + 4*m + ( m - 1 )*ilaenv( 1,
322 $
'SORMBR',
'PLN', m, nrhs, m, -1 ) )
324 maxwrk = max( maxwrk, m*m + m + m*nrhs )
326 maxwrk = max( maxwrk, m*m + 2*m )
328 maxwrk = max( maxwrk, m + nrhs*ilaenv( 1,
'SORMLQ',
329 $
'LT', n, nrhs, m, -1 ) )
330 maxwrk = max( maxwrk, m*m + 4*m + wlalsd )
333 maxwrk = max( maxwrk,
334 $ 4*m+m*m+max( m, 2*m-4, nrhs, n-3*m ) )
339 maxwrk = 3*m + ( n + m )*ilaenv( 1,
'SGEBRD',
' ', m,
341 maxwrk = max( maxwrk, 3*m + nrhs*ilaenv( 1,
'SORMBR',
342 $
'QLT', m, nrhs, n, -1 ) )
343 maxwrk = max( maxwrk, 3*m + m*ilaenv( 1,
'SORMBR',
344 $
'PLN', n, nrhs, m, -1 ) )
345 maxwrk = max( maxwrk, 3*m + wlalsd )
347 minwrk = max( 3*m + nrhs, 3*m + m, 3*m + wlalsd )
350 minwrk = min( minwrk, maxwrk )
351 work( 1 ) = sroundup_lwork(maxwrk)
354 IF( lwork.LT.minwrk .AND. .NOT.lquery )
THEN
360 CALL xerbla(
'SGELSD', -info )
362 ELSE IF( lquery )
THEN
368 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
376 sfmin = slamch(
'S' )
378 bignum = one / smlnum
382 anrm = slange(
'M', m, n, a, lda, work )
384 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
388 CALL slascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
390 ELSE IF( anrm.GT.bignum )
THEN
394 CALL slascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
396 ELSE IF( anrm.EQ.zero )
THEN
400 CALL slaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
401 CALL slaset(
'F', minmn, 1, zero, zero, s, 1 )
408 bnrm = slange(
'M', m, nrhs, b, ldb, work )
410 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
414 CALL slascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
416 ELSE IF( bnrm.GT.bignum )
THEN
420 CALL slascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
427 $
CALL slaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
436 IF( m.GE.mnthr )
THEN
447 CALL sgeqrf( m, n, a, lda, work( itau ), work( nwork ),
448 $ lwork-nwork+1, info )
453 CALL sormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ), b,
454 $ ldb, work( nwork ), lwork-nwork+1, info )
459 CALL slaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), lda )
471 CALL sgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
472 $ work( itaup ), work( nwork ), lwork-nwork+1,
478 CALL sormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, work( itauq ),
479 $ b, ldb, work( nwork ), lwork-nwork+1, info )
483 CALL slalsd(
'U', smlsiz, n, nrhs, s, work( ie ), b, ldb,
484 $ rcond, rank, work( nwork ), iwork, info )
491 CALL sormbr(
'P',
'L',
'N', n, nrhs, n, a, lda, work( itaup ),
492 $ b, ldb, work( nwork ), lwork-nwork+1, info )
494 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
495 $ max( m, 2*m-4, nrhs, n-3*m, wlalsd ) )
THEN
501 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
502 $ m*lda+m+m*nrhs, 4*m+m*lda+wlalsd ) )ldwork = lda
509 CALL sgelqf( m, n, a, lda, work( itau ), work( nwork ),
510 $ lwork-nwork+1, info )
515 CALL slacpy(
'L', m, m, a, lda, work( il ), ldwork )
516 CALL slaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
526 CALL sgebrd( m, m, work( il ), ldwork, s, work( ie ),
527 $ work( itauq ), work( itaup ), work( nwork ),
528 $ lwork-nwork+1, info )
533 CALL sormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
534 $ work( itauq ), b, ldb, work( nwork ),
535 $ lwork-nwork+1, info )
539 CALL slalsd(
'U', smlsiz, m, nrhs, s, work( ie ), b, ldb,
540 $ rcond, rank, work( nwork ), iwork, info )
547 CALL sormbr(
'P',
'L',
'N', m, nrhs, m, work( il ), ldwork,
548 $ work( itaup ), b, ldb, work( nwork ),
549 $ lwork-nwork+1, info )
553 CALL slaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
559 CALL sormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
560 $ ldb, work( nwork ), lwork-nwork+1, info )
574 CALL sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
575 $ work( itaup ), work( nwork ), lwork-nwork+1,
581 CALL sormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda, work( itauq ),
582 $ b, ldb, work( nwork ), lwork-nwork+1, info )
586 CALL slalsd(
'L', smlsiz, m, nrhs, s, work( ie ), b, ldb,
587 $ rcond, rank, work( nwork ), iwork, info )
594 CALL sormbr(
'P',
'L',
'N', n, nrhs, m, a, lda, work( itaup ),
595 $ b, ldb, work( nwork ), lwork-nwork+1, info )
601 IF( iascl.EQ.1 )
THEN
602 CALL slascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
603 CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
605 ELSE IF( iascl.EQ.2 )
THEN
606 CALL slascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
607 CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
610 IF( ibscl.EQ.1 )
THEN
611 CALL slascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
612 ELSE IF( ibscl.EQ.2 )
THEN
613 CALL slascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
617 work( 1 ) = sroundup_lwork(maxwrk)
subroutine xerbla(srname, info)
subroutine sgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
SGEBRD
subroutine sgelqf(m, n, a, lda, tau, work, lwork, info)
SGELQF
subroutine sgelsd(m, n, nrhs, a, lda, b, ldb, s, rcond, rank, work, lwork, iwork, info)
SGELSD computes the minimum-norm solution to a linear least squares problem for GE matrices
subroutine sgeqrf(m, n, a, lda, tau, work, lwork, info)
SGEQRF
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
subroutine slalsd(uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond, rank, work, iwork, info)
SLALSD uses the singular value decomposition of A to solve the least squares problem.
subroutine slascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
SLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine slaset(uplo, m, n, alpha, beta, a, lda)
SLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine sormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMBR
subroutine sormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMLQ
subroutine sormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMQR