1 SUBROUTINE dgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
10 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
11 DOUBLE PRECISION RCOND
14 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
104 DOUBLE PRECISION ZERO, ONE
105 parameter( zero = 0.0d+0, one = 1.0d+0 )
109 INTEGER BDSPAC, BL, CHUNK, I, IASCL, IBSCL, IE, IL,
110 $ itau, itaup, itauq, iwork, ldwork, maxmn,
111 $ maxwrk, minmn, minwrk, mm, mnthr
112 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
115 DOUBLE PRECISION VDUM( 1 )
124 DOUBLE PRECISION DLAMCH, DLANGE
125 EXTERNAL ilaenv, dlamch, dlange
137 mnthr = ilaenv( 6,
'DGELSS',
' ', m, n, nrhs, -1 )
138 lquery = ( lwork.EQ.-1 )
141 ELSE IF( n.LT.0 )
THEN
143 ELSE IF( nrhs.LT.0 )
THEN
145 ELSE IF( lda.LT.max( 1, m ) )
THEN
147 ELSE IF( ldb.LT.max( 1, maxmn ) )
THEN
159 IF( info.EQ.0 .AND. ( lwork.GE.1 .OR. lquery ) )
THEN
162 IF( m.GE.n .AND. m.GE.mnthr )
THEN
167 maxwrk = max( maxwrk, n+n*ilaenv( 1,
'DGEQRF',
' ', m, n,
169 maxwrk = max( maxwrk, n+nrhs*
170 $ ilaenv( 1,
'DORMQR',
'LT', m, nrhs, n, -1 ) )
178 bdspac = max( 1, 5*n )
179 maxwrk = max( maxwrk, 3*n+( mm+n )*
180 $ ilaenv( 1,
'DGEBRD',
' ', mm, n, -1, -1 ) )
181 maxwrk = max( maxwrk, 3*n+nrhs*
182 $ ilaenv( 1,
'DORMBR',
'QLT', mm, nrhs, n, -1 ) )
183 maxwrk = max( maxwrk, 3*n+( n-1 )*
184 $ ilaenv( 1,
'DORGBR',
'P', n, n, n, -1 ) )
185 maxwrk = max( maxwrk, bdspac )
186 maxwrk = max( maxwrk, n*nrhs )
187 minwrk = max( 3*n+mm, 3*n+nrhs, bdspac )
188 maxwrk = max( minwrk, maxwrk )
194 bdspac = max( 1, 5*m )
195 minwrk = max( 3*m+nrhs, 3*m+n, bdspac )
196 IF( n.GE.mnthr )
THEN
201 maxwrk = m + m*ilaenv( 1,
'DGELQF',
' ', m, n, -1, -1 )
202 maxwrk = max( maxwrk, m*m+4*m+2*m*
203 $ ilaenv( 1,
'DGEBRD',
' ', m, m, -1, -1 ) )
204 maxwrk = max( maxwrk, m*m+4*m+nrhs*
205 $ ilaenv( 1,
'DORMBR',
'QLT', m, nrhs, m, -1 ) )
206 maxwrk = max( maxwrk, m*m+4*m+( m-1 )*
207 $ ilaenv( 1,
'DORGBR',
'P', m, m, m, -1 ) )
208 maxwrk = max( maxwrk, m*m+m+bdspac )
210 maxwrk = max( maxwrk, m*m+m+m*nrhs )
212 maxwrk = max( maxwrk, m*m+2*m )
214 maxwrk = max( maxwrk, m+nrhs*
215 $ ilaenv( 1,
'DORMLQ',
'LT', n, nrhs, m, -1 ) )
220 maxwrk = 3*m + ( n+m )*ilaenv( 1,
'DGEBRD',
' ', m, n,
222 maxwrk = max( maxwrk, 3*m+nrhs*
223 $ ilaenv( 1,
'DORMBR',
'QLT', m, nrhs, m, -1 ) )
224 maxwrk = max( maxwrk, 3*m+m*
225 $ ilaenv( 1,
'DORGBR',
'P', m, n, m, -1 ) )
226 maxwrk = max( maxwrk, bdspac )
227 maxwrk = max( maxwrk, n*nrhs )
230 maxwrk = max( minwrk, maxwrk )
234 minwrk = max( minwrk, 1 )
235 IF( lwork.LT.minwrk .AND. .NOT.lquery )
238 CALL xerbla(
'DGELSS', -info )
240 ELSE IF( lquery )
THEN
246 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
254 sfmin = dlamch(
'S' )
256 bignum = one / smlnum
257 CALL dlabad( smlnum, bignum )
261 anrm = dlange(
'M', m, n, a, lda, work )
263 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
267 CALL dlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
269 ELSE IF( anrm.GT.bignum )
THEN
273 CALL dlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
275 ELSE IF( anrm.EQ.zero )
THEN
279 CALL dlaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
280 CALL dlaset(
'F', minmn, 1, zero, zero, s, 1 )
287 bnrm = dlange(
'M', m, nrhs, b, ldb, work )
289 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
293 CALL dlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
295 ELSE IF( bnrm.GT.bignum )
THEN
299 CALL dlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
310 IF( m.GE.mnthr )
THEN
321 CALL dgeqrf( m, n, a, lda, work( itau ), work( iwork ),
322 $ lwork-iwork+1, info )
327 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ), b,
328 $ ldb, work( iwork ), lwork-iwork+1, info )
333 $
CALL dlaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), lda )
344 CALL dgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
345 $ work( itaup ), work( iwork ), lwork-iwork+1,
351 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, work( itauq ),
352 $ b, ldb, work( iwork ), lwork-iwork+1, info )
357 CALL dorgbr(
'P', n, n, n, a, lda, work( itaup ),
358 $ work( iwork ), lwork-iwork+1, info )
366 CALL dbdsqr(
'U', n, n, 0, nrhs, s, work( ie ), a, lda, vdum,
367 $ 1, b, ldb, work( iwork ), info )
373 thr = max( rcond*s( 1 ), sfmin )
375 $ thr = max( eps*s( 1 ), sfmin )
378 IF( s( i ).GT.thr )
THEN
379 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
382 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
389 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
390 CALL dgemm(
'T',
'N', n, nrhs, n, one, a, lda, b, ldb, zero,
392 CALL dlacpy(
'G', n, nrhs, work, ldb, b, ldb )
393 ELSE IF( nrhs.GT.1 )
THEN
395 DO 20 i = 1, nrhs, chunk
396 bl = min( nrhs-i+1, chunk )
397 CALL dgemm(
'T',
'N', n, bl, n, one, a, lda, b( 1, i ),
398 $ ldb, zero, work, n )
399 CALL dlacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
402 CALL dgemv(
'T', n, n, one, a, lda, b, 1, zero, work, 1 )
403 CALL dcopy( n, work, 1, b, 1 )
406 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
407 $ max( m, 2*m-4, nrhs, n-3*m ) )
THEN
413 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
414 $ m*lda+m+m*nrhs ) )ldwork = lda
421 CALL dgelqf( m, n, a, lda, work( itau ), work( iwork ),
422 $ lwork-iwork+1, info )
427 CALL dlacpy(
'L', m, m, a, lda, work( il ), ldwork )
428 CALL dlaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
438 CALL dgebrd( m, m, work( il ), ldwork, s, work( ie ),
439 $ work( itauq ), work( itaup ), work( iwork ),
440 $ lwork-iwork+1, info )
445 CALL dormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
446 $ work( itauq ), b, ldb, work( iwork ),
447 $ lwork-iwork+1, info )
452 CALL dorgbr(
'P', m, m, m, work( il ), ldwork, work( itaup ),
453 $ work( iwork ), lwork-iwork+1, info )
461 CALL dbdsqr(
'U', m, m, 0, nrhs, s, work( ie ), work( il ),
462 $ ldwork, a, lda, b, ldb, work( iwork ), info )
468 thr = max( rcond*s( 1 ), sfmin )
470 $ thr = max( eps*s( 1 ), sfmin )
473 IF( s( i ).GT.thr )
THEN
474 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
477 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
485 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 )
THEN
486 CALL dgemm(
'T',
'N', m, nrhs, m, one, work( il ), ldwork,
487 $ b, ldb, zero, work( iwork ), ldb )
488 CALL dlacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
489 ELSE IF( nrhs.GT.1 )
THEN
490 chunk = ( lwork-iwork+1 ) / m
491 DO 40 i = 1, nrhs, chunk
492 bl = min( nrhs-i+1, chunk )
493 CALL dgemm(
'T',
'N', m, bl, m, one, work( il ), ldwork,
494 $ b( 1, i ), ldb, zero, work( iwork ), n )
495 CALL dlacpy(
'G', m, bl, work( iwork ), n, b( 1, i ),
499 CALL dgemv(
'T', m, m, one, work( il ), ldwork, b( 1, 1 ),
500 $ 1, zero, work( iwork ), 1 )
501 CALL dcopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
506 CALL dlaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
512 CALL dormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
513 $ ldb, work( iwork ), lwork-iwork+1, info )
527 CALL dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
528 $ work( itaup ), work( iwork ), lwork-iwork+1,
534 CALL dormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda, work( itauq ),
535 $ b, ldb, work( iwork ), lwork-iwork+1, info )
540 CALL dorgbr(
'P', m, n, m, a, lda, work( itaup ),
541 $ work( iwork ), lwork-iwork+1, info )
549 CALL dbdsqr(
'L', m, n, 0, nrhs, s, work( ie ), a, lda, vdum,
550 $ 1, b, ldb, work( iwork ), info )
556 thr = max( rcond*s( 1 ), sfmin )
558 $ thr = max( eps*s( 1 ), sfmin )
561 IF( s( i ).GT.thr )
THEN
562 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
565 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
572 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 )
THEN
573 CALL dgemm(
'T',
'N', n, nrhs, m, one, a, lda, b, ldb, zero,
575 CALL dlacpy(
'F', n, nrhs, work, ldb, b, ldb )
576 ELSE IF( nrhs.GT.1 )
THEN
578 DO 60 i = 1, nrhs, chunk
579 bl = min( nrhs-i+1, chunk )
580 CALL dgemm(
'T',
'N', n, bl, m, one, a, lda, b( 1, i ),
581 $ ldb, zero, work, n )
582 CALL dlacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
585 CALL dgemv(
'T', m, n, one, a, lda, b, 1, zero, work, 1 )
586 CALL dcopy( n, work, 1, b, 1 )
592 IF( iascl.EQ.1 )
THEN
593 CALL dlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
594 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
596 ELSE IF( iascl.EQ.2 )
THEN
597 CALL dlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
598 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
601 IF( ibscl.EQ.1 )
THEN
602 CALL dlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
603 ELSE IF( ibscl.EQ.2 )
THEN
604 CALL dlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
subroutine dbdsqr(UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U, LDU, C, LDC, WORK, INFO)
subroutine dcopy(n, dx, incx, dy, incy)
subroutine dgebrd(M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, INFO)
subroutine dgelqf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
subroutine dgelss(M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, WORK, LWORK, INFO)
subroutine dgemm(TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC)
subroutine dgemv(TRANS, M, N, ALPHA, A, LDA, X, INCX, BETA, Y, INCY)
subroutine dgeqrf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
subroutine dlabad(SMALL, LARGE)
subroutine dlacpy(UPLO, M, N, A, LDA, B, LDB)
subroutine dlascl(TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO)
subroutine dlaset(UPLO, M, N, ALPHA, BETA, A, LDA)
subroutine dorgbr(VECT, M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
subroutine dormbr(VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
subroutine dormlq(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
subroutine dormqr(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
subroutine drscl(N, SA, SX, INCX)
subroutine xerbla(SRNAME, INFO)