176 SUBROUTINE cgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
177 $ WORK, LWORK, RWORK, INFO )
184 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
188 REAL RWORK( * ), S( * )
189 COMPLEX A( LDA, * ), B( LDB, * ), WORK( * )
196 parameter( zero = 0.0e+0, one = 1.0e+0 )
198 parameter( czero = ( 0.0e+0, 0.0e+0 ),
199 $ cone = ( 1.0e+0, 0.0e+0 ) )
203 INTEGER BL, CHUNK, I, IASCL, IBSCL, IE, IL, IRWORK,
204 $ itau, itaup, itauq, iwork, ldwork, maxmn,
205 $ maxwrk, minmn, minwrk, mm, mnthr
206 INTEGER LWORK_CGEQRF, LWORK_CUNMQR, LWORK_CGEBRD,
207 $ lwork_cunmbr, lwork_cungbr, lwork_cunmlq,
209 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
223 EXTERNAL ilaenv, clange, slamch
235 lquery = ( lwork.EQ.-1 )
238 ELSE IF( n.LT.0 )
THEN
240 ELSE IF( nrhs.LT.0 )
THEN
242 ELSE IF( lda.LT.max( 1, m ) )
THEN
244 ELSE IF( ldb.LT.max( 1, maxmn ) )
THEN
259 IF( minmn.GT.0 )
THEN
261 mnthr = ilaenv( 6,
'CGELSS',
' ', m, n, nrhs, -1 )
262 IF( m.GE.n .AND. m.GE.mnthr )
THEN
268 CALL cgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
271 CALL cunmqr(
'L',
'C', m, nrhs, n, a, lda, dum(1), b,
272 $ ldb, dum(1), -1, info )
275 maxwrk = max( maxwrk, n + n*ilaenv( 1,
'CGEQRF',
' ', m,
277 maxwrk = max( maxwrk, n + nrhs*ilaenv( 1,
'CUNMQR',
'LC',
285 CALL cgebrd( mm, n, a, lda, s, s, dum(1), dum(1), dum(1),
289 CALL cunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda, dum(1),
290 $ b, ldb, dum(1), -1, info )
293 CALL cungbr(
'P', n, n, n, a, lda, dum(1),
297 maxwrk = max( maxwrk, 2*n + lwork_cgebrd )
298 maxwrk = max( maxwrk, 2*n + lwork_cunmbr )
299 maxwrk = max( maxwrk, 2*n + lwork_cungbr )
300 maxwrk = max( maxwrk, n*nrhs )
301 minwrk = 2*n + max( nrhs, m )
304 minwrk = 2*m + max( nrhs, n )
305 IF( n.GE.mnthr )
THEN
311 CALL cgelqf( m, n, a, lda, dum(1), dum(1),
315 CALL cgebrd( m, m, a, lda, s, s, dum(1), dum(1),
319 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda,
320 $ dum(1), b, ldb, dum(1), -1, info )
323 CALL cungbr(
'P', m, m, m, a, lda, dum(1),
327 CALL cunmlq(
'L',
'C', n, nrhs, m, a, lda, dum(1),
328 $ b, ldb, dum(1), -1, info )
331 maxwrk = m + lwork_cgelqf
332 maxwrk = max( maxwrk, 3*m + m*m + lwork_cgebrd )
333 maxwrk = max( maxwrk, 3*m + m*m + lwork_cunmbr )
334 maxwrk = max( maxwrk, 3*m + m*m + lwork_cungbr )
336 maxwrk = max( maxwrk, m*m + m + m*nrhs )
338 maxwrk = max( maxwrk, m*m + 2*m )
340 maxwrk = max( maxwrk, m + lwork_cunmlq )
346 CALL cgebrd( m, n, a, lda, s, s, dum(1), dum(1),
350 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, m, a, lda,
351 $ dum(1), b, ldb, dum(1), -1, info )
354 CALL cungbr(
'P', m, n, m, a, lda, dum(1),
357 maxwrk = 2*m + lwork_cgebrd
358 maxwrk = max( maxwrk, 2*m + lwork_cunmbr )
359 maxwrk = max( maxwrk, 2*m + lwork_cungbr )
360 maxwrk = max( maxwrk, n*nrhs )
363 maxwrk = max( minwrk, maxwrk )
367 IF( lwork.LT.minwrk .AND. .NOT.lquery )
372 CALL xerbla(
'CGELSS', -info )
374 ELSE IF( lquery )
THEN
380 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
388 sfmin = slamch(
'S' )
390 bignum = one / smlnum
391 CALL slabad( smlnum, bignum )
395 anrm = clange(
'M', m, n, a, lda, rwork )
397 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
401 CALL clascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
403 ELSE IF( anrm.GT.bignum )
THEN
407 CALL clascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
409 ELSE IF( anrm.EQ.zero )
THEN
413 CALL claset(
'F', max( m, n ), nrhs, czero, czero, b, ldb )
414 CALL slaset(
'F', minmn, 1, zero, zero, s, minmn )
421 bnrm = clange(
'M', m, nrhs, b, ldb, rwork )
423 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
427 CALL clascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
429 ELSE IF( bnrm.GT.bignum )
THEN
433 CALL clascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
444 IF( m.GE.mnthr )
THEN
456 CALL cgeqrf( m, n, a, lda, work( itau ), work( iwork ),
457 $ lwork-iwork+1, info )
463 CALL cunmqr(
'L',
'C', m, nrhs, n, a, lda, work( itau ), b,
464 $ ldb, work( iwork ), lwork-iwork+1, info )
469 $
CALL claset(
'L', n-1, n-1, czero, czero, a( 2, 1 ),
482 CALL cgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),
483 $ work( itaup ), work( iwork ), lwork-iwork+1,
490 CALL cunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda, work( itauq ),
491 $ b, ldb, work( iwork ), lwork-iwork+1, info )
497 CALL cungbr(
'P', n, n, n, a, lda, work( itaup ),
498 $ work( iwork ), lwork-iwork+1, info )
507 CALL cbdsqr(
'U', n, n, 0, nrhs, s, rwork( ie ), a, lda, dum,
508 $ 1, b, ldb, rwork( irwork ), info )
514 thr = max( rcond*s( 1 ), sfmin )
516 $ thr = max( eps*s( 1 ), sfmin )
519 IF( s( i ).GT.thr )
THEN
520 CALL csrscl( nrhs, s( i ), b( i, 1 ), ldb )
523 CALL claset(
'F', 1, nrhs, czero, czero, b( i, 1 ), ldb )
531 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
532 CALL cgemm(
'C',
'N', n, nrhs, n, cone, a, lda, b, ldb,
534 CALL clacpy(
'G', n, nrhs, work, ldb, b, ldb )
535 ELSE IF( nrhs.GT.1 )
THEN
537 DO 20 i = 1, nrhs, chunk
538 bl = min( nrhs-i+1, chunk )
539 CALL cgemm(
'C',
'N', n, bl, n, cone, a, lda, b( 1, i ),
540 $ ldb, czero, work, n )
541 CALL clacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
544 CALL cgemv(
'C', n, n, cone, a, lda, b, 1, czero, work, 1 )
545 CALL ccopy( n, work, 1, b, 1 )
548 ELSE IF( n.GE.mnthr .AND. lwork.GE.3*m+m*m+max( m, nrhs, n-2*m ) )
557 IF( lwork.GE.3*m+m*lda+max( m, nrhs, n-2*m ) )
566 CALL cgelqf( m, n, a, lda, work( itau ), work( iwork ),
567 $ lwork-iwork+1, info )
572 CALL clacpy(
'L', m, m, a, lda, work( il ), ldwork )
573 CALL claset(
'U', m-1, m-1, czero, czero, work( il+ldwork ),
576 itauq = il + ldwork*m
584 CALL cgebrd( m, m, work( il ), ldwork, s, rwork( ie ),
585 $ work( itauq ), work( itaup ), work( iwork ),
586 $ lwork-iwork+1, info )
592 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, m, work( il ), ldwork,
593 $ work( itauq ), b, ldb, work( iwork ),
594 $ lwork-iwork+1, info )
600 CALL cungbr(
'P', m, m, m, work( il ), ldwork, work( itaup ),
601 $ work( iwork ), lwork-iwork+1, info )
610 CALL cbdsqr(
'U', m, m, 0, nrhs, s, rwork( ie ), work( il ),
611 $ ldwork, a, lda, b, ldb, rwork( irwork ), info )
617 thr = max( rcond*s( 1 ), sfmin )
619 $ thr = max( eps*s( 1 ), sfmin )
622 IF( s( i ).GT.thr )
THEN
623 CALL csrscl( nrhs, s( i ), b( i, 1 ), ldb )
626 CALL claset(
'F', 1, nrhs, czero, czero, b( i, 1 ), ldb )
629 iwork = il + m*ldwork
635 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 )
THEN
636 CALL cgemm(
'C',
'N', m, nrhs, m, cone, work( il ), ldwork,
637 $ b, ldb, czero, work( iwork ), ldb )
638 CALL clacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
639 ELSE IF( nrhs.GT.1 )
THEN
640 chunk = ( lwork-iwork+1 ) / m
641 DO 40 i = 1, nrhs, chunk
642 bl = min( nrhs-i+1, chunk )
643 CALL cgemm(
'C',
'N', m, bl, m, cone, work( il ), ldwork,
644 $ b( 1, i ), ldb, czero, work( iwork ), m )
645 CALL clacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
649 CALL cgemv(
'C', m, m, cone, work( il ), ldwork, b( 1, 1 ),
650 $ 1, czero, work( iwork ), 1 )
651 CALL ccopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
656 CALL claset(
'F', n-m, nrhs, czero, czero, b( m+1, 1 ), ldb )
663 CALL cunmlq(
'L',
'C', n, nrhs, m, a, lda, work( itau ), b,
664 $ ldb, work( iwork ), lwork-iwork+1, info )
679 CALL cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),
680 $ work( itaup ), work( iwork ), lwork-iwork+1,
687 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda, work( itauq ),
688 $ b, ldb, work( iwork ), lwork-iwork+1, info )
694 CALL cungbr(
'P', m, n, m, a, lda, work( itaup ),
695 $ work( iwork ), lwork-iwork+1, info )
704 CALL cbdsqr(
'L', m, n, 0, nrhs, s, rwork( ie ), a, lda, dum,
705 $ 1, b, ldb, rwork( irwork ), info )
711 thr = max( rcond*s( 1 ), sfmin )
713 $ thr = max( eps*s( 1 ), sfmin )
716 IF( s( i ).GT.thr )
THEN
717 CALL csrscl( nrhs, s( i ), b( i, 1 ), ldb )
720 CALL claset(
'F', 1, nrhs, czero, czero, b( i, 1 ), ldb )
728 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
729 CALL cgemm(
'C',
'N', n, nrhs, m, cone, a, lda, b, ldb,
731 CALL clacpy(
'G', n, nrhs, work, ldb, b, ldb )
732 ELSE IF( nrhs.GT.1 )
THEN
734 DO 60 i = 1, nrhs, chunk
735 bl = min( nrhs-i+1, chunk )
736 CALL cgemm(
'C',
'N', n, bl, m, cone, a, lda, b( 1, i ),
737 $ ldb, czero, work, n )
738 CALL clacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
741 CALL cgemv(
'C', m, n, cone, a, lda, b, 1, czero, work, 1 )
742 CALL ccopy( n, work, 1, b, 1 )
748 IF( iascl.EQ.1 )
THEN
749 CALL clascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
750 CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
752 ELSE IF( iascl.EQ.2 )
THEN
753 CALL clascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
754 CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
757 IF( ibscl.EQ.1 )
THEN
758 CALL clascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
759 ELSE IF( ibscl.EQ.2 )
THEN
760 CALL clascl(
'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 xerbla(SRNAME, INFO)
XERBLA
subroutine ccopy(N, CX, INCX, CY, INCY)
CCOPY
subroutine cgemv(TRANS, M, N, ALPHA, A, LDA, X, INCX, BETA, Y, INCY)
CGEMV
subroutine cgemm(TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC)
CGEMM
subroutine cungbr(VECT, M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
CUNGBR
subroutine cgeqrf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
CGEQRF
subroutine cgebrd(M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, INFO)
CGEBRD
subroutine cgelqf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
CGELQF
subroutine cgelss(M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, WORK, LWORK, RWORK, INFO)
CGELSS solves overdetermined or underdetermined systems for GE matrices
subroutine claset(UPLO, M, N, ALPHA, BETA, A, LDA)
CLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine csrscl(N, SA, SX, INCX)
CSRSCL multiplies a vector by the reciprocal of a real scalar.
subroutine clascl(TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO)
CLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine clacpy(UPLO, M, N, A, LDA, B, LDB)
CLACPY copies all or part of one two-dimensional array to another.
subroutine cunmbr(VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
CUNMBR
subroutine cbdsqr(UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U, LDU, C, LDC, RWORK, INFO)
CBDSQR
subroutine cunmlq(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
CUNMLQ
subroutine cunmqr(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
CUNMQR