269 SUBROUTINE zgesvdx( JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU,
270 $ il, iu, ns, s, u, ldu, vt, ldvt, work,
271 $ lwork, rwork, iwork, info )
279 CHARACTER JOBU, JOBVT, RANGE
280 INTEGER IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
281 DOUBLE PRECISION VL, VU
285 DOUBLE PRECISION S( * ), RWORK( * )
286 COMPLEX*16 A( lda, * ), U( ldu, * ), VT( ldvt, * ),
293 COMPLEX*16 CZERO, CONE
294 parameter ( czero = ( 0.0d0, 0.0d0 ),
295 $ cone = ( 1.0d0, 0.0d0 ) )
296 DOUBLE PRECISION ZERO, ONE
297 parameter ( zero = 0.0d0, one = 1.0d0 )
300 CHARACTER JOBZ, RNGTGK
301 LOGICAL ALLS, INDS, LQUERY, VALS, WANTU, WANTVT
302 INTEGER I, ID, IE, IERR, ILQF, ILTGK, IQRF, ISCL,
303 $ itau, itaup, itauq, itemp, itempr, itgkz,
304 $ iutgk, j, k, maxwrk, minmn, minwrk, mnthr
305 DOUBLE PRECISION ABSTOL, ANRM, BIGNUM, EPS, SMLNUM
308 DOUBLE PRECISION DUM( 1 )
317 DOUBLE PRECISION DLAMCH, ZLANGE
318 EXTERNAL lsame, ilaenv, dlamch, zlange
321 INTRINSIC max, min, sqrt
329 abstol = 2*dlamch(
'S')
330 lquery = ( lwork.EQ.-1 )
333 wantu = lsame( jobu,
'V' )
334 wantvt = lsame( jobvt,
'V' )
335 IF( wantu .OR. wantvt )
THEN
340 alls = lsame( range,
'A' )
341 vals = lsame( range,
'V' )
342 inds = lsame( range,
'I' )
345 IF( .NOT.lsame( jobu,
'V' ) .AND.
346 $ .NOT.lsame( jobu,
'N' ) )
THEN
348 ELSE IF( .NOT.lsame( jobvt,
'V' ) .AND.
349 $ .NOT.lsame( jobvt,
'N' ) )
THEN
351 ELSE IF( .NOT.( alls .OR. vals .OR. inds ) )
THEN
353 ELSE IF( m.LT.0 )
THEN
355 ELSE IF( n.LT.0 )
THEN
357 ELSE IF( m.GT.lda )
THEN
359 ELSE IF( minmn.GT.0 )
THEN
361 IF( vl.LT.zero )
THEN
363 ELSE IF( vu.LE.vl )
THEN
367 IF( il.LT.1 .OR. il.GT.max( 1, minmn ) )
THEN
369 ELSE IF( iu.LT.min( minmn, il ) .OR. iu.GT.minmn )
THEN
374 IF( wantu .AND. ldu.LT.m )
THEN
376 ELSE IF( wantvt )
THEN
378 IF( ldvt.LT.iu-il+1 )
THEN
381 ELSE IF( ldvt.LT.minmn )
THEN
398 IF( minmn.GT.0 )
THEN
400 mnthr = ilaenv( 6,
'ZGESVD', jobu // jobvt, m, n, 0, 0 )
401 IF( m.GE.mnthr )
THEN
406 maxwrk = n + n*ilaenv(1,
'ZGEQRF',
' ',m,n,-1,-1)
408 $ n*n+2*n+2*n*ilaenv(1,
'ZGEBRD',
' ',n,n,-1,-1))
409 IF (wantu .OR. wantvt)
THEN
411 $ n*n+2*n+n*ilaenv(1,
'ZUNMQR',
'LN',n,n,n,-1))
418 maxwrk = 2*n + (m+n)*ilaenv(1,
'ZGEBRD',
' ',m,n,-1,-1)
419 IF (wantu .OR. wantvt)
THEN
421 $ 2*n+n*ilaenv(1,
'ZUNMQR',
'LN',n,n,n,-1))
425 mnthr = ilaenv( 6,
'ZGESVD', jobu // jobvt, m, n, 0, 0 )
426 IF( n.GE.mnthr )
THEN
431 maxwrk = m + m*ilaenv(1,
'ZGELQF',
' ',m,n,-1,-1)
433 $ m*m+2*m+2*m*ilaenv(1,
'ZGEBRD',
' ',m,m,-1,-1))
434 IF (wantu .OR. wantvt)
THEN
436 $ m*m+2*m+m*ilaenv(1,
'ZUNMQR',
'LN',m,m,m,-1))
444 maxwrk = 2*m + (m+n)*ilaenv(1,
'ZGEBRD',
' ',m,n,-1,-1)
445 IF (wantu .OR. wantvt)
THEN
447 $ 2*m+m*ilaenv(1,
'ZUNMQR',
'LN',m,m,m,-1))
452 maxwrk = max( maxwrk, minwrk )
453 work( 1 ) = dcmplx( dble( maxwrk ), zero )
455 IF( lwork.LT.minwrk .AND. .NOT.lquery )
THEN
461 CALL xerbla(
'ZGESVDX', -info )
463 ELSE IF( lquery )
THEN
469 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
492 smlnum = sqrt( dlamch(
'S' ) ) / eps
493 bignum = one / smlnum
497 anrm = zlange(
'M', m, n, a, lda, dum )
499 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
501 CALL zlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
502 ELSE IF( anrm.GT.bignum )
THEN
504 CALL zlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
513 IF( m.GE.mnthr )
THEN
525 CALL zgeqrf( m, n, a, lda, work( itau ), work( itemp ),
526 $ lwork-itemp+1, info )
538 CALL zlacpy(
'U', n, n, a, lda, work( iqrf ), n )
539 CALL zlaset(
'L', n-1, n-1, czero, czero,
540 $ work( iqrf+1 ), n )
541 CALL zgebrd( n, n, work( iqrf ), n, rwork( id ),
542 $ rwork( ie ), work( itauq ), work( itaup ),
543 $ work( itemp ), lwork-itemp+1, info )
544 itempr = itgkz + n*(n*2+1)
549 CALL dbdsvdx(
'U', jobz, rngtgk, n, rwork( id ),
550 $ rwork( ie ), vl, vu, iltgk, iutgk, ns, s,
551 $ rwork( itgkz ), n*2, rwork( itempr ),
560 u( j, i ) = dcmplx( rwork( k ), zero )
565 CALL zlaset(
'A', m-n, ns, czero, czero, u( n+1,1 ), ldu)
570 CALL zunmbr(
'Q',
'L',
'N', n, ns, n, work( iqrf ), n,
571 $ work( itauq ), u, ldu, work( itemp ),
572 $ lwork-itemp+1, info )
577 CALL zunmqr(
'L',
'N', m, ns, n, a, lda,
578 $ work( itau ), u, ldu, work( itemp ),
579 $ lwork-itemp+1, info )
588 vt( i, j ) = dcmplx( rwork( k ), zero )
597 CALL zunmbr(
'P',
'R',
'C', ns, n, n, work( iqrf ), n,
598 $ work( itaup ), vt, ldvt, work( itemp ),
599 $ lwork-itemp+1, info )
617 CALL zgebrd( m, n, a, lda, rwork( id ), rwork( ie ),
618 $ work( itauq ), work( itaup ), work( itemp ),
619 $ lwork-itemp+1, info )
620 itempr = itgkz + n*(n*2+1)
625 CALL dbdsvdx(
'U', jobz, rngtgk, n, rwork( id ),
626 $ rwork( ie ), vl, vu, iltgk, iutgk, ns, s,
627 $ rwork( itgkz ), n*2, rwork( itempr ),
636 u( j, i ) = dcmplx( rwork( k ), zero )
641 CALL zlaset(
'A', m-n, ns, czero, czero, u( n+1,1 ), ldu)
646 CALL zunmbr(
'Q',
'L',
'N', m, ns, n, a, lda,
647 $ work( itauq ), u, ldu, work( itemp ),
648 $ lwork-itemp+1, ierr )
657 vt( i, j ) = dcmplx( rwork( k ), zero )
666 CALL zunmbr(
'P',
'R',
'C', ns, n, n, a, lda,
667 $ work( itaup ), vt, ldvt, work( itemp ),
668 $ lwork-itemp+1, ierr )
676 IF( n.GE.mnthr )
THEN
688 CALL zgelqf( m, n, a, lda, work( itau ), work( itemp ),
689 $ lwork-itemp+1, info )
701 CALL zlacpy(
'L', m, m, a, lda, work( ilqf ), m )
702 CALL zlaset(
'U', m-1, m-1, czero, czero,
703 $ work( ilqf+m ), m )
704 CALL zgebrd( m, m, work( ilqf ), m, rwork( id ),
705 $ rwork( ie ), work( itauq ), work( itaup ),
706 $ work( itemp ), lwork-itemp+1, info )
707 itempr = itgkz + m*(m*2+1)
712 CALL dbdsvdx(
'U', jobz, rngtgk, m, rwork( id ),
713 $ rwork( ie ), vl, vu, iltgk, iutgk, ns, s,
714 $ rwork( itgkz ), m*2, rwork( itempr ),
723 u( j, i ) = dcmplx( rwork( k ), zero )
732 CALL zunmbr(
'Q',
'L',
'N', m, ns, m, work( ilqf ), m,
733 $ work( itauq ), u, ldu, work( itemp ),
734 $ lwork-itemp+1, info )
743 vt( i, j ) = dcmplx( rwork( k ), zero )
748 CALL zlaset(
'A', ns, n-m, czero, czero,
749 $ vt( 1,m+1 ), ldvt )
754 CALL zunmbr(
'P',
'R',
'C', ns, m, m, work( ilqf ), m,
755 $ work( itaup ), vt, ldvt, work( itemp ),
756 $ lwork-itemp+1, info )
761 CALL zunmlq(
'R',
'N', ns, n, m, a, lda,
762 $ work( itau ), vt, ldvt, work( itemp ),
763 $ lwork-itemp+1, info )
781 CALL zgebrd( m, n, a, lda, rwork( id ), rwork( ie ),
782 $ work( itauq ), work( itaup ), work( itemp ),
783 $ lwork-itemp+1, info )
784 itempr = itgkz + m*(m*2+1)
789 CALL dbdsvdx(
'L', jobz, rngtgk, m, rwork( id ),
790 $ rwork( ie ), vl, vu, iltgk, iutgk, ns, s,
791 $ rwork( itgkz ), m*2, rwork( itempr ),
800 u( j, i ) = dcmplx( rwork( k ), zero )
809 CALL zunmbr(
'Q',
'L',
'N', m, ns, n, a, lda,
810 $ work( itauq ), u, ldu, work( itemp ),
811 $ lwork-itemp+1, info )
820 vt( i, j ) = dcmplx( rwork( k ), zero )
825 CALL zlaset(
'A', ns, n-m, czero, czero,
826 $ vt( 1,m+1 ), ldvt )
831 CALL zunmbr(
'P',
'R',
'C', ns, n, m, a, lda,
832 $ work( itaup ), vt, ldvt, work( itemp ),
833 $ lwork-itemp+1, info )
842 $
CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1,
845 $
CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1,
851 work( 1 ) = dcmplx( dble( maxwrk ), zero )
subroutine zlacpy(UPLO, M, N, A, LDA, B, LDB)
ZLACPY copies all or part of one two-dimensional array to another.
subroutine zgeqrf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
ZGEQRF VARIANT: left-looking Level 3 BLAS of the algorithm.
subroutine zunmbr(VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
ZUNMBR
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 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 xerbla(SRNAME, INFO)
XERBLA
subroutine zgesvdx(JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU, IL, IU, NS, S, U, LDU, VT, LDVT, WORK, LWORK, RWORK, IWORK, INFO)
ZGESVDX computes the singular value decomposition (SVD) for GE matrices
subroutine zgebrd(M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, INFO)
ZGEBRD
subroutine zunmqr(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
ZUNMQR
subroutine zunmlq(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
ZUNMLQ
subroutine dbdsvdx(UPLO, JOBZ, RANGE, N, D, E, VL, VU, IL, IU, NS, S, Z, LDZ, WORK, IWORK, INFO)
DBDSVDX
subroutine zgelqf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
ZGELQF
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.