168 SUBROUTINE sgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
169 $ WORK, LWORK, INFO )
176 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
180 REAL A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
187 parameter( zero = 0.0e+0, one = 1.0e+0 )
191 INTEGER BDSPAC, BL, CHUNK, I, IASCL, IBSCL, IE, IL,
192 $ itau, itaup, itauq, iwork, ldwork, maxmn,
193 $ maxwrk, minmn, minwrk, mm, mnthr
194 INTEGER LWORK_SGEQRF, LWORK_SORMQR, LWORK_SGEBRD,
195 $ lwork_sormbr, lwork_sorgbr, lwork_sormlq
196 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
209 REAL SLAMCH, SLANGE, SROUNDUP_LWORK
210 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 )
256 lwork_sgeqrf = int( dum(1) )
258 CALL sormqr(
'L',
'T', m, nrhs, n, a, lda, dum(1), b,
259 $ ldb, dum(1), -1, info )
260 lwork_sormqr = int( dum(1) )
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 )
275 lwork_sgebrd = int( dum(1) )
277 CALL sormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda,
279 $ b, ldb, dum(1), -1, info )
280 lwork_sormbr = int( dum(1) )
282 CALL sorgbr(
'P', n, n, n, a, lda, dum(1),
284 lwork_sorgbr = int( dum(1) )
286 maxwrk = max( maxwrk, 3*n + lwork_sgebrd )
287 maxwrk = max( maxwrk, 3*n + lwork_sormbr )
288 maxwrk = max( maxwrk, 3*n + lwork_sorgbr )
289 maxwrk = max( maxwrk, bdspac )
290 maxwrk = max( maxwrk, n*nrhs )
291 minwrk = max( 3*n + mm, 3*n + nrhs, bdspac )
292 maxwrk = max( minwrk, maxwrk )
298 bdspac = max( 1, 5*m )
299 minwrk = max( 3*m+nrhs, 3*m+n, bdspac )
300 IF( n.GE.mnthr )
THEN
306 CALL sgebrd( m, m, a, lda, s, dum(1), dum(1),
307 $ dum(1), dum(1), -1, info )
308 lwork_sgebrd = int( dum(1) )
310 CALL sormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda,
311 $ dum(1), b, ldb, dum(1), -1, info )
312 lwork_sormbr = int( dum(1) )
314 CALL sorgbr(
'P', m, m, m, a, lda, dum(1),
316 lwork_sorgbr = int( dum(1) )
318 CALL sormlq(
'L',
'T', n, nrhs, m, a, lda, dum(1),
319 $ b, ldb, dum(1), -1, info )
320 lwork_sormlq = int( dum(1) )
322 maxwrk = m + m*ilaenv( 1,
'SGELQF',
' ', m, n, -1,
324 maxwrk = max( maxwrk, m*m + 4*m + lwork_sgebrd )
325 maxwrk = max( maxwrk, m*m + 4*m + lwork_sormbr )
326 maxwrk = max( maxwrk, m*m + 4*m + lwork_sorgbr )
327 maxwrk = max( maxwrk, m*m + m + bdspac )
329 maxwrk = max( maxwrk, m*m + m + m*nrhs )
331 maxwrk = max( maxwrk, m*m + 2*m )
333 maxwrk = max( maxwrk, m + lwork_sormlq )
339 CALL sgebrd( m, n, a, lda, s, dum(1), dum(1),
340 $ dum(1), dum(1), -1, info )
341 lwork_sgebrd = int( dum(1) )
343 CALL sormbr(
'Q',
'L',
'T', m, nrhs, m, a, lda,
344 $ dum(1), b, ldb, dum(1), -1, info )
345 lwork_sormbr = int( dum(1) )
347 CALL sorgbr(
'P', m, n, m, a, lda, dum(1),
349 lwork_sorgbr = int( dum(1) )
350 maxwrk = 3*m + lwork_sgebrd
351 maxwrk = max( maxwrk, 3*m + lwork_sormbr )
352 maxwrk = max( maxwrk, 3*m + lwork_sorgbr )
353 maxwrk = max( maxwrk, bdspac )
354 maxwrk = max( maxwrk, n*nrhs )
357 maxwrk = max( minwrk, maxwrk )
359 work( 1 ) = sroundup_lwork(maxwrk)
361 IF( lwork.LT.minwrk .AND. .NOT.lquery )
366 CALL xerbla(
'SGELSS', -info )
368 ELSE IF( lquery )
THEN
374 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
382 sfmin = slamch(
'S' )
384 bignum = one / smlnum
388 anrm = slange(
'M', m, n, a, lda, work )
390 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
394 CALL slascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
396 ELSE IF( anrm.GT.bignum )
THEN
400 CALL slascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
402 ELSE IF( anrm.EQ.zero )
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 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
420 CALL slascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
423 ELSE IF( bnrm.GT.bignum )
THEN
427 CALL slascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb,
439 IF( m.GE.mnthr )
THEN
450 CALL sgeqrf( m, n, a, lda, work( itau ), work( iwork ),
451 $ lwork-iwork+1, info )
456 CALL sormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ),
458 $ ldb, work( iwork ), lwork-iwork+1, info )
463 $
CALL slaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ),
475 CALL sgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
476 $ work( itaup ), work( iwork ), lwork-iwork+1,
482 CALL sormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda,
484 $ b, ldb, work( iwork ), lwork-iwork+1, info )
489 CALL sorgbr(
'P', n, n, n, a, lda, work( itaup ),
490 $ work( iwork ), lwork-iwork+1, info )
498 CALL sbdsqr(
'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
499 $ 1, b, ldb, work( iwork ), info )
505 thr = max( rcond*s( 1 ), sfmin )
507 $ thr = max( eps*s( 1 ), sfmin )
510 IF( s( i ).GT.thr )
THEN
511 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
514 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ),
522 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
523 CALL sgemm(
'T',
'N', n, nrhs, n, one, a, lda, b, ldb,
526 CALL slacpy(
'G', n, nrhs, work, ldb, b, ldb )
527 ELSE IF( nrhs.GT.1 )
THEN
529 DO 20 i = 1, nrhs, chunk
530 bl = min( nrhs-i+1, chunk )
531 CALL sgemm(
'T',
'N', n, bl, n, one, a, lda, b( 1,
533 $ ldb, zero, work, n )
534 CALL slacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
536 ELSE IF( nrhs.EQ.1 )
THEN
537 CALL sgemv(
'T', n, n, one, a, lda, b, 1, zero, work, 1 )
538 CALL scopy( n, work, 1, b, 1 )
541 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
542 $ max( m, 2*m-4, nrhs, n-3*m ) )
THEN
548 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
549 $ m*lda+m+m*nrhs ) )ldwork = lda
556 CALL sgelqf( m, n, a, lda, work( itau ), work( iwork ),
557 $ lwork-iwork+1, info )
562 CALL slacpy(
'L', m, m, a, lda, work( il ), ldwork )
563 CALL slaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
573 CALL sgebrd( m, m, work( il ), ldwork, s, work( ie ),
574 $ work( itauq ), work( itaup ), work( iwork ),
575 $ lwork-iwork+1, info )
580 CALL sormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
581 $ work( itauq ), b, ldb, work( iwork ),
582 $ lwork-iwork+1, info )
587 CALL sorgbr(
'P', m, m, m, work( il ), ldwork,
589 $ work( iwork ), lwork-iwork+1, info )
597 CALL sbdsqr(
'U', m, m, 0, nrhs, s, work( ie ), work( il ),
598 $ ldwork, a, lda, b, ldb, work( iwork ), info )
604 thr = max( rcond*s( 1 ), sfmin )
606 $ thr = max( eps*s( 1 ), sfmin )
609 IF( s( i ).GT.thr )
THEN
610 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
613 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ),
622 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 )
THEN
623 CALL sgemm(
'T',
'N', m, nrhs, m, one, work( il ),
625 $ b, ldb, zero, work( iwork ), ldb )
626 CALL slacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
627 ELSE IF( nrhs.GT.1 )
THEN
628 chunk = ( lwork-iwork+1 ) / m
629 DO 40 i = 1, nrhs, chunk
630 bl = min( nrhs-i+1, chunk )
631 CALL sgemm(
'T',
'N', m, bl, m, one, work( il ),
633 $ b( 1, i ), ldb, zero, work( iwork ), m )
634 CALL slacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
637 ELSE IF( nrhs.EQ.1 )
THEN
638 CALL sgemv(
'T', m, m, one, work( il ), ldwork, b( 1,
639 $ 1 ), 1, zero, work( iwork ), 1 )
640 CALL scopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
645 CALL slaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
651 CALL sormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
652 $ ldb, work( iwork ), lwork-iwork+1, info )
666 CALL sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
667 $ work( itaup ), work( iwork ), lwork-iwork+1,
673 CALL sormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda,
675 $ b, ldb, work( iwork ), lwork-iwork+1, info )
680 CALL sorgbr(
'P', m, n, m, a, lda, work( itaup ),
681 $ work( iwork ), lwork-iwork+1, info )
689 CALL sbdsqr(
'L', m, n, 0, nrhs, s, work( ie ), a, lda, dum,
690 $ 1, b, ldb, work( iwork ), info )
696 thr = max( rcond*s( 1 ), sfmin )
698 $ thr = max( eps*s( 1 ), sfmin )
701 IF( s( i ).GT.thr )
THEN
702 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
705 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ),
713 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
714 CALL sgemm(
'T',
'N', n, nrhs, m, one, a, lda, b, ldb,
717 CALL slacpy(
'F', n, nrhs, work, ldb, b, ldb )
718 ELSE IF( nrhs.GT.1 )
THEN
720 DO 60 i = 1, nrhs, chunk
721 bl = min( nrhs-i+1, chunk )
722 CALL sgemm(
'T',
'N', n, bl, m, one, a, lda, b( 1,
724 $ ldb, zero, work, n )
725 CALL slacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
727 ELSE IF( nrhs.EQ.1 )
THEN
728 CALL sgemv(
'T', m, n, one, a, lda, b, 1, zero, work, 1 )
729 CALL scopy( n, work, 1, b, 1 )
735 IF( iascl.EQ.1 )
THEN
736 CALL slascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
738 CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
740 ELSE IF( iascl.EQ.2 )
THEN
741 CALL slascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
743 CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
746 IF( ibscl.EQ.1 )
THEN
747 CALL slascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
749 ELSE IF( ibscl.EQ.2 )
THEN
750 CALL slascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,
755 work( 1 ) = sroundup_lwork(maxwrk)