176 SUBROUTINE cgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
177 $ WORK, LWORK, RWORK, INFO )
184 INTEGER , LDA, LDB, , 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 )
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.LT..AND..NOT.
IF( LWORKMINWRK LQUERY )
372 CALL XERBLA( 'cgelss', -INFO )
374 ELSE IF( LQUERY ) THEN
380.EQ..OR..EQ.
IF( M0 N0 ) THEN
388 SFMIN = SLAMCH( 's
' )
390 BIGNUM = ONE / SMLNUM
391 CALL SLABAD( SMLNUM, BIGNUM )
395 ANRM = CLANGE( 'm
', M, N, A, LDA, RWORK )
397.GT..AND..LT.
IF( ANRMZERO ANRMSMLNUM ) THEN
401 CALL CLASCL( 'g
', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
403.GT.
ELSE IF( ANRMBIGNUM ) THEN
407 CALL CLASCL( 'g
', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
409.EQ.
ELSE IF( ANRMZERO ) 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.GT..AND..LT.
IF( BNRMZERO BNRMSMLNUM ) THEN
427 CALL CLASCL( 'g
', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
429.GT.
ELSE IF( BNRMBIGNUM ) THEN
433 CALL CLASCL( 'g
', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )
444.GE.
IF( MMNTHR ) 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.GT.
IF( S( I )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.GE..AND..GT.
IF( LWORKLDB*NRHS NRHS1 ) 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.GT.
ELSE IF( NRHS1 ) 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.GE..AND..GE.
ELSE IF( NMNTHR LWORK3*M+M*M+MAX( M, NRHS, N-2*M ) )
557.GE.
IF( LWORK3*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.GT.
IF( S( I )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.GE..AND..GT.
IF( LWORKLDB*NRHS+IWORK-1 NRHS1 ) 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.GT.
ELSE IF( NRHS1 ) 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 )