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
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 )
269 lwork_cgeqrf = real( dum(1) )
271 CALL cunmqr(
'L',
'C', m, nrhs, n, a, lda, dum(1), b,
272 $ ldb, dum(1), -1, info )
273 lwork_cunmqr = real( dum(1) )
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),
287 lwork_cgebrd = real( dum(1) )
289 CALL cunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda, dum(1),
290 $ b, ldb, dum(1), -1, info )
291 lwork_cunmbr = real( dum(1) )
293 CALL cungbr(
'P', n, n, n, a, lda, dum(1),
295 lwork_cungbr = real( 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),
313 lwork_cgelqf = real( dum(1) )
315 CALL cgebrd( m, m, a, lda, s, s, dum(1), dum(1),
317 lwork_cgebrd = real( dum(1) )
319 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda,
320 $ dum(1), b, ldb, dum(1), -1, info )
321 lwork_cunmbr = real( dum(1) )
323 CALL cungbr(
'P', m, m, m, a, lda, dum(1),
325 lwork_cungbr = real( dum(1) )
327 CALL cunmlq(
'L',
'C', n, nrhs, m, a, lda, dum(1),
328 $ b, ldb, dum(1), -1, info )
329 lwork_cunmlq = real( dum(1) )
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),
348 lwork_cgebrd = real( dum(1) )
350 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, m, a, lda,
351 $ dum(1), b, ldb, dum(1), -1, info )
352 lwork_cunmbr = real( dum(1) )
354 CALL cungbr(
'P', m, n, m, a, lda, dum(1),
356 lwork_cungbr = real( 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
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.
integer function ilaenv(ISPEC, NAME, OPTS, N1, N2, N3, N4)
ILAENV
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
real function clange(NORM, M, N, A, LDA, WORK)
CLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
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 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
real function slamch(CMACH)
SLAMCH