217 SUBROUTINE zgelsd( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
218 $ WORK, LWORK, RWORK, IWORK, INFO )
225 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
226 DOUBLE PRECISION RCOND
230 DOUBLE PRECISION RWORK( * ), S( * )
231 COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * )
237 DOUBLE PRECISION ZERO, ONE, TWO
238 parameter( zero = 0.0d+0, one = 1.0d+0, two = 2.0d+0 )
240 parameter( czero = ( 0.0d+0, 0.0d+0 ) )
244 INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,
245 $ ldwork, liwork, lrwork, maxmn, maxwrk, minmn,
246 $ minwrk, mm, mnthr, nlvl, nrwork, nwork, smlsiz
247 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM
256 DOUBLE PRECISION DLAMCH, ZLANGE
257 EXTERNAL ilaenv, dlamch, zlange
260 INTRINSIC int, log, max, min, dble
269 lquery = ( lwork.EQ.-1 )
272 ELSE IF( n.LT.0 )
THEN
274 ELSE IF( nrhs.LT.0 )
THEN
276 ELSE IF( lda.LT.max( 1, m ) )
THEN
278 ELSE IF( ldb.LT.max( 1, maxmn ) )
THEN
294 IF( minmn.GT.0 )
THEN
295 smlsiz = ilaenv( 9,
'ZGELSD',
' ', 0, 0, 0, 0 )
296 mnthr = ilaenv( 6,
'ZGELSD',
' ', m, n, nrhs, -1 )
297 nlvl = max( int( log( dble( minmn ) / dble( smlsiz + 1 ) ) /
298 $ log( two ) ) + 1, 0 )
299 liwork = 3*minmn*nlvl + 11*minmn
301 IF( m.GE.n .AND. m.GE.mnthr )
THEN
307 maxwrk = max( maxwrk, n*ilaenv( 1,
'ZGEQRF',
' ', m, n,
309 maxwrk = max( maxwrk, nrhs*ilaenv( 1,
'ZUNMQR',
'LC', m,
316 lrwork = 10*n + 2*n*smlsiz + 8*n*nlvl + 3*smlsiz*nrhs +
317 $ max( (smlsiz+1)**2, n*(1+nrhs) + 2*nrhs )
318 maxwrk = max( maxwrk, 2*n + ( mm + n )*ilaenv( 1,
319 $
'ZGEBRD',
' ', mm, n, -1, -1 ) )
320 maxwrk = max( maxwrk, 2*n + nrhs*ilaenv( 1,
'ZUNMBR',
321 $
'QLC', mm, nrhs, n, -1 ) )
322 maxwrk = max( maxwrk, 2*n + ( n - 1 )*ilaenv( 1,
323 $
'ZUNMBR',
'PLN', n, nrhs, n, -1 ) )
324 maxwrk = max( maxwrk, 2*n + n*nrhs )
325 minwrk = max( 2*n + mm, 2*n + n*nrhs )
328 lrwork = 10*m + 2*m*smlsiz + 8*m*nlvl + 3*smlsiz*nrhs +
329 $ max( (smlsiz+1)**2, n*(1+nrhs) + 2*nrhs )
330 IF( n.GE.mnthr )
THEN
335 maxwrk = m + m*ilaenv( 1,
'ZGELQF',
' ', m, n, -1,
337 maxwrk = max( maxwrk, m*m + 4*m + 2*m*ilaenv( 1,
338 $
'ZGEBRD',
' ', m, m, -1, -1 ) )
339 maxwrk = max( maxwrk, m*m + 4*m + nrhs*ilaenv( 1,
340 $
'ZUNMBR',
'QLC', m, nrhs, m, -1 ) )
341 maxwrk = max( maxwrk, m*m + 4*m + ( m - 1 )*ilaenv( 1,
342 $
'ZUNMLQ',
'LC', n, nrhs, m, -1 ) )
344 maxwrk = max( maxwrk, m*m + m + m*nrhs )
346 maxwrk = max( maxwrk, m*m + 2*m )
348 maxwrk = max( maxwrk, m*m + 4*m + m*nrhs )
351 maxwrk = max( maxwrk,
352 $ 4*m+m*m+max( m, 2*m-4, nrhs, n-3*m ) )
357 maxwrk = 2*m + ( n + m )*ilaenv( 1,
'ZGEBRD',
' ', m,
359 maxwrk = max( maxwrk, 2*m + nrhs*ilaenv( 1,
'ZUNMBR',
360 $
'QLC', m, nrhs, m, -1 ) )
361 maxwrk = max( maxwrk, 2*m + m*ilaenv( 1,
'ZUNMBR',
362 $
'PLN', n, nrhs, m, -1 ) )
363 maxwrk = max( maxwrk, 2*m + m*nrhs )
365 minwrk = max( 2*m + n, 2*m + m*nrhs )
368 minwrk = min( minwrk, maxwrk )
373 IF( lwork.LT.minwrk .AND. .NOT.lquery )
THEN
379 CALL xerbla(
'ZGELSD', -info )
381 ELSE IF( lquery )
THEN
387 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
395 sfmin = dlamch(
'S' )
397 bignum = one / smlnum
401 anrm = zlange(
'M', m, n, a, lda, rwork )
403 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
407 CALL zlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
409 ELSE IF( anrm.GT.bignum )
THEN
413 CALL zlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
415 ELSE IF( anrm.EQ.zero )
THEN
419 CALL zlaset(
'F', max( m, n ), nrhs, czero, czero, b, ldb )
420 CALL dlaset(
'F', minmn, 1, zero, zero, s, 1 )
427 bnrm = zlange(
'M', m, nrhs, b, ldb, rwork )
429 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum )
THEN
433 CALL zlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
435 ELSE IF( bnrm.GT.bignum )
THEN
439 CALL zlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
446 $
CALL zlaset(
'F', n-m, nrhs, czero, czero, b( m+1, 1 ), ldb )
455 IF( m.GE.mnthr )
THEN
467 CALL zgeqrf( m, n, a, lda, work( itau ), work( nwork ),
468 $ lwork-nwork+1, info )
474 CALL zunmqr(
'L',
'C', m, nrhs, n, a, lda, work( itau ), b,
475 $ ldb, work( nwork ), lwork-nwork+1, info )
480 CALL zlaset(
'L', n-1, n-1, czero, czero, a( 2, 1 ),
495 CALL zgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),
496 $ work( itaup ), work( nwork ), lwork-nwork+1,
502 CALL zunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda, work( itauq ),
503 $ b, ldb, work( nwork ), lwork-nwork+1, info )
507 CALL zlalsd(
'U', smlsiz, n, nrhs, s, rwork( ie ), b, ldb,
508 $ rcond, rank, work( nwork ), rwork( nrwork ),
516 CALL zunmbr(
'P',
'L',
'N', n, nrhs, n, a, lda, work( itaup ),
517 $ b, ldb, work( nwork ), lwork-nwork+1, info )
519 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
520 $ max( m, 2*m-4, nrhs, n-3*m ) )
THEN
526 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
527 $ m*lda+m+m*nrhs ) )ldwork = lda
534 CALL zgelqf( m, n, a, lda, work( itau ), work( nwork ),
535 $ lwork-nwork+1, info )
540 CALL zlacpy(
'L', m, m, a, lda, work( il ), ldwork )
541 CALL zlaset(
'U', m-1, m-1, czero, czero, work( il+ldwork ),
543 itauq = il + ldwork*m
553 CALL zgebrd( m, m, work( il ), ldwork, s, rwork( ie ),
554 $ work( itauq ), work( itaup ), work( nwork ),
555 $ lwork-nwork+1, info )
560 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, m, work( il ), ldwork,
561 $ work( itauq ), b, ldb, work( nwork ),
562 $ lwork-nwork+1, info )
566 CALL zlalsd(
'U', smlsiz, m, nrhs, s, rwork( ie ), b, ldb,
567 $ rcond, rank, work( nwork ), rwork( nrwork ),
575 CALL zunmbr(
'P',
'L',
'N', m, nrhs, m, work( il ), ldwork,
576 $ work( itaup ), b, ldb, work( nwork ),
577 $ lwork-nwork+1, info )
581 CALL zlaset(
'F', n-m, nrhs, czero, czero, b( m+1, 1 ), ldb )
587 CALL zunmlq(
'L',
'C', n, nrhs, m, a, lda, work( itau ), b,
588 $ ldb, work( nwork ), lwork-nwork+1, info )
604 CALL zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),
605 $ work( itaup ), work( nwork ), lwork-nwork+1,
611 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda, work( itauq ),
612 $ b, ldb, work( nwork ), lwork-nwork+1, info )
616 CALL zlalsd(
'L', smlsiz, m, nrhs, s, rwork( ie ), b, ldb,
617 $ rcond, rank, work( nwork ), rwork( nrwork ),
625 CALL zunmbr(
'P',
'L',
'N', n, nrhs, m, a, lda, work( itaup ),
626 $ b, ldb, work( nwork ), lwork-nwork+1, info )
632 IF( iascl.EQ.1 )
THEN
633 CALL zlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
634 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
636 ELSE IF( iascl.EQ.2 )
THEN
637 CALL zlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
638 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
641 IF( ibscl.EQ.1 )
THEN
642 CALL zlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
643 ELSE IF( ibscl.EQ.2 )
THEN
644 CALL zlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
subroutine xerbla(srname, info)
subroutine zgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
ZGEBRD
subroutine zgelqf(m, n, a, lda, tau, work, lwork, info)
ZGELQF
subroutine zgelsd(m, n, nrhs, a, lda, b, ldb, s, rcond, rank, work, lwork, rwork, iwork, info)
ZGELSD computes the minimum-norm solution to a linear least squares problem for GE matrices
subroutine zgeqrf(m, n, a, lda, tau, work, lwork, info)
ZGEQRF
subroutine zlacpy(uplo, m, n, a, lda, b, ldb)
ZLACPY copies all or part of one two-dimensional array to another.
subroutine zlalsd(uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond, rank, work, rwork, iwork, info)
ZLALSD uses the singular value decomposition of A to solve the least squares problem.
subroutine zlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
ZLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine dlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine dlaset(uplo, m, n, alpha, beta, a, lda)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine zlaset(uplo, m, n, alpha, beta, a, lda)
ZLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine zunmbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
ZUNMBR
subroutine zunmlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
ZUNMLQ
subroutine zunmqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
ZUNMQR