170 SUBROUTINE sgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
171 $ WORK, LWORK, INFO )
178 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
182 REAL A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
189 parameter( zero = 0.0e+0, one = 1.0e+0 )
193 INTEGER BDSPAC, BL, CHUNK, I, IASCL, IBSCL, IE, IL,
194 $ itau, itaup, itauq, iwork, ldwork, maxmn,
195 $ maxwrk, minmn, minwrk, mm, mnthr
196 INTEGER LWORK_SGEQRF, LWORK_SORMQR, LWORK_SGEBRD,
197 $ lwork_sormbr, lwork_sorgbr, lwork_sormlq
198 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
211 EXTERNAL ilaenv, slamch, slange
223 lquery = ( lwork.EQ.-1 )
226 ELSE IF( n.LT.0 )
THEN
228 ELSE IF( nrhs.LT.0 )
THEN
230 ELSE IF( lda.LT.
max( 1, m ) )
THEN
232 ELSE IF( ldb.LT.
max( 1, maxmn ) )
THEN
246 IF( minmn.GT.0 )
THEN
248 mnthr =
ilaenv( 6,
'SGELSS',
' ', m, n, nrhs, -1 )
249 IF( m.GE.n .AND. m.GE.mnthr )
THEN
255 CALL sgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
258 CALL sormqr(
'L',
'T', m, nrhs, n, a, lda, dum(1), b,
259 $ ldb, dum(1), -1, info )
262 maxwrk =
max( maxwrk, n + lwork_sgeqrf )
263 maxwrk =
max( maxwrk, n + lwork_sormqr )
271 bdspac =
max( 1, 5*n )
273 CALL sgebrd( mm, n, a, lda, s, dum(1), dum(1),
274 $ dum(1), dum(1), -1, info )
277 CALL sormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, dum(1),
278 $ b, ldb, dum(1), -1, info )
281 CALL sorgbr(
'P', n, n, n, a, lda, dum(1),
285 maxwrk =
max( maxwrk, 3*n + lwork_sgebrd )
286 maxwrk =
max( maxwrk, 3*n + lwork_sormbr )
287 maxwrk =
max( maxwrk, 3*n + lwork_sorgbr )
288 maxwrk =
max( maxwrk, bdspac )
289 maxwrk =
max( maxwrk, n*nrhs )
290 minwrk =
max( 3*n + mm, 3*n + nrhs, bdspac )
291 maxwrk =
max( minwrk, maxwrk )
297 bdspac =
max( 1, 5*m )
298 minwrk =
max( 3*m+nrhs, 3*m+n, bdspac )
299 IF( n.GE.mnthr )
THEN
305 CALL sgebrd( m, m, a, lda, s, dum(1), dum(1),
306 $ dum(1), dum(1), -1, info )
309 CALL sormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda,
310 $ dum(1), b, ldb, dum(1), -1, info )
313 CALL sorgbr( 'p
', M, M, M, A, LDA, DUM(1),
317 CALL SORMLQ( 'l
', 't
', N, NRHS, M, A, LDA, DUM(1),
318 $ B, LDB, DUM(1), -1, INFO )
321 MAXWRK = M + M*ILAENV( 1, 'sgelqf', ' ', M, N, -1,
323 MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_SGEBRD )
324 MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_SORMBR )
325 MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_SORGBR )
326 MAXWRK = MAX( MAXWRK, M*M + M + BDSPAC )
328 MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS )
330 MAXWRK = MAX( MAXWRK, M*M + 2*M )
332 MAXWRK = MAX( MAXWRK, M + LWORK_SORMLQ )
338 CALL SGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
339 $ DUM(1), DUM(1), -1, INFO )
342 CALL SORMBR( 'q
', 'l
', 't
', M, NRHS, M, A, LDA,
343 $ DUM(1), B, LDB, DUM(1), -1, INFO )
346 CALL SORGBR( 'p
', M, N, M, A, LDA, DUM(1),
349 MAXWRK = 3*M + LWORK_SGEBRD
350 MAXWRK = MAX( MAXWRK, 3*M + LWORK_SORMBR )
351 MAXWRK = MAX( MAXWRK, 3*M + LWORK_SORGBR )
352 MAXWRK = MAX( MAXWRK, BDSPAC )
353 MAXWRK = MAX( MAXWRK, N*NRHS )
356 MAXWRK = MAX( MINWRK, MAXWRK )
360.LT..AND..NOT.
IF( LWORKMINWRK LQUERY )
365 CALL XERBLA( 'sgelss', -INFO )
367 ELSE IF( LQUERY ) THEN
373.EQ..OR..EQ.
IF( M0 N0 ) THEN
381 SFMIN = SLAMCH( 's
' )
383 BIGNUM = ONE / SMLNUM
384 CALL SLABAD( SMLNUM, BIGNUM )
388 ANRM = SLANGE( 'm
', M, N, A, LDA, WORK )
390.GT..AND..LT.
IF( ANRMZERO ANRMSMLNUM ) THEN
394 CALL SLASCL( 'g
', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
396.GT.
ELSE IF( ANRMBIGNUM ) THEN
400 CALL SLASCL( 'g
', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
402.EQ.
ELSE IF( ANRMZERO ) THEN
406 CALL SLASET( 'f
', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )
407 CALL SLASET( 'f
', MINMN, 1, ZERO, ZERO, S, MINMN )
414 BNRM = SLANGE( 'm
', M, NRHS, B, LDB, WORK )
416.GT..AND..LT.
IF( BNRMZERO BNRMSMLNUM ) THEN
420 CALL SLASCL( 'g
', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
422.GT.
ELSE IF( BNRMBIGNUM ) THEN
426 CALL SLASCL( 'g
', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )
437.GE.
IF( MMNTHR ) THEN
448 CALL SGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
449 $ LWORK-IWORK+1, INFO )
454 CALL SORMQR( 'l
', 't
', M, NRHS, N, A, LDA, WORK( ITAU ), B,
455 $ LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
460 $ 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( IWORK ), LWORK-IWORK+1,
478 CALL SORMBR( 'q
', 'l
', 't
', MM, NRHS, N, A, LDA, WORK( ITAUQ ),
479 $ B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
484 CALL SORGBR( 'p', n, n, n, a, lda, work( itaup ),
485 $ work( iwork ), lwork-iwork+1, info )
493 CALL sbdsqr(
'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
494 $ 1, b, ldb, work( iwork ), info )
500 thr =
max( rcond*s( 1 ), sfmin )
502 $ thr =
max( eps*s( 1 ), sfmin )
505 IF( s( i ).GT.thr )
THEN
506 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
509 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
516 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
517 CALL sgemm(
'T',
'N', n, nrhs, n, one, a, lda, b, ldb, zero,
519 CALL slacpy(
'G', n, nrhs, work, ldb, b, ldb )
520 ELSE IF( nrhs.GT.1 )
THEN
522 DO 20 i = 1, nrhs, chunk
523 bl =
min( nrhs-i+1, chunk )
524 CALL sgemm(
'T',
'N', n, bl, n, one, a, lda, b( 1, i ),
525 $ ldb, zero, work, n )
526 CALL slacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
529 CALL sgemv(
'T', n, n, one, a, lda, b, 1, zero, work, 1 )
530 CALL scopy( n, work, 1, b, 1 )
533 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
534 $
max( m, 2*m-4, nrhs, n-3*m ) )
THEN
540 IF( lwork.GE.
max( 4*m+m*lda+
max( m, 2*m-4, nrhs, n-3*m ),
541 $ m*lda+m+m*nrhs ) )ldwork = lda
548 CALL sgelqf( m, n, a, lda, work( itau ), work( iwork ),
554 CALL slacpy(
'L', m, m, a, lda, work( il ), ldwork )
555 CALL slaset(
'U', m-1, m-1, zero, zero, work( il+ldwork
565 CALL sgebrd( m, m, work( il ), ldwork, s, work( ie ),
567 $ lwork-iwork+1, info )
572 CALL sormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
573 $ work( itauq ), b, ldb, work( iwork
580 $ work( iwork ), lwork-iwork+1, info )
588 CALL sbdsqr(
'U', m, m, 0, nrhs, s, work( ie ), work( il ),
589 $ ldwork, a, lda, b, ldb, work( iwork ), info )
595 thr =
max( rcond*s( 1 ), sfmin )
597 $ thr =
max( eps*s( 1 ), sfmin )
600 IF( s( i ).GT.thr )
THEN
601 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
604 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
612 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 )
THEN
613 CALL sgemm(
'T',
'N', m, nrhs, m, one, work( il ), ldwork,
614 $ b, ldb, zero, work( iwork ), ldb )
615 CALL slacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
616 ELSE IF( nrhs.GT.1 )
THEN
617 chunk = ( lwork-iwork+1 ) / m
618 DO 40 i = 1, nrhs, chunk
619 bl =
min( nrhs-i+1, chunk )
620 CALL sgemm(
'T',
'N', m, bl, m, one, work( il ), ldwork,
621 $ b( 1, i ), ldb, zero, work( iwork ), m )
622 CALL slacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
626 CALL sgemv(
'T', m, m, one, work( il ), ldwork, b( 1, 1 ),
627 $ 1, zero, work( iwork ), 1 )
628 CALL scopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
633 CALL slaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
639 CALL sormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
640 $ ldb, work( iwork ), lwork-iwork+1, info )
654 CALL sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
655 $ work( itaup ), work( iwork ), lwork-iwork+1,
661 CALL sormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda, work( itauq ),
662 $ b, ldb, work( iwork ), lwork-iwork+1, info )
667 CALL sorgbr(
'P', m, n, m, a, lda, work( itaup ),
668 $ work( iwork ), lwork-iwork+1, info )
676 CALL sbdsqr(
'L', m, n, 0, nrhs, s, work( ie ), a, lda, dum,
677 $ 1, b, ldb, work( iwork ), info )
683 thr =
max( rcond*s( 1 ), sfmin )
685 $ thr =
max( eps*s( 1 ), sfmin )
688 IF( s( i ).GT.thr )
THEN
689 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
692 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
699 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
700 CALL sgemm(
'T',
'N', n, nrhs, m, one, a, lda, b, ldb, zero,
702 CALL slacpy(
'F', n, nrhs, work, ldb, b, ldb )
703 ELSE IF( nrhs.GT.1 )
THEN
705 DO 60 i = 1, nrhs, chunk
706 bl =
min( nrhs-i+1, chunk )
707 CALL sgemm(
'T',
'N', n, bl, m, one, a, lda, b( 1, i ),
708 $ ldb, zero, work, n )
709 CALL slacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
712 CALL sgemv(
'T', m, n, one, a, lda, b, 1, zero, work, 1 )
713 CALL scopy( n, work, 1, b, 1 )
719 IF( iascl.EQ.1 )
THEN
720 CALL slascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
721 CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
723 ELSE IF( iascl.EQ.2 )
THEN
724 CALL slascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
725 CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
728 IF( ibscl.EQ.1 )
THEN
729 CALL slascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
730 ELSE IF( ibscl.EQ.2 )
THEN
731 CALL slascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )