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
221 REAL CLANGE, SLAMCH, SROUNDUP_LWORK
222 EXTERNAL ilaenv, clange, slamch, sroundup_lwork
234 lquery = ( lwork.EQ.-1 )
237 ELSE IF( n.LT.0 )
THEN
239 ELSE IF( nrhs.LT.0 )
THEN
241 ELSE IF( lda.LT.max( 1, m ) )
THEN
243 ELSE IF( ldb.LT.max( 1, maxmn ) )
THEN
258 IF( minmn.GT.0 )
THEN
260 mnthr = ilaenv( 6,
'CGELSS',
' ', m, n, nrhs, -1 )
261 IF( m.GE.n .AND. m.GE.mnthr )
THEN
267 CALL cgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
268 lwork_cgeqrf = int( dum(1) )
270 CALL cunmqr(
'L',
'C', m, nrhs, n, a, lda, dum(1), b,
271 $ ldb, dum(1), -1, info )
272 lwork_cunmqr = int( dum(1) )
274 maxwrk = max( maxwrk, n + n*ilaenv( 1,
'CGEQRF',
' ', m,
276 maxwrk = max( maxwrk, n + nrhs*ilaenv( 1,
'CUNMQR',
'LC',
284 CALL cgebrd( mm, n, a, lda, s, s, dum(1), dum(1), dum(1),
286 lwork_cgebrd = int( dum(1) )
288 CALL cunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda, dum(1),
289 $ b, ldb, dum(1), -1, info )
290 lwork_cunmbr = int( dum(1) )
292 CALL cungbr(
'P', n, n, n, a, lda, dum(1),
294 lwork_cungbr = int( dum(1) )
296 maxwrk = max( maxwrk, 2*n + lwork_cgebrd )
297 maxwrk = max( maxwrk, 2*n + lwork_cunmbr )
298 maxwrk = max( maxwrk, 2*n + lwork_cungbr )
299 maxwrk = max( maxwrk, n*nrhs )
300 minwrk = 2*n + max( nrhs, m )
303 minwrk = 2*m + max( nrhs, n )
304 IF( n.GE.mnthr )
THEN
310 CALL cgelqf( m, n, a, lda, dum(1), dum(1),
312 lwork_cgelqf = int( dum(1) )
314 CALL cgebrd( m, m, a, lda, s, s, dum(1), dum(1),
316 lwork_cgebrd = int( dum(1) )
318 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda,
319 $ dum(1), b, ldb, dum(1), -1, info )
320 lwork_cunmbr = int( dum(1) )
322 CALL cungbr(
'P', m, m, m, a, lda, dum(1),
324 lwork_cungbr = int( dum(1) )
326 CALL cunmlq(
'L',
'C', n, nrhs, m, a, lda, dum(1),
327 $ b, ldb, dum(1), -1, info )
328 lwork_cunmlq = int( dum(1) )
330 maxwrk = m + lwork_cgelqf
331 maxwrk = max( maxwrk, 3*m + m*m + lwork_cgebrd )
332 maxwrk = max( maxwrk, 3*m + m*m + lwork_cunmbr )
333 maxwrk = max( maxwrk, 3*m + m*m + lwork_cungbr )
335 maxwrk = max( maxwrk, m*m + m + m*nrhs )
337 maxwrk = max( maxwrk, m*m + 2*m )
339 maxwrk = max( maxwrk, m + lwork_cunmlq )
345 CALL cgebrd( m, n, a, lda, s, s, dum(1), dum(1),
347 lwork_cgebrd = int( dum(1) )
349 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, m, a, lda,
350 $ dum(1), b, ldb, dum(1), -1, info )
351 lwork_cunmbr = int( dum(1) )
353 CALL cungbr(
'P', m, n, m, a, lda, dum(1),
355 lwork_cungbr = int( dum(1) )
356 maxwrk = 2*m + lwork_cgebrd
357 maxwrk = max( maxwrk, 2*m + lwork_cunmbr )
358 maxwrk = max( maxwrk, 2*m + lwork_cungbr )
359 maxwrk = max( maxwrk, n*nrhs )
362 maxwrk = max( minwrk, maxwrk )
364 work( 1 ) = sroundup_lwork(maxwrk)
366 IF( lwork.LT.minwrk .AND. .NOT.lquery )
371 CALL xerbla(
'CGELSS', -info )
373 ELSE IF( lquery )
THEN
379 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
387 sfmin = slamch(
'S' )
389 bignum = one / smlnum
393 anrm = clange(
'M', m, n, a, lda, rwork )
395 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
399 CALL clascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
401 ELSE IF( anrm.GT.bignum )
THEN
405 CALL clascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
407 ELSE IF( anrm.EQ.zero )
THEN
411 CALL claset(
'F', max( m, n ), nrhs, czero, czero, b, ldb )
412 CALL slaset(
'F', minmn, 1, zero, zero, s, minmn )
419 bnrm = clange(
'M', m, nrhs, b, ldb, rwork )
421 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
425 CALL clascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
427 ELSE IF( bnrm.GT.bignum )
THEN
431 CALL clascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
442 IF( m.GE.mnthr )
THEN
454 CALL cgeqrf( m, n, a, lda, work( itau ), work( iwork ),
455 $ lwork-iwork+1, info )
461 CALL cunmqr(
'L',
'C', m, nrhs, n, a, lda, work( itau ), b,
462 $ ldb, work( iwork ), lwork-iwork+1, info )
467 $
CALL claset(
'L', n-1, n-1, czero, czero, a( 2, 1 ),
480 CALL cgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),
481 $ work( itaup ), work( iwork ), lwork-iwork+1,
488 CALL cunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda, work( itauq ),
489 $ b, ldb, work( iwork ), lwork-iwork+1, info )
495 CALL cungbr(
'P', n, n, n, a, lda, work( itaup ),
496 $ work( iwork ), lwork-iwork+1, info )
505 CALL cbdsqr(
'U', n, n, 0, nrhs, s, rwork( ie ), a, lda, dum,
506 $ 1, b, ldb, rwork( irwork ), info )
512 thr = max( rcond*s( 1 ), sfmin )
514 $ thr = max( eps*s( 1 ), sfmin )
517 IF( s( i ).GT.thr )
THEN
518 CALL csrscl( nrhs, s( i ), b( i, 1 ), ldb )
521 CALL claset(
'F', 1, nrhs, czero, czero, b( i, 1 ), ldb )
529 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
530 CALL cgemm(
'C',
'N', n, nrhs, n, cone, a, lda, b, ldb,
532 CALL clacpy(
'G', n, nrhs, work, ldb, b, ldb )
533 ELSE IF( nrhs.GT.1 )
THEN
535 DO 20 i = 1, nrhs, chunk
536 bl = min( nrhs-i+1, chunk )
537 CALL cgemm(
'C',
'N', n, bl, n, cone, a, lda, b( 1, i ),
538 $ ldb, czero, work, n )
539 CALL clacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
541 ELSE IF( nrhs.EQ.1 )
THEN
542 CALL cgemv(
'C', n, n, cone, a, lda, b, 1, czero, work, 1 )
543 CALL ccopy( n, work, 1, b, 1 )
546 ELSE IF( n.GE.mnthr .AND. lwork.GE.3*m+m*m+max( m, nrhs, n-2*m ) )
555 IF( lwork.GE.3*m+m*lda+max( m, nrhs, n-2*m ) )
564 CALL cgelqf( m, n, a, lda, work( itau ), work( iwork ),
565 $ lwork-iwork+1, info )
570 CALL clacpy(
'L', m, m, a, lda, work( il ), ldwork )
571 CALL claset(
'U', m-1, m-1, czero, czero, work( il+ldwork ),
574 itauq = il + ldwork*m
582 CALL cgebrd( m, m, work( il ), ldwork, s, rwork( ie ),
583 $ work( itauq ), work( itaup ), work( iwork ),
584 $ lwork-iwork+1, info )
590 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, m, work( il ), ldwork,
591 $ work( itauq ), b, ldb, work( iwork ),
592 $ lwork-iwork+1, info )
598 CALL cungbr(
'P', m, m, m, work( il ), ldwork, work( itaup ),
599 $ work( iwork ), lwork-iwork+1, info )
608 CALL cbdsqr(
'U', m, m, 0, nrhs, s, rwork( ie ), work( il ),
609 $ ldwork, a, lda, b, ldb, rwork( irwork ), info )
615 thr = max( rcond*s( 1 ), sfmin )
617 $ thr = max( eps*s( 1 ), sfmin )
620 IF( s( i ).GT.thr )
THEN
621 CALL csrscl( nrhs, s( i ), b( i, 1 ), ldb )
624 CALL claset(
'F', 1, nrhs, czero, czero, b( i, 1 ), ldb )
627 iwork = il + m*ldwork
633 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 )
THEN
634 CALL cgemm(
'C',
'N', m, nrhs, m, cone, work( il ), ldwork,
635 $ b, ldb, czero, work( iwork ), ldb )
636 CALL clacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
637 ELSE IF( nrhs.GT.1 )
THEN
638 chunk = ( lwork-iwork+1 ) / m
639 DO 40 i = 1, nrhs, chunk
640 bl = min( nrhs-i+1, chunk )
641 CALL cgemm(
'C',
'N', m, bl, m, cone, work( il ), ldwork,
642 $ b( 1, i ), ldb, czero, work( iwork ), m )
643 CALL clacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
646 ELSE IF( nrhs.EQ.1 )
THEN
647 CALL cgemv(
'C', m, m, cone, work( il ), ldwork, b( 1, 1 ),
648 $ 1, czero, work( iwork ), 1 )
649 CALL ccopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
654 CALL claset(
'F', n-m, nrhs, czero, czero, b( m+1, 1 ), ldb )
661 CALL cunmlq(
'L',
'C', n, nrhs, m, a, lda, work( itau ), b,
662 $ ldb, work( iwork ), lwork-iwork+1, info )
677 CALL cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),
678 $ work( itaup ), work( iwork ), lwork-iwork+1,
685 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda, work( itauq ),
686 $ b, ldb, work( iwork ), lwork-iwork+1, info )
692 CALL cungbr(
'P', m, n, m, a, lda, work( itaup ),
693 $ work( iwork ), lwork-iwork+1, info )
702 CALL cbdsqr(
'L', m, n, 0, nrhs, s, rwork( ie ), a, lda, dum,
703 $ 1, b, ldb, rwork( irwork ), info )
709 thr = max( rcond*s( 1 ), sfmin )
711 $ thr = max( eps*s( 1 ), sfmin )
714 IF( s( i ).GT.thr )
THEN
715 CALL csrscl( nrhs, s( i ), b( i, 1 ), ldb )
718 CALL claset(
'F', 1, nrhs, czero, czero, b( i, 1 ), ldb )
726 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
727 CALL cgemm(
'C',
'N', n, nrhs, m, cone, a, lda, b, ldb,
729 CALL clacpy(
'G', n, nrhs, work, ldb, b, ldb )
730 ELSE IF( nrhs.GT.1 )
THEN
732 DO 60 i = 1, nrhs, chunk
733 bl = min( nrhs-i+1, chunk )
734 CALL cgemm(
'C',
'N', n, bl, m, cone, a, lda, b( 1, i ),
735 $ ldb, czero, work, n )
736 CALL clacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
738 ELSE IF( nrhs.EQ.1 )
THEN
739 CALL cgemv(
'C', m, n, cone, a, lda, b, 1, czero, work, 1 )
740 CALL ccopy( n, work, 1, b, 1 )
746 IF( iascl.EQ.1 )
THEN
747 CALL clascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
748 CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
750 ELSE IF( iascl.EQ.2 )
THEN
751 CALL clascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
752 CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
755 IF( ibscl.EQ.1 )
THEN
756 CALL clascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
757 ELSE IF( ibscl.EQ.2 )
THEN
758 CALL clascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
761 work( 1 ) = sroundup_lwork(maxwrk)
subroutine xerbla(srname, info)
subroutine cbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, rwork, info)
CBDSQR
subroutine ccopy(n, cx, incx, cy, incy)
CCOPY
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 cgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
CGEMM
subroutine cgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
CGEMV
subroutine cgeqrf(m, n, a, lda, tau, work, lwork, info)
CGEQRF
subroutine clacpy(uplo, m, n, a, lda, b, ldb)
CLACPY copies all or part of one two-dimensional array to another.
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 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 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 cungbr(vect, m, n, k, a, lda, tau, work, lwork, info)
CUNGBR
subroutine cunmbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
CUNMBR
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