170 SUBROUTINE dgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
171 $ WORK, LWORK, INFO )
178 INTEGER INFO, LDA, LDB, LWORK, M, N, , RANK
179 DOUBLE PRECISION RCOND
182 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
188 DOUBLE PRECISION ZERO, ONE
189 parameter( zero = 0.0d+0, one = 1.0d+0 )
193 INTEGER , BL, , I, IASCL, IBSCL, IE, IL,
194 $ itau, itaup, itauq, iwork, ldwork, maxmn,
195 $ maxwrk, minmn, minwrk, mm, mnthr
196 INTEGER LWORK_DGEQRF, LWORK_DORMQR, LWORK_DGEBRD,
197 $ lwork_dormbr, lwork_dorgbr, lwork_dormlq,
199 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, , SMLNUM, THR
202 DOUBLE PRECISION DUM( 1 )
211 DOUBLE PRECISION DLAMCH, DLANGE
212 EXTERNAL ilaenv, dlamch, dlange
224 lquery = ( lwork.EQ.-1 )
227 ELSE IF( n.LT.0 )
THEN
229 ELSE IF( nrhs.LT.0 )
THEN
231 ELSE IF( lda.LT.
max( 1, m ) )
THEN
233 ELSE IF( ldb.LT.
max( 1, maxmn ) )
THEN
247 IF( minmn.GT.0 )
THEN
249 mnthr = ilaenv( 6,
'DGELSS',
' ', m, n, nrhs, -1 )
250 IF( m.GE.n .AND. m.GE.mnthr )
THEN
256 CALL dgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
259 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, dum(1), b,
260 $ ldb, dum(1), -1, info )
263 maxwrk =
max( maxwrk, n + lwork_dgeqrf )
264 maxwrk =
max( maxwrk, n + lwork_dormqr )
272 bdspac =
max( 1, 5*n )
274 CALL dgebrd( mm, n, a, lda, s, dum(1), dum(1),
275 $ dum(1), dum(1), -1, info )
278 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, dum(1),
279 $ b, ldb, dum(1), -1, info )
282 CALL dorgbr(
'P', n, n, n, a, lda, dum(1),
286 maxwrk =
max( maxwrk, 3*n + lwork_dgebrd )
287 maxwrk =
max( maxwrk, 3*n + lwork_dormbr )
288 maxwrk =
max( maxwrk, 3*n + lwork_dorgbr )
289 maxwrk =
max( maxwrk, bdspac )
290 maxwrk =
max( maxwrk, n*nrhs )
291 minwrk =
max( 3*n + mm, 3*n + nrhs, bdspac )
292 maxwrk =
max( minwrk, maxwrk )
298 bdspac =
max( 1, 5*m )
299 minwrk =
max( 3*m+nrhs, 3*m+n, bdspac )
300 IF( n.GE.mnthr )
THEN
306 CALL dgelqf( m, n, a, lda, dum(1), dum(1),
310 CALL dgebrd( m, m, a, lda, s, dum(1), dum(1),
311 $ dum(1), dum(1), -1, info )
314 CALL dormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda,
315 $ dum(1), b, ldb, dum(1), -1, info )
318 CALL dorgbr(
'P', m, m, m, a, lda, dum(1),
322 CALL dormlq(
'L',
'T', n, nrhs, m, a, lda, dum(1),
323 $ b, ldb, dum(1), -1, info )
326 maxwrk = m + lwork_dgelqf
327 maxwrk =
max( maxwrk, m*m + 4*m + lwork_dgebrd )
328 maxwrk =
max( maxwrk, m*m + 4*m + lwork_dormbr )
329 maxwrk =
max( maxwrk, m*m + 4*m + lwork_dorgbr )
330 maxwrk =
max( maxwrk, m*m + m + bdspac )
332 maxwrk =
max( maxwrk, m*m + m + m*nrhs )
334 maxwrk =
max( maxwrk, m*m + 2*m )
336 maxwrk =
max( maxwrk, m + lwork_dormlq )
342 CALL dgebrd( m, n, a, lda, s, dum(1), dum(1),
343 $ dum(1), dum(1), -1, info )
346 CALL dormbr(
'Q',
'L',
'T', m, nrhs, m, a, lda,
347 $ dum(1), b, ldb, dum(1), -1, info )
350 CALL dorgbr(
'P', m, n, m, a, lda, dum(1),
353 maxwrk = 3*m + lwork_dgebrd
354 maxwrk =
max( maxwrk, 3*m + lwork_dormbr )
355 maxwrk =
max( maxwrk, 3*m + lwork_dorgbr )
356 maxwrk =
max( maxwrk, bdspac )
357 maxwrk =
max( maxwrk, n*nrhs )
360 maxwrk =
max( minwrk, maxwrk )
364 IF( lwork.LT.minwrk .AND. .NOT.lquery )
369 CALL xerbla(
'DGELSS', -info )
371 ELSE IF( lquery )
THEN
377 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
385 sfmin = dlamch(
'S' )
387 bignum = one / smlnum
388 CALL dlabad( smlnum, bignum )
392 anrm = dlange(
'M', m, n, a, lda, work )
394 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
398 CALL dlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
400 ELSE IF( anrm.GT.bignum )
THEN
404 CALL dlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
406 ELSE IF( anrm.EQ.zero )
THEN
410 CALL dlaset(
'F',
max( m, n ), nrhs, zero, zero, b, ldb )
411 CALL dlaset(
'F', minmn, 1, zero, zero, s, minmn )
418 bnrm = dlange(
'M', m, nrhs, b, ldb, work )
420 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
424 CALL dlascl(
'G', 0, 0, bnrm, smlnum, m,
426 ELSE IF( bnrm.GT.bignum )
THEN
430 CALL dlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
441 IF( m.GE.mnthr )
THEN
453 $ lwork-iwork+1, info )
458 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ), b,
459 $ ldb, work( iwork ), lwork-iwork+1, info )
464 $
CALL dlaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), lda )
475 CALL dgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
476 $ work( itaup ), work( iwork ), lwork-iwork+1,
482 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, work( itauq ),
483 $ b, ldb, work( iwork ), lwork-iwork+1, info )
488 CALL dorgbr(
'P', n, n, n, a, lda, work( itaup ),
489 $ work( iwork ), lwork-iwork+1, info )
497 CALL dbdsqr(
'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
504 thr =
max( rcond*s( 1 ), sfmin )
506 $ thr =
max( eps*s( 1 ), sfmin )
509 IF( s( i ).GT.thr
THEN
510 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
513 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
520 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
521 CALL dgemm(
'T',
'N', n, nrhs, n, one, a, lda, b, ldb, zero,
523 CALL dlacpy(
'G', n, nrhs, work, ldb, b, ldb )
524 ELSE IF( nrhs.GT.1 )
THEN
526 DO 20 i = 1, nrhs, chunk
527 bl =
min( nrhs-i+1, chunk )
528 CALL dgemm(
'T',
'N', n, bl, n, one, a, lda, b( 1, i ),
529 $ ldb, zero, work, n )
530 CALL dlacpy( 'g
', N, BL, WORK, N, B( 1, I ), LDB )
533 CALL DGEMV( 't
', N, N, ONE, A, LDA, B, 1, ZERO, WORK, 1 )
534 CALL DCOPY( N, WORK, 1, B, 1 )
537.GE..AND..GE.
ELSE IF( NMNTHR LWORK4*M+M*M+
538 $ MAX( M, 2*M-4, NRHS, N-3*M ) ) THEN
544.GE.
IF( LWORKMAX( 4*M+M*LDA+MAX( M, 2*M-4, NRHS, N-3*M ),
545 $ M*LDA+M+M*NRHS ) )LDWORK = LDA
552 CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
553 $ LWORK-IWORK+1, INFO )
558 CALL DLACPY( 'l
', M, M, A, LDA, WORK( IL ), LDWORK )
559 CALL DLASET( 'u
', M-1, M-1, ZERO, ZERO, WORK( IL+LDWORK ),
569 CALL DGEBRD( M, M, WORK( IL ), LDWORK, S, WORK( IE ),
570 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( IWORK ),
571 $ LWORK-IWORK+1, INFO )
576 CALL DORMBR( 'q
', 'l
', 't
', M, NRHS, M, WORK( IL ), LDWORK,
577 $ WORK( ITAUQ ), B, LDB, WORK( IWORK ),
578 $ LWORK-IWORK+1, INFO )
583 CALL DORGBR( 'p
', M, M, M, WORK( IL ), LDWORK, WORK( ITAUP ),
584 $ WORK( IWORK ), LWORK-IWORK+1, INFO )
592 CALL DBDSQR( 'u
', M, M, 0, NRHS, S, WORK( IE ), WORK( IL ),
593 $ LDWORK, A, LDA, B, LDB, WORK( IWORK ), INFO )
599 THR = MAX( RCOND*S( 1 ), SFMIN )
601 $ THR = MAX( EPS*S( 1 ), SFMIN )
604.GT.
IF( S( I )THR ) THEN
605 CALL DRSCL( NRHS, S( I ), B( I, 1 ), LDB )
608 CALL DLASET( 'f
', 1, NRHS, ZERO, ZERO, B( I, 1 ), LDB )
616.GE..AND..GT.
IF( LWORKLDB*NRHS+IWORK-1 NRHS1 ) THEN
617 CALL DGEMM( 't
', 'n
', M, NRHS, M, ONE, WORK( IL ), LDWORK,
618 $ B, LDB, ZERO, WORK( IWORK ), LDB )
619 CALL DLACPY( 'g
', M, NRHS, WORK( IWORK ), LDB, B, LDB )
620.GT.
ELSE IF( NRHS1 ) THEN
621 CHUNK = ( LWORK-IWORK+1 ) / M
622 DO 40 I = 1, NRHS, CHUNK
623 BL = MIN( NRHS-I+1, CHUNK )
624 CALL DGEMM( 't
', 'n
', M, BL, M, ONE, WORK( IL ), LDWORK,
625 $ B( 1, I ), LDB, ZERO, WORK( IWORK ), M )
626 CALL DLACPY( 'g
', M, BL, WORK( IWORK ), M, B( 1, I ),
630 CALL DGEMV( 't
', M, M, ONE, WORK( IL ), LDWORK, B( 1, 1 ),
631 $ 1, ZERO, WORK( IWORK ), 1 )
632 CALL DCOPY( M, WORK( IWORK ), 1, B( 1, 1 ), 1 )
637 CALL DLASET( 'f
', N-M, NRHS, ZERO, ZERO, B( M+1, 1 ), LDB )
643 CALL DORMLQ( 'l
', 't
', N, NRHS, M, A, LDA, WORK( ITAU ), B,
644 $ LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
658 CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
659 $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
665 CALL DORMBR( 'q
', 'l
', 't
', M, NRHS, N, A, LDA, WORK( ITAUQ ),
666 $ B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
671 CALL DORGBR( 'p
', M, N, M, A, LDA, WORK( ITAUP ),
672 $ WORK( IWORK ), LWORK-IWORK+1, INFO )
680 CALL DBDSQR( 'l
', M, N, 0, NRHS, S, WORK( IE ), A, LDA, DUM,
681 $ 1, B, LDB, WORK( IWORK ), INFO )
687 THR = MAX( RCOND*S( 1 ), SFMIN )
689 $ THR = MAX( EPS*S( 1 ), SFMIN )
692.GT.
IF( S( I )THR ) THEN
693 CALL DRSCL( NRHS, S( I ), B( I, 1 ), LDB )
696 CALL DLASET( 'f
', 1, NRHS, ZERO, ZERO, B( I, 1 ), LDB )
703.GE..AND..GT.
IF( LWORKLDB*NRHS NRHS1 ) THEN
704 CALL DGEMM( 't
', 'n
', N, NRHS, M, ONE, A, LDA, B, LDB, ZERO,
706 CALL DLACPY( 'f
', N, NRHS, WORK, LDB, B, LDB )
707.GT.
ELSE IF( NRHS1 ) THEN
709 DO 60 I = 1, NRHS, CHUNK
710 BL = MIN( NRHS-I+1, CHUNK )
711 CALL DGEMM( 't
', 'n
', N, BL, M, ONE, A, LDA, B( 1, I ),
712 $ LDB, ZERO, WORK, N )
713 CALL DLACPY( 'f
', N, BL, WORK, N, B( 1, I ), LDB )
716 CALL DGEMV( 't
', M, N, ONE, A, LDA, B, 1, ZERO, WORK, 1 )
717 CALL DCOPY( N, WORK, 1, B, 1 )
723.EQ.
IF( IASCL1 ) THEN
724 CALL DLASCL( 'g
', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )
725 CALL DLASCL( 'g
', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
727.EQ.
ELSE IF( IASCL2 ) THEN
728 CALL DLASCL( 'g
', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )
729 CALL DLASCL( 'g
', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
732.EQ.
IF( IBSCL1 ) THEN
733 CALL DLASCL( 'g
', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )
734.EQ.
ELSE IF( IBSCL2 ) THEN
735 CALL DLASCL( 'g
', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )