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
210 REAL SLAMCH, SLANGE, SROUNDUP_LWORK
211 EXTERNAL ilaenv, slamch, slange, sroundup_lwork
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, dum(1),
278 $ b, ldb, dum(1), -1, info )
279 lwork_sormbr = int( dum(1) )
281 CALL sorgbr(
'P', n, n, n, a, lda, dum(1),
283 lwork_sorgbr = int( 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 )
307 lwork_sgebrd = int( dum(1) )
309 CALL sormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda,
310 $ dum(1), b, ldb, dum(1), -1, info )
311 lwork_sormbr = int( dum(1) )
313 CALL sorgbr(
'P', m, m, m, a, lda, dum(1),
315 lwork_sorgbr = int( dum(1) )
317 CALL sormlq(
'L',
'T', n, nrhs, m, a, lda, dum(1),
318 $ b, ldb, dum(1), -1, info )
319 lwork_sormlq = int( dum(1) )
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 )
340 lwork_sgebrd = int( dum(1) )
342 CALL sormbr(
'Q',
'L',
'T', m, nrhs, m, a, lda,
343 $ dum(1), b, ldb, dum(1), -1, info )
344 lwork_sormbr = int( dum(1) )
346 CALL sorgbr(
'P', m, n, m, a, lda, dum(1),
348 lwork_sorgbr = int( 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 )
358 work( 1 ) = sroundup_lwork(maxwrk)
360 IF( lwork.LT.minwrk .AND. .NOT.lquery )
365 CALL xerbla(
'SGELSS', -info )
367 ELSE IF( lquery )
THEN
373 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
381 sfmin = slamch(
'S' )
383 bignum = one / smlnum
387 anrm = slange(
'M', m, n, a, lda, work )
389 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
393 CALL slascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
395 ELSE IF( anrm.GT.bignum )
THEN
399 CALL slascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
401 ELSE IF( anrm.EQ.zero )
THEN
405 CALL slaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
406 CALL slaset(
'F', minmn, 1, zero, zero, s, minmn )
413 bnrm = slange(
'M', m, nrhs, b, ldb, work )
415 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
419 CALL slascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
421 ELSE IF( bnrm.GT.bignum )
THEN
425 CALL slascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
436 IF( m.GE.mnthr )
THEN
447 CALL sgeqrf( m, n, a, lda, work( itau ), work( iwork ),
448 $ lwork-iwork+1, info )
453 CALL sormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ), b,
454 $ ldb, work( iwork ), lwork-iwork+1, info )
459 $
CALL slaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), lda )
470 CALL sgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
471 $ work( itaup ), work( iwork ), lwork-iwork+1,
477 CALL sormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, work( itauq ),
478 $ b, ldb, work( iwork ), lwork-iwork+1, info )
483 CALL sorgbr(
'P', n, n, n, a, lda, work( itaup ),
484 $ work( iwork ), lwork-iwork+1, info )
492 CALL sbdsqr(
'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
493 $ 1, b, ldb, work( iwork ), info )
499 thr = max( rcond*s( 1 ), sfmin )
501 $ thr = max( eps*s( 1 ), sfmin )
504 IF( s( i ).GT.thr )
THEN
505 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
508 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
515 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
516 CALL sgemm(
'T',
'N', n, nrhs, n, one, a, lda, b, ldb, zero,
518 CALL slacpy(
'G', n, nrhs, work, ldb, b, ldb )
519 ELSE IF( nrhs.GT.1 )
THEN
521 DO 20 i = 1, nrhs, chunk
522 bl = min( nrhs-i+1, chunk )
523 CALL sgemm(
'T',
'N', n, bl, n, one, a, lda, b( 1, i ),
524 $ ldb, zero, work, n )
525 CALL slacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
527 ELSE IF( nrhs.EQ.1 )
THEN
528 CALL sgemv(
'T', n, n, one, a, lda, b, 1, zero, work, 1 )
529 CALL scopy( n, work, 1, b, 1 )
532 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
533 $ max( m, 2*m-4, nrhs, n-3*m ) )
THEN
539 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
540 $ m*lda+m+m*nrhs ) )ldwork = lda
547 CALL sgelqf( m, n, a, lda, work( itau ), work( iwork ),
548 $ lwork-iwork+1, info )
553 CALL slacpy(
'L', m, m, a, lda, work( il ), ldwork )
554 CALL slaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
564 CALL sgebrd( m, m, work( il ), ldwork, s, work( ie ),
565 $ work( itauq ), work( itaup ), work( iwork ),
566 $ lwork-iwork+1, info )
571 CALL sormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
572 $ work( itauq ), b, ldb, work( iwork ),
573 $ lwork-iwork+1, info )
578 CALL sorgbr(
'P', m, m, m, work( il ), ldwork, work( itaup ),
579 $ work( iwork ), lwork-iwork+1, info )
587 CALL sbdsqr(
'U', m, m, 0, nrhs, s, work( ie ), work( il ),
588 $ ldwork, a, lda, b, ldb, work( iwork ), info )
594 thr = max( rcond*s( 1 ), sfmin )
596 $ thr = max( eps*s( 1 ), sfmin )
599 IF( s( i ).GT.thr )
THEN
600 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
603 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
611 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 )
THEN
612 CALL sgemm(
'T',
'N', m, nrhs, m, one, work( il ), ldwork,
613 $ b, ldb, zero, work( iwork ), ldb )
614 CALL slacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
615 ELSE IF( nrhs.GT.1 )
THEN
616 chunk = ( lwork-iwork+1 ) / m
617 DO 40 i = 1, nrhs, chunk
618 bl = min( nrhs-i+1, chunk )
619 CALL sgemm(
'T',
'N', m, bl, m, one, work( il ), ldwork,
620 $ b( 1, i ), ldb, zero, work( iwork ), m )
621 CALL slacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
624 ELSE IF( nrhs.EQ.1 )
THEN
625 CALL sgemv(
'T', m, m, one, work( il ), ldwork, b( 1, 1 ),
626 $ 1, zero, work( iwork ), 1 )
627 CALL scopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
632 CALL slaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
638 CALL sormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
639 $ ldb, work( iwork ), lwork-iwork+1, info )
653 CALL sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
654 $ work( itaup ), work( iwork ), lwork-iwork+1,
660 CALL sormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda, work( itauq ),
661 $ b, ldb, work( iwork ), lwork-iwork+1, info )
666 CALL sorgbr(
'P', m, n, m, a, lda, work( itaup ),
667 $ work( iwork ), lwork-iwork+1, info )
675 CALL sbdsqr(
'L', m, n, 0, nrhs, s, work( ie ), a, lda, dum,
676 $ 1, b, ldb, work( iwork ), info )
682 thr = max( rcond*s( 1 ), sfmin )
684 $ thr = max( eps*s( 1 ), sfmin )
687 IF( s( i ).GT.thr )
THEN
688 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
691 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
698 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
699 CALL sgemm(
'T',
'N', n, nrhs, m, one, a, lda, b, ldb, zero,
701 CALL slacpy(
'F', n, nrhs, work, ldb, b, ldb )
702 ELSE IF( nrhs.GT.1 )
THEN
704 DO 60 i = 1, nrhs, chunk
705 bl = min( nrhs-i+1, chunk )
706 CALL sgemm(
'T',
'N', n, bl, m, one, a, lda, b( 1, i ),
707 $ ldb, zero, work, n )
708 CALL slacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
710 ELSE IF( nrhs.EQ.1 )
THEN
711 CALL sgemv(
'T', m, n, one, a, lda, b, 1, zero, work, 1 )
712 CALL scopy( n, work, 1, b, 1 )
718 IF( iascl.EQ.1 )
THEN
719 CALL slascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
720 CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
722 ELSE IF( iascl.EQ.2 )
THEN
723 CALL slascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
724 CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
727 IF( ibscl.EQ.1 )
THEN
728 CALL slascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
729 ELSE IF( ibscl.EQ.2 )
THEN
730 CALL slascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
734 work( 1 ) = sroundup_lwork(maxwrk)
subroutine xerbla(srname, info)
subroutine sbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work, info)
SBDSQR
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
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 sgelss(m, n, nrhs, a, lda, b, ldb, s, rcond, rank, work, lwork, info)
SGELSS solves overdetermined or underdetermined systems for GE matrices
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
subroutine sgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
SGEMV
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 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 srscl(n, sa, sx, incx)
SRSCL multiplies a vector by the reciprocal of a real scalar.
subroutine sorgbr(vect, m, n, k, a, lda, tau, work, lwork, info)
SORGBR
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