File:  [local] / rpl / lapack / lapack / dgesdd.f
Revision 1.14: download - view: text, annotated - select for diffs - revision graph
Mon Jan 27 09:28:17 2014 UTC (10 years, 3 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_23, rpl-4_1_22, rpl-4_1_21, rpl-4_1_20, rpl-4_1_19, rpl-4_1_18, rpl-4_1_17, HEAD
Cohérence.

    1: *> \brief \b DGESDD
    2: *
    3: *  =========== DOCUMENTATION ===========
    4: *
    5: * Online html documentation available at 
    6: *            http://www.netlib.org/lapack/explore-html/ 
    7: *
    8: *> \htmlonly
    9: *> Download DGESDD + dependencies 
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dgesdd.f"> 
   11: *> [TGZ]</a> 
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dgesdd.f"> 
   13: *> [ZIP]</a> 
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgesdd.f"> 
   15: *> [TXT]</a>
   16: *> \endhtmlonly 
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *       SUBROUTINE DGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK,
   22: *                          LWORK, IWORK, INFO )
   23:    24: *       .. Scalar Arguments ..
   25: *       CHARACTER          JOBZ
   26: *       INTEGER            INFO, LDA, LDU, LDVT, LWORK, M, N
   27: *       ..
   28: *       .. Array Arguments ..
   29: *       INTEGER            IWORK( * )
   30: *       DOUBLE PRECISION   A( LDA, * ), S( * ), U( LDU, * ),
   31: *      $                   VT( LDVT, * ), WORK( * )
   32: *       ..
   33: *  
   34: *
   35: *> \par Purpose:
   36: *  =============
   37: *>
   38: *> \verbatim
   39: *>
   40: *> DGESDD computes the singular value decomposition (SVD) of a real
   41: *> M-by-N matrix A, optionally computing the left and right singular
   42: *> vectors.  If singular vectors are desired, it uses a
   43: *> divide-and-conquer algorithm.
   44: *>
   45: *> 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: *> Note that the routine returns VT = V**T, not V.
   57: *>
   58: *> The divide and conquer algorithm makes very mild assumptions about
   59: *> floating point arithmetic. It will work on machines with a guard
   60: *> digit in add/subtract, or on those binary machines without guard
   61: *> digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
   62: *> Cray-2. It could conceivably fail on hexadecimal or decimal machines
   63: *> without guard digits, but we know of none.
   64: *> \endverbatim
   65: *
   66: *  Arguments:
   67: *  ==========
   68: *
   69: *> \param[in] JOBZ
   70: *> \verbatim
   71: *>          JOBZ is CHARACTER*1
   72: *>          Specifies options for computing all or part of the matrix U:
   73: *>          = 'A':  all M columns of U and all N rows of V**T are
   74: *>                  returned in the arrays U and VT;
   75: *>          = 'S':  the first min(M,N) columns of U and the first
   76: *>                  min(M,N) rows of V**T are returned in the arrays U
   77: *>                  and VT;
   78: *>          = 'O':  If M >= N, the first N columns of U are overwritten
   79: *>                  on the array A and all rows of V**T are returned in
   80: *>                  the array VT;
   81: *>                  otherwise, all columns of U are returned in the
   82: *>                  array U and the first M rows of V**T are overwritten
   83: *>                  in the array A;
   84: *>          = 'N':  no columns of U or rows of V**T are computed.
   85: *> \endverbatim
   86: *>
   87: *> \param[in] M
   88: *> \verbatim
   89: *>          M is INTEGER
   90: *>          The number of rows of the input matrix A.  M >= 0.
   91: *> \endverbatim
   92: *>
   93: *> \param[in] N
   94: *> \verbatim
   95: *>          N is INTEGER
   96: *>          The number of columns of the input matrix A.  N >= 0.
   97: *> \endverbatim
   98: *>
   99: *> \param[in,out] A
  100: *> \verbatim
  101: *>          A is DOUBLE PRECISION array, dimension (LDA,N)
  102: *>          On entry, the M-by-N matrix A.
  103: *>          On exit,
  104: *>          if JOBZ = 'O',  A is overwritten with the first N columns
  105: *>                          of U (the left singular vectors, stored
  106: *>                          columnwise) if M >= N;
  107: *>                          A is overwritten with the first M rows
  108: *>                          of V**T (the right singular vectors, stored
  109: *>                          rowwise) otherwise.
  110: *>          if JOBZ .ne. 'O', the contents of A are destroyed.
  111: *> \endverbatim
  112: *>
  113: *> \param[in] LDA
  114: *> \verbatim
  115: *>          LDA is INTEGER
  116: *>          The leading dimension of the array A.  LDA >= max(1,M).
  117: *> \endverbatim
  118: *>
  119: *> \param[out] S
  120: *> \verbatim
  121: *>          S is DOUBLE PRECISION array, dimension (min(M,N))
  122: *>          The singular values of A, sorted so that S(i) >= S(i+1).
  123: *> \endverbatim
  124: *>
  125: *> \param[out] U
  126: *> \verbatim
  127: *>          U is DOUBLE PRECISION array, dimension (LDU,UCOL)
  128: *>          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N;
  129: *>          UCOL = min(M,N) if JOBZ = 'S'.
  130: *>          If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M
  131: *>          orthogonal matrix U;
  132: *>          if JOBZ = 'S', U contains the first min(M,N) columns of U
  133: *>          (the left singular vectors, stored columnwise);
  134: *>          if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced.
  135: *> \endverbatim
  136: *>
  137: *> \param[in] LDU
  138: *> \verbatim
  139: *>          LDU is INTEGER
  140: *>          The leading dimension of the array U.  LDU >= 1; if
  141: *>          JOBZ = 'S' or 'A' or JOBZ = 'O' and M < N, LDU >= M.
  142: *> \endverbatim
  143: *>
  144: *> \param[out] VT
  145: *> \verbatim
  146: *>          VT is DOUBLE PRECISION array, dimension (LDVT,N)
  147: *>          If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the
  148: *>          N-by-N orthogonal matrix V**T;
  149: *>          if JOBZ = 'S', VT contains the first min(M,N) rows of
  150: *>          V**T (the right singular vectors, stored rowwise);
  151: *>          if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced.
  152: *> \endverbatim
  153: *>
  154: *> \param[in] LDVT
  155: *> \verbatim
  156: *>          LDVT is INTEGER
  157: *>          The leading dimension of the array VT.  LDVT >= 1; if
  158: *>          JOBZ = 'A' or JOBZ = 'O' and M >= N, LDVT >= N;
  159: *>          if JOBZ = 'S', LDVT >= min(M,N).
  160: *> \endverbatim
  161: *>
  162: *> \param[out] WORK
  163: *> \verbatim
  164: *>          WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
  165: *>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
  166: *> \endverbatim
  167: *>
  168: *> \param[in] LWORK
  169: *> \verbatim
  170: *>          LWORK is INTEGER
  171: *>          The dimension of the array WORK. LWORK >= 1.
  172: *>          If JOBZ = 'N',
  173: *>            LWORK >= 3*min(M,N) + max(max(M,N),7*min(M,N)).
  174: *>          If JOBZ = 'O',
  175: *>            LWORK >= 3*min(M,N) + 
  176: *>                     max(max(M,N),5*min(M,N)*min(M,N)+4*min(M,N)).
  177: *>          If JOBZ = 'S' or 'A'
  178: *>            LWORK >= min(M,N)*(6+4*min(M,N))+max(M,N)
  179: *>          For good performance, LWORK should generally be larger.
  180: *>          If LWORK = -1 but other input arguments are legal, WORK(1)
  181: *>          returns the optimal LWORK.
  182: *> \endverbatim
  183: *>
  184: *> \param[out] IWORK
  185: *> \verbatim
  186: *>          IWORK is INTEGER array, dimension (8*min(M,N))
  187: *> \endverbatim
  188: *>
  189: *> \param[out] INFO
  190: *> \verbatim
  191: *>          INFO is INTEGER
  192: *>          = 0:  successful exit.
  193: *>          < 0:  if INFO = -i, the i-th argument had an illegal value.
  194: *>          > 0:  DBDSDC did not converge, updating process failed.
  195: *> \endverbatim
  196: *
  197: *  Authors:
  198: *  ========
  199: *
  200: *> \author Univ. of Tennessee 
  201: *> \author Univ. of California Berkeley 
  202: *> \author Univ. of Colorado Denver 
  203: *> \author NAG Ltd. 
  204: *
  205: *> \date November 2013
  206: *
  207: *> \ingroup doubleGEsing
  208: *
  209: *> \par Contributors:
  210: *  ==================
  211: *>
  212: *>     Ming Gu and Huan Ren, Computer Science Division, University of
  213: *>     California at Berkeley, USA
  214: *>
  215: *  =====================================================================
  216:       SUBROUTINE DGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK,
  217:      $                   LWORK, IWORK, INFO )
  218: *
  219: *  -- LAPACK driver routine (version 3.5.0) --
  220: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  221: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  222: *     November 2013
  223: *
  224: *     .. Scalar Arguments ..
  225:       CHARACTER          JOBZ
  226:       INTEGER            INFO, LDA, LDU, LDVT, LWORK, M, N
  227: *     ..
  228: *     .. Array Arguments ..
  229:       INTEGER            IWORK( * )
  230:       DOUBLE PRECISION   A( LDA, * ), S( * ), U( LDU, * ),
  231:      $                   VT( LDVT, * ), WORK( * )
  232: *     ..
  233: *
  234: *  =====================================================================
  235: *
  236: *     .. Parameters ..
  237:       DOUBLE PRECISION   ZERO, ONE
  238:       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
  239: *     ..
  240: *     .. Local Scalars ..
  241:       LOGICAL            LQUERY, WNTQA, WNTQAS, WNTQN, WNTQO, WNTQS
  242:       INTEGER            BDSPAC, BLK, CHUNK, I, IE, IERR, IL,
  243:      $                   IR, ISCL, ITAU, ITAUP, ITAUQ, IU, IVT, LDWKVT,
  244:      $                   LDWRKL, LDWRKR, LDWRKU, MAXWRK, MINMN, MINWRK,
  245:      $                   MNTHR, NWORK, WRKBL
  246:       DOUBLE PRECISION   ANRM, BIGNUM, EPS, SMLNUM
  247: *     ..
  248: *     .. Local Arrays ..
  249:       INTEGER            IDUM( 1 )
  250:       DOUBLE PRECISION   DUM( 1 )
  251: *     ..
  252: *     .. External Subroutines ..
  253:       EXTERNAL           DBDSDC, DGEBRD, DGELQF, DGEMM, DGEQRF, DLACPY,
  254:      $                   DLASCL, DLASET, DORGBR, DORGLQ, DORGQR, DORMBR,
  255:      $                   XERBLA
  256: *     ..
  257: *     .. External Functions ..
  258:       LOGICAL            LSAME
  259:       INTEGER            ILAENV
  260:       DOUBLE PRECISION   DLAMCH, DLANGE
  261:       EXTERNAL           DLAMCH, DLANGE, ILAENV, LSAME
  262: *     ..
  263: *     .. Intrinsic Functions ..
  264:       INTRINSIC          INT, MAX, MIN, SQRT
  265: *     ..
  266: *     .. Executable Statements ..
  267: *
  268: *     Test the input arguments
  269: *
  270:       INFO = 0
  271:       MINMN = MIN( M, N )
  272:       WNTQA = LSAME( JOBZ, 'A' )
  273:       WNTQS = LSAME( JOBZ, 'S' )
  274:       WNTQAS = WNTQA .OR. WNTQS
  275:       WNTQO = LSAME( JOBZ, 'O' )
  276:       WNTQN = LSAME( JOBZ, 'N' )
  277:       LQUERY = ( LWORK.EQ.-1 )
  278: *
  279:       IF( .NOT.( WNTQA .OR. WNTQS .OR. WNTQO .OR. WNTQN ) ) THEN
  280:          INFO = -1
  281:       ELSE IF( M.LT.0 ) THEN
  282:          INFO = -2
  283:       ELSE IF( N.LT.0 ) THEN
  284:          INFO = -3
  285:       ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
  286:          INFO = -5
  287:       ELSE IF( LDU.LT.1 .OR. ( WNTQAS .AND. LDU.LT.M ) .OR.
  288:      $         ( WNTQO .AND. M.LT.N .AND. LDU.LT.M ) ) THEN
  289:          INFO = -8
  290:       ELSE IF( LDVT.LT.1 .OR. ( WNTQA .AND. LDVT.LT.N ) .OR.
  291:      $         ( WNTQS .AND. LDVT.LT.MINMN ) .OR.
  292:      $         ( WNTQO .AND. M.GE.N .AND. LDVT.LT.N ) ) THEN
  293:          INFO = -10
  294:       END IF
  295: *
  296: *     Compute workspace
  297: *      (Note: Comments in the code beginning "Workspace:" describe the
  298: *       minimal amount of workspace needed at that point in the code,
  299: *       as well as the preferred amount for good performance.
  300: *       NB refers to the optimal block size for the immediately
  301: *       following subroutine, as returned by ILAENV.)
  302: *
  303:       IF( INFO.EQ.0 ) THEN
  304:          MINWRK = 1
  305:          MAXWRK = 1
  306:          IF( M.GE.N .AND. MINMN.GT.0 ) THEN
  307: *
  308: *           Compute space needed for DBDSDC
  309: *
  310:             MNTHR = INT( MINMN*11.0D0 / 6.0D0 )
  311:             IF( WNTQN ) THEN
  312:                BDSPAC = 7*N
  313:             ELSE
  314:                BDSPAC = 3*N*N + 4*N
  315:             END IF
  316:             IF( M.GE.MNTHR ) THEN
  317:                IF( WNTQN ) THEN
  318: *
  319: *                 Path 1 (M much larger than N, JOBZ='N')
  320: *
  321:                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1,
  322:      $                    -1 )
  323:                   WRKBL = MAX( WRKBL, 3*N+2*N*
  324:      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
  325:                   MAXWRK = MAX( WRKBL, BDSPAC+N )
  326:                   MINWRK = BDSPAC + N
  327:                ELSE IF( WNTQO ) THEN
  328: *
  329: *                 Path 2 (M much larger than N, JOBZ='O')
  330: *
  331:                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
  332:                   WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
  333:      $                    N, N, -1 ) )
  334:                   WRKBL = MAX( WRKBL, 3*N+2*N*
  335:      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
  336:                   WRKBL = MAX( WRKBL, 3*N+N*
  337:      $                    ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )
  338:                   WRKBL = MAX( WRKBL, 3*N+N*
  339:      $                    ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
  340:                   WRKBL = MAX( WRKBL, BDSPAC+3*N )
  341:                   MAXWRK = WRKBL + 2*N*N
  342:                   MINWRK = BDSPAC + 2*N*N + 3*N
  343:                ELSE IF( WNTQS ) THEN
  344: *
  345: *                 Path 3 (M much larger than N, JOBZ='S')
  346: *
  347:                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
  348:                   WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
  349:      $                    N, N, -1 ) )
  350:                   WRKBL = MAX( WRKBL, 3*N+2*N*
  351:      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
  352:                   WRKBL = MAX( WRKBL, 3*N+N*
  353:      $                    ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )
  354:                   WRKBL = MAX( WRKBL, 3*N+N*
  355:      $                    ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
  356:                   WRKBL = MAX( WRKBL, BDSPAC+3*N )
  357:                   MAXWRK = WRKBL + N*N
  358:                   MINWRK = BDSPAC + N*N + 3*N
  359:                ELSE IF( WNTQA ) THEN
  360: *
  361: *                 Path 4 (M much larger than N, JOBZ='A')
  362: *
  363:                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
  364:                   WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
  365:      $                    M, N, -1 ) )
  366:                   WRKBL = MAX( WRKBL, 3*N+2*N*
  367:      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
  368:                   WRKBL = MAX( WRKBL, 3*N+N*
  369:      $                    ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )
  370:                   WRKBL = MAX( WRKBL, 3*N+N*
  371:      $                    ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
  372:                   WRKBL = MAX( WRKBL, BDSPAC+3*N )
  373:                   MAXWRK = WRKBL + N*N
  374:                   MINWRK = BDSPAC + N*N + 2*N + M
  375:                END IF
  376:             ELSE
  377: *
  378: *              Path 5 (M at least N, but not much larger)
  379: *
  380:                WRKBL = 3*N + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, -1,
  381:      $                 -1 )
  382:                IF( WNTQN ) THEN
  383:                   MAXWRK = MAX( WRKBL, BDSPAC+3*N )
  384:                   MINWRK = 3*N + MAX( M, BDSPAC )
  385:                ELSE IF( WNTQO ) THEN
  386:                   WRKBL = MAX( WRKBL, 3*N+N*
  387:      $                    ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) )
  388:                   WRKBL = MAX( WRKBL, 3*N+N*
  389:      $                    ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
  390:                   WRKBL = MAX( WRKBL, BDSPAC+3*N )
  391:                   MAXWRK = WRKBL + M*N
  392:                   MINWRK = 3*N + MAX( M, N*N+BDSPAC )
  393:                ELSE IF( WNTQS ) THEN
  394:                   WRKBL = MAX( WRKBL, 3*N+N*
  395:      $                    ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) )
  396:                   WRKBL = MAX( WRKBL, 3*N+N*
  397:      $                    ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
  398:                   MAXWRK = MAX( WRKBL, BDSPAC+3*N )
  399:                   MINWRK = 3*N + MAX( M, BDSPAC )
  400:                ELSE IF( WNTQA ) THEN
  401:                   WRKBL = MAX( WRKBL, 3*N+M*
  402:      $                    ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
  403:                   WRKBL = MAX( WRKBL, 3*N+N*
  404:      $                    ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )
  405:                   MAXWRK = MAX( MAXWRK, BDSPAC+3*N )
  406:                   MINWRK = 3*N + MAX( M, BDSPAC )
  407:                END IF
  408:             END IF
  409:          ELSE IF( MINMN.GT.0 ) THEN
  410: *
  411: *           Compute space needed for DBDSDC
  412: *
  413:             MNTHR = INT( MINMN*11.0D0 / 6.0D0 )
  414:             IF( WNTQN ) THEN
  415:                BDSPAC = 7*M
  416:             ELSE
  417:                BDSPAC = 3*M*M + 4*M
  418:             END IF
  419:             IF( N.GE.MNTHR ) THEN
  420:                IF( WNTQN ) THEN
  421: *
  422: *                 Path 1t (N much larger than M, JOBZ='N')
  423: *
  424:                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1,
  425:      $                    -1 )
  426:                   WRKBL = MAX( WRKBL, 3*M+2*M*
  427:      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
  428:                   MAXWRK = MAX( WRKBL, BDSPAC+M )
  429:                   MINWRK = BDSPAC + M
  430:                ELSE IF( WNTQO ) THEN
  431: *
  432: *                 Path 2t (N much larger than M, JOBZ='O')
  433: *
  434:                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
  435:                   WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
  436:      $                    N, M, -1 ) )
  437:                   WRKBL = MAX( WRKBL, 3*M+2*M*
  438:      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
  439:                   WRKBL = MAX( WRKBL, 3*M+M*
  440:      $                    ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )
  441:                   WRKBL = MAX( WRKBL, 3*M+M*
  442:      $                    ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )
  443:                   WRKBL = MAX( WRKBL, BDSPAC+3*M )
  444:                   MAXWRK = WRKBL + 2*M*M
  445:                   MINWRK = BDSPAC + 2*M*M + 3*M
  446:                ELSE IF( WNTQS ) THEN
  447: *
  448: *                 Path 3t (N much larger than M, JOBZ='S')
  449: *
  450:                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
  451:                   WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
  452:      $                    N, M, -1 ) )
  453:                   WRKBL = MAX( WRKBL, 3*M+2*M*
  454:      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
  455:                   WRKBL = MAX( WRKBL, 3*M+M*
  456:      $                    ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )
  457:                   WRKBL = MAX( WRKBL, 3*M+M*
  458:      $                    ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )
  459:                   WRKBL = MAX( WRKBL, BDSPAC+3*M )
  460:                   MAXWRK = WRKBL + M*M
  461:                   MINWRK = BDSPAC + M*M + 3*M
  462:                ELSE IF( WNTQA ) THEN
  463: *
  464: *                 Path 4t (N much larger than M, JOBZ='A')
  465: *
  466:                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
  467:                   WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
  468:      $                    N, M, -1 ) )
  469:                   WRKBL = MAX( WRKBL, 3*M+2*M*
  470:      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
  471:                   WRKBL = MAX( WRKBL, 3*M+M*
  472:      $                    ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )
  473:                   WRKBL = MAX( WRKBL, 3*M+M*
  474:      $                    ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )
  475:                   WRKBL = MAX( WRKBL, BDSPAC+3*M )
  476:                   MAXWRK = WRKBL + M*M
  477:                   MINWRK = BDSPAC + M*M + 3*M
  478:                END IF
  479:             ELSE
  480: *
  481: *              Path 5t (N greater than M, but not much larger)
  482: *
  483:                WRKBL = 3*M + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, -1,
  484:      $                 -1 )
  485:                IF( WNTQN ) THEN
  486:                   MAXWRK = MAX( WRKBL, BDSPAC+3*M )
  487:                   MINWRK = 3*M + MAX( N, BDSPAC )
  488:                ELSE IF( WNTQO ) THEN
  489:                   WRKBL = MAX( WRKBL, 3*M+M*
  490:      $                    ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
  491:                   WRKBL = MAX( WRKBL, 3*M+M*
  492:      $                    ILAENV( 1, 'DORMBR', 'PRT', M, N, M, -1 ) )
  493:                   WRKBL = MAX( WRKBL, BDSPAC+3*M )
  494:                   MAXWRK = WRKBL + M*N
  495:                   MINWRK = 3*M + MAX( N, M*M+BDSPAC )
  496:                ELSE IF( WNTQS ) THEN
  497:                   WRKBL = MAX( WRKBL, 3*M+M*
  498:      $                    ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
  499:                   WRKBL = MAX( WRKBL, 3*M+M*
  500:      $                    ILAENV( 1, 'DORMBR', 'PRT', M, N, M, -1 ) )
  501:                   MAXWRK = MAX( WRKBL, BDSPAC+3*M )
  502:                   MINWRK = 3*M + MAX( N, BDSPAC )
  503:                ELSE IF( WNTQA ) THEN
  504:                   WRKBL = MAX( WRKBL, 3*M+M*
  505:      $                    ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )
  506:                   WRKBL = MAX( WRKBL, 3*M+M*
  507:      $                    ILAENV( 1, 'DORMBR', 'PRT', N, N, M, -1 ) )
  508:                   MAXWRK = MAX( WRKBL, BDSPAC+3*M )
  509:                   MINWRK = 3*M + MAX( N, BDSPAC )
  510:                END IF
  511:             END IF
  512:          END IF
  513:          MAXWRK = MAX( MAXWRK, MINWRK )
  514:          WORK( 1 ) = MAXWRK
  515: *
  516:          IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
  517:             INFO = -12
  518:          END IF
  519:       END IF
  520: *
  521:       IF( INFO.NE.0 ) THEN
  522:          CALL XERBLA( 'DGESDD', -INFO )
  523:          RETURN
  524:       ELSE IF( LQUERY ) THEN
  525:          RETURN
  526:       END IF
  527: *
  528: *     Quick return if possible
  529: *
  530:       IF( M.EQ.0 .OR. N.EQ.0 ) THEN
  531:          RETURN
  532:       END IF
  533: *
  534: *     Get machine constants
  535: *
  536:       EPS = DLAMCH( 'P' )
  537:       SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPS
  538:       BIGNUM = ONE / SMLNUM
  539: *
  540: *     Scale A if max element outside range [SMLNUM,BIGNUM]
  541: *
  542:       ANRM = DLANGE( 'M', M, N, A, LDA, DUM )
  543:       ISCL = 0
  544:       IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
  545:          ISCL = 1
  546:          CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, IERR )
  547:       ELSE IF( ANRM.GT.BIGNUM ) THEN
  548:          ISCL = 1
  549:          CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, IERR )
  550:       END IF
  551: *
  552:       IF( M.GE.N ) THEN
  553: *
  554: *        A has at least as many rows as columns. If A has sufficiently
  555: *        more rows than columns, first reduce using the QR
  556: *        decomposition (if sufficient workspace available)
  557: *
  558:          IF( M.GE.MNTHR ) THEN
  559: *
  560:             IF( WNTQN ) THEN
  561: *
  562: *              Path 1 (M much larger than N, JOBZ='N')
  563: *              No singular vectors to be computed
  564: *
  565:                ITAU = 1
  566:                NWORK = ITAU + N
  567: *
  568: *              Compute A=Q*R
  569: *              (Workspace: need 2*N, prefer N+N*NB)
  570: *
  571:                CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
  572:      $                      LWORK-NWORK+1, IERR )
  573: *
  574: *              Zero out below R
  575: *
  576:                CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
  577:                IE = 1
  578:                ITAUQ = IE + N
  579:                ITAUP = ITAUQ + N
  580:                NWORK = ITAUP + N
  581: *
  582: *              Bidiagonalize R in A
  583: *              (Workspace: need 4*N, prefer 3*N+2*N*NB)
  584: *
  585:                CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
  586:      $                      WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
  587:      $                      IERR )
  588:                NWORK = IE + N
  589: *
  590: *              Perform bidiagonal SVD, computing singular values only
  591: *              (Workspace: need N+BDSPAC)
  592: *
  593:                CALL DBDSDC( 'U', 'N', N, S, WORK( IE ), DUM, 1, DUM, 1,
  594:      $                      DUM, IDUM, WORK( NWORK ), IWORK, INFO )
  595: *
  596:             ELSE IF( WNTQO ) THEN
  597: *
  598: *              Path 2 (M much larger than N, JOBZ = 'O')
  599: *              N left singular vectors to be overwritten on A and
  600: *              N right singular vectors to be computed in VT
  601: *
  602:                IR = 1
  603: *
  604: *              WORK(IR) is LDWRKR by N
  605: *
  606:                IF( LWORK.GE.LDA*N+N*N+3*N+BDSPAC ) THEN
  607:                   LDWRKR = LDA
  608:                ELSE
  609:                   LDWRKR = ( LWORK-N*N-3*N-BDSPAC ) / N
  610:                END IF
  611:                ITAU = IR + LDWRKR*N
  612:                NWORK = ITAU + N
  613: *
  614: *              Compute A=Q*R
  615: *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
  616: *
  617:                CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
  618:      $                      LWORK-NWORK+1, IERR )
  619: *
  620: *              Copy R to WORK(IR), zeroing out below it
  621: *
  622:                CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )
  623:                CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),
  624:      $                      LDWRKR )
  625: *
  626: *              Generate Q in A
  627: *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
  628: *
  629:                CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
  630:      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
  631:                IE = ITAU
  632:                ITAUQ = IE + N
  633:                ITAUP = ITAUQ + N
  634:                NWORK = ITAUP + N
  635: *
  636: *              Bidiagonalize R in VT, copying result to WORK(IR)
  637: *              (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
  638: *
  639:                CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),
  640:      $                      WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
  641:      $                      LWORK-NWORK+1, IERR )
  642: *
  643: *              WORK(IU) is N by N
  644: *
  645:                IU = NWORK
  646:                NWORK = IU + N*N
  647: *
  648: *              Perform bidiagonal SVD, computing left singular vectors
  649: *              of bidiagonal matrix in WORK(IU) and computing right
  650: *              singular vectors of bidiagonal matrix in VT
  651: *              (Workspace: need N+N*N+BDSPAC)
  652: *
  653:                CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ), N,
  654:      $                      VT, LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
  655:      $                      INFO )
  656: *
  657: *              Overwrite WORK(IU) by left singular vectors of R
  658: *              and VT by right singular vectors of R
  659: *              (Workspace: need 2*N*N+3*N, prefer 2*N*N+2*N+N*NB)
  660: *
  661:                CALL DORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR,
  662:      $                      WORK( ITAUQ ), WORK( IU ), N, WORK( NWORK ),
  663:      $                      LWORK-NWORK+1, IERR )
  664:                CALL DORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR,
  665:      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
  666:      $                      LWORK-NWORK+1, IERR )
  667: *
  668: *              Multiply Q in A by left singular vectors of R in
  669: *              WORK(IU), storing result in WORK(IR) and copying to A
  670: *              (Workspace: need 2*N*N, prefer N*N+M*N)
  671: *
  672:                DO 10 I = 1, M, LDWRKR
  673:                   CHUNK = MIN( M-I+1, LDWRKR )
  674:                   CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
  675:      $                        LDA, WORK( IU ), N, ZERO, WORK( IR ),
  676:      $                        LDWRKR )
  677:                   CALL DLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR,
  678:      $                         A( I, 1 ), LDA )
  679:    10          CONTINUE
  680: *
  681:             ELSE IF( WNTQS ) THEN
  682: *
  683: *              Path 3 (M much larger than N, JOBZ='S')
  684: *              N left singular vectors to be computed in U and
  685: *              N right singular vectors to be computed in VT
  686: *
  687:                IR = 1
  688: *
  689: *              WORK(IR) is N by N
  690: *
  691:                LDWRKR = N
  692:                ITAU = IR + LDWRKR*N
  693:                NWORK = ITAU + N
  694: *
  695: *              Compute A=Q*R
  696: *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
  697: *
  698:                CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
  699:      $                      LWORK-NWORK+1, IERR )
  700: *
  701: *              Copy R to WORK(IR), zeroing out below it
  702: *
  703:                CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )
  704:                CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),
  705:      $                      LDWRKR )
  706: *
  707: *              Generate Q in A
  708: *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
  709: *
  710:                CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
  711:      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
  712:                IE = ITAU
  713:                ITAUQ = IE + N
  714:                ITAUP = ITAUQ + N
  715:                NWORK = ITAUP + N
  716: *
  717: *              Bidiagonalize R in WORK(IR)
  718: *              (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
  719: *
  720:                CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),
  721:      $                      WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
  722:      $                      LWORK-NWORK+1, IERR )
  723: *
  724: *              Perform bidiagonal SVD, computing left singular vectors
  725: *              of bidiagoal matrix in U and computing right singular
  726: *              vectors of bidiagonal matrix in VT
  727: *              (Workspace: need N+BDSPAC)
  728: *
  729:                CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
  730:      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
  731:      $                      INFO )
  732: *
  733: *              Overwrite U by left singular vectors of R and VT
  734: *              by right singular vectors of R
  735: *              (Workspace: need N*N+3*N, prefer N*N+2*N+N*NB)
  736: *
  737:                CALL DORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR,
  738:      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
  739:      $                      LWORK-NWORK+1, IERR )
  740: *
  741:                CALL DORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR,
  742:      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
  743:      $                      LWORK-NWORK+1, IERR )
  744: *
  745: *              Multiply Q in A by left singular vectors of R in
  746: *              WORK(IR), storing result in U
  747: *              (Workspace: need N*N)
  748: *
  749:                CALL DLACPY( 'F', N, N, U, LDU, WORK( IR ), LDWRKR )
  750:                CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA, WORK( IR ),
  751:      $                     LDWRKR, ZERO, U, LDU )
  752: *
  753:             ELSE IF( WNTQA ) THEN
  754: *
  755: *              Path 4 (M much larger than N, JOBZ='A')
  756: *              M left singular vectors to be computed in U and
  757: *              N right singular vectors to be computed in VT
  758: *
  759:                IU = 1
  760: *
  761: *              WORK(IU) is N by N
  762: *
  763:                LDWRKU = N
  764:                ITAU = IU + LDWRKU*N
  765:                NWORK = ITAU + N
  766: *
  767: *              Compute A=Q*R, copying result to U
  768: *              (Workspace: need N*N+N+M, prefer N*N+N+M*NB)
  769: *
  770:                CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
  771:      $                      LWORK-NWORK+1, IERR )
  772:                CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
  773: *
  774: *              Generate Q in U
  775: *              (Workspace: need N*N+N+M, prefer N*N+N+M*NB)
  776:                CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
  777:      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
  778: *
  779: *              Produce R in A, zeroing out other entries
  780: *
  781:                CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
  782:                IE = ITAU
  783:                ITAUQ = IE + N
  784:                ITAUP = ITAUQ + N
  785:                NWORK = ITAUP + N
  786: *
  787: *              Bidiagonalize R in A
  788: *              (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
  789: *
  790:                CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
  791:      $                      WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
  792:      $                      IERR )
  793: *
  794: *              Perform bidiagonal SVD, computing left singular vectors
  795: *              of bidiagonal matrix in WORK(IU) and computing right
  796: *              singular vectors of bidiagonal matrix in VT
  797: *              (Workspace: need N+N*N+BDSPAC)
  798: *
  799:                CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ), N,
  800:      $                      VT, LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
  801:      $                      INFO )
  802: *
  803: *              Overwrite WORK(IU) by left singular vectors of R and VT
  804: *              by right singular vectors of R
  805: *              (Workspace: need N*N+3*N, prefer N*N+2*N+N*NB)
  806: *
  807:                CALL DORMBR( 'Q', 'L', 'N', N, N, N, A, LDA,
  808:      $                      WORK( ITAUQ ), WORK( IU ), LDWRKU,
  809:      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
  810:                CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
  811:      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
  812:      $                      LWORK-NWORK+1, IERR )
  813: *
  814: *              Multiply Q in U by left singular vectors of R in
  815: *              WORK(IU), storing result in A
  816: *              (Workspace: need N*N)
  817: *
  818:                CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU, WORK( IU ),
  819:      $                     LDWRKU, ZERO, A, LDA )
  820: *
  821: *              Copy left singular vectors of A from A to U
  822: *
  823:                CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
  824: *
  825:             END IF
  826: *
  827:          ELSE
  828: *
  829: *           M .LT. MNTHR
  830: *
  831: *           Path 5 (M at least N, but not much larger)
  832: *           Reduce to bidiagonal form without QR decomposition
  833: *
  834:             IE = 1
  835:             ITAUQ = IE + N
  836:             ITAUP = ITAUQ + N
  837:             NWORK = ITAUP + N
  838: *
  839: *           Bidiagonalize A
  840: *           (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)
  841: *
  842:             CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
  843:      $                   WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
  844:      $                   IERR )
  845:             IF( WNTQN ) THEN
  846: *
  847: *              Perform bidiagonal SVD, only computing singular values
  848: *              (Workspace: need N+BDSPAC)
  849: *
  850:                CALL DBDSDC( 'U', 'N', N, S, WORK( IE ), DUM, 1, DUM, 1,
  851:      $                      DUM, IDUM, WORK( NWORK ), IWORK, INFO )
  852:             ELSE IF( WNTQO ) THEN
  853:                IU = NWORK
  854:                IF( LWORK.GE.M*N+3*N+BDSPAC ) THEN
  855: *
  856: *                 WORK( IU ) is M by N
  857: *
  858:                   LDWRKU = M
  859:                   NWORK = IU + LDWRKU*N
  860:                   CALL DLASET( 'F', M, N, ZERO, ZERO, WORK( IU ),
  861:      $                         LDWRKU )
  862:                ELSE
  863: *
  864: *                 WORK( IU ) is N by N
  865: *
  866:                   LDWRKU = N
  867:                   NWORK = IU + LDWRKU*N
  868: *
  869: *                 WORK(IR) is LDWRKR by N
  870: *
  871:                   IR = NWORK
  872:                   LDWRKR = ( LWORK-N*N-3*N ) / N
  873:                END IF
  874:                NWORK = IU + LDWRKU*N
  875: *
  876: *              Perform bidiagonal SVD, computing left singular vectors
  877: *              of bidiagonal matrix in WORK(IU) and computing right
  878: *              singular vectors of bidiagonal matrix in VT
  879: *              (Workspace: need N+N*N+BDSPAC)
  880: *
  881:                CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ),
  882:      $                      LDWRKU, VT, LDVT, DUM, IDUM, WORK( NWORK ),
  883:      $                      IWORK, INFO )
  884: *
  885: *              Overwrite VT by right singular vectors of A
  886: *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
  887: *
  888:                CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
  889:      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
  890:      $                      LWORK-NWORK+1, IERR )
  891: *
  892:                IF( LWORK.GE.M*N+3*N+BDSPAC ) THEN
  893: *
  894: *                 Overwrite WORK(IU) by left singular vectors of A
  895: *                 (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
  896: *
  897:                   CALL DORMBR( 'Q', 'L', 'N', M, N, N, A, LDA,
  898:      $                         WORK( ITAUQ ), WORK( IU ), LDWRKU,
  899:      $                         WORK( NWORK ), LWORK-NWORK+1, IERR )
  900: *
  901: *                 Copy left singular vectors of A from WORK(IU) to A
  902: *
  903:                   CALL DLACPY( 'F', M, N, WORK( IU ), LDWRKU, A, LDA )
  904:                ELSE
  905: *
  906: *                 Generate Q in A
  907: *                 (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
  908: *
  909:                   CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),
  910:      $                         WORK( NWORK ), LWORK-NWORK+1, IERR )
  911: *
  912: *                 Multiply Q in A by left singular vectors of
  913: *                 bidiagonal matrix in WORK(IU), storing result in
  914: *                 WORK(IR) and copying to A
  915: *                 (Workspace: need 2*N*N, prefer N*N+M*N)
  916: *
  917:                   DO 20 I = 1, M, LDWRKR
  918:                      CHUNK = MIN( M-I+1, LDWRKR )
  919:                      CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
  920:      $                           LDA, WORK( IU ), LDWRKU, ZERO,
  921:      $                           WORK( IR ), LDWRKR )
  922:                      CALL DLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR,
  923:      $                            A( I, 1 ), LDA )
  924:    20             CONTINUE
  925:                END IF
  926: *
  927:             ELSE IF( WNTQS ) THEN
  928: *
  929: *              Perform bidiagonal SVD, computing left singular vectors
  930: *              of bidiagonal matrix in U and computing right singular
  931: *              vectors of bidiagonal matrix in VT
  932: *              (Workspace: need N+BDSPAC)
  933: *
  934:                CALL DLASET( 'F', M, N, ZERO, ZERO, U, LDU )
  935:                CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
  936:      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
  937:      $                      INFO )
  938: *
  939: *              Overwrite U by left singular vectors of A and VT
  940: *              by right singular vectors of A
  941: *              (Workspace: need 3*N, prefer 2*N+N*NB)
  942: *
  943:                CALL DORMBR( 'Q', 'L', 'N', M, N, N, A, LDA,
  944:      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
  945:      $                      LWORK-NWORK+1, IERR )
  946:                CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
  947:      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
  948:      $                      LWORK-NWORK+1, IERR )
  949:             ELSE IF( WNTQA ) THEN
  950: *
  951: *              Perform bidiagonal SVD, computing left singular vectors
  952: *              of bidiagonal matrix in U and computing right singular
  953: *              vectors of bidiagonal matrix in VT
  954: *              (Workspace: need N+BDSPAC)
  955: *
  956:                CALL DLASET( 'F', M, M, ZERO, ZERO, U, LDU )
  957:                CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
  958:      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
  959:      $                      INFO )
  960: *
  961: *              Set the right corner of U to identity matrix
  962: *
  963:                IF( M.GT.N ) THEN
  964:                   CALL DLASET( 'F', M-N, M-N, ZERO, ONE, U( N+1, N+1 ),
  965:      $                         LDU )
  966:                END IF
  967: *
  968: *              Overwrite U by left singular vectors of A and VT
  969: *              by right singular vectors of A
  970: *              (Workspace: need N*N+2*N+M, prefer N*N+2*N+M*NB)
  971: *
  972:                CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
  973:      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
  974:      $                      LWORK-NWORK+1, IERR )
  975:                CALL DORMBR( 'P', 'R', 'T', N, N, M, A, LDA,
  976:      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
  977:      $                      LWORK-NWORK+1, IERR )
  978:             END IF
  979: *
  980:          END IF
  981: *
  982:       ELSE
  983: *
  984: *        A has more columns than rows. If A has sufficiently more
  985: *        columns than rows, first reduce using the LQ decomposition (if
  986: *        sufficient workspace available)
  987: *
  988:          IF( N.GE.MNTHR ) THEN
  989: *
  990:             IF( WNTQN ) THEN
  991: *
  992: *              Path 1t (N much larger than M, JOBZ='N')
  993: *              No singular vectors to be computed
  994: *
  995:                ITAU = 1
  996:                NWORK = ITAU + M
  997: *
  998: *              Compute A=L*Q
  999: *              (Workspace: need 2*M, prefer M+M*NB)
 1000: *
 1001:                CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
 1002:      $                      LWORK-NWORK+1, IERR )
 1003: *
 1004: *              Zero out above L
 1005: *
 1006:                CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )
 1007:                IE = 1
 1008:                ITAUQ = IE + M
 1009:                ITAUP = ITAUQ + M
 1010:                NWORK = ITAUP + M
 1011: *
 1012: *              Bidiagonalize L in A
 1013: *              (Workspace: need 4*M, prefer 3*M+2*M*NB)
 1014: *
 1015:                CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
 1016:      $                      WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
 1017:      $                      IERR )
 1018:                NWORK = IE + M
 1019: *
 1020: *              Perform bidiagonal SVD, computing singular values only
 1021: *              (Workspace: need M+BDSPAC)
 1022: *
 1023:                CALL DBDSDC( 'U', 'N', M, S, WORK( IE ), DUM, 1, DUM, 1,
 1024:      $                      DUM, IDUM, WORK( NWORK ), IWORK, INFO )
 1025: *
 1026:             ELSE IF( WNTQO ) THEN
 1027: *
 1028: *              Path 2t (N much larger than M, JOBZ='O')
 1029: *              M right singular vectors to be overwritten on A and
 1030: *              M left singular vectors to be computed in U
 1031: *
 1032:                IVT = 1
 1033: *
 1034: *              IVT is M by M
 1035: *
 1036:                IL = IVT + M*M
 1037:                IF( LWORK.GE.M*N+M*M+3*M+BDSPAC ) THEN
 1038: *
 1039: *                 WORK(IL) is M by N
 1040: *
 1041:                   LDWRKL = M
 1042:                   CHUNK = N
 1043:                ELSE
 1044:                   LDWRKL = M
 1045:                   CHUNK = ( LWORK-M*M ) / M
 1046:                END IF
 1047:                ITAU = IL + LDWRKL*M
 1048:                NWORK = ITAU + M
 1049: *
 1050: *              Compute A=L*Q
 1051: *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
 1052: *
 1053:                CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
 1054:      $                      LWORK-NWORK+1, IERR )
 1055: *
 1056: *              Copy L to WORK(IL), zeroing about above it
 1057: *
 1058:                CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWRKL )
 1059:                CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
 1060:      $                      WORK( IL+LDWRKL ), LDWRKL )
 1061: *
 1062: *              Generate Q in A
 1063: *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
 1064: *
 1065:                CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
 1066:      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
 1067:                IE = ITAU
 1068:                ITAUQ = IE + M
 1069:                ITAUP = ITAUQ + M
 1070:                NWORK = ITAUP + M
 1071: *
 1072: *              Bidiagonalize L in WORK(IL)
 1073: *              (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
 1074: *
 1075:                CALL DGEBRD( M, M, WORK( IL ), LDWRKL, S, WORK( IE ),
 1076:      $                      WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
 1077:      $                      LWORK-NWORK+1, IERR )
 1078: *
 1079: *              Perform bidiagonal SVD, computing left singular vectors
 1080: *              of bidiagonal matrix in U, and computing right singular
 1081: *              vectors of bidiagonal matrix in WORK(IVT)
 1082: *              (Workspace: need M+M*M+BDSPAC)
 1083: *
 1084:                CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU,
 1085:      $                      WORK( IVT ), M, DUM, IDUM, WORK( NWORK ),
 1086:      $                      IWORK, INFO )
 1087: *
 1088: *              Overwrite U by left singular vectors of L and WORK(IVT)
 1089: *              by right singular vectors of L
 1090: *              (Workspace: need 2*M*M+3*M, prefer 2*M*M+2*M+M*NB)
 1091: *
 1092:                CALL DORMBR( 'Q', 'L', 'N', M, M, M, WORK( IL ), LDWRKL,
 1093:      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
 1094:      $                      LWORK-NWORK+1, IERR )
 1095:                CALL DORMBR( 'P', 'R', 'T', M, M, M, WORK( IL ), LDWRKL,
 1096:      $                      WORK( ITAUP ), WORK( IVT ), M,
 1097:      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
 1098: *
 1099: *              Multiply right singular vectors of L in WORK(IVT) by Q
 1100: *              in A, storing result in WORK(IL) and copying to A
 1101: *              (Workspace: need 2*M*M, prefer M*M+M*N)
 1102: *
 1103:                DO 30 I = 1, N, CHUNK
 1104:                   BLK = MIN( N-I+1, CHUNK )
 1105:                   CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IVT ), M,
 1106:      $                        A( 1, I ), LDA, ZERO, WORK( IL ), LDWRKL )
 1107:                   CALL DLACPY( 'F', M, BLK, WORK( IL ), LDWRKL,
 1108:      $                         A( 1, I ), LDA )
 1109:    30          CONTINUE
 1110: *
 1111:             ELSE IF( WNTQS ) THEN
 1112: *
 1113: *              Path 3t (N much larger than M, JOBZ='S')
 1114: *              M right singular vectors to be computed in VT and
 1115: *              M left singular vectors to be computed in U
 1116: *
 1117:                IL = 1
 1118: *
 1119: *              WORK(IL) is M by M
 1120: *
 1121:                LDWRKL = M
 1122:                ITAU = IL + LDWRKL*M
 1123:                NWORK = ITAU + M
 1124: *
 1125: *              Compute A=L*Q
 1126: *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
 1127: *
 1128:                CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
 1129:      $                      LWORK-NWORK+1, IERR )
 1130: *
 1131: *              Copy L to WORK(IL), zeroing out above it
 1132: *
 1133:                CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWRKL )
 1134:                CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
 1135:      $                      WORK( IL+LDWRKL ), LDWRKL )
 1136: *
 1137: *              Generate Q in A
 1138: *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
 1139: *
 1140:                CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
 1141:      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
 1142:                IE = ITAU
 1143:                ITAUQ = IE + M
 1144:                ITAUP = ITAUQ + M
 1145:                NWORK = ITAUP + M
 1146: *
 1147: *              Bidiagonalize L in WORK(IU), copying result to U
 1148: *              (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
 1149: *
 1150:                CALL DGEBRD( M, M, WORK( IL ), LDWRKL, S, WORK( IE ),
 1151:      $                      WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
 1152:      $                      LWORK-NWORK+1, IERR )
 1153: *
 1154: *              Perform bidiagonal SVD, computing left singular vectors
 1155: *              of bidiagonal matrix in U and computing right singular
 1156: *              vectors of bidiagonal matrix in VT
 1157: *              (Workspace: need M+BDSPAC)
 1158: *
 1159:                CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU, VT,
 1160:      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
 1161:      $                      INFO )
 1162: *
 1163: *              Overwrite U by left singular vectors of L and VT
 1164: *              by right singular vectors of L
 1165: *              (Workspace: need M*M+3*M, prefer M*M+2*M+M*NB)
 1166: *
 1167:                CALL DORMBR( 'Q', 'L', 'N', M, M, M, WORK( IL ), LDWRKL,
 1168:      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
 1169:      $                      LWORK-NWORK+1, IERR )
 1170:                CALL DORMBR( 'P', 'R', 'T', M, M, M, WORK( IL ), LDWRKL,
 1171:      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
 1172:      $                      LWORK-NWORK+1, IERR )
 1173: *
 1174: *              Multiply right singular vectors of L in WORK(IL) by
 1175: *              Q in A, storing result in VT
 1176: *              (Workspace: need M*M)
 1177: *
 1178:                CALL DLACPY( 'F', M, M, VT, LDVT, WORK( IL ), LDWRKL )
 1179:                CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IL ), LDWRKL,
 1180:      $                     A, LDA, ZERO, VT, LDVT )
 1181: *
 1182:             ELSE IF( WNTQA ) THEN
 1183: *
 1184: *              Path 4t (N much larger than M, JOBZ='A')
 1185: *              N right singular vectors to be computed in VT and
 1186: *              M left singular vectors to be computed in U
 1187: *
 1188:                IVT = 1
 1189: *
 1190: *              WORK(IVT) is M by M
 1191: *
 1192:                LDWKVT = M
 1193:                ITAU = IVT + LDWKVT*M
 1194:                NWORK = ITAU + M
 1195: *
 1196: *              Compute A=L*Q, copying result to VT
 1197: *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
 1198: *
 1199:                CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
 1200:      $                      LWORK-NWORK+1, IERR )
 1201:                CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
 1202: *
 1203: *              Generate Q in VT
 1204: *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
 1205: *
 1206:                CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
 1207:      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
 1208: *
 1209: *              Produce L in A, zeroing out other entries
 1210: *
 1211:                CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )
 1212:                IE = ITAU
 1213:                ITAUQ = IE + M
 1214:                ITAUP = ITAUQ + M
 1215:                NWORK = ITAUP + M
 1216: *
 1217: *              Bidiagonalize L in A
 1218: *              (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
 1219: *
 1220:                CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
 1221:      $                      WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
 1222:      $                      IERR )
 1223: *
 1224: *              Perform bidiagonal SVD, computing left singular vectors
 1225: *              of bidiagonal matrix in U and computing right singular
 1226: *              vectors of bidiagonal matrix in WORK(IVT)
 1227: *              (Workspace: need M+M*M+BDSPAC)
 1228: *
 1229:                CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU,
 1230:      $                      WORK( IVT ), LDWKVT, DUM, IDUM,
 1231:      $                      WORK( NWORK ), IWORK, INFO )
 1232: *
 1233: *              Overwrite U by left singular vectors of L and WORK(IVT)
 1234: *              by right singular vectors of L
 1235: *              (Workspace: need M*M+3*M, prefer M*M+2*M+M*NB)
 1236: *
 1237:                CALL DORMBR( 'Q', 'L', 'N', M, M, M, A, LDA,
 1238:      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
 1239:      $                      LWORK-NWORK+1, IERR )
 1240:                CALL DORMBR( 'P', 'R', 'T', M, M, M, A, LDA,
 1241:      $                      WORK( ITAUP ), WORK( IVT ), LDWKVT,
 1242:      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
 1243: *
 1244: *              Multiply right singular vectors of L in WORK(IVT) by
 1245: *              Q in VT, storing result in A
 1246: *              (Workspace: need M*M)
 1247: *
 1248:                CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IVT ), LDWKVT,
 1249:      $                     VT, LDVT, ZERO, A, LDA )
 1250: *
 1251: *              Copy right singular vectors of A from A to VT
 1252: *
 1253:                CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
 1254: *
 1255:             END IF
 1256: *
 1257:          ELSE
 1258: *
 1259: *           N .LT. MNTHR
 1260: *
 1261: *           Path 5t (N greater than M, but not much larger)
 1262: *           Reduce to bidiagonal form without LQ decomposition
 1263: *
 1264:             IE = 1
 1265:             ITAUQ = IE + M
 1266:             ITAUP = ITAUQ + M
 1267:             NWORK = ITAUP + M
 1268: *
 1269: *           Bidiagonalize A
 1270: *           (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
 1271: *
 1272:             CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
 1273:      $                   WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
 1274:      $                   IERR )
 1275:             IF( WNTQN ) THEN
 1276: *
 1277: *              Perform bidiagonal SVD, only computing singular values
 1278: *              (Workspace: need M+BDSPAC)
 1279: *
 1280:                CALL DBDSDC( 'L', 'N', M, S, WORK( IE ), DUM, 1, DUM, 1,
 1281:      $                      DUM, IDUM, WORK( NWORK ), IWORK, INFO )
 1282:             ELSE IF( WNTQO ) THEN
 1283:                LDWKVT = M
 1284:                IVT = NWORK
 1285:                IF( LWORK.GE.M*N+3*M+BDSPAC ) THEN
 1286: *
 1287: *                 WORK( IVT ) is M by N
 1288: *
 1289:                   CALL DLASET( 'F', M, N, ZERO, ZERO, WORK( IVT ),
 1290:      $                         LDWKVT )
 1291:                   NWORK = IVT + LDWKVT*N
 1292:                ELSE
 1293: *
 1294: *                 WORK( IVT ) is M by M
 1295: *
 1296:                   NWORK = IVT + LDWKVT*M
 1297:                   IL = NWORK
 1298: *
 1299: *                 WORK(IL) is M by CHUNK
 1300: *
 1301:                   CHUNK = ( LWORK-M*M-3*M ) / M
 1302:                END IF
 1303: *
 1304: *              Perform bidiagonal SVD, computing left singular vectors
 1305: *              of bidiagonal matrix in U and computing right singular
 1306: *              vectors of bidiagonal matrix in WORK(IVT)
 1307: *              (Workspace: need M*M+BDSPAC)
 1308: *
 1309:                CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU,
 1310:      $                      WORK( IVT ), LDWKVT, DUM, IDUM,
 1311:      $                      WORK( NWORK ), IWORK, INFO )
 1312: *
 1313: *              Overwrite U by left singular vectors of A
 1314: *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
 1315: *
 1316:                CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
 1317:      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
 1318:      $                      LWORK-NWORK+1, IERR )
 1319: *
 1320:                IF( LWORK.GE.M*N+3*M+BDSPAC ) THEN
 1321: *
 1322: *                 Overwrite WORK(IVT) by left singular vectors of A
 1323: *                 (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
 1324: *
 1325:                   CALL DORMBR( 'P', 'R', 'T', M, N, M, A, LDA,
 1326:      $                         WORK( ITAUP ), WORK( IVT ), LDWKVT,
 1327:      $                         WORK( NWORK ), LWORK-NWORK+1, IERR )
 1328: *
 1329: *                 Copy right singular vectors of A from WORK(IVT) to A
 1330: *
 1331:                   CALL DLACPY( 'F', M, N, WORK( IVT ), LDWKVT, A, LDA )
 1332:                ELSE
 1333: *
 1334: *                 Generate P**T in A
 1335: *                 (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
 1336: *
 1337:                   CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
 1338:      $                         WORK( NWORK ), LWORK-NWORK+1, IERR )
 1339: *
 1340: *                 Multiply Q in A by right singular vectors of
 1341: *                 bidiagonal matrix in WORK(IVT), storing result in
 1342: *                 WORK(IL) and copying to A
 1343: *                 (Workspace: need 2*M*M, prefer M*M+M*N)
 1344: *
 1345:                   DO 40 I = 1, N, CHUNK
 1346:                      BLK = MIN( N-I+1, CHUNK )
 1347:                      CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IVT ),
 1348:      $                           LDWKVT, A( 1, I ), LDA, ZERO,
 1349:      $                           WORK( IL ), M )
 1350:                      CALL DLACPY( 'F', M, BLK, WORK( IL ), M, A( 1, I ),
 1351:      $                            LDA )
 1352:    40             CONTINUE
 1353:                END IF
 1354:             ELSE IF( WNTQS ) THEN
 1355: *
 1356: *              Perform bidiagonal SVD, computing left singular vectors
 1357: *              of bidiagonal matrix in U and computing right singular
 1358: *              vectors of bidiagonal matrix in VT
 1359: *              (Workspace: need M+BDSPAC)
 1360: *
 1361:                CALL DLASET( 'F', M, N, ZERO, ZERO, VT, LDVT )
 1362:                CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU, VT,
 1363:      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
 1364:      $                      INFO )
 1365: *
 1366: *              Overwrite U by left singular vectors of A and VT
 1367: *              by right singular vectors of A
 1368: *              (Workspace: need 3*M, prefer 2*M+M*NB)
 1369: *
 1370:                CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
 1371:      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
 1372:      $                      LWORK-NWORK+1, IERR )
 1373:                CALL DORMBR( 'P', 'R', 'T', M, N, M, A, LDA,
 1374:      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
 1375:      $                      LWORK-NWORK+1, IERR )
 1376:             ELSE IF( WNTQA ) THEN
 1377: *
 1378: *              Perform bidiagonal SVD, computing left singular vectors
 1379: *              of bidiagonal matrix in U and computing right singular
 1380: *              vectors of bidiagonal matrix in VT
 1381: *              (Workspace: need M+BDSPAC)
 1382: *
 1383:                CALL DLASET( 'F', N, N, ZERO, ZERO, VT, LDVT )
 1384:                CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU, VT,
 1385:      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
 1386:      $                      INFO )
 1387: *
 1388: *              Set the right corner of VT to identity matrix
 1389: *
 1390:                IF( N.GT.M ) THEN
 1391:                   CALL DLASET( 'F', N-M, N-M, ZERO, ONE, VT( M+1, M+1 ),
 1392:      $                         LDVT )
 1393:                END IF
 1394: *
 1395: *              Overwrite U by left singular vectors of A and VT
 1396: *              by right singular vectors of A
 1397: *              (Workspace: need 2*M+N, prefer 2*M+N*NB)
 1398: *
 1399:                CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
 1400:      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
 1401:      $                      LWORK-NWORK+1, IERR )
 1402:                CALL DORMBR( 'P', 'R', 'T', N, N, M, A, LDA,
 1403:      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
 1404:      $                      LWORK-NWORK+1, IERR )
 1405:             END IF
 1406: *
 1407:          END IF
 1408: *
 1409:       END IF
 1410: *
 1411: *     Undo scaling if necessary
 1412: *
 1413:       IF( ISCL.EQ.1 ) THEN
 1414:          IF( ANRM.GT.BIGNUM )
 1415:      $      CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
 1416:      $                   IERR )
 1417:          IF( ANRM.LT.SMLNUM )
 1418:      $      CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
 1419:      $                   IERR )
 1420:       END IF
 1421: *
 1422: *     Return optimal workspace in WORK(1)
 1423: *
 1424:       WORK( 1 ) = MAXWRK
 1425: *
 1426:       RETURN
 1427: *
 1428: *     End of DGESDD
 1429: *
 1430:       END

CVSweb interface <joel.bertrand@systella.fr>