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, , 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 ),
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.GE..AND..GE.
ELSE IF( NMNTHR LWORK4*M+M*M+
502 $ MAX( M, 2*M-4, NRHS, N-3*M, WLALSD ) ) THEN
508.GE.
IF( LWORKMAX( 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.EQ.
IF( IASCL1 ) 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.EQ.
ELSE IF( IASCL2 ) 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.EQ.
IF( IBSCL1 ) THEN
618 CALL SLASCL( 'g
', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )
619.EQ.
ELSE IF( IBSCL2 ) THEN
620 CALL SLASCL( 'g
', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )