File:  [local] / rpl / lapack / lapack / zgesvdx.f
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Thu Nov 26 11:44:21 2015 UTC (8 years, 5 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_24, HEAD
Mise à jour de Lapack (3.6.0) et du numéro de version du RPL/2.

    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>