208 SUBROUTINE sgelsd( M, N, NRHS, A, LDA, B, LDB, S, RCOND,
209 $ RANK, WORK, LWORK, IWORK, INFO )
216 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
221 REAL A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
228 parameter( zero = 0.0e0, one = 1.0e0, two = 2.0e0 )
232 INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,
233 $ ldwork, liwork, maxmn, maxwrk, minmn, minwrk,
234 $ mm, mnthr, nlvl, nwork, smlsiz, wlalsd
235 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM
244 EXTERNAL slamch, slange, ilaenv
247 INTRINSIC int, log, max, min, real
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
280 IF( minmn.GT.0 )
THEN
281 smlsiz = ilaenv( 9,
'SGELSD',
' ', 0, 0, 0, 0 )
282 mnthr = ilaenv( 6,
'SGELSD',
' ', m, n, nrhs, -1 )
283 nlvl = max( int( log( real( minmn ) / real( smlsiz + 1 ) ) /
284 $ log( two ) ) + 1, 0 )
285 liwork = 3*minmn*nlvl + 11*minmn
287 IF( m.GE.n .AND. m.GE.mnthr )
THEN
293 maxwrk = max( maxwrk, n + n*ilaenv( 1,
'SGEQRF',
' ', m,
295 maxwrk = max( maxwrk, n + nrhs*ilaenv( 1,
'SORMQR',
'LT',
302 maxwrk = max( maxwrk, 3*n + ( mm + n )*ilaenv( 1,
303 $
'SGEBRD',
' ', mm, n, -1, -1 ) )
304 maxwrk = max( maxwrk, 3*n + nrhs*ilaenv( 1,
'SORMBR',
305 $
'QLT', mm, nrhs, n, -1 ) )
306 maxwrk = max( maxwrk, 3*n + ( n - 1 )*ilaenv( 1,
307 $
'SORMBR',
'PLN', n, nrhs, n, -1 ) )
308 wlalsd = 9*n + 2*n*smlsiz + 8*n*nlvl + n*nrhs +
310 maxwrk = max( maxwrk, 3*n + wlalsd )
311 minwrk = max( 3*n + mm, 3*n + nrhs, 3*n + wlalsd )
314 wlalsd = 9*m + 2*m*smlsiz + 8*m*nlvl + m*nrhs +
316 IF( n.GE.mnthr )
THEN
321 maxwrk = m + m*ilaenv( 1,
'SGELQF',
' ', m, n, -1,
323 maxwrk = max( maxwrk, m*m + 4*m + 2*m*ilaenv( 1,
324 $
'SGEBRD',
' ', m, m, -1, -1 ) )
325 maxwrk = max( maxwrk, m*m + 4*m + nrhs*ilaenv( 1,
326 $
'SORMBR',
'QLT', m, nrhs, m, -1 ) )
327 maxwrk = max( maxwrk, m*m + 4*m + ( m - 1 )*ilaenv( 1,
328 $
'SORMBR',
'PLN', m, nrhs, m, -1 ) )
330 maxwrk = max( maxwrk, m*m + m + m*nrhs )
332 maxwrk = max( maxwrk, m*m + 2*m )
334 maxwrk = max( maxwrk, m + nrhs*ilaenv( 1,
'SORMLQ',
335 $
'LT', n, nrhs, m, -1 ) )
336 maxwrk = max( maxwrk, m*m + 4*m + wlalsd )
339 maxwrk = max( maxwrk,
340 $ 4*m+m*m+max( m, 2*m-4, nrhs, n-3*m ) )
345 maxwrk = 3*m + ( n + m )*ilaenv( 1,
'SGEBRD',
' ', m,
347 maxwrk = max( maxwrk, 3*m + nrhs*ilaenv( 1,
'SORMBR',
348 $
'QLT', m, nrhs, n, -1 ) )
349 maxwrk = max( maxwrk, 3*m + m*ilaenv( 1,
'SORMBR',
350 $
'PLN', n, nrhs, m, -1 ) )
351 maxwrk = max( maxwrk, 3*m + wlalsd )
353 minwrk = max( 3*m + nrhs, 3*m + m, 3*m + wlalsd )
356 minwrk = min( minwrk, maxwrk )
360 IF( lwork.LT.minwrk .AND. .NOT.lquery )
THEN
366 CALL xerbla(
'SGELSD', -info )
368 ELSE IF( lquery )
THEN
374 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
382 sfmin = slamch(
'S' )
384 bignum = one / smlnum
385 CALL slabad( smlnum, bignum )
389 anrm = slange(
'M', m, n, a, lda, work )
391 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
395 CALL slascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
397 ELSE IF( anrm.GT.bignum )
THEN
401 CALL slascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
403 ELSE IF( anrm.EQ.zero )
THEN
407 CALL slaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
408 CALL slaset(
'F', minmn, 1, zero, zero, s, 1 )
415 bnrm = slange(
'M', m, nrhs, b, ldb, work )
417 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
421 CALL slascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
423 ELSE IF( bnrm.GT.bignum )
THEN
427 CALL slascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
434 $
CALL slaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
443 IF( m.GE.mnthr )
THEN
454 CALL sgeqrf( m, n, a, lda, work( itau ), work( nwork ),
455 $ lwork-nwork+1, info )
460 CALL sormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ), b,
461 $ ldb, work( nwork ), lwork-nwork+1, info )
466 CALL slaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), lda )
478 CALL sgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
479 $ work( itaup ), work( nwork ), lwork-nwork+1,
485 CALL sormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, work( itauq ),
486 $ b, ldb, work( nwork ), lwork-nwork+1, info )
490 CALL slalsd(
'U', smlsiz, n, nrhs, s, work( ie ), b, ldb,
491 $ rcond, rank, work( nwork ), iwork, info )
498 CALL sormbr(
'P',
'L',
'N', n, nrhs, n, a, lda, work( itaup ),
499 $ b, ldb, work( nwork ), lwork-nwork+1, info )
501 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
502 $ max( m, 2*m-4, nrhs, n-3*m, wlalsd ) )
THEN
508 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
509 $ m*lda+m+m*nrhs, 4*m+m*lda+wlalsd ) )ldwork = lda
516 CALL sgelqf( m, n, a, lda, work( itau ), work( nwork ),
517 $ lwork-nwork+1, info )
522 CALL slacpy(
'L', m, m, a, lda, work( il ), ldwork )
523 CALL slaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
533 CALL sgebrd( m, m, work( il ), ldwork, s, work( ie ),
534 $ work( itauq ), work( itaup ), work( nwork ),
535 $ lwork-nwork+1, info )
540 CALL sormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
541 $ work( itauq ), b, ldb, work( nwork ),
542 $ lwork-nwork+1, info )
546 CALL slalsd(
'U', smlsiz, m, nrhs, s, work( ie ), b, ldb,
547 $ rcond, rank, work( nwork ), iwork, info )
554 CALL sormbr(
'P',
'L',
'N', m, nrhs, m, work( il ), ldwork,
555 $ work( itaup ), b, ldb, work( nwork ),
556 $ lwork-nwork+1, info )
560 CALL slaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
566 CALL sormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
567 $ ldb, work( nwork ), lwork-nwork+1, info )
581 CALL sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
582 $ work( itaup ), work( nwork ), lwork-nwork+1,
588 CALL sormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda, work( itauq ),
589 $ b, ldb, work( nwork ), lwork-nwork+1, info )
593 CALL slalsd(
'L', smlsiz, m, nrhs, s, work( ie ), b, ldb,
594 $ rcond, rank, work( nwork ), iwork, info )
601 CALL sormbr(
'P',
'L',
'N', n, nrhs, m, a, lda, work( itaup ),
602 $ b, ldb, work( nwork ), lwork-nwork+1, info )
608 IF( iascl.EQ.1 )
THEN
609 CALL slascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
610 CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
612 ELSE IF( iascl.EQ.2 )
THEN
613 CALL slascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
614 CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
617 IF( ibscl.EQ.1 )
THEN
618 CALL slascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
619 ELSE IF( ibscl.EQ.2 )
THEN
620 CALL slascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
subroutine slabad(SMALL, LARGE)
SLABAD
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 slacpy(UPLO, M, N, A, LDA, B, LDB)
SLACPY copies all or part of one two-dimensional array to another.
subroutine xerbla(SRNAME, INFO)
XERBLA
subroutine sgeqrf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
SGEQRF
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 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 sormbr(VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
SORMBR
subroutine sormqr(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
SORMQR
subroutine sormlq(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
SORMLQ