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

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

CVSweb interface <joel.bertrand@systella.fr>