Annotation of rpl/lapack/lapack/zgesvdx.f, revision 1.1

1.1     ! bertrand    1: *> \brief <b> ZGESVDX computes the singular value decomposition (SVD) for GE matrices</b>
        !             2: *
        !             3: *  =========== DOCUMENTATION ===========
        !             4: *
        !             5: * Online html documentation available at 
        !             6: *            http://www.netlib.org/lapack/explore-html/ 
        !             7: *
        !             8: *> \htmlonly
        !             9: *> Download ZGESVDX + dependencies 
        !            10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zgesvdx.f"> 
        !            11: *> [TGZ]</a> 
        !            12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zgesvdx.f"> 
        !            13: *> [ZIP]</a> 
        !            14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgesvdx.f"> 
        !            15: *> [TXT]</a>
        !            16: *> \endhtmlonly 
        !            17: *
        !            18: *  Definition:
        !            19: *  ===========
        !            20: *
        !            21: *     SUBROUTINE CGESVDX( JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU, 
        !            22: *    $                    IL, IU, NS, S, U, LDU, VT, LDVT, WORK, 
        !            23: *    $                    LWORK, RWORK, IWORK, INFO )
        !            24: *      
        !            25: *
        !            26: *     .. Scalar Arguments ..
        !            27: *      CHARACTER          JOBU, JOBVT, RANGE
        !            28: *      INTEGER            IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
        !            29: *      DOUBLE PRECISION   VL, VU
        !            30: *     ..
        !            31: *     .. Array Arguments ..
        !            32: *      INTEGER            IWORK( * )
        !            33: *      DOUBLE PRECISION   S( * ), RWORK( * )
        !            34: *      COMPLEX*16         A( LDA, * ), U( LDU, * ), VT( LDVT, * ), 
        !            35: *     $                   WORK( * )
        !            36: *     ..
        !            37: *
        !            38: *
        !            39: *  Purpose
        !            40: *  =======
        !            41: *
        !            42: *  ZGESVDX computes the singular value decomposition (SVD) of a complex
        !            43: *  M-by-N matrix A, optionally computing the left and/or right singular
        !            44: *  vectors. The SVD is written
        !            45: * 
        !            46: *       A = U * SIGMA * transpose(V)
        !            47: * 
        !            48: *  where SIGMA is an M-by-N matrix which is zero except for its
        !            49: *  min(m,n) diagonal elements, U is an M-by-M unitary matrix, and
        !            50: *  V is an N-by-N unitary matrix.  The diagonal elements of SIGMA
        !            51: *  are the singular values of A; they are real and non-negative, and
        !            52: *  are returned in descending order.  The first min(m,n) columns of
        !            53: *  U and V are the left and right singular vectors of A.
        !            54: * 
        !            55: *  ZGESVDX uses an eigenvalue problem for obtaining the SVD, which 
        !            56: *  allows for the computation of a subset of singular values and 
        !            57: *  vectors. See DBDSVDX for details.
        !            58: * 
        !            59: *  Note that the routine returns V**T, not V.
        !            60: *   
        !            61: *  Arguments:
        !            62: *  ==========
        !            63: *
        !            64: *> \param[in] JOBU
        !            65: *> \verbatim
        !            66: *>          JOBU is CHARACTER*1
        !            67: *>          Specifies options for computing all or part of the matrix U:
        !            68: *>          = 'V':  the first min(m,n) columns of U (the left singular
        !            69: *>                  vectors) or as specified by RANGE are returned in 
        !            70: *>                  the array U;
        !            71: *>          = 'N':  no columns of U (no left singular vectors) are
        !            72: *>                  computed.
        !            73: *> \endverbatim
        !            74: *>
        !            75: *> \param[in] JOBVT
        !            76: *> \verbatim
        !            77: *>          JOBVT is CHARACTER*1
        !            78: *>           Specifies options for computing all or part of the matrix
        !            79: *>           V**T:
        !            80: *>           = 'V':  the first min(m,n) rows of V**T (the right singular
        !            81: *>                   vectors) or as specified by RANGE are returned in 
        !            82: *>                   the array VT;
        !            83: *>           = 'N':  no rows of V**T (no right singular vectors) are
        !            84: *>                   computed.
        !            85: *> \endverbatim
        !            86: *>
        !            87: *> \param[in] RANGE
        !            88: *> \verbatim
        !            89: *>          RANGE is CHARACTER*1
        !            90: *>          = 'A': all singular values will be found.
        !            91: *>          = 'V': all singular values in the half-open interval (VL,VU]
        !            92: *>                 will be found.
        !            93: *>          = 'I': the IL-th through IU-th singular values will be found. 
        !            94: *> \endverbatim
        !            95: *>
        !            96: *> \param[in] M
        !            97: *> \verbatim
        !            98: *>          M is INTEGER
        !            99: *>          The number of rows of the input matrix A.  M >= 0.
        !           100: *> \endverbatim
        !           101: *>
        !           102: *> \param[in] N
        !           103: *> \verbatim
        !           104: *>          N is INTEGER
        !           105: *>          The number of columns of the input matrix A.  N >= 0.
        !           106: *> \endverbatim
        !           107: *>
        !           108: *> \param[in,out] A
        !           109: *> \verbatim
        !           110: *>          A is COMPLEX array, dimension (LDA,N)
        !           111: *>          On entry, the M-by-N matrix A.
        !           112: *>          On exit, the contents of A are destroyed.
        !           113: *> \endverbatim
        !           114: *>
        !           115: *> \param[in] LDA
        !           116: *> \verbatim
        !           117: *>          LDA is INTEGER
        !           118: *>          The leading dimension of the array A.  LDA >= max(1,M).
        !           119: *> \endverbatim
        !           120: *>
        !           121: *> \param[in] VL
        !           122: *> \verbatim
        !           123: *>          VL is DOUBLE PRECISION
        !           124: *>          VL >=0.
        !           125: *> \endverbatim
        !           126: *>
        !           127: *> \param[in] VU
        !           128: *> \verbatim
        !           129: *>          VU is DOUBLE PRECISION
        !           130: *>          If RANGE='V', the lower and upper bounds of the interval to
        !           131: *>          be searched for singular values. VU > VL.
        !           132: *>          Not referenced if RANGE = 'A' or 'I'.
        !           133: *> \endverbatim
        !           134: *>
        !           135: *> \param[in] IL
        !           136: *> \verbatim
        !           137: *>          IL is INTEGER
        !           138: *> \endverbatim
        !           139: *>
        !           140: *> \param[in] IU
        !           141: *> \verbatim
        !           142: *>          IU is INTEGER
        !           143: *>          If RANGE='I', the indices (in ascending order) of the
        !           144: *>          smallest and largest singular values to be returned.
        !           145: *>          1 <= IL <= IU <= min(M,N), if min(M,N) > 0.
        !           146: *>          Not referenced if RANGE = 'A' or 'V'.
        !           147: *> \endverbatim
        !           148: *>
        !           149: *> \param[out] NS
        !           150: *> \verbatim
        !           151: *>          NS is INTEGER
        !           152: *>          The total number of singular values found,  
        !           153: *>          0 <= NS <= min(M,N).
        !           154: *>          If RANGE = 'A', NS = min(M,N); if RANGE = 'I', NS = IU-IL+1.
        !           155: *> \endverbatim
        !           156: *>
        !           157: *> \param[out] S
        !           158: *> \verbatim
        !           159: *>          S is DOUBLE PRECISION array, dimension (min(M,N))
        !           160: *>          The singular values of A, sorted so that S(i) >= S(i+1).
        !           161: *> \endverbatim
        !           162: *>
        !           163: *> \param[out] U
        !           164: *> \verbatim
        !           165: *>          U is COMPLEX*16 array, dimension (LDU,UCOL)
        !           166: *>          If JOBU = 'V', U contains columns of U (the left singular 
        !           167: *>          vectors, stored columnwise) as specified by RANGE; if 
        !           168: *>          JOBU = 'N', U is not referenced.
        !           169: *>          Note: The user must ensure that UCOL >= NS; if RANGE = 'V', 
        !           170: *>          the exact value of NS is not known ILQFin advance and an upper 
        !           171: *>          bound must be used.
        !           172: *> \endverbatim
        !           173: *>
        !           174: *> \param[in] LDU
        !           175: *> \verbatim
        !           176: *>          LDU is INTEGER
        !           177: *>          The leading dimension of the array U.  LDU >= 1; if
        !           178: *>          JOBU = 'V', LDU >= M.
        !           179: *> \endverbatim
        !           180: *>
        !           181: *> \param[out] VT
        !           182: *> \verbatim
        !           183: *>          VT is COMPLEX*16 array, dimension (LDVT,N)
        !           184: *>          If JOBVT = 'V', VT contains the rows of V**T (the right singular 
        !           185: *>          vectors, stored rowwise) as specified by RANGE; if JOBVT = 'N', 
        !           186: *>          VT is not referenced.
        !           187: *>          Note: The user must ensure that LDVT >= NS; if RANGE = 'V', 
        !           188: *>          the exact value of NS is not known in advance and an upper 
        !           189: *>          bound must be used.
        !           190: *> \endverbatim
        !           191: *>
        !           192: *> \param[in] LDVT
        !           193: *> \verbatim
        !           194: *>          LDVT is INTEGER
        !           195: *>          The leading dimension of the array VT.  LDVT >= 1; if
        !           196: *>          JOBVT = 'V', LDVT >= NS (see above).
        !           197: *> \endverbatim
        !           198: *>
        !           199: *> \param[out] WORK
        !           200: *> \verbatim
        !           201: *>          WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
        !           202: *>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
        !           203: *> \endverbatim
        !           204: *>
        !           205: *> \param[in] LWORK
        !           206: *> \verbatim
        !           207: *>          LWORK is INTEGER
        !           208: *>          The dimension of the array WORK.
        !           209: *>          LWORK >= MAX(1,MIN(M,N)*(MIN(M,N)+4)) for the paths (see 
        !           210: *>          comments inside the code):
        !           211: *>             - PATH 1  (M much larger than N) 
        !           212: *>             - PATH 1t (N much larger than M)
        !           213: *>          LWORK >= MAX(1,MIN(M,N)*2+MAX(M,N)) for the other paths.
        !           214: *>          For good performance, LWORK should generally be larger.
        !           215: *>
        !           216: *>          If LWORK = -1, then a workspace query is assumed; the routine
        !           217: *>          only calculates the optimal size of the WORK array, returns
        !           218: *>          this value as the first entry of the WORK array, and no error
        !           219: *>          message related to LWORK is issued by XERBLA.
        !           220: *> \endverbatim
        !           221: *>
        !           222: *> \param[out] RWORK
        !           223: *> \verbatim
        !           224: *>          RWORK is DOUBLE PRECISION array, dimension (MAX(1,LRWORK))
        !           225: *>          LRWORK >= MIN(M,N)*(MIN(M,N)*2+15*MIN(M,N)).
        !           226: *> \endverbatim
        !           227: *>
        !           228: *> \param[out] IWORK
        !           229: *> \verbatim
        !           230: *>          IWORK is INTEGER array, dimension (12*MIN(M,N))
        !           231: *>          If INFO = 0, the first NS elements of IWORK are zero. If INFO > 0, 
        !           232: *>          then IWORK contains the indices of the eigenvectors that failed 
        !           233: *>          to converge in DBDSVDX/DSTEVX.
        !           234: *> \endverbatim
        !           235: *>
        !           236: *> \param[out] INFO
        !           237: *> \verbatim
        !           238: *>     INFO is INTEGER
        !           239: *>           = 0:  successful exit
        !           240: *>           < 0:  if INFO = -i, the i-th argument had an illegal value
        !           241: *>           > 0:  if INFO = i, then i eigenvectors failed to converge
        !           242: *>                 in DBDSVDX/DSTEVX.
        !           243: *>                 if INFO = N*2 + 1, an internal error occurred in
        !           244: *>                 DBDSVDX
        !           245: *> \endverbatim
        !           246: *
        !           247: *  Authors:
        !           248: *  ========
        !           249: *
        !           250: *> \author Univ. of Tennessee 
        !           251: *> \author Univ. of California Berkeley 
        !           252: *> \author Univ. of Colorado Denver 
        !           253: *> \author NAG Ltd. 
        !           254: *
        !           255: *> \date November 2015
        !           256: *
        !           257: *> \ingroup complex16GEsing
        !           258: *
        !           259: *  =====================================================================
        !           260:       SUBROUTINE ZGESVDX( JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU, 
        !           261:      $                    IL, IU, NS, S, U, LDU, VT, LDVT, WORK, 
        !           262:      $                    LWORK, RWORK, IWORK, INFO )
        !           263: *
        !           264: *  -- LAPACK driver routine (version 3.6.0) --
        !           265: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
        !           266: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
        !           267: *     November 2015
        !           268: *
        !           269: *     .. Scalar Arguments ..
        !           270:       CHARACTER          JOBU, JOBVT, RANGE
        !           271:       INTEGER            IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
        !           272:       DOUBLE PRECISION   VL, VU
        !           273: *     ..
        !           274: *     .. Array Arguments ..
        !           275:       INTEGER            IWORK( * )
        !           276:       DOUBLE PRECISION   S( * ), RWORK( * )
        !           277:       COMPLEX*16         A( LDA, * ), U( LDU, * ), VT( LDVT, * ), 
        !           278:      $                   WORK( * )
        !           279: *     ..
        !           280: *
        !           281: *  =====================================================================
        !           282: *
        !           283: *     .. Parameters ..
        !           284:       COMPLEX*16         CZERO, CONE
        !           285:       PARAMETER          ( CZERO = ( 0.0D0, 0.0D0 ),
        !           286:      $                   CONE = ( 1.0D0, 0.0D0 ) )
        !           287:       DOUBLE PRECISION   ZERO, ONE
        !           288:       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
        !           289: *     ..
        !           290: *     .. Local Scalars ..
        !           291:       CHARACTER          JOBZ, RNGTGK
        !           292:       LOGICAL            ALLS, INDS, LQUERY, VALS, WANTU, WANTVT
        !           293:       INTEGER            I, ID, IE, IERR, ILQF, ILTGK, IQRF, ISCL,
        !           294:      $                   ITAU, ITAUP, ITAUQ, ITEMP, ITGKZ, IUTGK,
        !           295:      $                   J, K, MAXWRK, MINMN, MINWRK, MNTHR
        !           296:       DOUBLE PRECISION   ABSTOL, ANRM, BIGNUM, EPS, SMLNUM
        !           297: *     ..
        !           298: *     .. Local Arrays ..
        !           299:       DOUBLE PRECISION   DUM( 1 )
        !           300: *     ..
        !           301: *     .. External Subroutines ..
        !           302:       EXTERNAL           ZGEBRD, ZGELQF, ZGEQRF, ZLASCL, ZLASET,
        !           303:      $                   DLASCL, XERBLA
        !           304: *     ..
        !           305: *     .. External Functions ..
        !           306:       LOGICAL            LSAME
        !           307:       INTEGER            ILAENV
        !           308:       DOUBLE PRECISION   DLAMCH, ZLANGE
        !           309:       EXTERNAL           LSAME, ILAENV, DLAMCH, ZLANGE
        !           310: *     ..
        !           311: *     .. Intrinsic Functions ..
        !           312:       INTRINSIC          MAX, MIN, SQRT
        !           313: *     ..
        !           314: *     .. Executable Statements ..
        !           315: *
        !           316: *     Test the input arguments.
        !           317: *
        !           318:       NS = 0
        !           319:       INFO = 0
        !           320:       ABSTOL = 2*DLAMCH('S')
        !           321:       LQUERY = ( LWORK.EQ.-1 )
        !           322:       MINMN = MIN( M, N )
        !           323: 
        !           324:       WANTU = LSAME( JOBU, 'V' )
        !           325:       WANTVT = LSAME( JOBVT, 'V' )
        !           326:       IF( WANTU .OR. WANTVT ) THEN
        !           327:          JOBZ = 'V'
        !           328:       ELSE
        !           329:          JOBZ = 'N'
        !           330:       END IF
        !           331:       ALLS = LSAME( RANGE, 'A' )
        !           332:       VALS = LSAME( RANGE, 'V' )
        !           333:       INDS = LSAME( RANGE, 'I' )
        !           334: *
        !           335:       INFO = 0
        !           336:       IF( .NOT.LSAME( JOBU, 'V' ) .AND.
        !           337:      $    .NOT.LSAME( JOBU, 'N' ) ) THEN
        !           338:          INFO = -1
        !           339:       ELSE IF( .NOT.LSAME( JOBVT, 'V' ) .AND.
        !           340:      $         .NOT.LSAME( JOBVT, 'N' ) ) THEN
        !           341:          INFO = -2
        !           342:       ELSE IF( .NOT.( ALLS .OR. VALS .OR. INDS ) ) THEN
        !           343:          INFO = -3
        !           344:       ELSE IF( M.LT.0 ) THEN
        !           345:          INFO = -4
        !           346:       ELSE IF( N.LT.0 ) THEN
        !           347:          INFO = -5
        !           348:       ELSE IF( M.GT.LDA ) THEN
        !           349:          INFO = -7
        !           350:       ELSE IF( MINMN.GT.0 ) THEN
        !           351:          IF( VALS ) THEN
        !           352:             IF( VL.LT.ZERO ) THEN
        !           353:                INFO = -8
        !           354:             ELSE IF( VU.LE.VL ) THEN
        !           355:                INFO = -9
        !           356:             END IF
        !           357:          ELSE IF( INDS ) THEN
        !           358:             IF( IL.LT.1 .OR. IL.GT.MAX( 1, MINMN ) ) THEN
        !           359:                INFO = -10
        !           360:             ELSE IF( IU.LT.MIN( MINMN, IL ) .OR. IU.GT.MINMN ) THEN
        !           361:                INFO = -11
        !           362:             END IF
        !           363:          END IF
        !           364:          IF( INFO.EQ.0 ) THEN
        !           365:             IF( WANTU .AND. LDU.LT.M ) THEN
        !           366:                INFO = -15
        !           367:             ELSE IF( WANTVT .AND. LDVT.LT.MINMN ) THEN
        !           368:                INFO = -16
        !           369:             END IF
        !           370:          END IF
        !           371:       END IF
        !           372: *
        !           373: *     Compute workspace
        !           374: *     (Note: Comments in the code beginning "Workspace:" describe the
        !           375: *     minimal amount of workspace needed at that point in the code,
        !           376: *     as well as the preferred amount for good performance.
        !           377: *     NB refers to the optimal block size for the immediately
        !           378: *     following subroutine, as returned by ILAENV.)
        !           379: *
        !           380:       IF( INFO.EQ.0 ) THEN
        !           381:          MINWRK = 1
        !           382:          MAXWRK = 1
        !           383:          IF( MINMN.GT.0 ) THEN
        !           384:             IF( M.GE.N ) THEN
        !           385:                MNTHR = ILAENV( 6, 'ZGESVD', JOBU // JOBVT, M, N, 0, 0 )
        !           386:                IF( M.GE.MNTHR ) THEN
        !           387: *
        !           388: *                 Path 1 (M much larger than N)
        !           389: *
        !           390:                   MAXWRK = N + N*
        !           391:      $                     ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
        !           392:                   MAXWRK = MAX( MAXWRK, N*N + N + 2*N*
        !           393:      $                     ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
        !           394:                   MINWRK = N*(N+4)
        !           395:                ELSE
        !           396: *
        !           397: *                 Path 2 (M at least N, but not much larger)
        !           398: *
        !           399:                   MAXWRK = 2*N + ( M+N )*
        !           400:      $                     ILAENV( 1, 'ZGEBRD', ' ', M, N, -1, -1 )
        !           401:                   MINWRK = 2*N + M
        !           402:                END IF
        !           403:             ELSE
        !           404:                MNTHR = ILAENV( 6, 'ZGESVD', JOBU // JOBVT, M, N, 0, 0 )
        !           405:                IF( N.GE.MNTHR ) THEN
        !           406: *
        !           407: *                 Path 1t (N much larger than M)
        !           408: *
        !           409:                   MAXWRK = M + M*
        !           410:      $                     ILAENV( 1, 'ZGELQF', ' ', M, N, -1, -1 )
        !           411:                   MAXWRK = MAX( MAXWRK, M*M + M + 2*M*
        !           412:      $                     ILAENV( 1, 'ZGEBRD', ' ', M, M, -1, -1 ) )
        !           413:                   MINWRK = M*(M+4)
        !           414:                ELSE
        !           415: *
        !           416: *                 Path 2t (N greater than M, but not much larger)
        !           417: *
        !           418:                   MAXWRK = M*(M*2+19) + ( M+N )*
        !           419:      $                     ILAENV( 1, 'ZGEBRD', ' ', M, N, -1, -1 )
        !           420:                   MINWRK = 2*M + N
        !           421:                END IF
        !           422:             END IF
        !           423:          END IF
        !           424:          MAXWRK = MAX( MAXWRK, MINWRK )
        !           425:          WORK( 1 ) = DCMPLX( DBLE( MAXWRK ), ZERO )
        !           426: *
        !           427:          IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
        !           428:             INFO = -19
        !           429:          END IF
        !           430:       END IF
        !           431: *
        !           432:       IF( INFO.NE.0 ) THEN
        !           433:          CALL XERBLA( 'ZGESVDX', -INFO )
        !           434:          RETURN
        !           435:       ELSE IF( LQUERY ) THEN
        !           436:          RETURN
        !           437:       END IF
        !           438: *
        !           439: *     Quick return if possible
        !           440: *
        !           441:       IF( M.EQ.0 .OR. N.EQ.0 ) THEN
        !           442:          RETURN
        !           443:       END IF
        !           444: *
        !           445: *     Set singular values indices accord to RANGE='A'.
        !           446: *
        !           447:       ALLS = LSAME( RANGE, 'A' )
        !           448:       INDS = LSAME( RANGE, 'I' )
        !           449:       IF( ALLS ) THEN
        !           450:          RNGTGK = 'I'
        !           451:          ILTGK = 1
        !           452:          IUTGK = MIN( M, N )
        !           453:       ELSE IF( INDS ) THEN
        !           454:          RNGTGK = 'I'
        !           455:          ILTGK = IL
        !           456:          IUTGK = IU
        !           457:       ELSE      
        !           458:          RNGTGK = 'V'
        !           459:          ILTGK = 0
        !           460:          IUTGK = 0
        !           461:       END IF
        !           462: *
        !           463: *     Get machine constants
        !           464: *
        !           465:       EPS = DLAMCH( 'P' )
        !           466:       SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPS
        !           467:       BIGNUM = ONE / SMLNUM
        !           468: *
        !           469: *     Scale A if max element outside range [SMLNUM,BIGNUM]
        !           470: *
        !           471:       ANRM = ZLANGE( 'M', M, N, A, LDA, DUM )
        !           472:       ISCL = 0
        !           473:       IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
        !           474:          ISCL = 1
        !           475:          CALL ZLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
        !           476:       ELSE IF( ANRM.GT.BIGNUM ) THEN
        !           477:          ISCL = 1
        !           478:          CALL ZLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
        !           479:       END IF
        !           480: *
        !           481:       IF( M.GE.N ) THEN
        !           482: *
        !           483: *        A has at least as many rows as columns. If A has sufficiently
        !           484: *        more rows than columns, first reduce A using the QR
        !           485: *        decomposition.
        !           486: *
        !           487:          IF( M.GE.MNTHR ) THEN
        !           488: *
        !           489: *           Path 1 (M much larger than N):
        !           490: *           A = Q * R = Q * ( QB * B * PB**T )
        !           491: *                     = Q * ( QB * ( UB * S * VB**T ) * PB**T )
        !           492: *           U = Q * QB * UB; V**T = VB**T * PB**T
        !           493: *
        !           494: *           Compute A=Q*R
        !           495: *           (Workspace: need 2*N, prefer N+N*NB)
        !           496: *
        !           497:             ITAU = 1
        !           498:             ITEMP = ITAU + N
        !           499:             CALL ZGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( ITEMP ),
        !           500:      $                   LWORK-ITEMP+1, INFO )
        !           501: *  
        !           502: *           Copy R into WORK and bidiagonalize it:
        !           503: *           (Workspace: need N*N+3*N, prefer N*N+N+2*N*NB)
        !           504: *   
        !           505:             IQRF = ITEMP
        !           506:             ITAUQ = ITEMP + N*N
        !           507:             ITAUP = ITAUQ + N
        !           508:             ITEMP = ITAUP + N
        !           509:             ID = 1   
        !           510:             IE = ID + N
        !           511:             ITGKZ = IE + N
        !           512:             CALL ZLACPY( 'U', N, N, A, LDA, WORK( IQRF ), N )
        !           513:             CALL ZLASET( 'L', N-1, N-1, CZERO, CZERO,
        !           514:      $                   WORK( IQRF+1 ), N )
        !           515:             CALL ZGEBRD( N, N, WORK( IQRF ), N, RWORK( ID ), 
        !           516:      $                   RWORK( IE ), WORK( ITAUQ ), WORK( ITAUP ),
        !           517:      $                   WORK( ITEMP ), LWORK-ITEMP+1, INFO )
        !           518:             ITEMP = ITGKZ + N*(N*2+1)
        !           519: *
        !           520: *           Solve eigenvalue problem TGK*Z=Z*S.
        !           521: *           (Workspace: need 2*N*N+14*N)          
        !           522: *                   
        !           523:             CALL DBDSVDX( 'U', JOBZ, RNGTGK, N, RWORK( ID ),
        !           524:      $                    RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S,
        !           525:      $                    RWORK( ITGKZ ), N*2, RWORK( ITEMP ),
        !           526:      $                    IWORK, INFO)
        !           527: *
        !           528: *           If needed, compute left singular vectors.
        !           529: *
        !           530:             IF( WANTU ) THEN
        !           531:                K = ITGKZ
        !           532:                DO I = 1, NS
        !           533:                   DO J = 1, N
        !           534:                      U( J, I ) = DCMPLX( RWORK( K ), ZERO )
        !           535:                      K = K + 1
        !           536:                   END DO
        !           537:                   K = K + N
        !           538:                END DO
        !           539:                CALL ZLASET( 'A', M-N, N, CZERO, CZERO, U( N+1,1 ), LDU )
        !           540: *
        !           541: *              Call ZUNMBR to compute QB*UB.
        !           542: *              (Workspace in WORK( ITEMP ): need N, prefer N*NB)
        !           543: *
        !           544:                CALL ZUNMBR( 'Q', 'L', 'N', N, NS, N, WORK( IQRF ), N, 
        !           545:      $                      WORK( ITAUQ ), U, LDU, WORK( ITEMP ), 
        !           546:      $                      LWORK-ITEMP+1, INFO )
        !           547: *
        !           548: *              Call ZUNMQR to compute Q*(QB*UB).
        !           549: *              (Workspace in WORK( ITEMP ): need N, prefer N*NB)
        !           550: *
        !           551:                CALL ZUNMQR( 'L', 'N', M, NS, N, A, LDA, 
        !           552:      $                      WORK( ITAU ), U, LDU, WORK( ITEMP ),
        !           553:      $                      LWORK-ITEMP+1, INFO )
        !           554:             END IF  
        !           555: *      
        !           556: *           If needed, compute right singular vectors.
        !           557: *
        !           558:             IF( WANTVT) THEN
        !           559:                K = ITGKZ + N
        !           560:                DO I = 1, NS
        !           561:                   DO J = 1, N
        !           562:                      VT( I, J ) = DCMPLX( RWORK( K ), ZERO )
        !           563:                      K = K + 1
        !           564:                   END DO
        !           565:                   K = K + N
        !           566:                END DO
        !           567: *
        !           568: *              Call ZUNMBR to compute VB**T * PB**T
        !           569: *              (Workspace in WORK( ITEMP ): need N, prefer N*NB)
        !           570: *
        !           571:                CALL ZUNMBR( 'P', 'R', 'C', NS, N, N, WORK( IQRF ), N, 
        !           572:      $                      WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
        !           573:      $                      LWORK-ITEMP+1, INFO )
        !           574:             END IF
        !           575:          ELSE
        !           576: *
        !           577: *           Path 2 (M at least N, but not much larger)
        !           578: *           Reduce A to bidiagonal form without QR decomposition
        !           579: *           A = QB * B * PB**T = QB * ( UB * S * VB**T ) * PB**T
        !           580: *           U = QB * UB; V**T = VB**T * PB**T
        !           581: *
        !           582: *           Bidiagonalize A
        !           583: *           (Workspace: need 2*N+M, prefer 2*N+(M+N)*NB)
        !           584: *
        !           585:             ITAUQ = 1
        !           586:             ITAUP = ITAUQ + N
        !           587:             ITEMP = ITAUP + N          
        !           588:             ID = 1
        !           589:             IE = ID + N
        !           590:             ITGKZ = IE + N
        !           591:             CALL ZGEBRD( M, N, A, LDA, RWORK( ID ), RWORK( IE ), 
        !           592:      $                   WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
        !           593:      $                   LWORK-ITEMP+1, INFO )
        !           594:             ITEMP = ITGKZ + N*(N*2+1)
        !           595: *
        !           596: *           Solve eigenvalue problem TGK*Z=Z*S.
        !           597: *           (Workspace: need 2*N*N+14*N)          
        !           598: *                     
        !           599:             CALL DBDSVDX( 'U', JOBZ, RNGTGK, N, RWORK( ID ),
        !           600:      $                    RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S, 
        !           601:      $                    RWORK( ITGKZ ), N*2, RWORK( ITEMP ), 
        !           602:      $                    IWORK, INFO)
        !           603: *
        !           604: *           If needed, compute left singular vectors.
        !           605: *
        !           606:             IF( WANTU ) THEN
        !           607:                K = ITGKZ
        !           608:                DO I = 1, NS
        !           609:                   DO J = 1, N              
        !           610:                      U( J, I ) = DCMPLX( RWORK( K ), ZERO )
        !           611:                      K = K + 1
        !           612:                   END DO
        !           613:                   K = K + N
        !           614:                END DO
        !           615:                CALL ZLASET( 'A', M-N, N, CZERO, CZERO, U( N+1,1 ), LDU )
        !           616: *
        !           617: *              Call ZUNMBR to compute QB*UB.
        !           618: *              (Workspace in WORK( ITEMP ): need N, prefer N*NB)
        !           619: *   
        !           620:                CALL ZUNMBR( 'Q', 'L', 'N', M, NS, N, A, LDA, 
        !           621:      $                      WORK( ITAUQ ), U, LDU, WORK( ITEMP ), 
        !           622:      $                      LWORK-ITEMP+1, IERR )
        !           623:             END IF  
        !           624: *      
        !           625: *           If needed, compute right singular vectors.
        !           626: *
        !           627:             IF( WANTVT) THEN
        !           628:                K = ITGKZ + N
        !           629:                DO I = 1, NS
        !           630:                   DO J = 1, N
        !           631:                      VT( I, J ) = DCMPLX( RWORK( K ), ZERO )
        !           632:                      K = K + 1
        !           633:                   END DO
        !           634:                   K = K + N
        !           635:                END DO
        !           636: *
        !           637: *              Call ZUNMBR to compute VB**T * PB**T
        !           638: *              (Workspace in WORK( ITEMP ): need N, prefer N*NB)
        !           639: *
        !           640:                CALL ZUNMBR( 'P', 'R', 'C', NS, N, N, A, LDA, 
        !           641:      $                      WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
        !           642:      $                      LWORK-ITEMP+1, IERR )
        !           643:             END IF
        !           644:          END IF                             
        !           645:       ELSE
        !           646: *
        !           647: *        A has more columns than rows. If A has sufficiently more
        !           648: *        columns than rows, first reduce A using the LQ decomposition.
        !           649: *
        !           650:          IF( N.GE.MNTHR ) THEN
        !           651: *
        !           652: *           Path 1t (N much larger than M):
        !           653: *           A = L * Q = ( QB * B * PB**T ) * Q 
        !           654: *                     = ( QB * ( UB * S * VB**T ) * PB**T ) * Q
        !           655: *           U = QB * UB ; V**T = VB**T * PB**T * Q
        !           656: *
        !           657: *           Compute A=L*Q
        !           658: *           (Workspace: need 2*M, prefer M+M*NB)
        !           659: *
        !           660:             ITAU = 1
        !           661:             ITEMP = ITAU + M
        !           662:             CALL ZGELQF( M, N, A, LDA, WORK( ITAU ), WORK( ITEMP ),
        !           663:      $                   LWORK-ITEMP+1, INFO )
        !           664: 
        !           665: *           Copy L into WORK and bidiagonalize it:
        !           666: *           (Workspace in WORK( ITEMP ): need M*M+3*M, prefer M*M+M+2*M*NB)
        !           667: *
        !           668:             ILQF = ITEMP       
        !           669:             ITAUQ = ILQF + M*M
        !           670:             ITAUP = ITAUQ + M
        !           671:             ITEMP = ITAUP + M
        !           672:             ID = 1
        !           673:             IE = ID + M
        !           674:             ITGKZ = IE + M
        !           675:             CALL ZLACPY( 'L', M, M, A, LDA, WORK( ILQF ), M )
        !           676:             CALL ZLASET( 'U', M-1, M-1, CZERO, CZERO, 
        !           677:      $                   WORK( ILQF+M ), M )
        !           678:             CALL ZGEBRD( M, M, WORK( ILQF ), M, RWORK( ID ),
        !           679:      $                   RWORK( IE ), WORK( ITAUQ ), WORK( ITAUP ), 
        !           680:      $                   WORK( ITEMP ), LWORK-ITEMP+1, INFO )
        !           681:             ITEMP = ITGKZ + M*(M*2+1)
        !           682: *
        !           683: *           Solve eigenvalue problem TGK*Z=Z*S.
        !           684: *           (Workspace: need 2*M*M+14*M)          
        !           685: *
        !           686:             CALL DBDSVDX( 'U', JOBZ, RNGTGK, M, RWORK( ID ),
        !           687:      $                    RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S, 
        !           688:      $                    RWORK( ITGKZ ), M*2, RWORK( ITEMP ), 
        !           689:      $                    IWORK, INFO)
        !           690: *
        !           691: *           If needed, compute left singular vectors.
        !           692: *
        !           693:             IF( WANTU ) THEN
        !           694:                K = ITGKZ
        !           695:                DO I = 1, NS
        !           696:                   DO J = 1, M
        !           697:                      U( J, I ) = DCMPLX( RWORK( K ), ZERO )
        !           698:                      K = K + 1
        !           699:                   END DO
        !           700:                   K = K + M
        !           701:                END DO
        !           702: *
        !           703: *              Call ZUNMBR to compute QB*UB.
        !           704: *              (Workspace in WORK( ITEMP ): need M, prefer M*NB)
        !           705: *
        !           706:                CALL ZUNMBR( 'Q', 'L', 'N', M, NS, M, WORK( ILQF ), M, 
        !           707:      $                      WORK( ITAUQ ), U, LDU, WORK( ITEMP ), 
        !           708:      $                      LWORK-ITEMP+1, INFO )
        !           709:             END IF  
        !           710: *      
        !           711: *           If needed, compute right singular vectors.
        !           712: *
        !           713:             IF( WANTVT) THEN
        !           714:                K = ITGKZ + M
        !           715:                DO I = 1, NS
        !           716:                   DO J = 1, M
        !           717:                      VT( I, J ) = DCMPLX( RWORK( K ), ZERO )
        !           718:                      K = K + 1
        !           719:                   END DO
        !           720:                   K = K + M
        !           721:                END DO
        !           722:                CALL ZLASET( 'A', M, N-M, CZERO, CZERO, 
        !           723:      $                      VT( 1,M+1 ), LDVT )
        !           724: *
        !           725: *              Call ZUNMBR to compute (VB**T)*(PB**T)
        !           726: *              (Workspace in WORK( ITEMP ): need M, prefer M*NB)
        !           727: *
        !           728:                CALL ZUNMBR( 'P', 'R', 'C', NS, M, M, WORK( ILQF ), M, 
        !           729:      $                      WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
        !           730:      $                      LWORK-ITEMP+1, INFO )
        !           731: *
        !           732: *              Call ZUNMLQ to compute ((VB**T)*(PB**T))*Q.
        !           733: *              (Workspace in WORK( ITEMP ): need M, prefer M*NB)
        !           734: *
        !           735:                CALL ZUNMLQ( 'R', 'N', NS, N, M, A, LDA, 
        !           736:      $                      WORK( ITAU ), VT, LDVT, WORK( ITEMP ),
        !           737:      $                      LWORK-ITEMP+1, INFO )
        !           738:             END IF  
        !           739:          ELSE
        !           740: *
        !           741: *           Path 2t (N greater than M, but not much larger)
        !           742: *           Reduce to bidiagonal form without LQ decomposition
        !           743: *           A = QB * B * PB**T = QB * ( UB * S * VB**T ) * PB**T
        !           744: *           U = QB * UB; V**T = VB**T * PB**T           
        !           745: *
        !           746: *           Bidiagonalize A
        !           747: *           (Workspace: need 2*M+N, prefer 2*M+(M+N)*NB)
        !           748: *            
        !           749:             ITAUQ = 1
        !           750:             ITAUP = ITAUQ + M
        !           751:             ITEMP = ITAUP + M
        !           752:             ID = 1
        !           753:             IE = ID + M
        !           754:             ITGKZ = IE + M
        !           755:             CALL ZGEBRD( M, N, A, LDA, RWORK( ID ), RWORK( IE ), 
        !           756:      $                   WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
        !           757:      $                   LWORK-ITEMP+1, INFO )
        !           758:             ITEMP = ITGKZ + M*(M*2+1)
        !           759: *
        !           760: *           Solve eigenvalue problem TGK*Z=Z*S.
        !           761: *           (Workspace: need 2*M*M+14*M)          
        !           762: *          
        !           763:             CALL DBDSVDX( 'L', JOBZ, RNGTGK, M, RWORK( ID ), 
        !           764:      $                    RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S, 
        !           765:      $                    RWORK( ITGKZ ), M*2, RWORK( ITEMP ), 
        !           766:      $                    IWORK, INFO)
        !           767: * 
        !           768: *           If needed, compute left singular vectors.
        !           769: *
        !           770:             IF( WANTU ) THEN
        !           771:                K = ITGKZ
        !           772:                DO I = 1, NS
        !           773:                   DO J = 1, M
        !           774:                      U( J, I ) = DCMPLX( RWORK( K ), ZERO )
        !           775:                      K = K + 1
        !           776:                   END DO
        !           777:                   K = K + M
        !           778:                END DO
        !           779: *
        !           780: *              Call ZUNMBR to compute QB*UB.
        !           781: *              (Workspace in WORK( ITEMP ): need M, prefer M*NB)
        !           782: *
        !           783:                CALL ZUNMBR( 'Q', 'L', 'N', M, NS, N, A, LDA, 
        !           784:      $                      WORK( ITAUQ ), U, LDU, WORK( ITEMP ), 
        !           785:      $                      LWORK-ITEMP+1, INFO )
        !           786:             END IF  
        !           787: *      
        !           788: *           If needed, compute right singular vectors.
        !           789: *
        !           790:             IF( WANTVT) THEN
        !           791:                K = ITGKZ + M
        !           792:                DO I = 1, NS
        !           793:                   DO J = 1, M
        !           794:                      VT( I, J ) = DCMPLX( RWORK( K ), ZERO )
        !           795:                      K = K + 1
        !           796:                   END DO
        !           797:                   K = K + M
        !           798:                END DO
        !           799:                CALL ZLASET( 'A', M, N-M, CZERO, CZERO, 
        !           800:      $                      VT( 1,M+1 ), LDVT )
        !           801: *
        !           802: *              Call ZUNMBR to compute VB**T * PB**T
        !           803: *              (Workspace in WORK( ITEMP ): need M, prefer M*NB)
        !           804: *
        !           805:                CALL ZUNMBR( 'P', 'R', 'C', NS, N, M, A, LDA, 
        !           806:      $                      WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
        !           807:      $                      LWORK-ITEMP+1, INFO )
        !           808:             END IF 
        !           809:          END IF
        !           810:       END IF
        !           811: *
        !           812: *     Undo scaling if necessary
        !           813: *
        !           814:       IF( ISCL.EQ.1 ) THEN
        !           815:          IF( ANRM.GT.BIGNUM )
        !           816:      $      CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1,
        !           817:      $                   S, MINMN, INFO )
        !           818:          IF( ANRM.LT.SMLNUM )
        !           819:      $      CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1,
        !           820:      $                   S, MINMN, INFO )
        !           821:       END IF
        !           822: *
        !           823: *     Return optimal workspace in WORK(1)
        !           824: *
        !           825:       WORK( 1 ) = DCMPLX( DBLE( MAXWRK ), ZERO )
        !           826: *
        !           827:       RETURN
        !           828: *
        !           829: *     End of ZGESVDX
        !           830: *
        !           831:       END

CVSweb interface <joel.bertrand@systella.fr>