File:  [local] / rpl / lapack / lapack / dgesvd.f
Revision 1.17: download - view: text, annotated - select for diffs - revision graph
Sat Jun 17 10:53:49 2017 UTC (6 years, 10 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Mise à jour de lapack.

    1: *> \brief <b> DGESVD 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 DGESVD + dependencies
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dgesvd.f">
   11: *> [TGZ]</a>
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dgesvd.f">
   13: *> [ZIP]</a>
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgesvd.f">
   15: *> [TXT]</a>
   16: *> \endhtmlonly
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *       SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT,
   22: *                          WORK, LWORK, INFO )
   23: *
   24: *       .. Scalar Arguments ..
   25: *       CHARACTER          JOBU, JOBVT
   26: *       INTEGER            INFO, LDA, LDU, LDVT, LWORK, M, N
   27: *       ..
   28: *       .. Array Arguments ..
   29: *       DOUBLE PRECISION   A( LDA, * ), S( * ), U( LDU, * ),
   30: *      $                   VT( LDVT, * ), WORK( * )
   31: *       ..
   32: *
   33: *
   34: *> \par Purpose:
   35: *  =============
   36: *>
   37: *> \verbatim
   38: *>
   39: *> DGESVD computes the singular value decomposition (SVD) of a real
   40: *> M-by-N matrix A, optionally computing the left and/or right singular
   41: *> vectors. The SVD is written
   42: *>
   43: *>      A = U * SIGMA * transpose(V)
   44: *>
   45: *> where SIGMA is an M-by-N matrix which is zero except for its
   46: *> min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
   47: *> V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
   48: *> are the singular values of A; they are real and non-negative, and
   49: *> are returned in descending order.  The first min(m,n) columns of
   50: *> U and V are the left and right singular vectors of A.
   51: *>
   52: *> Note that the routine returns V**T, not V.
   53: *> \endverbatim
   54: *
   55: *  Arguments:
   56: *  ==========
   57: *
   58: *> \param[in] JOBU
   59: *> \verbatim
   60: *>          JOBU is CHARACTER*1
   61: *>          Specifies options for computing all or part of the matrix U:
   62: *>          = 'A':  all M columns of U are returned in array U:
   63: *>          = 'S':  the first min(m,n) columns of U (the left singular
   64: *>                  vectors) are returned in the array U;
   65: *>          = 'O':  the first min(m,n) columns of U (the left singular
   66: *>                  vectors) are overwritten on the array A;
   67: *>          = 'N':  no columns of U (no left singular vectors) are
   68: *>                  computed.
   69: *> \endverbatim
   70: *>
   71: *> \param[in] JOBVT
   72: *> \verbatim
   73: *>          JOBVT is CHARACTER*1
   74: *>          Specifies options for computing all or part of the matrix
   75: *>          V**T:
   76: *>          = 'A':  all N rows of V**T are returned in the array VT;
   77: *>          = 'S':  the first min(m,n) rows of V**T (the right singular
   78: *>                  vectors) are returned in the array VT;
   79: *>          = 'O':  the first min(m,n) rows of V**T (the right singular
   80: *>                  vectors) are overwritten on the array A;
   81: *>          = 'N':  no rows of V**T (no right singular vectors) are
   82: *>                  computed.
   83: *>
   84: *>          JOBVT and JOBU cannot both be 'O'.
   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 JOBU = 'O',  A is overwritten with the first min(m,n)
  105: *>                          columns of U (the left singular vectors,
  106: *>                          stored columnwise);
  107: *>          if JOBVT = 'O', A is overwritten with the first min(m,n)
  108: *>                          rows of V**T (the right singular vectors,
  109: *>                          stored rowwise);
  110: *>          if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A
  111: *>                          are destroyed.
  112: *> \endverbatim
  113: *>
  114: *> \param[in] LDA
  115: *> \verbatim
  116: *>          LDA is INTEGER
  117: *>          The leading dimension of the array A.  LDA >= max(1,M).
  118: *> \endverbatim
  119: *>
  120: *> \param[out] S
  121: *> \verbatim
  122: *>          S is DOUBLE PRECISION array, dimension (min(M,N))
  123: *>          The singular values of A, sorted so that S(i) >= S(i+1).
  124: *> \endverbatim
  125: *>
  126: *> \param[out] U
  127: *> \verbatim
  128: *>          U is DOUBLE PRECISION array, dimension (LDU,UCOL)
  129: *>          (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'.
  130: *>          If JOBU = 'A', U contains the M-by-M orthogonal matrix U;
  131: *>          if JOBU = 'S', U contains the first min(m,n) columns of U
  132: *>          (the left singular vectors, stored columnwise);
  133: *>          if JOBU = 'N' or 'O', U is not referenced.
  134: *> \endverbatim
  135: *>
  136: *> \param[in] LDU
  137: *> \verbatim
  138: *>          LDU is INTEGER
  139: *>          The leading dimension of the array U.  LDU >= 1; if
  140: *>          JOBU = 'S' or 'A', LDU >= M.
  141: *> \endverbatim
  142: *>
  143: *> \param[out] VT
  144: *> \verbatim
  145: *>          VT is DOUBLE PRECISION array, dimension (LDVT,N)
  146: *>          If JOBVT = 'A', VT contains the N-by-N orthogonal matrix
  147: *>          V**T;
  148: *>          if JOBVT = 'S', VT contains the first min(m,n) rows of
  149: *>          V**T (the right singular vectors, stored rowwise);
  150: *>          if JOBVT = 'N' or 'O', VT is not referenced.
  151: *> \endverbatim
  152: *>
  153: *> \param[in] LDVT
  154: *> \verbatim
  155: *>          LDVT is INTEGER
  156: *>          The leading dimension of the array VT.  LDVT >= 1; if
  157: *>          JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N).
  158: *> \endverbatim
  159: *>
  160: *> \param[out] WORK
  161: *> \verbatim
  162: *>          WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
  163: *>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
  164: *>          if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged
  165: *>          superdiagonal elements of an upper bidiagonal matrix B
  166: *>          whose diagonal is in S (not necessarily sorted). B
  167: *>          satisfies A = U * B * VT, so it has the same singular values
  168: *>          as A, and singular vectors related by U and VT.
  169: *> \endverbatim
  170: *>
  171: *> \param[in] LWORK
  172: *> \verbatim
  173: *>          LWORK is INTEGER
  174: *>          The dimension of the array WORK.
  175: *>          LWORK >= MAX(1,5*MIN(M,N)) for the paths (see comments inside code):
  176: *>             - PATH 1  (M much larger than N, JOBU='N')
  177: *>             - PATH 1t (N much larger than M, JOBVT='N')
  178: *>          LWORK >= MAX(1,3*MIN(M,N) + MAX(M,N),5*MIN(M,N)) for the other paths
  179: *>          For good performance, LWORK should generally be larger.
  180: *>
  181: *>          If LWORK = -1, then a workspace query is assumed; the routine
  182: *>          only calculates the optimal size of the WORK array, returns
  183: *>          this value as the first entry of the WORK array, and no error
  184: *>          message related to LWORK is issued by XERBLA.
  185: *> \endverbatim
  186: *>
  187: *> \param[out] INFO
  188: *> \verbatim
  189: *>          INFO is INTEGER
  190: *>          = 0:  successful exit.
  191: *>          < 0:  if INFO = -i, the i-th argument had an illegal value.
  192: *>          > 0:  if DBDSQR did not converge, INFO specifies how many
  193: *>                superdiagonals of an intermediate bidiagonal form B
  194: *>                did not converge to zero. See the description of WORK
  195: *>                above for details.
  196: *> \endverbatim
  197: *
  198: *  Authors:
  199: *  ========
  200: *
  201: *> \author Univ. of Tennessee
  202: *> \author Univ. of California Berkeley
  203: *> \author Univ. of Colorado Denver
  204: *> \author NAG Ltd.
  205: *
  206: *> \date April 2012
  207: *
  208: *> \ingroup doubleGEsing
  209: *
  210: *  =====================================================================
  211:       SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU,
  212:      $                   VT, LDVT, WORK, LWORK, INFO )
  213: *
  214: *  -- LAPACK driver routine (version 3.7.0) --
  215: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  216: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  217: *     April 2012
  218: *
  219: *     .. Scalar Arguments ..
  220:       CHARACTER          JOBU, JOBVT
  221:       INTEGER            INFO, LDA, LDU, LDVT, LWORK, M, N
  222: *     ..
  223: *     .. Array Arguments ..
  224:       DOUBLE PRECISION   A( LDA, * ), S( * ), U( LDU, * ),
  225:      $                   VT( LDVT, * ), WORK( * )
  226: *     ..
  227: *
  228: *  =====================================================================
  229: *
  230: *     .. Parameters ..
  231:       DOUBLE PRECISION   ZERO, ONE
  232:       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
  233: *     ..
  234: *     .. Local Scalars ..
  235:       LOGICAL            LQUERY, WNTUA, WNTUAS, WNTUN, WNTUO, WNTUS,
  236:      $                   WNTVA, WNTVAS, WNTVN, WNTVO, WNTVS
  237:       INTEGER            BDSPAC, BLK, CHUNK, I, IE, IERR, IR, ISCL,
  238:      $                   ITAU, ITAUP, ITAUQ, IU, IWORK, LDWRKR, LDWRKU,
  239:      $                   MAXWRK, MINMN, MINWRK, MNTHR, NCU, NCVT, NRU,
  240:      $                   NRVT, WRKBL
  241:       INTEGER            LWORK_DGEQRF, LWORK_DORGQR_N, LWORK_DORGQR_M,
  242:      $                   LWORK_DGEBRD, LWORK_DORGBR_P, LWORK_DORGBR_Q,
  243:      $                   LWORK_DGELQF, LWORK_DORGLQ_N, LWORK_DORGLQ_M
  244:       DOUBLE PRECISION   ANRM, BIGNUM, EPS, SMLNUM
  245: *     ..
  246: *     .. Local Arrays ..
  247:       DOUBLE PRECISION   DUM( 1 )
  248: *     ..
  249: *     .. External Subroutines ..
  250:       EXTERNAL           DBDSQR, DGEBRD, DGELQF, DGEMM, DGEQRF, DLACPY,
  251:      $                   DLASCL, DLASET, DORGBR, DORGLQ, DORGQR, DORMBR,
  252:      $                   XERBLA
  253: *     ..
  254: *     .. External Functions ..
  255:       LOGICAL            LSAME
  256:       INTEGER            ILAENV
  257:       DOUBLE PRECISION   DLAMCH, DLANGE
  258:       EXTERNAL           LSAME, ILAENV, DLAMCH, DLANGE
  259: *     ..
  260: *     .. Intrinsic Functions ..
  261:       INTRINSIC          MAX, MIN, SQRT
  262: *     ..
  263: *     .. Executable Statements ..
  264: *
  265: *     Test the input arguments
  266: *
  267:       INFO = 0
  268:       MINMN = MIN( M, N )
  269:       WNTUA = LSAME( JOBU, 'A' )
  270:       WNTUS = LSAME( JOBU, 'S' )
  271:       WNTUAS = WNTUA .OR. WNTUS
  272:       WNTUO = LSAME( JOBU, 'O' )
  273:       WNTUN = LSAME( JOBU, 'N' )
  274:       WNTVA = LSAME( JOBVT, 'A' )
  275:       WNTVS = LSAME( JOBVT, 'S' )
  276:       WNTVAS = WNTVA .OR. WNTVS
  277:       WNTVO = LSAME( JOBVT, 'O' )
  278:       WNTVN = LSAME( JOBVT, 'N' )
  279:       LQUERY = ( LWORK.EQ.-1 )
  280: *
  281:       IF( .NOT.( WNTUA .OR. WNTUS .OR. WNTUO .OR. WNTUN ) ) THEN
  282:          INFO = -1
  283:       ELSE IF( .NOT.( WNTVA .OR. WNTVS .OR. WNTVO .OR. WNTVN ) .OR.
  284:      $         ( WNTVO .AND. WNTUO ) ) THEN
  285:          INFO = -2
  286:       ELSE IF( M.LT.0 ) THEN
  287:          INFO = -3
  288:       ELSE IF( N.LT.0 ) THEN
  289:          INFO = -4
  290:       ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
  291:          INFO = -6
  292:       ELSE IF( LDU.LT.1 .OR. ( WNTUAS .AND. LDU.LT.M ) ) THEN
  293:          INFO = -9
  294:       ELSE IF( LDVT.LT.1 .OR. ( WNTVA .AND. LDVT.LT.N ) .OR.
  295:      $         ( WNTVS .AND. LDVT.LT.MINMN ) ) THEN
  296:          INFO = -11
  297:       END IF
  298: *
  299: *     Compute workspace
  300: *      (Note: Comments in the code beginning "Workspace:" describe the
  301: *       minimal amount of workspace needed at that point in the code,
  302: *       as well as the preferred amount for good performance.
  303: *       NB refers to the optimal block size for the immediately
  304: *       following subroutine, as returned by ILAENV.)
  305: *
  306:       IF( INFO.EQ.0 ) THEN
  307:          MINWRK = 1
  308:          MAXWRK = 1
  309:          IF( M.GE.N .AND. MINMN.GT.0 ) THEN
  310: *
  311: *           Compute space needed for DBDSQR
  312: *
  313:             MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
  314:             BDSPAC = 5*N
  315: *           Compute space needed for DGEQRF
  316:             CALL DGEQRF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
  317:             LWORK_DGEQRF = INT( DUM(1) )
  318: *           Compute space needed for DORGQR
  319:             CALL DORGQR( M, N, N, A, LDA, DUM(1), DUM(1), -1, IERR )
  320:             LWORK_DORGQR_N = INT( DUM(1) )
  321:             CALL DORGQR( M, M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
  322:             LWORK_DORGQR_M = INT( DUM(1) )
  323: *           Compute space needed for DGEBRD
  324:             CALL DGEBRD( N, N, A, LDA, S, DUM(1), DUM(1),
  325:      $                   DUM(1), DUM(1), -1, IERR )
  326:             LWORK_DGEBRD = INT( DUM(1) )
  327: *           Compute space needed for DORGBR P
  328:             CALL DORGBR( 'P', N, N, N, A, LDA, DUM(1),
  329:      $                   DUM(1), -1, IERR )
  330:             LWORK_DORGBR_P = INT( DUM(1) )
  331: *           Compute space needed for DORGBR Q
  332:             CALL DORGBR( 'Q', N, N, N, A, LDA, DUM(1),
  333:      $                   DUM(1), -1, IERR )
  334:             LWORK_DORGBR_Q = INT( DUM(1) )
  335: *
  336:             IF( M.GE.MNTHR ) THEN
  337:                IF( WNTUN ) THEN
  338: *
  339: *                 Path 1 (M much larger than N, JOBU='N')
  340: *
  341:                   MAXWRK = N + LWORK_DGEQRF
  342:                   MAXWRK = MAX( MAXWRK, 3*N + LWORK_DGEBRD )
  343:                   IF( WNTVO .OR. WNTVAS )
  344:      $               MAXWRK = MAX( MAXWRK, 3*N + LWORK_DORGBR_P )
  345:                   MAXWRK = MAX( MAXWRK, BDSPAC )
  346:                   MINWRK = MAX( 4*N, BDSPAC )
  347:                ELSE IF( WNTUO .AND. WNTVN ) THEN
  348: *
  349: *                 Path 2 (M much larger than N, JOBU='O', JOBVT='N')
  350: *
  351:                   WRKBL = N + LWORK_DGEQRF
  352:                   WRKBL = MAX( WRKBL, N + LWORK_DORGQR_N )
  353:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DGEBRD )
  354:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_Q )
  355:                   WRKBL = MAX( WRKBL, BDSPAC )
  356:                   MAXWRK = MAX( N*N + WRKBL, N*N + M*N + N )
  357:                   MINWRK = MAX( 3*N + M, BDSPAC )
  358:                ELSE IF( WNTUO .AND. WNTVAS ) THEN
  359: *
  360: *                 Path 3 (M much larger than N, JOBU='O', JOBVT='S' or
  361: *                 'A')
  362: *
  363:                   WRKBL = N + LWORK_DGEQRF
  364:                   WRKBL = MAX( WRKBL, N + LWORK_DORGQR_N )
  365:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DGEBRD )
  366:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_Q )
  367:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_P )
  368:                   WRKBL = MAX( WRKBL, BDSPAC )
  369:                   MAXWRK = MAX( N*N + WRKBL, N*N + M*N + N )
  370:                   MINWRK = MAX( 3*N + M, BDSPAC )
  371:                ELSE IF( WNTUS .AND. WNTVN ) THEN
  372: *
  373: *                 Path 4 (M much larger than N, JOBU='S', JOBVT='N')
  374: *
  375:                   WRKBL = N + LWORK_DGEQRF
  376:                   WRKBL = MAX( WRKBL, N + LWORK_DORGQR_N )
  377:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DGEBRD )
  378:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_Q )
  379:                   WRKBL = MAX( WRKBL, BDSPAC )
  380:                   MAXWRK = N*N + WRKBL
  381:                   MINWRK = MAX( 3*N + M, BDSPAC )
  382:                ELSE IF( WNTUS .AND. WNTVO ) THEN
  383: *
  384: *                 Path 5 (M much larger than N, JOBU='S', JOBVT='O')
  385: *
  386:                   WRKBL = N + LWORK_DGEQRF
  387:                   WRKBL = MAX( WRKBL, N + LWORK_DORGQR_N )
  388:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DGEBRD )
  389:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_Q )
  390:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_P )
  391:                   WRKBL = MAX( WRKBL, BDSPAC )
  392:                   MAXWRK = 2*N*N + WRKBL
  393:                   MINWRK = MAX( 3*N + M, BDSPAC )
  394:                ELSE IF( WNTUS .AND. WNTVAS ) THEN
  395: *
  396: *                 Path 6 (M much larger than N, JOBU='S', JOBVT='S' or
  397: *                 'A')
  398: *
  399:                   WRKBL = N + LWORK_DGEQRF
  400:                   WRKBL = MAX( WRKBL, N + LWORK_DORGQR_N )
  401:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DGEBRD )
  402:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_Q )
  403:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_P )
  404:                   WRKBL = MAX( WRKBL, BDSPAC )
  405:                   MAXWRK = N*N + WRKBL
  406:                   MINWRK = MAX( 3*N + M, BDSPAC )
  407:                ELSE IF( WNTUA .AND. WNTVN ) THEN
  408: *
  409: *                 Path 7 (M much larger than N, JOBU='A', JOBVT='N')
  410: *
  411:                   WRKBL = N + LWORK_DGEQRF
  412:                   WRKBL = MAX( WRKBL, N + LWORK_DORGQR_M )
  413:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DGEBRD )
  414:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_Q )
  415:                   WRKBL = MAX( WRKBL, BDSPAC )
  416:                   MAXWRK = N*N + WRKBL
  417:                   MINWRK = MAX( 3*N + M, BDSPAC )
  418:                ELSE IF( WNTUA .AND. WNTVO ) THEN
  419: *
  420: *                 Path 8 (M much larger than N, JOBU='A', JOBVT='O')
  421: *
  422:                   WRKBL = N + LWORK_DGEQRF
  423:                   WRKBL = MAX( WRKBL, N + LWORK_DORGQR_M )
  424:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DGEBRD )
  425:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_Q )
  426:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_P )
  427:                   WRKBL = MAX( WRKBL, BDSPAC )
  428:                   MAXWRK = 2*N*N + WRKBL
  429:                   MINWRK = MAX( 3*N + M, BDSPAC )
  430:                ELSE IF( WNTUA .AND. WNTVAS ) THEN
  431: *
  432: *                 Path 9 (M much larger than N, JOBU='A', JOBVT='S' or
  433: *                 'A')
  434: *
  435:                   WRKBL = N + LWORK_DGEQRF
  436:                   WRKBL = MAX( WRKBL, N + LWORK_DORGQR_M )
  437:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DGEBRD )
  438:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_Q )
  439:                   WRKBL = MAX( WRKBL, 3*N + LWORK_DORGBR_P )
  440:                   WRKBL = MAX( WRKBL, BDSPAC )
  441:                   MAXWRK = N*N + WRKBL
  442:                   MINWRK = MAX( 3*N + M, BDSPAC )
  443:                END IF
  444:             ELSE
  445: *
  446: *              Path 10 (M at least N, but not much larger)
  447: *
  448:                CALL DGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
  449:      $                   DUM(1), DUM(1), -1, IERR )
  450:                LWORK_DGEBRD = INT( DUM(1) )
  451:                MAXWRK = 3*N + LWORK_DGEBRD
  452:                IF( WNTUS .OR. WNTUO ) THEN
  453:                   CALL DORGBR( 'Q', M, N, N, A, LDA, DUM(1),
  454:      $                   DUM(1), -1, IERR )
  455:                   LWORK_DORGBR_Q = INT( DUM(1) )
  456:                   MAXWRK = MAX( MAXWRK, 3*N + LWORK_DORGBR_Q )
  457:                END IF
  458:                IF( WNTUA ) THEN
  459:                   CALL DORGBR( 'Q', M, M, N, A, LDA, DUM(1),
  460:      $                   DUM(1), -1, IERR )
  461:                   LWORK_DORGBR_Q = INT( DUM(1) )
  462:                   MAXWRK = MAX( MAXWRK, 3*N + LWORK_DORGBR_Q )
  463:                END IF
  464:                IF( .NOT.WNTVN ) THEN
  465:                  MAXWRK = MAX( MAXWRK, 3*N + LWORK_DORGBR_P )
  466:                END IF
  467:                MAXWRK = MAX( MAXWRK, BDSPAC )
  468:                MINWRK = MAX( 3*N + M, BDSPAC )
  469:             END IF
  470:          ELSE IF( MINMN.GT.0 ) THEN
  471: *
  472: *           Compute space needed for DBDSQR
  473: *
  474:             MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
  475:             BDSPAC = 5*M
  476: *           Compute space needed for DGELQF
  477:             CALL DGELQF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
  478:             LWORK_DGELQF = INT( DUM(1) )
  479: *           Compute space needed for DORGLQ
  480:             CALL DORGLQ( N, N, M, DUM(1), N, DUM(1), DUM(1), -1, IERR )
  481:             LWORK_DORGLQ_N = INT( DUM(1) )
  482:             CALL DORGLQ( M, N, M, A, LDA, DUM(1), DUM(1), -1, IERR )
  483:             LWORK_DORGLQ_M = INT( DUM(1) )
  484: *           Compute space needed for DGEBRD
  485:             CALL DGEBRD( M, M, A, LDA, S, DUM(1), DUM(1),
  486:      $                   DUM(1), DUM(1), -1, IERR )
  487:             LWORK_DGEBRD = INT( DUM(1) )
  488: *            Compute space needed for DORGBR P
  489:             CALL DORGBR( 'P', M, M, M, A, N, DUM(1),
  490:      $                   DUM(1), -1, IERR )
  491:             LWORK_DORGBR_P = INT( DUM(1) )
  492: *           Compute space needed for DORGBR Q
  493:             CALL DORGBR( 'Q', M, M, M, A, N, DUM(1),
  494:      $                   DUM(1), -1, IERR )
  495:             LWORK_DORGBR_Q = INT( DUM(1) )
  496:             IF( N.GE.MNTHR ) THEN
  497:                IF( WNTVN ) THEN
  498: *
  499: *                 Path 1t(N much larger than M, JOBVT='N')
  500: *
  501:                   MAXWRK = M + LWORK_DGELQF
  502:                   MAXWRK = MAX( MAXWRK, 3*M + LWORK_DGEBRD )
  503:                   IF( WNTUO .OR. WNTUAS )
  504:      $               MAXWRK = MAX( MAXWRK, 3*M + LWORK_DORGBR_Q )
  505:                   MAXWRK = MAX( MAXWRK, BDSPAC )
  506:                   MINWRK = MAX( 4*M, BDSPAC )
  507:                ELSE IF( WNTVO .AND. WNTUN ) THEN
  508: *
  509: *                 Path 2t(N much larger than M, JOBU='N', JOBVT='O')
  510: *
  511:                   WRKBL = M + LWORK_DGELQF
  512:                   WRKBL = MAX( WRKBL, M + LWORK_DORGLQ_M )
  513:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DGEBRD )
  514:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_P )
  515:                   WRKBL = MAX( WRKBL, BDSPAC )
  516:                   MAXWRK = MAX( M*M + WRKBL, M*M + M*N + M )
  517:                   MINWRK = MAX( 3*M + N, BDSPAC )
  518:                ELSE IF( WNTVO .AND. WNTUAS ) THEN
  519: *
  520: *                 Path 3t(N much larger than M, JOBU='S' or 'A',
  521: *                 JOBVT='O')
  522: *
  523:                   WRKBL = M + LWORK_DGELQF
  524:                   WRKBL = MAX( WRKBL, M + LWORK_DORGLQ_M )
  525:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DGEBRD )
  526:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_P )
  527:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_Q )
  528:                   WRKBL = MAX( WRKBL, BDSPAC )
  529:                   MAXWRK = MAX( M*M + WRKBL, M*M + M*N + M )
  530:                   MINWRK = MAX( 3*M + N, BDSPAC )
  531:                ELSE IF( WNTVS .AND. WNTUN ) THEN
  532: *
  533: *                 Path 4t(N much larger than M, JOBU='N', JOBVT='S')
  534: *
  535:                   WRKBL = M + LWORK_DGELQF
  536:                   WRKBL = MAX( WRKBL, M + LWORK_DORGLQ_M )
  537:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DGEBRD )
  538:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_P )
  539:                   WRKBL = MAX( WRKBL, BDSPAC )
  540:                   MAXWRK = M*M + WRKBL
  541:                   MINWRK = MAX( 3*M + N, BDSPAC )
  542:                ELSE IF( WNTVS .AND. WNTUO ) THEN
  543: *
  544: *                 Path 5t(N much larger than M, JOBU='O', JOBVT='S')
  545: *
  546:                   WRKBL = M + LWORK_DGELQF
  547:                   WRKBL = MAX( WRKBL, M + LWORK_DORGLQ_M )
  548:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DGEBRD )
  549:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_P )
  550:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_Q )
  551:                   WRKBL = MAX( WRKBL, BDSPAC )
  552:                   MAXWRK = 2*M*M + WRKBL
  553:                   MINWRK = MAX( 3*M + N, BDSPAC )
  554:                ELSE IF( WNTVS .AND. WNTUAS ) THEN
  555: *
  556: *                 Path 6t(N much larger than M, JOBU='S' or 'A',
  557: *                 JOBVT='S')
  558: *
  559:                   WRKBL = M + LWORK_DGELQF
  560:                   WRKBL = MAX( WRKBL, M + LWORK_DORGLQ_M )
  561:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DGEBRD )
  562:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_P )
  563:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_Q )
  564:                   WRKBL = MAX( WRKBL, BDSPAC )
  565:                   MAXWRK = M*M + WRKBL
  566:                   MINWRK = MAX( 3*M + N, BDSPAC )
  567:                ELSE IF( WNTVA .AND. WNTUN ) THEN
  568: *
  569: *                 Path 7t(N much larger than M, JOBU='N', JOBVT='A')
  570: *
  571:                   WRKBL = M + LWORK_DGELQF
  572:                   WRKBL = MAX( WRKBL, M + LWORK_DORGLQ_N )
  573:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DGEBRD )
  574:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_P )
  575:                   WRKBL = MAX( WRKBL, BDSPAC )
  576:                   MAXWRK = M*M + WRKBL
  577:                   MINWRK = MAX( 3*M + N, BDSPAC )
  578:                ELSE IF( WNTVA .AND. WNTUO ) THEN
  579: *
  580: *                 Path 8t(N much larger than M, JOBU='O', JOBVT='A')
  581: *
  582:                   WRKBL = M + LWORK_DGELQF
  583:                   WRKBL = MAX( WRKBL, M + LWORK_DORGLQ_N )
  584:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DGEBRD )
  585:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_P )
  586:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_Q )
  587:                   WRKBL = MAX( WRKBL, BDSPAC )
  588:                   MAXWRK = 2*M*M + WRKBL
  589:                   MINWRK = MAX( 3*M + N, BDSPAC )
  590:                ELSE IF( WNTVA .AND. WNTUAS ) THEN
  591: *
  592: *                 Path 9t(N much larger than M, JOBU='S' or 'A',
  593: *                 JOBVT='A')
  594: *
  595:                   WRKBL = M + LWORK_DGELQF
  596:                   WRKBL = MAX( WRKBL, M + LWORK_DORGLQ_N )
  597:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DGEBRD )
  598:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_P )
  599:                   WRKBL = MAX( WRKBL, 3*M + LWORK_DORGBR_Q )
  600:                   WRKBL = MAX( WRKBL, BDSPAC )
  601:                   MAXWRK = M*M + WRKBL
  602:                   MINWRK = MAX( 3*M + N, BDSPAC )
  603:                END IF
  604:             ELSE
  605: *
  606: *              Path 10t(N greater than M, but not much larger)
  607: *
  608:                CALL DGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
  609:      $                   DUM(1), DUM(1), -1, IERR )
  610:                LWORK_DGEBRD = INT( DUM(1) )
  611:                MAXWRK = 3*M + LWORK_DGEBRD
  612:                IF( WNTVS .OR. WNTVO ) THEN
  613: *                Compute space needed for DORGBR P
  614:                  CALL DORGBR( 'P', M, N, M, A, N, DUM(1),
  615:      $                   DUM(1), -1, IERR )
  616:                  LWORK_DORGBR_P = INT( DUM(1) )
  617:                  MAXWRK = MAX( MAXWRK, 3*M + LWORK_DORGBR_P )
  618:                END IF
  619:                IF( WNTVA ) THEN
  620:                  CALL DORGBR( 'P', N, N, M, A, N, DUM(1),
  621:      $                   DUM(1), -1, IERR )
  622:                  LWORK_DORGBR_P = INT( DUM(1) )
  623:                  MAXWRK = MAX( MAXWRK, 3*M + LWORK_DORGBR_P )
  624:                END IF
  625:                IF( .NOT.WNTUN ) THEN
  626:                   MAXWRK = MAX( MAXWRK, 3*M + LWORK_DORGBR_Q )
  627:                END IF
  628:                MAXWRK = MAX( MAXWRK, BDSPAC )
  629:                MINWRK = MAX( 3*M + N, BDSPAC )
  630:             END IF
  631:          END IF
  632:          MAXWRK = MAX( MAXWRK, MINWRK )
  633:          WORK( 1 ) = MAXWRK
  634: *
  635:          IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
  636:             INFO = -13
  637:          END IF
  638:       END IF
  639: *
  640:       IF( INFO.NE.0 ) THEN
  641:          CALL XERBLA( 'DGESVD', -INFO )
  642:          RETURN
  643:       ELSE IF( LQUERY ) THEN
  644:          RETURN
  645:       END IF
  646: *
  647: *     Quick return if possible
  648: *
  649:       IF( M.EQ.0 .OR. N.EQ.0 ) THEN
  650:          RETURN
  651:       END IF
  652: *
  653: *     Get machine constants
  654: *
  655:       EPS = DLAMCH( 'P' )
  656:       SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPS
  657:       BIGNUM = ONE / SMLNUM
  658: *
  659: *     Scale A if max element outside range [SMLNUM,BIGNUM]
  660: *
  661:       ANRM = DLANGE( 'M', M, N, A, LDA, DUM )
  662:       ISCL = 0
  663:       IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
  664:          ISCL = 1
  665:          CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, IERR )
  666:       ELSE IF( ANRM.GT.BIGNUM ) THEN
  667:          ISCL = 1
  668:          CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, IERR )
  669:       END IF
  670: *
  671:       IF( M.GE.N ) THEN
  672: *
  673: *        A has at least as many rows as columns. If A has sufficiently
  674: *        more rows than columns, first reduce using the QR
  675: *        decomposition (if sufficient workspace available)
  676: *
  677:          IF( M.GE.MNTHR ) THEN
  678: *
  679:             IF( WNTUN ) THEN
  680: *
  681: *              Path 1 (M much larger than N, JOBU='N')
  682: *              No left singular vectors to be computed
  683: *
  684:                ITAU = 1
  685:                IWORK = ITAU + N
  686: *
  687: *              Compute A=Q*R
  688: *              (Workspace: need 2*N, prefer N + N*NB)
  689: *
  690:                CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
  691:      $                      LWORK-IWORK+1, IERR )
  692: *
  693: *              Zero out below R
  694: *
  695:                IF( N .GT. 1 ) THEN
  696:                   CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),
  697:      $                         LDA )
  698:                END IF
  699:                IE = 1
  700:                ITAUQ = IE + N
  701:                ITAUP = ITAUQ + N
  702:                IWORK = ITAUP + N
  703: *
  704: *              Bidiagonalize R in A
  705: *              (Workspace: need 4*N, prefer 3*N + 2*N*NB)
  706: *
  707:                CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
  708:      $                      WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
  709:      $                      IERR )
  710:                NCVT = 0
  711:                IF( WNTVO .OR. WNTVAS ) THEN
  712: *
  713: *                 If right singular vectors desired, generate P'.
  714: *                 (Workspace: need 4*N-1, prefer 3*N + (N-1)*NB)
  715: *
  716:                   CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
  717:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  718:                   NCVT = N
  719:                END IF
  720:                IWORK = IE + N
  721: *
  722: *              Perform bidiagonal QR iteration, computing right
  723: *              singular vectors of A in A if desired
  724: *              (Workspace: need BDSPAC)
  725: *
  726:                CALL DBDSQR( 'U', N, NCVT, 0, 0, S, WORK( IE ), A, LDA,
  727:      $                      DUM, 1, DUM, 1, WORK( IWORK ), INFO )
  728: *
  729: *              If right singular vectors desired in VT, copy them there
  730: *
  731:                IF( WNTVAS )
  732:      $            CALL DLACPY( 'F', N, N, A, LDA, VT, LDVT )
  733: *
  734:             ELSE IF( WNTUO .AND. WNTVN ) THEN
  735: *
  736: *              Path 2 (M much larger than N, JOBU='O', JOBVT='N')
  737: *              N left singular vectors to be overwritten on A and
  738: *              no right singular vectors to be computed
  739: *
  740:                IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
  741: *
  742: *                 Sufficient workspace for a fast algorithm
  743: *
  744:                   IR = 1
  745:                   IF( LWORK.GE.MAX( WRKBL, LDA*N + N ) + LDA*N ) THEN
  746: *
  747: *                    WORK(IU) is LDA by N, WORK(IR) is LDA by N
  748: *
  749:                      LDWRKU = LDA
  750:                      LDWRKR = LDA
  751:                   ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N + N ) + N*N ) THEN
  752: *
  753: *                    WORK(IU) is LDA by N, WORK(IR) is N by N
  754: *
  755:                      LDWRKU = LDA
  756:                      LDWRKR = N
  757:                   ELSE
  758: *
  759: *                    WORK(IU) is LDWRKU by N, WORK(IR) is N by N
  760: *
  761:                      LDWRKU = ( LWORK-N*N-N ) / N
  762:                      LDWRKR = N
  763:                   END IF
  764:                   ITAU = IR + LDWRKR*N
  765:                   IWORK = ITAU + N
  766: *
  767: *                 Compute A=Q*R
  768: *                 (Workspace: need N*N + 2*N, prefer N*N + N + N*NB)
  769: *
  770:                   CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
  771:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  772: *
  773: *                 Copy R to WORK(IR) and zero out below it
  774: *
  775:                   CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )
  776:                   CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),
  777:      $                         LDWRKR )
  778: *
  779: *                 Generate Q in A
  780: *                 (Workspace: need N*N + 2*N, prefer N*N + N + N*NB)
  781: *
  782:                   CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
  783:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  784:                   IE = ITAU
  785:                   ITAUQ = IE + N
  786:                   ITAUP = ITAUQ + N
  787:                   IWORK = ITAUP + N
  788: *
  789: *                 Bidiagonalize R in WORK(IR)
  790: *                 (Workspace: need N*N + 4*N, prefer N*N + 3*N + 2*N*NB)
  791: *
  792:                   CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),
  793:      $                         WORK( ITAUQ ), WORK( ITAUP ),
  794:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  795: *
  796: *                 Generate left vectors bidiagonalizing R
  797: *                 (Workspace: need N*N + 4*N, prefer N*N + 3*N + N*NB)
  798: *
  799:                   CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
  800:      $                         WORK( ITAUQ ), WORK( IWORK ),
  801:      $                         LWORK-IWORK+1, IERR )
  802:                   IWORK = IE + N
  803: *
  804: *                 Perform bidiagonal QR iteration, computing left
  805: *                 singular vectors of R in WORK(IR)
  806: *                 (Workspace: need N*N + BDSPAC)
  807: *
  808:                   CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM, 1,
  809:      $                         WORK( IR ), LDWRKR, DUM, 1,
  810:      $                         WORK( IWORK ), INFO )
  811:                   IU = IE + N
  812: *
  813: *                 Multiply Q in A by left singular vectors of R in
  814: *                 WORK(IR), storing result in WORK(IU) and copying to A
  815: *                 (Workspace: need N*N + 2*N, prefer N*N + M*N + N)
  816: *
  817:                   DO 10 I = 1, M, LDWRKU
  818:                      CHUNK = MIN( M-I+1, LDWRKU )
  819:                      CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
  820:      $                           LDA, WORK( IR ), LDWRKR, ZERO,
  821:      $                           WORK( IU ), LDWRKU )
  822:                      CALL DLACPY( 'F', CHUNK, N, WORK( IU ), LDWRKU,
  823:      $                            A( I, 1 ), LDA )
  824:    10             CONTINUE
  825: *
  826:                ELSE
  827: *
  828: *                 Insufficient workspace for a fast algorithm
  829: *
  830:                   IE = 1
  831:                   ITAUQ = IE + N
  832:                   ITAUP = ITAUQ + N
  833:                   IWORK = ITAUP + N
  834: *
  835: *                 Bidiagonalize A
  836: *                 (Workspace: need 3*N + M, prefer 3*N + (M + N)*NB)
  837: *
  838:                   CALL DGEBRD( M, N, A, LDA, S, WORK( IE ),
  839:      $                         WORK( ITAUQ ), WORK( ITAUP ),
  840:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  841: *
  842: *                 Generate left vectors bidiagonalizing A
  843: *                 (Workspace: need 4*N, prefer 3*N + N*NB)
  844: *
  845:                   CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),
  846:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  847:                   IWORK = IE + N
  848: *
  849: *                 Perform bidiagonal QR iteration, computing left
  850: *                 singular vectors of A in A
  851: *                 (Workspace: need BDSPAC)
  852: *
  853:                   CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM, 1,
  854:      $                         A, LDA, DUM, 1, WORK( IWORK ), INFO )
  855: *
  856:                END IF
  857: *
  858:             ELSE IF( WNTUO .AND. WNTVAS ) THEN
  859: *
  860: *              Path 3 (M much larger than N, JOBU='O', JOBVT='S' or 'A')
  861: *              N left singular vectors to be overwritten on A and
  862: *              N right singular vectors to be computed in VT
  863: *
  864:                IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
  865: *
  866: *                 Sufficient workspace for a fast algorithm
  867: *
  868:                   IR = 1
  869:                   IF( LWORK.GE.MAX( WRKBL, LDA*N + N ) + LDA*N ) THEN
  870: *
  871: *                    WORK(IU) is LDA by N and WORK(IR) is LDA by N
  872: *
  873:                      LDWRKU = LDA
  874:                      LDWRKR = LDA
  875:                   ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N + N ) + N*N ) THEN
  876: *
  877: *                    WORK(IU) is LDA by N and WORK(IR) is N by N
  878: *
  879:                      LDWRKU = LDA
  880:                      LDWRKR = N
  881:                   ELSE
  882: *
  883: *                    WORK(IU) is LDWRKU by N and WORK(IR) is N by N
  884: *
  885:                      LDWRKU = ( LWORK-N*N-N ) / N
  886:                      LDWRKR = N
  887:                   END IF
  888:                   ITAU = IR + LDWRKR*N
  889:                   IWORK = ITAU + N
  890: *
  891: *                 Compute A=Q*R
  892: *                 (Workspace: need N*N + 2*N, prefer N*N + N + N*NB)
  893: *
  894:                   CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
  895:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  896: *
  897: *                 Copy R to VT, zeroing out below it
  898: *
  899:                   CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
  900:                   IF( N.GT.1 )
  901:      $               CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
  902:      $                            VT( 2, 1 ), LDVT )
  903: *
  904: *                 Generate Q in A
  905: *                 (Workspace: need N*N + 2*N, prefer N*N + N + N*NB)
  906: *
  907:                   CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
  908:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  909:                   IE = ITAU
  910:                   ITAUQ = IE + N
  911:                   ITAUP = ITAUQ + N
  912:                   IWORK = ITAUP + N
  913: *
  914: *                 Bidiagonalize R in VT, copying result to WORK(IR)
  915: *                 (Workspace: need N*N + 4*N, prefer N*N + 3*N + 2*N*NB)
  916: *
  917:                   CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
  918:      $                         WORK( ITAUQ ), WORK( ITAUP ),
  919:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  920:                   CALL DLACPY( 'L', N, N, VT, LDVT, WORK( IR ), LDWRKR )
  921: *
  922: *                 Generate left vectors bidiagonalizing R in WORK(IR)
  923: *                 (Workspace: need N*N + 4*N, prefer N*N + 3*N + N*NB)
  924: *
  925:                   CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
  926:      $                         WORK( ITAUQ ), WORK( IWORK ),
  927:      $                         LWORK-IWORK+1, IERR )
  928: *
  929: *                 Generate right vectors bidiagonalizing R in VT
  930: *                 (Workspace: need N*N + 4*N-1, prefer N*N + 3*N + (N-1)*NB)
  931: *
  932:                   CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
  933:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  934:                   IWORK = IE + N
  935: *
  936: *                 Perform bidiagonal QR iteration, computing left
  937: *                 singular vectors of R in WORK(IR) and computing right
  938: *                 singular vectors of R in VT
  939: *                 (Workspace: need N*N + BDSPAC)
  940: *
  941:                   CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT, LDVT,
  942:      $                         WORK( IR ), LDWRKR, DUM, 1,
  943:      $                         WORK( IWORK ), INFO )
  944:                   IU = IE + N
  945: *
  946: *                 Multiply Q in A by left singular vectors of R in
  947: *                 WORK(IR), storing result in WORK(IU) and copying to A
  948: *                 (Workspace: need N*N + 2*N, prefer N*N + M*N + N)
  949: *
  950:                   DO 20 I = 1, M, LDWRKU
  951:                      CHUNK = MIN( M-I+1, LDWRKU )
  952:                      CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
  953:      $                           LDA, WORK( IR ), LDWRKR, ZERO,
  954:      $                           WORK( IU ), LDWRKU )
  955:                      CALL DLACPY( 'F', CHUNK, N, WORK( IU ), LDWRKU,
  956:      $                            A( I, 1 ), LDA )
  957:    20             CONTINUE
  958: *
  959:                ELSE
  960: *
  961: *                 Insufficient workspace for a fast algorithm
  962: *
  963:                   ITAU = 1
  964:                   IWORK = ITAU + N
  965: *
  966: *                 Compute A=Q*R
  967: *                 (Workspace: need 2*N, prefer N + N*NB)
  968: *
  969:                   CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
  970:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  971: *
  972: *                 Copy R to VT, zeroing out below it
  973: *
  974:                   CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
  975:                   IF( N.GT.1 )
  976:      $               CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
  977:      $                            VT( 2, 1 ), LDVT )
  978: *
  979: *                 Generate Q in A
  980: *                 (Workspace: need 2*N, prefer N + N*NB)
  981: *
  982:                   CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
  983:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  984:                   IE = ITAU
  985:                   ITAUQ = IE + N
  986:                   ITAUP = ITAUQ + N
  987:                   IWORK = ITAUP + N
  988: *
  989: *                 Bidiagonalize R in VT
  990: *                 (Workspace: need 4*N, prefer 3*N + 2*N*NB)
  991: *
  992:                   CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
  993:      $                         WORK( ITAUQ ), WORK( ITAUP ),
  994:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
  995: *
  996: *                 Multiply Q in A by left vectors bidiagonalizing R
  997: *                 (Workspace: need 3*N + M, prefer 3*N + M*NB)
  998: *
  999:                   CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,
 1000:      $                         WORK( ITAUQ ), A, LDA, WORK( IWORK ),
 1001:      $                         LWORK-IWORK+1, IERR )
 1002: *
 1003: *                 Generate right vectors bidiagonalizing R in VT
 1004: *                 (Workspace: need 4*N-1, prefer 3*N + (N-1)*NB)
 1005: *
 1006:                   CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
 1007:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 1008:                   IWORK = IE + N
 1009: *
 1010: *                 Perform bidiagonal QR iteration, computing left
 1011: *                 singular vectors of A in A and computing right
 1012: *                 singular vectors of A in VT
 1013: *                 (Workspace: need BDSPAC)
 1014: *
 1015:                   CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT, LDVT,
 1016:      $                         A, LDA, DUM, 1, WORK( IWORK ), INFO )
 1017: *
 1018:                END IF
 1019: *
 1020:             ELSE IF( WNTUS ) THEN
 1021: *
 1022:                IF( WNTVN ) THEN
 1023: *
 1024: *                 Path 4 (M much larger than N, JOBU='S', JOBVT='N')
 1025: *                 N left singular vectors to be computed in U and
 1026: *                 no right singular vectors to be computed
 1027: *
 1028:                   IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
 1029: *
 1030: *                    Sufficient workspace for a fast algorithm
 1031: *
 1032:                      IR = 1
 1033:                      IF( LWORK.GE.WRKBL+LDA*N ) THEN
 1034: *
 1035: *                       WORK(IR) is LDA by N
 1036: *
 1037:                         LDWRKR = LDA
 1038:                      ELSE
 1039: *
 1040: *                       WORK(IR) is N by N
 1041: *
 1042:                         LDWRKR = N
 1043:                      END IF
 1044:                      ITAU = IR + LDWRKR*N
 1045:                      IWORK = ITAU + N
 1046: *
 1047: *                    Compute A=Q*R
 1048: *                    (Workspace: need N*N + 2*N, prefer N*N + N + N*NB)
 1049: *
 1050:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1051:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1052: *
 1053: *                    Copy R to WORK(IR), zeroing out below it
 1054: *
 1055:                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ),
 1056:      $                            LDWRKR )
 1057:                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1058:      $                            WORK( IR+1 ), LDWRKR )
 1059: *
 1060: *                    Generate Q in A
 1061: *                    (Workspace: need N*N + 2*N, prefer N*N + N + N*NB)
 1062: *
 1063:                      CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
 1064:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1065:                      IE = ITAU
 1066:                      ITAUQ = IE + N
 1067:                      ITAUP = ITAUQ + N
 1068:                      IWORK = ITAUP + N
 1069: *
 1070: *                    Bidiagonalize R in WORK(IR)
 1071: *                    (Workspace: need N*N + 4*N, prefer N*N + 3*N + 2*N*NB)
 1072: *
 1073:                      CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S,
 1074:      $                            WORK( IE ), WORK( ITAUQ ),
 1075:      $                            WORK( ITAUP ), WORK( IWORK ),
 1076:      $                            LWORK-IWORK+1, IERR )
 1077: *
 1078: *                    Generate left vectors bidiagonalizing R in WORK(IR)
 1079: *                    (Workspace: need N*N + 4*N, prefer N*N + 3*N + N*NB)
 1080: *
 1081:                      CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
 1082:      $                            WORK( ITAUQ ), WORK( IWORK ),
 1083:      $                            LWORK-IWORK+1, IERR )
 1084:                      IWORK = IE + N
 1085: *
 1086: *                    Perform bidiagonal QR iteration, computing left
 1087: *                    singular vectors of R in WORK(IR)
 1088: *                    (Workspace: need N*N + BDSPAC)
 1089: *
 1090:                      CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM,
 1091:      $                            1, WORK( IR ), LDWRKR, DUM, 1,
 1092:      $                            WORK( IWORK ), INFO )
 1093: *
 1094: *                    Multiply Q in A by left singular vectors of R in
 1095: *                    WORK(IR), storing result in U
 1096: *                    (Workspace: need N*N)
 1097: *
 1098:                      CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,
 1099:      $                           WORK( IR ), LDWRKR, ZERO, U, LDU )
 1100: *
 1101:                   ELSE
 1102: *
 1103: *                    Insufficient workspace for a fast algorithm
 1104: *
 1105:                      ITAU = 1
 1106:                      IWORK = ITAU + N
 1107: *
 1108: *                    Compute A=Q*R, copying result to U
 1109: *                    (Workspace: need 2*N, prefer N + N*NB)
 1110: *
 1111:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1112:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1113:                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
 1114: *
 1115: *                    Generate Q in U
 1116: *                    (Workspace: need 2*N, prefer N + N*NB)
 1117: *
 1118:                      CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),
 1119:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1120:                      IE = ITAU
 1121:                      ITAUQ = IE + N
 1122:                      ITAUP = ITAUQ + N
 1123:                      IWORK = ITAUP + N
 1124: *
 1125: *                    Zero out below R in A
 1126: *
 1127:                      IF( N .GT. 1 ) THEN
 1128:                         CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1129:      $                               A( 2, 1 ), LDA )
 1130:                      END IF
 1131: *
 1132: *                    Bidiagonalize R in A
 1133: *                    (Workspace: need 4*N, prefer 3*N + 2*N*NB)
 1134: *
 1135:                      CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
 1136:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 1137:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1138: *
 1139: *                    Multiply Q in U by left vectors bidiagonalizing R
 1140: *                    (Workspace: need 3*N + M, prefer 3*N + M*NB)
 1141: *
 1142:                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
 1143:      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
 1144:      $                            LWORK-IWORK+1, IERR )
 1145:                      IWORK = IE + N
 1146: *
 1147: *                    Perform bidiagonal QR iteration, computing left
 1148: *                    singular vectors of A in U
 1149: *                    (Workspace: need BDSPAC)
 1150: *
 1151:                      CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM,
 1152:      $                            1, U, LDU, DUM, 1, WORK( IWORK ),
 1153:      $                            INFO )
 1154: *
 1155:                   END IF
 1156: *
 1157:                ELSE IF( WNTVO ) THEN
 1158: *
 1159: *                 Path 5 (M much larger than N, JOBU='S', JOBVT='O')
 1160: *                 N left singular vectors to be computed in U and
 1161: *                 N right singular vectors to be overwritten on A
 1162: *
 1163:                   IF( LWORK.GE.2*N*N+MAX( 4*N, BDSPAC ) ) THEN
 1164: *
 1165: *                    Sufficient workspace for a fast algorithm
 1166: *
 1167:                      IU = 1
 1168:                      IF( LWORK.GE.WRKBL+2*LDA*N ) THEN
 1169: *
 1170: *                       WORK(IU) is LDA by N and WORK(IR) is LDA by N
 1171: *
 1172:                         LDWRKU = LDA
 1173:                         IR = IU + LDWRKU*N
 1174:                         LDWRKR = LDA
 1175:                      ELSE IF( LWORK.GE.WRKBL+( LDA + N )*N ) THEN
 1176: *
 1177: *                       WORK(IU) is LDA by N and WORK(IR) is N by N
 1178: *
 1179:                         LDWRKU = LDA
 1180:                         IR = IU + LDWRKU*N
 1181:                         LDWRKR = N
 1182:                      ELSE
 1183: *
 1184: *                       WORK(IU) is N by N and WORK(IR) is N by N
 1185: *
 1186:                         LDWRKU = N
 1187:                         IR = IU + LDWRKU*N
 1188:                         LDWRKR = N
 1189:                      END IF
 1190:                      ITAU = IR + LDWRKR*N
 1191:                      IWORK = ITAU + N
 1192: *
 1193: *                    Compute A=Q*R
 1194: *                    (Workspace: need 2*N*N + 2*N, prefer 2*N*N + N + N*NB)
 1195: *
 1196:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1197:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1198: *
 1199: *                    Copy R to WORK(IU), zeroing out below it
 1200: *
 1201:                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
 1202:      $                            LDWRKU )
 1203:                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1204:      $                            WORK( IU+1 ), LDWRKU )
 1205: *
 1206: *                    Generate Q in A
 1207: *                    (Workspace: need 2*N*N + 2*N, prefer 2*N*N + N + N*NB)
 1208: *
 1209:                      CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
 1210:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1211:                      IE = ITAU
 1212:                      ITAUQ = IE + N
 1213:                      ITAUP = ITAUQ + N
 1214:                      IWORK = ITAUP + N
 1215: *
 1216: *                    Bidiagonalize R in WORK(IU), copying result to
 1217: *                    WORK(IR)
 1218: *                    (Workspace: need 2*N*N + 4*N,
 1219: *                                prefer 2*N*N+3*N+2*N*NB)
 1220: *
 1221:                      CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
 1222:      $                            WORK( IE ), WORK( ITAUQ ),
 1223:      $                            WORK( ITAUP ), WORK( IWORK ),
 1224:      $                            LWORK-IWORK+1, IERR )
 1225:                      CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU,
 1226:      $                            WORK( IR ), LDWRKR )
 1227: *
 1228: *                    Generate left bidiagonalizing vectors in WORK(IU)
 1229: *                    (Workspace: need 2*N*N + 4*N, prefer 2*N*N + 3*N + N*NB)
 1230: *
 1231:                      CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
 1232:      $                            WORK( ITAUQ ), WORK( IWORK ),
 1233:      $                            LWORK-IWORK+1, IERR )
 1234: *
 1235: *                    Generate right bidiagonalizing vectors in WORK(IR)
 1236: *                    (Workspace: need 2*N*N + 4*N-1,
 1237: *                                prefer 2*N*N+3*N+(N-1)*NB)
 1238: *
 1239:                      CALL DORGBR( 'P', N, N, N, WORK( IR ), LDWRKR,
 1240:      $                            WORK( ITAUP ), WORK( IWORK ),
 1241:      $                            LWORK-IWORK+1, IERR )
 1242:                      IWORK = IE + N
 1243: *
 1244: *                    Perform bidiagonal QR iteration, computing left
 1245: *                    singular vectors of R in WORK(IU) and computing
 1246: *                    right singular vectors of R in WORK(IR)
 1247: *                    (Workspace: need 2*N*N + BDSPAC)
 1248: *
 1249:                      CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ),
 1250:      $                            WORK( IR ), LDWRKR, WORK( IU ),
 1251:      $                            LDWRKU, DUM, 1, WORK( IWORK ), INFO )
 1252: *
 1253: *                    Multiply Q in A by left singular vectors of R in
 1254: *                    WORK(IU), storing result in U
 1255: *                    (Workspace: need N*N)
 1256: *
 1257:                      CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,
 1258:      $                           WORK( IU ), LDWRKU, ZERO, U, LDU )
 1259: *
 1260: *                    Copy right singular vectors of R to A
 1261: *                    (Workspace: need N*N)
 1262: *
 1263:                      CALL DLACPY( 'F', N, N, WORK( IR ), LDWRKR, A,
 1264:      $                            LDA )
 1265: *
 1266:                   ELSE
 1267: *
 1268: *                    Insufficient workspace for a fast algorithm
 1269: *
 1270:                      ITAU = 1
 1271:                      IWORK = ITAU + N
 1272: *
 1273: *                    Compute A=Q*R, copying result to U
 1274: *                    (Workspace: need 2*N, prefer N + N*NB)
 1275: *
 1276:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1277:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1278:                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
 1279: *
 1280: *                    Generate Q in U
 1281: *                    (Workspace: need 2*N, prefer N + N*NB)
 1282: *
 1283:                      CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),
 1284:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1285:                      IE = ITAU
 1286:                      ITAUQ = IE + N
 1287:                      ITAUP = ITAUQ + N
 1288:                      IWORK = ITAUP + N
 1289: *
 1290: *                    Zero out below R in A
 1291: *
 1292:                      IF( N .GT. 1 ) THEN
 1293:                         CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1294:      $                               A( 2, 1 ), LDA )
 1295:                      END IF
 1296: *
 1297: *                    Bidiagonalize R in A
 1298: *                    (Workspace: need 4*N, prefer 3*N + 2*N*NB)
 1299: *
 1300:                      CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
 1301:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 1302:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1303: *
 1304: *                    Multiply Q in U by left vectors bidiagonalizing R
 1305: *                    (Workspace: need 3*N + M, prefer 3*N + M*NB)
 1306: *
 1307:                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
 1308:      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
 1309:      $                            LWORK-IWORK+1, IERR )
 1310: *
 1311: *                    Generate right vectors bidiagonalizing R in A
 1312: *                    (Workspace: need 4*N-1, prefer 3*N + (N-1)*NB)
 1313: *
 1314:                      CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
 1315:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1316:                      IWORK = IE + N
 1317: *
 1318: *                    Perform bidiagonal QR iteration, computing left
 1319: *                    singular vectors of A in U and computing right
 1320: *                    singular vectors of A in A
 1321: *                    (Workspace: need BDSPAC)
 1322: *
 1323:                      CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), A,
 1324:      $                            LDA, U, LDU, DUM, 1, WORK( IWORK ),
 1325:      $                            INFO )
 1326: *
 1327:                   END IF
 1328: *
 1329:                ELSE IF( WNTVAS ) THEN
 1330: *
 1331: *                 Path 6 (M much larger than N, JOBU='S', JOBVT='S'
 1332: *                         or 'A')
 1333: *                 N left singular vectors to be computed in U and
 1334: *                 N right singular vectors to be computed in VT
 1335: *
 1336:                   IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
 1337: *
 1338: *                    Sufficient workspace for a fast algorithm
 1339: *
 1340:                      IU = 1
 1341:                      IF( LWORK.GE.WRKBL+LDA*N ) THEN
 1342: *
 1343: *                       WORK(IU) is LDA by N
 1344: *
 1345:                         LDWRKU = LDA
 1346:                      ELSE
 1347: *
 1348: *                       WORK(IU) is N by N
 1349: *
 1350:                         LDWRKU = N
 1351:                      END IF
 1352:                      ITAU = IU + LDWRKU*N
 1353:                      IWORK = ITAU + N
 1354: *
 1355: *                    Compute A=Q*R
 1356: *                    (Workspace: need N*N + 2*N, prefer N*N + N + N*NB)
 1357: *
 1358:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1359:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1360: *
 1361: *                    Copy R to WORK(IU), zeroing out below it
 1362: *
 1363:                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
 1364:      $                            LDWRKU )
 1365:                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1366:      $                            WORK( IU+1 ), LDWRKU )
 1367: *
 1368: *                    Generate Q in A
 1369: *                    (Workspace: need N*N + 2*N, prefer N*N + N + N*NB)
 1370: *
 1371:                      CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
 1372:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1373:                      IE = ITAU
 1374:                      ITAUQ = IE + N
 1375:                      ITAUP = ITAUQ + N
 1376:                      IWORK = ITAUP + N
 1377: *
 1378: *                    Bidiagonalize R in WORK(IU), copying result to VT
 1379: *                    (Workspace: need N*N + 4*N, prefer N*N + 3*N + 2*N*NB)
 1380: *
 1381:                      CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
 1382:      $                            WORK( IE ), WORK( ITAUQ ),
 1383:      $                            WORK( ITAUP ), WORK( IWORK ),
 1384:      $                            LWORK-IWORK+1, IERR )
 1385:                      CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, VT,
 1386:      $                            LDVT )
 1387: *
 1388: *                    Generate left bidiagonalizing vectors in WORK(IU)
 1389: *                    (Workspace: need N*N + 4*N, prefer N*N + 3*N + N*NB)
 1390: *
 1391:                      CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
 1392:      $                            WORK( ITAUQ ), WORK( IWORK ),
 1393:      $                            LWORK-IWORK+1, IERR )
 1394: *
 1395: *                    Generate right bidiagonalizing vectors in VT
 1396: *                    (Workspace: need N*N + 4*N-1,
 1397: *                                prefer N*N+3*N+(N-1)*NB)
 1398: *
 1399:                      CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
 1400:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1401:                      IWORK = IE + N
 1402: *
 1403: *                    Perform bidiagonal QR iteration, computing left
 1404: *                    singular vectors of R in WORK(IU) and computing
 1405: *                    right singular vectors of R in VT
 1406: *                    (Workspace: need N*N + BDSPAC)
 1407: *
 1408:                      CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT,
 1409:      $                            LDVT, WORK( IU ), LDWRKU, DUM, 1,
 1410:      $                            WORK( IWORK ), INFO )
 1411: *
 1412: *                    Multiply Q in A by left singular vectors of R in
 1413: *                    WORK(IU), storing result in U
 1414: *                    (Workspace: need N*N)
 1415: *
 1416:                      CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,
 1417:      $                           WORK( IU ), LDWRKU, ZERO, U, LDU )
 1418: *
 1419:                   ELSE
 1420: *
 1421: *                    Insufficient workspace for a fast algorithm
 1422: *
 1423:                      ITAU = 1
 1424:                      IWORK = ITAU + N
 1425: *
 1426: *                    Compute A=Q*R, copying result to U
 1427: *                    (Workspace: need 2*N, prefer N + N*NB)
 1428: *
 1429:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1430:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1431:                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
 1432: *
 1433: *                    Generate Q in U
 1434: *                    (Workspace: need 2*N, prefer N + N*NB)
 1435: *
 1436:                      CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),
 1437:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1438: *
 1439: *                    Copy R to VT, zeroing out below it
 1440: *
 1441:                      CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
 1442:                      IF( N.GT.1 )
 1443:      $                  CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1444:      $                               VT( 2, 1 ), LDVT )
 1445:                      IE = ITAU
 1446:                      ITAUQ = IE + N
 1447:                      ITAUP = ITAUQ + N
 1448:                      IWORK = ITAUP + N
 1449: *
 1450: *                    Bidiagonalize R in VT
 1451: *                    (Workspace: need 4*N, prefer 3*N + 2*N*NB)
 1452: *
 1453:                      CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
 1454:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 1455:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1456: *
 1457: *                    Multiply Q in U by left bidiagonalizing vectors
 1458: *                    in VT
 1459: *                    (Workspace: need 3*N + M, prefer 3*N + M*NB)
 1460: *
 1461:                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,
 1462:      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
 1463:      $                            LWORK-IWORK+1, IERR )
 1464: *
 1465: *                    Generate right bidiagonalizing vectors in VT
 1466: *                    (Workspace: need 4*N-1, prefer 3*N + (N-1)*NB)
 1467: *
 1468:                      CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
 1469:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1470:                      IWORK = IE + N
 1471: *
 1472: *                    Perform bidiagonal QR iteration, computing left
 1473: *                    singular vectors of A in U and computing right
 1474: *                    singular vectors of A in VT
 1475: *                    (Workspace: need BDSPAC)
 1476: *
 1477:                      CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT,
 1478:      $                            LDVT, U, LDU, DUM, 1, WORK( IWORK ),
 1479:      $                            INFO )
 1480: *
 1481:                   END IF
 1482: *
 1483:                END IF
 1484: *
 1485:             ELSE IF( WNTUA ) THEN
 1486: *
 1487:                IF( WNTVN ) THEN
 1488: *
 1489: *                 Path 7 (M much larger than N, JOBU='A', JOBVT='N')
 1490: *                 M left singular vectors to be computed in U and
 1491: *                 no right singular vectors to be computed
 1492: *
 1493:                   IF( LWORK.GE.N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN
 1494: *
 1495: *                    Sufficient workspace for a fast algorithm
 1496: *
 1497:                      IR = 1
 1498:                      IF( LWORK.GE.WRKBL+LDA*N ) THEN
 1499: *
 1500: *                       WORK(IR) is LDA by N
 1501: *
 1502:                         LDWRKR = LDA
 1503:                      ELSE
 1504: *
 1505: *                       WORK(IR) is N by N
 1506: *
 1507:                         LDWRKR = N
 1508:                      END IF
 1509:                      ITAU = IR + LDWRKR*N
 1510:                      IWORK = ITAU + N
 1511: *
 1512: *                    Compute A=Q*R, copying result to U
 1513: *                    (Workspace: need N*N + 2*N, prefer N*N + N + N*NB)
 1514: *
 1515:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1516:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1517:                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
 1518: *
 1519: *                    Copy R to WORK(IR), zeroing out below it
 1520: *
 1521:                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ),
 1522:      $                            LDWRKR )
 1523:                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1524:      $                            WORK( IR+1 ), LDWRKR )
 1525: *
 1526: *                    Generate Q in U
 1527: *                    (Workspace: need N*N + N + M, prefer N*N + N + M*NB)
 1528: *
 1529:                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
 1530:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1531:                      IE = ITAU
 1532:                      ITAUQ = IE + N
 1533:                      ITAUP = ITAUQ + N
 1534:                      IWORK = ITAUP + N
 1535: *
 1536: *                    Bidiagonalize R in WORK(IR)
 1537: *                    (Workspace: need N*N + 4*N, prefer N*N + 3*N + 2*N*NB)
 1538: *
 1539:                      CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S,
 1540:      $                            WORK( IE ), WORK( ITAUQ ),
 1541:      $                            WORK( ITAUP ), WORK( IWORK ),
 1542:      $                            LWORK-IWORK+1, IERR )
 1543: *
 1544: *                    Generate left bidiagonalizing vectors in WORK(IR)
 1545: *                    (Workspace: need N*N + 4*N, prefer N*N + 3*N + N*NB)
 1546: *
 1547:                      CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
 1548:      $                            WORK( ITAUQ ), WORK( IWORK ),
 1549:      $                            LWORK-IWORK+1, IERR )
 1550:                      IWORK = IE + N
 1551: *
 1552: *                    Perform bidiagonal QR iteration, computing left
 1553: *                    singular vectors of R in WORK(IR)
 1554: *                    (Workspace: need N*N + BDSPAC)
 1555: *
 1556:                      CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM,
 1557:      $                            1, WORK( IR ), LDWRKR, DUM, 1,
 1558:      $                            WORK( IWORK ), INFO )
 1559: *
 1560: *                    Multiply Q in U by left singular vectors of R in
 1561: *                    WORK(IR), storing result in A
 1562: *                    (Workspace: need N*N)
 1563: *
 1564:                      CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,
 1565:      $                           WORK( IR ), LDWRKR, ZERO, A, LDA )
 1566: *
 1567: *                    Copy left singular vectors of A from A to U
 1568: *
 1569:                      CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
 1570: *
 1571:                   ELSE
 1572: *
 1573: *                    Insufficient workspace for a fast algorithm
 1574: *
 1575:                      ITAU = 1
 1576:                      IWORK = ITAU + N
 1577: *
 1578: *                    Compute A=Q*R, copying result to U
 1579: *                    (Workspace: need 2*N, prefer N + N*NB)
 1580: *
 1581:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1582:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1583:                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
 1584: *
 1585: *                    Generate Q in U
 1586: *                    (Workspace: need N + M, prefer N + M*NB)
 1587: *
 1588:                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
 1589:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1590:                      IE = ITAU
 1591:                      ITAUQ = IE + N
 1592:                      ITAUP = ITAUQ + N
 1593:                      IWORK = ITAUP + N
 1594: *
 1595: *                    Zero out below R in A
 1596: *
 1597:                      IF( N .GT. 1 ) THEN
 1598:                         CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1599:      $                                A( 2, 1 ), LDA )
 1600:                      END IF
 1601: *
 1602: *                    Bidiagonalize R in A
 1603: *                    (Workspace: need 4*N, prefer 3*N + 2*N*NB)
 1604: *
 1605:                      CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
 1606:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 1607:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1608: *
 1609: *                    Multiply Q in U by left bidiagonalizing vectors
 1610: *                    in A
 1611: *                    (Workspace: need 3*N + M, prefer 3*N + M*NB)
 1612: *
 1613:                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
 1614:      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
 1615:      $                            LWORK-IWORK+1, IERR )
 1616:                      IWORK = IE + N
 1617: *
 1618: *                    Perform bidiagonal QR iteration, computing left
 1619: *                    singular vectors of A in U
 1620: *                    (Workspace: need BDSPAC)
 1621: *
 1622:                      CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM,
 1623:      $                            1, U, LDU, DUM, 1, WORK( IWORK ),
 1624:      $                            INFO )
 1625: *
 1626:                   END IF
 1627: *
 1628:                ELSE IF( WNTVO ) THEN
 1629: *
 1630: *                 Path 8 (M much larger than N, JOBU='A', JOBVT='O')
 1631: *                 M left singular vectors to be computed in U and
 1632: *                 N right singular vectors to be overwritten on A
 1633: *
 1634:                   IF( LWORK.GE.2*N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN
 1635: *
 1636: *                    Sufficient workspace for a fast algorithm
 1637: *
 1638:                      IU = 1
 1639:                      IF( LWORK.GE.WRKBL+2*LDA*N ) THEN
 1640: *
 1641: *                       WORK(IU) is LDA by N and WORK(IR) is LDA by N
 1642: *
 1643:                         LDWRKU = LDA
 1644:                         IR = IU + LDWRKU*N
 1645:                         LDWRKR = LDA
 1646:                      ELSE IF( LWORK.GE.WRKBL+( LDA + N )*N ) THEN
 1647: *
 1648: *                       WORK(IU) is LDA by N and WORK(IR) is N by N
 1649: *
 1650:                         LDWRKU = LDA
 1651:                         IR = IU + LDWRKU*N
 1652:                         LDWRKR = N
 1653:                      ELSE
 1654: *
 1655: *                       WORK(IU) is N by N and WORK(IR) is N by N
 1656: *
 1657:                         LDWRKU = N
 1658:                         IR = IU + LDWRKU*N
 1659:                         LDWRKR = N
 1660:                      END IF
 1661:                      ITAU = IR + LDWRKR*N
 1662:                      IWORK = ITAU + N
 1663: *
 1664: *                    Compute A=Q*R, copying result to U
 1665: *                    (Workspace: need 2*N*N + 2*N, prefer 2*N*N + N + N*NB)
 1666: *
 1667:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1668:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1669:                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
 1670: *
 1671: *                    Generate Q in U
 1672: *                    (Workspace: need 2*N*N + N + M, prefer 2*N*N + N + M*NB)
 1673: *
 1674:                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
 1675:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1676: *
 1677: *                    Copy R to WORK(IU), zeroing out below it
 1678: *
 1679:                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
 1680:      $                            LDWRKU )
 1681:                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1682:      $                            WORK( IU+1 ), LDWRKU )
 1683:                      IE = ITAU
 1684:                      ITAUQ = IE + N
 1685:                      ITAUP = ITAUQ + N
 1686:                      IWORK = ITAUP + N
 1687: *
 1688: *                    Bidiagonalize R in WORK(IU), copying result to
 1689: *                    WORK(IR)
 1690: *                    (Workspace: need 2*N*N + 4*N,
 1691: *                                prefer 2*N*N+3*N+2*N*NB)
 1692: *
 1693:                      CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
 1694:      $                            WORK( IE ), WORK( ITAUQ ),
 1695:      $                            WORK( ITAUP ), WORK( IWORK ),
 1696:      $                            LWORK-IWORK+1, IERR )
 1697:                      CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU,
 1698:      $                            WORK( IR ), LDWRKR )
 1699: *
 1700: *                    Generate left bidiagonalizing vectors in WORK(IU)
 1701: *                    (Workspace: need 2*N*N + 4*N, prefer 2*N*N + 3*N + N*NB)
 1702: *
 1703:                      CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
 1704:      $                            WORK( ITAUQ ), WORK( IWORK ),
 1705:      $                            LWORK-IWORK+1, IERR )
 1706: *
 1707: *                    Generate right bidiagonalizing vectors in WORK(IR)
 1708: *                    (Workspace: need 2*N*N + 4*N-1,
 1709: *                                prefer 2*N*N+3*N+(N-1)*NB)
 1710: *
 1711:                      CALL DORGBR( 'P', N, N, N, WORK( IR ), LDWRKR,
 1712:      $                            WORK( ITAUP ), WORK( IWORK ),
 1713:      $                            LWORK-IWORK+1, IERR )
 1714:                      IWORK = IE + N
 1715: *
 1716: *                    Perform bidiagonal QR iteration, computing left
 1717: *                    singular vectors of R in WORK(IU) and computing
 1718: *                    right singular vectors of R in WORK(IR)
 1719: *                    (Workspace: need 2*N*N + BDSPAC)
 1720: *
 1721:                      CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ),
 1722:      $                            WORK( IR ), LDWRKR, WORK( IU ),
 1723:      $                            LDWRKU, DUM, 1, WORK( IWORK ), INFO )
 1724: *
 1725: *                    Multiply Q in U by left singular vectors of R in
 1726: *                    WORK(IU), storing result in A
 1727: *                    (Workspace: need N*N)
 1728: *
 1729:                      CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,
 1730:      $                           WORK( IU ), LDWRKU, ZERO, A, LDA )
 1731: *
 1732: *                    Copy left singular vectors of A from A to U
 1733: *
 1734:                      CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
 1735: *
 1736: *                    Copy right singular vectors of R from WORK(IR) to A
 1737: *
 1738:                      CALL DLACPY( 'F', N, N, WORK( IR ), LDWRKR, A,
 1739:      $                            LDA )
 1740: *
 1741:                   ELSE
 1742: *
 1743: *                    Insufficient workspace for a fast algorithm
 1744: *
 1745:                      ITAU = 1
 1746:                      IWORK = ITAU + N
 1747: *
 1748: *                    Compute A=Q*R, copying result to U
 1749: *                    (Workspace: need 2*N, prefer N + N*NB)
 1750: *
 1751:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1752:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1753:                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
 1754: *
 1755: *                    Generate Q in U
 1756: *                    (Workspace: need N + M, prefer N + M*NB)
 1757: *
 1758:                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
 1759:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1760:                      IE = ITAU
 1761:                      ITAUQ = IE + N
 1762:                      ITAUP = ITAUQ + N
 1763:                      IWORK = ITAUP + N
 1764: *
 1765: *                    Zero out below R in A
 1766: *
 1767:                      IF( N .GT. 1 ) THEN
 1768:                         CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1769:      $                                A( 2, 1 ), LDA )
 1770:                      END IF
 1771: *
 1772: *                    Bidiagonalize R in A
 1773: *                    (Workspace: need 4*N, prefer 3*N + 2*N*NB)
 1774: *
 1775:                      CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
 1776:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 1777:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1778: *
 1779: *                    Multiply Q in U by left bidiagonalizing vectors
 1780: *                    in A
 1781: *                    (Workspace: need 3*N + M, prefer 3*N + M*NB)
 1782: *
 1783:                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
 1784:      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
 1785:      $                            LWORK-IWORK+1, IERR )
 1786: *
 1787: *                    Generate right bidiagonalizing vectors in A
 1788: *                    (Workspace: need 4*N-1, prefer 3*N + (N-1)*NB)
 1789: *
 1790:                      CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
 1791:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1792:                      IWORK = IE + N
 1793: *
 1794: *                    Perform bidiagonal QR iteration, computing left
 1795: *                    singular vectors of A in U and computing right
 1796: *                    singular vectors of A in A
 1797: *                    (Workspace: need BDSPAC)
 1798: *
 1799:                      CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), A,
 1800:      $                            LDA, U, LDU, DUM, 1, WORK( IWORK ),
 1801:      $                            INFO )
 1802: *
 1803:                   END IF
 1804: *
 1805:                ELSE IF( WNTVAS ) THEN
 1806: *
 1807: *                 Path 9 (M much larger than N, JOBU='A', JOBVT='S'
 1808: *                         or 'A')
 1809: *                 M left singular vectors to be computed in U and
 1810: *                 N right singular vectors to be computed in VT
 1811: *
 1812:                   IF( LWORK.GE.N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN
 1813: *
 1814: *                    Sufficient workspace for a fast algorithm
 1815: *
 1816:                      IU = 1
 1817:                      IF( LWORK.GE.WRKBL+LDA*N ) THEN
 1818: *
 1819: *                       WORK(IU) is LDA by N
 1820: *
 1821:                         LDWRKU = LDA
 1822:                      ELSE
 1823: *
 1824: *                       WORK(IU) is N by N
 1825: *
 1826:                         LDWRKU = N
 1827:                      END IF
 1828:                      ITAU = IU + LDWRKU*N
 1829:                      IWORK = ITAU + N
 1830: *
 1831: *                    Compute A=Q*R, copying result to U
 1832: *                    (Workspace: need N*N + 2*N, prefer N*N + N + N*NB)
 1833: *
 1834:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1835:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1836:                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
 1837: *
 1838: *                    Generate Q in U
 1839: *                    (Workspace: need N*N + N + M, prefer N*N + N + M*NB)
 1840: *
 1841:                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
 1842:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1843: *
 1844: *                    Copy R to WORK(IU), zeroing out below it
 1845: *
 1846:                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
 1847:      $                            LDWRKU )
 1848:                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1849:      $                            WORK( IU+1 ), LDWRKU )
 1850:                      IE = ITAU
 1851:                      ITAUQ = IE + N
 1852:                      ITAUP = ITAUQ + N
 1853:                      IWORK = ITAUP + N
 1854: *
 1855: *                    Bidiagonalize R in WORK(IU), copying result to VT
 1856: *                    (Workspace: need N*N + 4*N, prefer N*N + 3*N + 2*N*NB)
 1857: *
 1858:                      CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
 1859:      $                            WORK( IE ), WORK( ITAUQ ),
 1860:      $                            WORK( ITAUP ), WORK( IWORK ),
 1861:      $                            LWORK-IWORK+1, IERR )
 1862:                      CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, VT,
 1863:      $                            LDVT )
 1864: *
 1865: *                    Generate left bidiagonalizing vectors in WORK(IU)
 1866: *                    (Workspace: need N*N + 4*N, prefer N*N + 3*N + N*NB)
 1867: *
 1868:                      CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
 1869:      $                            WORK( ITAUQ ), WORK( IWORK ),
 1870:      $                            LWORK-IWORK+1, IERR )
 1871: *
 1872: *                    Generate right bidiagonalizing vectors in VT
 1873: *                    (Workspace: need N*N + 4*N-1,
 1874: *                                prefer N*N+3*N+(N-1)*NB)
 1875: *
 1876:                      CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
 1877:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1878:                      IWORK = IE + N
 1879: *
 1880: *                    Perform bidiagonal QR iteration, computing left
 1881: *                    singular vectors of R in WORK(IU) and computing
 1882: *                    right singular vectors of R in VT
 1883: *                    (Workspace: need N*N + BDSPAC)
 1884: *
 1885:                      CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT,
 1886:      $                            LDVT, WORK( IU ), LDWRKU, DUM, 1,
 1887:      $                            WORK( IWORK ), INFO )
 1888: *
 1889: *                    Multiply Q in U by left singular vectors of R in
 1890: *                    WORK(IU), storing result in A
 1891: *                    (Workspace: need N*N)
 1892: *
 1893:                      CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,
 1894:      $                           WORK( IU ), LDWRKU, ZERO, A, LDA )
 1895: *
 1896: *                    Copy left singular vectors of A from A to U
 1897: *
 1898:                      CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
 1899: *
 1900:                   ELSE
 1901: *
 1902: *                    Insufficient workspace for a fast algorithm
 1903: *
 1904:                      ITAU = 1
 1905:                      IWORK = ITAU + N
 1906: *
 1907: *                    Compute A=Q*R, copying result to U
 1908: *                    (Workspace: need 2*N, prefer N + N*NB)
 1909: *
 1910:                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
 1911:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1912:                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
 1913: *
 1914: *                    Generate Q in U
 1915: *                    (Workspace: need N + M, prefer N + M*NB)
 1916: *
 1917:                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
 1918:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1919: *
 1920: *                    Copy R from A to VT, zeroing out below it
 1921: *
 1922:                      CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
 1923:                      IF( N.GT.1 )
 1924:      $                  CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
 1925:      $                               VT( 2, 1 ), LDVT )
 1926:                      IE = ITAU
 1927:                      ITAUQ = IE + N
 1928:                      ITAUP = ITAUQ + N
 1929:                      IWORK = ITAUP + N
 1930: *
 1931: *                    Bidiagonalize R in VT
 1932: *                    (Workspace: need 4*N, prefer 3*N + 2*N*NB)
 1933: *
 1934:                      CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
 1935:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 1936:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1937: *
 1938: *                    Multiply Q in U by left bidiagonalizing vectors
 1939: *                    in VT
 1940: *                    (Workspace: need 3*N + M, prefer 3*N + M*NB)
 1941: *
 1942:                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,
 1943:      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
 1944:      $                            LWORK-IWORK+1, IERR )
 1945: *
 1946: *                    Generate right bidiagonalizing vectors in VT
 1947: *                    (Workspace: need 4*N-1, prefer 3*N + (N-1)*NB)
 1948: *
 1949:                      CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
 1950:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 1951:                      IWORK = IE + N
 1952: *
 1953: *                    Perform bidiagonal QR iteration, computing left
 1954: *                    singular vectors of A in U and computing right
 1955: *                    singular vectors of A in VT
 1956: *                    (Workspace: need BDSPAC)
 1957: *
 1958:                      CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT,
 1959:      $                            LDVT, U, LDU, DUM, 1, WORK( IWORK ),
 1960:      $                            INFO )
 1961: *
 1962:                   END IF
 1963: *
 1964:                END IF
 1965: *
 1966:             END IF
 1967: *
 1968:          ELSE
 1969: *
 1970: *           M .LT. MNTHR
 1971: *
 1972: *           Path 10 (M at least N, but not much larger)
 1973: *           Reduce to bidiagonal form without QR decomposition
 1974: *
 1975:             IE = 1
 1976:             ITAUQ = IE + N
 1977:             ITAUP = ITAUQ + N
 1978:             IWORK = ITAUP + N
 1979: *
 1980: *           Bidiagonalize A
 1981: *           (Workspace: need 3*N + M, prefer 3*N + (M + N)*NB)
 1982: *
 1983:             CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
 1984:      $                   WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
 1985:      $                   IERR )
 1986:             IF( WNTUAS ) THEN
 1987: *
 1988: *              If left singular vectors desired in U, copy result to U
 1989: *              and generate left bidiagonalizing vectors in U
 1990: *              (Workspace: need 3*N + NCU, prefer 3*N + NCU*NB)
 1991: *
 1992:                CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
 1993:                IF( WNTUS )
 1994:      $            NCU = N
 1995:                IF( WNTUA )
 1996:      $            NCU = M
 1997:                CALL DORGBR( 'Q', M, NCU, N, U, LDU, WORK( ITAUQ ),
 1998:      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
 1999:             END IF
 2000:             IF( WNTVAS ) THEN
 2001: *
 2002: *              If right singular vectors desired in VT, copy result to
 2003: *              VT and generate right bidiagonalizing vectors in VT
 2004: *              (Workspace: need 4*N-1, prefer 3*N + (N-1)*NB)
 2005: *
 2006:                CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
 2007:                CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
 2008:      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
 2009:             END IF
 2010:             IF( WNTUO ) THEN
 2011: *
 2012: *              If left singular vectors desired in A, generate left
 2013: *              bidiagonalizing vectors in A
 2014: *              (Workspace: need 4*N, prefer 3*N + N*NB)
 2015: *
 2016:                CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),
 2017:      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
 2018:             END IF
 2019:             IF( WNTVO ) THEN
 2020: *
 2021: *              If right singular vectors desired in A, generate right
 2022: *              bidiagonalizing vectors in A
 2023: *              (Workspace: need 4*N-1, prefer 3*N + (N-1)*NB)
 2024: *
 2025:                CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
 2026:      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
 2027:             END IF
 2028:             IWORK = IE + N
 2029:             IF( WNTUAS .OR. WNTUO )
 2030:      $         NRU = M
 2031:             IF( WNTUN )
 2032:      $         NRU = 0
 2033:             IF( WNTVAS .OR. WNTVO )
 2034:      $         NCVT = N
 2035:             IF( WNTVN )
 2036:      $         NCVT = 0
 2037:             IF( ( .NOT.WNTUO ) .AND. ( .NOT.WNTVO ) ) THEN
 2038: *
 2039: *              Perform bidiagonal QR iteration, if desired, computing
 2040: *              left singular vectors in U and computing right singular
 2041: *              vectors in VT
 2042: *              (Workspace: need BDSPAC)
 2043: *
 2044:                CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), VT,
 2045:      $                      LDVT, U, LDU, DUM, 1, WORK( IWORK ), INFO )
 2046:             ELSE IF( ( .NOT.WNTUO ) .AND. WNTVO ) THEN
 2047: *
 2048: *              Perform bidiagonal QR iteration, if desired, computing
 2049: *              left singular vectors in U and computing right singular
 2050: *              vectors in A
 2051: *              (Workspace: need BDSPAC)
 2052: *
 2053:                CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), A, LDA,
 2054:      $                      U, LDU, DUM, 1, WORK( IWORK ), INFO )
 2055:             ELSE
 2056: *
 2057: *              Perform bidiagonal QR iteration, if desired, computing
 2058: *              left singular vectors in A and computing right singular
 2059: *              vectors in VT
 2060: *              (Workspace: need BDSPAC)
 2061: *
 2062:                CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), VT,
 2063:      $                      LDVT, A, LDA, DUM, 1, WORK( IWORK ), INFO )
 2064:             END IF
 2065: *
 2066:          END IF
 2067: *
 2068:       ELSE
 2069: *
 2070: *        A has more columns than rows. If A has sufficiently more
 2071: *        columns than rows, first reduce using the LQ decomposition (if
 2072: *        sufficient workspace available)
 2073: *
 2074:          IF( N.GE.MNTHR ) THEN
 2075: *
 2076:             IF( WNTVN ) THEN
 2077: *
 2078: *              Path 1t(N much larger than M, JOBVT='N')
 2079: *              No right singular vectors to be computed
 2080: *
 2081:                ITAU = 1
 2082:                IWORK = ITAU + M
 2083: *
 2084: *              Compute A=L*Q
 2085: *              (Workspace: need 2*M, prefer M + M*NB)
 2086: *
 2087:                CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
 2088:      $                      LWORK-IWORK+1, IERR )
 2089: *
 2090: *              Zero out above L
 2091: *
 2092:                CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )
 2093:                IE = 1
 2094:                ITAUQ = IE + M
 2095:                ITAUP = ITAUQ + M
 2096:                IWORK = ITAUP + M
 2097: *
 2098: *              Bidiagonalize L in A
 2099: *              (Workspace: need 4*M, prefer 3*M + 2*M*NB)
 2100: *
 2101:                CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
 2102:      $                      WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
 2103:      $                      IERR )
 2104:                IF( WNTUO .OR. WNTUAS ) THEN
 2105: *
 2106: *                 If left singular vectors desired, generate Q
 2107: *                 (Workspace: need 4*M, prefer 3*M + M*NB)
 2108: *
 2109:                   CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),
 2110:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2111:                END IF
 2112:                IWORK = IE + M
 2113:                NRU = 0
 2114:                IF( WNTUO .OR. WNTUAS )
 2115:      $            NRU = M
 2116: *
 2117: *              Perform bidiagonal QR iteration, computing left singular
 2118: *              vectors of A in A if desired
 2119: *              (Workspace: need BDSPAC)
 2120: *
 2121:                CALL DBDSQR( 'U', M, 0, NRU, 0, S, WORK( IE ), DUM, 1, A,
 2122:      $                      LDA, DUM, 1, WORK( IWORK ), INFO )
 2123: *
 2124: *              If left singular vectors desired in U, copy them there
 2125: *
 2126:                IF( WNTUAS )
 2127:      $            CALL DLACPY( 'F', M, M, A, LDA, U, LDU )
 2128: *
 2129:             ELSE IF( WNTVO .AND. WNTUN ) THEN
 2130: *
 2131: *              Path 2t(N much larger than M, JOBU='N', JOBVT='O')
 2132: *              M right singular vectors to be overwritten on A and
 2133: *              no left singular vectors to be computed
 2134: *
 2135:                IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
 2136: *
 2137: *                 Sufficient workspace for a fast algorithm
 2138: *
 2139:                   IR = 1
 2140:                   IF( LWORK.GE.MAX( WRKBL, LDA*N + M ) + LDA*M ) THEN
 2141: *
 2142: *                    WORK(IU) is LDA by N and WORK(IR) is LDA by M
 2143: *
 2144:                      LDWRKU = LDA
 2145:                      CHUNK = N
 2146:                      LDWRKR = LDA
 2147:                   ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N + M ) + M*M ) THEN
 2148: *
 2149: *                    WORK(IU) is LDA by N and WORK(IR) is M by M
 2150: *
 2151:                      LDWRKU = LDA
 2152:                      CHUNK = N
 2153:                      LDWRKR = M
 2154:                   ELSE
 2155: *
 2156: *                    WORK(IU) is M by CHUNK and WORK(IR) is M by M
 2157: *
 2158:                      LDWRKU = M
 2159:                      CHUNK = ( LWORK-M*M-M ) / M
 2160:                      LDWRKR = M
 2161:                   END IF
 2162:                   ITAU = IR + LDWRKR*M
 2163:                   IWORK = ITAU + M
 2164: *
 2165: *                 Compute A=L*Q
 2166: *                 (Workspace: need M*M + 2*M, prefer M*M + M + M*NB)
 2167: *
 2168:                   CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 2169:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2170: *
 2171: *                 Copy L to WORK(IR) and zero out above it
 2172: *
 2173:                   CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ), LDWRKR )
 2174:                   CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
 2175:      $                         WORK( IR+LDWRKR ), LDWRKR )
 2176: *
 2177: *                 Generate Q in A
 2178: *                 (Workspace: need M*M + 2*M, prefer M*M + M + M*NB)
 2179: *
 2180:                   CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
 2181:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2182:                   IE = ITAU
 2183:                   ITAUQ = IE + M
 2184:                   ITAUP = ITAUQ + M
 2185:                   IWORK = ITAUP + M
 2186: *
 2187: *                 Bidiagonalize L in WORK(IR)
 2188: *                 (Workspace: need M*M + 4*M, prefer M*M + 3*M + 2*M*NB)
 2189: *
 2190:                   CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S, WORK( IE ),
 2191:      $                         WORK( ITAUQ ), WORK( ITAUP ),
 2192:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2193: *
 2194: *                 Generate right vectors bidiagonalizing L
 2195: *                 (Workspace: need M*M + 4*M-1, prefer M*M + 3*M + (M-1)*NB)
 2196: *
 2197:                   CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
 2198:      $                         WORK( ITAUP ), WORK( IWORK ),
 2199:      $                         LWORK-IWORK+1, IERR )
 2200:                   IWORK = IE + M
 2201: *
 2202: *                 Perform bidiagonal QR iteration, computing right
 2203: *                 singular vectors of L in WORK(IR)
 2204: *                 (Workspace: need M*M + BDSPAC)
 2205: *
 2206:                   CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),
 2207:      $                         WORK( IR ), LDWRKR, DUM, 1, DUM, 1,
 2208:      $                         WORK( IWORK ), INFO )
 2209:                   IU = IE + M
 2210: *
 2211: *                 Multiply right singular vectors of L in WORK(IR) by Q
 2212: *                 in A, storing result in WORK(IU) and copying to A
 2213: *                 (Workspace: need M*M + 2*M, prefer M*M + M*N + M)
 2214: *
 2215:                   DO 30 I = 1, N, CHUNK
 2216:                      BLK = MIN( N-I+1, CHUNK )
 2217:                      CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IR ),
 2218:      $                           LDWRKR, A( 1, I ), LDA, ZERO,
 2219:      $                           WORK( IU ), LDWRKU )
 2220:                      CALL DLACPY( 'F', M, BLK, WORK( IU ), LDWRKU,
 2221:      $                            A( 1, I ), LDA )
 2222:    30             CONTINUE
 2223: *
 2224:                ELSE
 2225: *
 2226: *                 Insufficient workspace for a fast algorithm
 2227: *
 2228:                   IE = 1
 2229:                   ITAUQ = IE + M
 2230:                   ITAUP = ITAUQ + M
 2231:                   IWORK = ITAUP + M
 2232: *
 2233: *                 Bidiagonalize A
 2234: *                 (Workspace: need 3*M + N, prefer 3*M + (M + N)*NB)
 2235: *
 2236:                   CALL DGEBRD( M, N, A, LDA, S, WORK( IE ),
 2237:      $                         WORK( ITAUQ ), WORK( ITAUP ),
 2238:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2239: *
 2240: *                 Generate right vectors bidiagonalizing A
 2241: *                 (Workspace: need 4*M, prefer 3*M + M*NB)
 2242: *
 2243:                   CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
 2244:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2245:                   IWORK = IE + M
 2246: *
 2247: *                 Perform bidiagonal QR iteration, computing right
 2248: *                 singular vectors of A in A
 2249: *                 (Workspace: need BDSPAC)
 2250: *
 2251:                   CALL DBDSQR( 'L', M, N, 0, 0, S, WORK( IE ), A, LDA,
 2252:      $                         DUM, 1, DUM, 1, WORK( IWORK ), INFO )
 2253: *
 2254:                END IF
 2255: *
 2256:             ELSE IF( WNTVO .AND. WNTUAS ) THEN
 2257: *
 2258: *              Path 3t(N much larger than M, JOBU='S' or 'A', JOBVT='O')
 2259: *              M right singular vectors to be overwritten on A and
 2260: *              M left singular vectors to be computed in U
 2261: *
 2262:                IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
 2263: *
 2264: *                 Sufficient workspace for a fast algorithm
 2265: *
 2266:                   IR = 1
 2267:                   IF( LWORK.GE.MAX( WRKBL, LDA*N + M ) + LDA*M ) THEN
 2268: *
 2269: *                    WORK(IU) is LDA by N and WORK(IR) is LDA by M
 2270: *
 2271:                      LDWRKU = LDA
 2272:                      CHUNK = N
 2273:                      LDWRKR = LDA
 2274:                   ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N + M ) + M*M ) THEN
 2275: *
 2276: *                    WORK(IU) is LDA by N and WORK(IR) is M by M
 2277: *
 2278:                      LDWRKU = LDA
 2279:                      CHUNK = N
 2280:                      LDWRKR = M
 2281:                   ELSE
 2282: *
 2283: *                    WORK(IU) is M by CHUNK and WORK(IR) is M by M
 2284: *
 2285:                      LDWRKU = M
 2286:                      CHUNK = ( LWORK-M*M-M ) / M
 2287:                      LDWRKR = M
 2288:                   END IF
 2289:                   ITAU = IR + LDWRKR*M
 2290:                   IWORK = ITAU + M
 2291: *
 2292: *                 Compute A=L*Q
 2293: *                 (Workspace: need M*M + 2*M, prefer M*M + M + M*NB)
 2294: *
 2295:                   CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 2296:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2297: *
 2298: *                 Copy L to U, zeroing about above it
 2299: *
 2300:                   CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
 2301:                   CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
 2302:      $                         LDU )
 2303: *
 2304: *                 Generate Q in A
 2305: *                 (Workspace: need M*M + 2*M, prefer M*M + M + M*NB)
 2306: *
 2307:                   CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
 2308:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2309:                   IE = ITAU
 2310:                   ITAUQ = IE + M
 2311:                   ITAUP = ITAUQ + M
 2312:                   IWORK = ITAUP + M
 2313: *
 2314: *                 Bidiagonalize L in U, copying result to WORK(IR)
 2315: *                 (Workspace: need M*M + 4*M, prefer M*M + 3*M + 2*M*NB)
 2316: *
 2317:                   CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
 2318:      $                         WORK( ITAUQ ), WORK( ITAUP ),
 2319:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2320:                   CALL DLACPY( 'U', M, M, U, LDU, WORK( IR ), LDWRKR )
 2321: *
 2322: *                 Generate right vectors bidiagonalizing L in WORK(IR)
 2323: *                 (Workspace: need M*M + 4*M-1, prefer M*M + 3*M + (M-1)*NB)
 2324: *
 2325:                   CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
 2326:      $                         WORK( ITAUP ), WORK( IWORK ),
 2327:      $                         LWORK-IWORK+1, IERR )
 2328: *
 2329: *                 Generate left vectors bidiagonalizing L in U
 2330: *                 (Workspace: need M*M + 4*M, prefer M*M + 3*M + M*NB)
 2331: *
 2332:                   CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
 2333:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2334:                   IWORK = IE + M
 2335: *
 2336: *                 Perform bidiagonal QR iteration, computing left
 2337: *                 singular vectors of L in U, and computing right
 2338: *                 singular vectors of L in WORK(IR)
 2339: *                 (Workspace: need M*M + BDSPAC)
 2340: *
 2341:                   CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
 2342:      $                         WORK( IR ), LDWRKR, U, LDU, DUM, 1,
 2343:      $                         WORK( IWORK ), INFO )
 2344:                   IU = IE + M
 2345: *
 2346: *                 Multiply right singular vectors of L in WORK(IR) by Q
 2347: *                 in A, storing result in WORK(IU) and copying to A
 2348: *                 (Workspace: need M*M + 2*M, prefer M*M + M*N + M))
 2349: *
 2350:                   DO 40 I = 1, N, CHUNK
 2351:                      BLK = MIN( N-I+1, CHUNK )
 2352:                      CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IR ),
 2353:      $                           LDWRKR, A( 1, I ), LDA, ZERO,
 2354:      $                           WORK( IU ), LDWRKU )
 2355:                      CALL DLACPY( 'F', M, BLK, WORK( IU ), LDWRKU,
 2356:      $                            A( 1, I ), LDA )
 2357:    40             CONTINUE
 2358: *
 2359:                ELSE
 2360: *
 2361: *                 Insufficient workspace for a fast algorithm
 2362: *
 2363:                   ITAU = 1
 2364:                   IWORK = ITAU + M
 2365: *
 2366: *                 Compute A=L*Q
 2367: *                 (Workspace: need 2*M, prefer M + M*NB)
 2368: *
 2369:                   CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 2370:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2371: *
 2372: *                 Copy L to U, zeroing out above it
 2373: *
 2374:                   CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
 2375:                   CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
 2376:      $                         LDU )
 2377: *
 2378: *                 Generate Q in A
 2379: *                 (Workspace: need 2*M, prefer M + M*NB)
 2380: *
 2381:                   CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
 2382:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2383:                   IE = ITAU
 2384:                   ITAUQ = IE + M
 2385:                   ITAUP = ITAUQ + M
 2386:                   IWORK = ITAUP + M
 2387: *
 2388: *                 Bidiagonalize L in U
 2389: *                 (Workspace: need 4*M, prefer 3*M + 2*M*NB)
 2390: *
 2391:                   CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
 2392:      $                         WORK( ITAUQ ), WORK( ITAUP ),
 2393:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2394: *
 2395: *                 Multiply right vectors bidiagonalizing L by Q in A
 2396: *                 (Workspace: need 3*M + N, prefer 3*M + N*NB)
 2397: *
 2398:                   CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,
 2399:      $                         WORK( ITAUP ), A, LDA, WORK( IWORK ),
 2400:      $                         LWORK-IWORK+1, IERR )
 2401: *
 2402: *                 Generate left vectors bidiagonalizing L in U
 2403: *                 (Workspace: need 4*M, prefer 3*M + M*NB)
 2404: *
 2405:                   CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
 2406:      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
 2407:                   IWORK = IE + M
 2408: *
 2409: *                 Perform bidiagonal QR iteration, computing left
 2410: *                 singular vectors of A in U and computing right
 2411: *                 singular vectors of A in A
 2412: *                 (Workspace: need BDSPAC)
 2413: *
 2414:                   CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), A, LDA,
 2415:      $                         U, LDU, DUM, 1, WORK( IWORK ), INFO )
 2416: *
 2417:                END IF
 2418: *
 2419:             ELSE IF( WNTVS ) THEN
 2420: *
 2421:                IF( WNTUN ) THEN
 2422: *
 2423: *                 Path 4t(N much larger than M, JOBU='N', JOBVT='S')
 2424: *                 M right singular vectors to be computed in VT and
 2425: *                 no left singular vectors to be computed
 2426: *
 2427:                   IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
 2428: *
 2429: *                    Sufficient workspace for a fast algorithm
 2430: *
 2431:                      IR = 1
 2432:                      IF( LWORK.GE.WRKBL+LDA*M ) THEN
 2433: *
 2434: *                       WORK(IR) is LDA by M
 2435: *
 2436:                         LDWRKR = LDA
 2437:                      ELSE
 2438: *
 2439: *                       WORK(IR) is M by M
 2440: *
 2441:                         LDWRKR = M
 2442:                      END IF
 2443:                      ITAU = IR + LDWRKR*M
 2444:                      IWORK = ITAU + M
 2445: *
 2446: *                    Compute A=L*Q
 2447: *                    (Workspace: need M*M + 2*M, prefer M*M + M + M*NB)
 2448: *
 2449:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 2450:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2451: *
 2452: *                    Copy L to WORK(IR), zeroing out above it
 2453: *
 2454:                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ),
 2455:      $                            LDWRKR )
 2456:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
 2457:      $                            WORK( IR+LDWRKR ), LDWRKR )
 2458: *
 2459: *                    Generate Q in A
 2460: *                    (Workspace: need M*M + 2*M, prefer M*M + M + M*NB)
 2461: *
 2462:                      CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
 2463:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2464:                      IE = ITAU
 2465:                      ITAUQ = IE + M
 2466:                      ITAUP = ITAUQ + M
 2467:                      IWORK = ITAUP + M
 2468: *
 2469: *                    Bidiagonalize L in WORK(IR)
 2470: *                    (Workspace: need M*M + 4*M, prefer M*M + 3*M + 2*M*NB)
 2471: *
 2472:                      CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S,
 2473:      $                            WORK( IE ), WORK( ITAUQ ),
 2474:      $                            WORK( ITAUP ), WORK( IWORK ),
 2475:      $                            LWORK-IWORK+1, IERR )
 2476: *
 2477: *                    Generate right vectors bidiagonalizing L in
 2478: *                    WORK(IR)
 2479: *                    (Workspace: need M*M + 4*M, prefer M*M + 3*M + (M-1)*NB)
 2480: *
 2481:                      CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
 2482:      $                            WORK( ITAUP ), WORK( IWORK ),
 2483:      $                            LWORK-IWORK+1, IERR )
 2484:                      IWORK = IE + M
 2485: *
 2486: *                    Perform bidiagonal QR iteration, computing right
 2487: *                    singular vectors of L in WORK(IR)
 2488: *                    (Workspace: need M*M + BDSPAC)
 2489: *
 2490:                      CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),
 2491:      $                            WORK( IR ), LDWRKR, DUM, 1, DUM, 1,
 2492:      $                            WORK( IWORK ), INFO )
 2493: *
 2494: *                    Multiply right singular vectors of L in WORK(IR) by
 2495: *                    Q in A, storing result in VT
 2496: *                    (Workspace: need M*M)
 2497: *
 2498:                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IR ),
 2499:      $                           LDWRKR, A, LDA, ZERO, VT, LDVT )
 2500: *
 2501:                   ELSE
 2502: *
 2503: *                    Insufficient workspace for a fast algorithm
 2504: *
 2505:                      ITAU = 1
 2506:                      IWORK = ITAU + M
 2507: *
 2508: *                    Compute A=L*Q
 2509: *                    (Workspace: need 2*M, prefer M + M*NB)
 2510: *
 2511:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 2512:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2513: *
 2514: *                    Copy result to VT
 2515: *
 2516:                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
 2517: *
 2518: *                    Generate Q in VT
 2519: *                    (Workspace: need 2*M, prefer M + M*NB)
 2520: *
 2521:                      CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),
 2522:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2523:                      IE = ITAU
 2524:                      ITAUQ = IE + M
 2525:                      ITAUP = ITAUQ + M
 2526:                      IWORK = ITAUP + M
 2527: *
 2528: *                    Zero out above L in A
 2529: *
 2530:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
 2531:      $                            LDA )
 2532: *
 2533: *                    Bidiagonalize L in A
 2534: *                    (Workspace: need 4*M, prefer 3*M + 2*M*NB)
 2535: *
 2536:                      CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
 2537:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 2538:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2539: *
 2540: *                    Multiply right vectors bidiagonalizing L by Q in VT
 2541: *                    (Workspace: need 3*M + N, prefer 3*M + N*NB)
 2542: *
 2543:                      CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
 2544:      $                            WORK( ITAUP ), VT, LDVT,
 2545:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2546:                      IWORK = IE + M
 2547: *
 2548: *                    Perform bidiagonal QR iteration, computing right
 2549: *                    singular vectors of A in VT
 2550: *                    (Workspace: need BDSPAC)
 2551: *
 2552:                      CALL DBDSQR( 'U', M, N, 0, 0, S, WORK( IE ), VT,
 2553:      $                            LDVT, DUM, 1, DUM, 1, WORK( IWORK ),
 2554:      $                            INFO )
 2555: *
 2556:                   END IF
 2557: *
 2558:                ELSE IF( WNTUO ) THEN
 2559: *
 2560: *                 Path 5t(N much larger than M, JOBU='O', JOBVT='S')
 2561: *                 M right singular vectors to be computed in VT and
 2562: *                 M left singular vectors to be overwritten on A
 2563: *
 2564:                   IF( LWORK.GE.2*M*M+MAX( 4*M, BDSPAC ) ) THEN
 2565: *
 2566: *                    Sufficient workspace for a fast algorithm
 2567: *
 2568:                      IU = 1
 2569:                      IF( LWORK.GE.WRKBL+2*LDA*M ) THEN
 2570: *
 2571: *                       WORK(IU) is LDA by M and WORK(IR) is LDA by M
 2572: *
 2573:                         LDWRKU = LDA
 2574:                         IR = IU + LDWRKU*M
 2575:                         LDWRKR = LDA
 2576:                      ELSE IF( LWORK.GE.WRKBL+( LDA + M )*M ) THEN
 2577: *
 2578: *                       WORK(IU) is LDA by M and WORK(IR) is M by M
 2579: *
 2580:                         LDWRKU = LDA
 2581:                         IR = IU + LDWRKU*M
 2582:                         LDWRKR = M
 2583:                      ELSE
 2584: *
 2585: *                       WORK(IU) is M by M and WORK(IR) is M by M
 2586: *
 2587:                         LDWRKU = M
 2588:                         IR = IU + LDWRKU*M
 2589:                         LDWRKR = M
 2590:                      END IF
 2591:                      ITAU = IR + LDWRKR*M
 2592:                      IWORK = ITAU + M
 2593: *
 2594: *                    Compute A=L*Q
 2595: *                    (Workspace: need 2*M*M + 2*M, prefer 2*M*M + M + M*NB)
 2596: *
 2597:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 2598:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2599: *
 2600: *                    Copy L to WORK(IU), zeroing out below it
 2601: *
 2602:                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
 2603:      $                            LDWRKU )
 2604:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
 2605:      $                            WORK( IU+LDWRKU ), LDWRKU )
 2606: *
 2607: *                    Generate Q in A
 2608: *                    (Workspace: need 2*M*M + 2*M, prefer 2*M*M + M + M*NB)
 2609: *
 2610:                      CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
 2611:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2612:                      IE = ITAU
 2613:                      ITAUQ = IE + M
 2614:                      ITAUP = ITAUQ + M
 2615:                      IWORK = ITAUP + M
 2616: *
 2617: *                    Bidiagonalize L in WORK(IU), copying result to
 2618: *                    WORK(IR)
 2619: *                    (Workspace: need 2*M*M + 4*M,
 2620: *                                prefer 2*M*M+3*M+2*M*NB)
 2621: *
 2622:                      CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
 2623:      $                            WORK( IE ), WORK( ITAUQ ),
 2624:      $                            WORK( ITAUP ), WORK( IWORK ),
 2625:      $                            LWORK-IWORK+1, IERR )
 2626:                      CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU,
 2627:      $                            WORK( IR ), LDWRKR )
 2628: *
 2629: *                    Generate right bidiagonalizing vectors in WORK(IU)
 2630: *                    (Workspace: need 2*M*M + 4*M-1,
 2631: *                                prefer 2*M*M+3*M+(M-1)*NB)
 2632: *
 2633:                      CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
 2634:      $                            WORK( ITAUP ), WORK( IWORK ),
 2635:      $                            LWORK-IWORK+1, IERR )
 2636: *
 2637: *                    Generate left bidiagonalizing vectors in WORK(IR)
 2638: *                    (Workspace: need 2*M*M + 4*M, prefer 2*M*M + 3*M + M*NB)
 2639: *
 2640:                      CALL DORGBR( 'Q', M, M, M, WORK( IR ), LDWRKR,
 2641:      $                            WORK( ITAUQ ), WORK( IWORK ),
 2642:      $                            LWORK-IWORK+1, IERR )
 2643:                      IWORK = IE + M
 2644: *
 2645: *                    Perform bidiagonal QR iteration, computing left
 2646: *                    singular vectors of L in WORK(IR) and computing
 2647: *                    right singular vectors of L in WORK(IU)
 2648: *                    (Workspace: need 2*M*M + BDSPAC)
 2649: *
 2650:                      CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
 2651:      $                            WORK( IU ), LDWRKU, WORK( IR ),
 2652:      $                            LDWRKR, DUM, 1, WORK( IWORK ), INFO )
 2653: *
 2654: *                    Multiply right singular vectors of L in WORK(IU) by
 2655: *                    Q in A, storing result in VT
 2656: *                    (Workspace: need M*M)
 2657: *
 2658:                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
 2659:      $                           LDWRKU, A, LDA, ZERO, VT, LDVT )
 2660: *
 2661: *                    Copy left singular vectors of L to A
 2662: *                    (Workspace: need M*M)
 2663: *
 2664:                      CALL DLACPY( 'F', M, M, WORK( IR ), LDWRKR, A,
 2665:      $                            LDA )
 2666: *
 2667:                   ELSE
 2668: *
 2669: *                    Insufficient workspace for a fast algorithm
 2670: *
 2671:                      ITAU = 1
 2672:                      IWORK = ITAU + M
 2673: *
 2674: *                    Compute A=L*Q, copying result to VT
 2675: *                    (Workspace: need 2*M, prefer M + M*NB)
 2676: *
 2677:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 2678:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2679:                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
 2680: *
 2681: *                    Generate Q in VT
 2682: *                    (Workspace: need 2*M, prefer M + M*NB)
 2683: *
 2684:                      CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),
 2685:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2686:                      IE = ITAU
 2687:                      ITAUQ = IE + M
 2688:                      ITAUP = ITAUQ + M
 2689:                      IWORK = ITAUP + M
 2690: *
 2691: *                    Zero out above L in A
 2692: *
 2693:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
 2694:      $                            LDA )
 2695: *
 2696: *                    Bidiagonalize L in A
 2697: *                    (Workspace: need 4*M, prefer 3*M + 2*M*NB)
 2698: *
 2699:                      CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
 2700:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 2701:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2702: *
 2703: *                    Multiply right vectors bidiagonalizing L by Q in VT
 2704: *                    (Workspace: need 3*M + N, prefer 3*M + N*NB)
 2705: *
 2706:                      CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
 2707:      $                            WORK( ITAUP ), VT, LDVT,
 2708:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2709: *
 2710: *                    Generate left bidiagonalizing vectors of L in A
 2711: *                    (Workspace: need 4*M, prefer 3*M + M*NB)
 2712: *
 2713:                      CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),
 2714:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2715:                      IWORK = IE + M
 2716: *
 2717: *                    Perform bidiagonal QR iteration, compute left
 2718: *                    singular vectors of A in A and compute right
 2719: *                    singular vectors of A in VT
 2720: *                    (Workspace: need BDSPAC)
 2721: *
 2722:                      CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
 2723:      $                            LDVT, A, LDA, DUM, 1, WORK( IWORK ),
 2724:      $                            INFO )
 2725: *
 2726:                   END IF
 2727: *
 2728:                ELSE IF( WNTUAS ) THEN
 2729: *
 2730: *                 Path 6t(N much larger than M, JOBU='S' or 'A',
 2731: *                         JOBVT='S')
 2732: *                 M right singular vectors to be computed in VT and
 2733: *                 M left singular vectors to be computed in U
 2734: *
 2735:                   IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
 2736: *
 2737: *                    Sufficient workspace for a fast algorithm
 2738: *
 2739:                      IU = 1
 2740:                      IF( LWORK.GE.WRKBL+LDA*M ) THEN
 2741: *
 2742: *                       WORK(IU) is LDA by N
 2743: *
 2744:                         LDWRKU = LDA
 2745:                      ELSE
 2746: *
 2747: *                       WORK(IU) is LDA by M
 2748: *
 2749:                         LDWRKU = M
 2750:                      END IF
 2751:                      ITAU = IU + LDWRKU*M
 2752:                      IWORK = ITAU + M
 2753: *
 2754: *                    Compute A=L*Q
 2755: *                    (Workspace: need M*M + 2*M, prefer M*M + M + M*NB)
 2756: *
 2757:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 2758:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2759: *
 2760: *                    Copy L to WORK(IU), zeroing out above it
 2761: *
 2762:                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
 2763:      $                            LDWRKU )
 2764:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
 2765:      $                            WORK( IU+LDWRKU ), LDWRKU )
 2766: *
 2767: *                    Generate Q in A
 2768: *                    (Workspace: need M*M + 2*M, prefer M*M + M + M*NB)
 2769: *
 2770:                      CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
 2771:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2772:                      IE = ITAU
 2773:                      ITAUQ = IE + M
 2774:                      ITAUP = ITAUQ + M
 2775:                      IWORK = ITAUP + M
 2776: *
 2777: *                    Bidiagonalize L in WORK(IU), copying result to U
 2778: *                    (Workspace: need M*M + 4*M, prefer M*M + 3*M + 2*M*NB)
 2779: *
 2780:                      CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
 2781:      $                            WORK( IE ), WORK( ITAUQ ),
 2782:      $                            WORK( ITAUP ), WORK( IWORK ),
 2783:      $                            LWORK-IWORK+1, IERR )
 2784:                      CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, U,
 2785:      $                            LDU )
 2786: *
 2787: *                    Generate right bidiagonalizing vectors in WORK(IU)
 2788: *                    (Workspace: need M*M + 4*M-1,
 2789: *                                prefer M*M+3*M+(M-1)*NB)
 2790: *
 2791:                      CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
 2792:      $                            WORK( ITAUP ), WORK( IWORK ),
 2793:      $                            LWORK-IWORK+1, IERR )
 2794: *
 2795: *                    Generate left bidiagonalizing vectors in U
 2796: *                    (Workspace: need M*M + 4*M, prefer M*M + 3*M + M*NB)
 2797: *
 2798:                      CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
 2799:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2800:                      IWORK = IE + M
 2801: *
 2802: *                    Perform bidiagonal QR iteration, computing left
 2803: *                    singular vectors of L in U and computing right
 2804: *                    singular vectors of L in WORK(IU)
 2805: *                    (Workspace: need M*M + BDSPAC)
 2806: *
 2807:                      CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
 2808:      $                            WORK( IU ), LDWRKU, U, LDU, DUM, 1,
 2809:      $                            WORK( IWORK ), INFO )
 2810: *
 2811: *                    Multiply right singular vectors of L in WORK(IU) by
 2812: *                    Q in A, storing result in VT
 2813: *                    (Workspace: need M*M)
 2814: *
 2815:                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
 2816:      $                           LDWRKU, A, LDA, ZERO, VT, LDVT )
 2817: *
 2818:                   ELSE
 2819: *
 2820: *                    Insufficient workspace for a fast algorithm
 2821: *
 2822:                      ITAU = 1
 2823:                      IWORK = ITAU + M
 2824: *
 2825: *                    Compute A=L*Q, copying result to VT
 2826: *                    (Workspace: need 2*M, prefer M + M*NB)
 2827: *
 2828:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 2829:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2830:                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
 2831: *
 2832: *                    Generate Q in VT
 2833: *                    (Workspace: need 2*M, prefer M + M*NB)
 2834: *
 2835:                      CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),
 2836:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2837: *
 2838: *                    Copy L to U, zeroing out above it
 2839: *
 2840:                      CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
 2841:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
 2842:      $                            LDU )
 2843:                      IE = ITAU
 2844:                      ITAUQ = IE + M
 2845:                      ITAUP = ITAUQ + M
 2846:                      IWORK = ITAUP + M
 2847: *
 2848: *                    Bidiagonalize L in U
 2849: *                    (Workspace: need 4*M, prefer 3*M + 2*M*NB)
 2850: *
 2851:                      CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
 2852:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 2853:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2854: *
 2855: *                    Multiply right bidiagonalizing vectors in U by Q
 2856: *                    in VT
 2857: *                    (Workspace: need 3*M + N, prefer 3*M + N*NB)
 2858: *
 2859:                      CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,
 2860:      $                            WORK( ITAUP ), VT, LDVT,
 2861:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2862: *
 2863: *                    Generate left bidiagonalizing vectors in U
 2864: *                    (Workspace: need 4*M, prefer 3*M + M*NB)
 2865: *
 2866:                      CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
 2867:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2868:                      IWORK = IE + M
 2869: *
 2870: *                    Perform bidiagonal QR iteration, computing left
 2871: *                    singular vectors of A in U and computing right
 2872: *                    singular vectors of A in VT
 2873: *                    (Workspace: need BDSPAC)
 2874: *
 2875:                      CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
 2876:      $                            LDVT, U, LDU, DUM, 1, WORK( IWORK ),
 2877:      $                            INFO )
 2878: *
 2879:                   END IF
 2880: *
 2881:                END IF
 2882: *
 2883:             ELSE IF( WNTVA ) THEN
 2884: *
 2885:                IF( WNTUN ) THEN
 2886: *
 2887: *                 Path 7t(N much larger than M, JOBU='N', JOBVT='A')
 2888: *                 N right singular vectors to be computed in VT and
 2889: *                 no left singular vectors to be computed
 2890: *
 2891:                   IF( LWORK.GE.M*M+MAX( N + M, 4*M, BDSPAC ) ) THEN
 2892: *
 2893: *                    Sufficient workspace for a fast algorithm
 2894: *
 2895:                      IR = 1
 2896:                      IF( LWORK.GE.WRKBL+LDA*M ) THEN
 2897: *
 2898: *                       WORK(IR) is LDA by M
 2899: *
 2900:                         LDWRKR = LDA
 2901:                      ELSE
 2902: *
 2903: *                       WORK(IR) is M by M
 2904: *
 2905:                         LDWRKR = M
 2906:                      END IF
 2907:                      ITAU = IR + LDWRKR*M
 2908:                      IWORK = ITAU + M
 2909: *
 2910: *                    Compute A=L*Q, copying result to VT
 2911: *                    (Workspace: need M*M + 2*M, prefer M*M + M + M*NB)
 2912: *
 2913:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 2914:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2915:                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
 2916: *
 2917: *                    Copy L to WORK(IR), zeroing out above it
 2918: *
 2919:                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ),
 2920:      $                            LDWRKR )
 2921:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
 2922:      $                            WORK( IR+LDWRKR ), LDWRKR )
 2923: *
 2924: *                    Generate Q in VT
 2925: *                    (Workspace: need M*M + M + N, prefer M*M + M + N*NB)
 2926: *
 2927:                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
 2928:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2929:                      IE = ITAU
 2930:                      ITAUQ = IE + M
 2931:                      ITAUP = ITAUQ + M
 2932:                      IWORK = ITAUP + M
 2933: *
 2934: *                    Bidiagonalize L in WORK(IR)
 2935: *                    (Workspace: need M*M + 4*M, prefer M*M + 3*M + 2*M*NB)
 2936: *
 2937:                      CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S,
 2938:      $                            WORK( IE ), WORK( ITAUQ ),
 2939:      $                            WORK( ITAUP ), WORK( IWORK ),
 2940:      $                            LWORK-IWORK+1, IERR )
 2941: *
 2942: *                    Generate right bidiagonalizing vectors in WORK(IR)
 2943: *                    (Workspace: need M*M + 4*M-1,
 2944: *                                prefer M*M+3*M+(M-1)*NB)
 2945: *
 2946:                      CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
 2947:      $                            WORK( ITAUP ), WORK( IWORK ),
 2948:      $                            LWORK-IWORK+1, IERR )
 2949:                      IWORK = IE + M
 2950: *
 2951: *                    Perform bidiagonal QR iteration, computing right
 2952: *                    singular vectors of L in WORK(IR)
 2953: *                    (Workspace: need M*M + BDSPAC)
 2954: *
 2955:                      CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),
 2956:      $                            WORK( IR ), LDWRKR, DUM, 1, DUM, 1,
 2957:      $                            WORK( IWORK ), INFO )
 2958: *
 2959: *                    Multiply right singular vectors of L in WORK(IR) by
 2960: *                    Q in VT, storing result in A
 2961: *                    (Workspace: need M*M)
 2962: *
 2963:                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IR ),
 2964:      $                           LDWRKR, VT, LDVT, ZERO, A, LDA )
 2965: *
 2966: *                    Copy right singular vectors of A from A to VT
 2967: *
 2968:                      CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
 2969: *
 2970:                   ELSE
 2971: *
 2972: *                    Insufficient workspace for a fast algorithm
 2973: *
 2974:                      ITAU = 1
 2975:                      IWORK = ITAU + M
 2976: *
 2977: *                    Compute A=L*Q, copying result to VT
 2978: *                    (Workspace: need 2*M, prefer M + M*NB)
 2979: *
 2980:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 2981:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2982:                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
 2983: *
 2984: *                    Generate Q in VT
 2985: *                    (Workspace: need M + N, prefer M + N*NB)
 2986: *
 2987:                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
 2988:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 2989:                      IE = ITAU
 2990:                      ITAUQ = IE + M
 2991:                      ITAUP = ITAUQ + M
 2992:                      IWORK = ITAUP + M
 2993: *
 2994: *                    Zero out above L in A
 2995: *
 2996:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
 2997:      $                            LDA )
 2998: *
 2999: *                    Bidiagonalize L in A
 3000: *                    (Workspace: need 4*M, prefer 3*M + 2*M*NB)
 3001: *
 3002:                      CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
 3003:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 3004:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3005: *
 3006: *                    Multiply right bidiagonalizing vectors in A by Q
 3007: *                    in VT
 3008: *                    (Workspace: need 3*M + N, prefer 3*M + N*NB)
 3009: *
 3010:                      CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
 3011:      $                            WORK( ITAUP ), VT, LDVT,
 3012:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3013:                      IWORK = IE + M
 3014: *
 3015: *                    Perform bidiagonal QR iteration, computing right
 3016: *                    singular vectors of A in VT
 3017: *                    (Workspace: need BDSPAC)
 3018: *
 3019:                      CALL DBDSQR( 'U', M, N, 0, 0, S, WORK( IE ), VT,
 3020:      $                            LDVT, DUM, 1, DUM, 1, WORK( IWORK ),
 3021:      $                            INFO )
 3022: *
 3023:                   END IF
 3024: *
 3025:                ELSE IF( WNTUO ) THEN
 3026: *
 3027: *                 Path 8t(N much larger than M, JOBU='O', JOBVT='A')
 3028: *                 N right singular vectors to be computed in VT and
 3029: *                 M left singular vectors to be overwritten on A
 3030: *
 3031:                   IF( LWORK.GE.2*M*M+MAX( N + M, 4*M, BDSPAC ) ) THEN
 3032: *
 3033: *                    Sufficient workspace for a fast algorithm
 3034: *
 3035:                      IU = 1
 3036:                      IF( LWORK.GE.WRKBL+2*LDA*M ) THEN
 3037: *
 3038: *                       WORK(IU) is LDA by M and WORK(IR) is LDA by M
 3039: *
 3040:                         LDWRKU = LDA
 3041:                         IR = IU + LDWRKU*M
 3042:                         LDWRKR = LDA
 3043:                      ELSE IF( LWORK.GE.WRKBL+( LDA + M )*M ) THEN
 3044: *
 3045: *                       WORK(IU) is LDA by M and WORK(IR) is M by M
 3046: *
 3047:                         LDWRKU = LDA
 3048:                         IR = IU + LDWRKU*M
 3049:                         LDWRKR = M
 3050:                      ELSE
 3051: *
 3052: *                       WORK(IU) is M by M and WORK(IR) is M by M
 3053: *
 3054:                         LDWRKU = M
 3055:                         IR = IU + LDWRKU*M
 3056:                         LDWRKR = M
 3057:                      END IF
 3058:                      ITAU = IR + LDWRKR*M
 3059:                      IWORK = ITAU + M
 3060: *
 3061: *                    Compute A=L*Q, copying result to VT
 3062: *                    (Workspace: need 2*M*M + 2*M, prefer 2*M*M + M + M*NB)
 3063: *
 3064:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 3065:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3066:                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
 3067: *
 3068: *                    Generate Q in VT
 3069: *                    (Workspace: need 2*M*M + M + N, prefer 2*M*M + M + N*NB)
 3070: *
 3071:                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
 3072:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3073: *
 3074: *                    Copy L to WORK(IU), zeroing out above it
 3075: *
 3076:                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
 3077:      $                            LDWRKU )
 3078:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
 3079:      $                            WORK( IU+LDWRKU ), LDWRKU )
 3080:                      IE = ITAU
 3081:                      ITAUQ = IE + M
 3082:                      ITAUP = ITAUQ + M
 3083:                      IWORK = ITAUP + M
 3084: *
 3085: *                    Bidiagonalize L in WORK(IU), copying result to
 3086: *                    WORK(IR)
 3087: *                    (Workspace: need 2*M*M + 4*M,
 3088: *                                prefer 2*M*M+3*M+2*M*NB)
 3089: *
 3090:                      CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
 3091:      $                            WORK( IE ), WORK( ITAUQ ),
 3092:      $                            WORK( ITAUP ), WORK( IWORK ),
 3093:      $                            LWORK-IWORK+1, IERR )
 3094:                      CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU,
 3095:      $                            WORK( IR ), LDWRKR )
 3096: *
 3097: *                    Generate right bidiagonalizing vectors in WORK(IU)
 3098: *                    (Workspace: need 2*M*M + 4*M-1,
 3099: *                                prefer 2*M*M+3*M+(M-1)*NB)
 3100: *
 3101:                      CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
 3102:      $                            WORK( ITAUP ), WORK( IWORK ),
 3103:      $                            LWORK-IWORK+1, IERR )
 3104: *
 3105: *                    Generate left bidiagonalizing vectors in WORK(IR)
 3106: *                    (Workspace: need 2*M*M + 4*M, prefer 2*M*M + 3*M + M*NB)
 3107: *
 3108:                      CALL DORGBR( 'Q', M, M, M, WORK( IR ), LDWRKR,
 3109:      $                            WORK( ITAUQ ), WORK( IWORK ),
 3110:      $                            LWORK-IWORK+1, IERR )
 3111:                      IWORK = IE + M
 3112: *
 3113: *                    Perform bidiagonal QR iteration, computing left
 3114: *                    singular vectors of L in WORK(IR) and computing
 3115: *                    right singular vectors of L in WORK(IU)
 3116: *                    (Workspace: need 2*M*M + BDSPAC)
 3117: *
 3118:                      CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
 3119:      $                            WORK( IU ), LDWRKU, WORK( IR ),
 3120:      $                            LDWRKR, DUM, 1, WORK( IWORK ), INFO )
 3121: *
 3122: *                    Multiply right singular vectors of L in WORK(IU) by
 3123: *                    Q in VT, storing result in A
 3124: *                    (Workspace: need M*M)
 3125: *
 3126:                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
 3127:      $                           LDWRKU, VT, LDVT, ZERO, A, LDA )
 3128: *
 3129: *                    Copy right singular vectors of A from A to VT
 3130: *
 3131:                      CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
 3132: *
 3133: *                    Copy left singular vectors of A from WORK(IR) to A
 3134: *
 3135:                      CALL DLACPY( 'F', M, M, WORK( IR ), LDWRKR, A,
 3136:      $                            LDA )
 3137: *
 3138:                   ELSE
 3139: *
 3140: *                    Insufficient workspace for a fast algorithm
 3141: *
 3142:                      ITAU = 1
 3143:                      IWORK = ITAU + M
 3144: *
 3145: *                    Compute A=L*Q, copying result to VT
 3146: *                    (Workspace: need 2*M, prefer M + M*NB)
 3147: *
 3148:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 3149:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3150:                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
 3151: *
 3152: *                    Generate Q in VT
 3153: *                    (Workspace: need M + N, prefer M + N*NB)
 3154: *
 3155:                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
 3156:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3157:                      IE = ITAU
 3158:                      ITAUQ = IE + M
 3159:                      ITAUP = ITAUQ + M
 3160:                      IWORK = ITAUP + M
 3161: *
 3162: *                    Zero out above L in A
 3163: *
 3164:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
 3165:      $                            LDA )
 3166: *
 3167: *                    Bidiagonalize L in A
 3168: *                    (Workspace: need 4*M, prefer 3*M + 2*M*NB)
 3169: *
 3170:                      CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
 3171:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 3172:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3173: *
 3174: *                    Multiply right bidiagonalizing vectors in A by Q
 3175: *                    in VT
 3176: *                    (Workspace: need 3*M + N, prefer 3*M + N*NB)
 3177: *
 3178:                      CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
 3179:      $                            WORK( ITAUP ), VT, LDVT,
 3180:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3181: *
 3182: *                    Generate left bidiagonalizing vectors in A
 3183: *                    (Workspace: need 4*M, prefer 3*M + M*NB)
 3184: *
 3185:                      CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),
 3186:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3187:                      IWORK = IE + M
 3188: *
 3189: *                    Perform bidiagonal QR iteration, computing left
 3190: *                    singular vectors of A in A and computing right
 3191: *                    singular vectors of A in VT
 3192: *                    (Workspace: need BDSPAC)
 3193: *
 3194:                      CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
 3195:      $                            LDVT, A, LDA, DUM, 1, WORK( IWORK ),
 3196:      $                            INFO )
 3197: *
 3198:                   END IF
 3199: *
 3200:                ELSE IF( WNTUAS ) THEN
 3201: *
 3202: *                 Path 9t(N much larger than M, JOBU='S' or 'A',
 3203: *                         JOBVT='A')
 3204: *                 N right singular vectors to be computed in VT and
 3205: *                 M left singular vectors to be computed in U
 3206: *
 3207:                   IF( LWORK.GE.M*M+MAX( N + M, 4*M, BDSPAC ) ) THEN
 3208: *
 3209: *                    Sufficient workspace for a fast algorithm
 3210: *
 3211:                      IU = 1
 3212:                      IF( LWORK.GE.WRKBL+LDA*M ) THEN
 3213: *
 3214: *                       WORK(IU) is LDA by M
 3215: *
 3216:                         LDWRKU = LDA
 3217:                      ELSE
 3218: *
 3219: *                       WORK(IU) is M by M
 3220: *
 3221:                         LDWRKU = M
 3222:                      END IF
 3223:                      ITAU = IU + LDWRKU*M
 3224:                      IWORK = ITAU + M
 3225: *
 3226: *                    Compute A=L*Q, copying result to VT
 3227: *                    (Workspace: need M*M + 2*M, prefer M*M + M + M*NB)
 3228: *
 3229:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 3230:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3231:                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
 3232: *
 3233: *                    Generate Q in VT
 3234: *                    (Workspace: need M*M + M + N, prefer M*M + M + N*NB)
 3235: *
 3236:                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
 3237:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3238: *
 3239: *                    Copy L to WORK(IU), zeroing out above it
 3240: *
 3241:                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
 3242:      $                            LDWRKU )
 3243:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
 3244:      $                            WORK( IU+LDWRKU ), LDWRKU )
 3245:                      IE = ITAU
 3246:                      ITAUQ = IE + M
 3247:                      ITAUP = ITAUQ + M
 3248:                      IWORK = ITAUP + M
 3249: *
 3250: *                    Bidiagonalize L in WORK(IU), copying result to U
 3251: *                    (Workspace: need M*M + 4*M, prefer M*M + 3*M + 2*M*NB)
 3252: *
 3253:                      CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
 3254:      $                            WORK( IE ), WORK( ITAUQ ),
 3255:      $                            WORK( ITAUP ), WORK( IWORK ),
 3256:      $                            LWORK-IWORK+1, IERR )
 3257:                      CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, U,
 3258:      $                            LDU )
 3259: *
 3260: *                    Generate right bidiagonalizing vectors in WORK(IU)
 3261: *                    (Workspace: need M*M + 4*M, prefer M*M + 3*M + (M-1)*NB)
 3262: *
 3263:                      CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
 3264:      $                            WORK( ITAUP ), WORK( IWORK ),
 3265:      $                            LWORK-IWORK+1, IERR )
 3266: *
 3267: *                    Generate left bidiagonalizing vectors in U
 3268: *                    (Workspace: need M*M + 4*M, prefer M*M + 3*M + M*NB)
 3269: *
 3270:                      CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
 3271:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3272:                      IWORK = IE + M
 3273: *
 3274: *                    Perform bidiagonal QR iteration, computing left
 3275: *                    singular vectors of L in U and computing right
 3276: *                    singular vectors of L in WORK(IU)
 3277: *                    (Workspace: need M*M + BDSPAC)
 3278: *
 3279:                      CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
 3280:      $                            WORK( IU ), LDWRKU, U, LDU, DUM, 1,
 3281:      $                            WORK( IWORK ), INFO )
 3282: *
 3283: *                    Multiply right singular vectors of L in WORK(IU) by
 3284: *                    Q in VT, storing result in A
 3285: *                    (Workspace: need M*M)
 3286: *
 3287:                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
 3288:      $                           LDWRKU, VT, LDVT, ZERO, A, LDA )
 3289: *
 3290: *                    Copy right singular vectors of A from A to VT
 3291: *
 3292:                      CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
 3293: *
 3294:                   ELSE
 3295: *
 3296: *                    Insufficient workspace for a fast algorithm
 3297: *
 3298:                      ITAU = 1
 3299:                      IWORK = ITAU + M
 3300: *
 3301: *                    Compute A=L*Q, copying result to VT
 3302: *                    (Workspace: need 2*M, prefer M + M*NB)
 3303: *
 3304:                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
 3305:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3306:                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
 3307: *
 3308: *                    Generate Q in VT
 3309: *                    (Workspace: need M + N, prefer M + N*NB)
 3310: *
 3311:                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
 3312:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3313: *
 3314: *                    Copy L to U, zeroing out above it
 3315: *
 3316:                      CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
 3317:                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
 3318:      $                            LDU )
 3319:                      IE = ITAU
 3320:                      ITAUQ = IE + M
 3321:                      ITAUP = ITAUQ + M
 3322:                      IWORK = ITAUP + M
 3323: *
 3324: *                    Bidiagonalize L in U
 3325: *                    (Workspace: need 4*M, prefer 3*M + 2*M*NB)
 3326: *
 3327:                      CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
 3328:      $                            WORK( ITAUQ ), WORK( ITAUP ),
 3329:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3330: *
 3331: *                    Multiply right bidiagonalizing vectors in U by Q
 3332: *                    in VT
 3333: *                    (Workspace: need 3*M + N, prefer 3*M + N*NB)
 3334: *
 3335:                      CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,
 3336:      $                            WORK( ITAUP ), VT, LDVT,
 3337:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3338: *
 3339: *                    Generate left bidiagonalizing vectors in U
 3340: *                    (Workspace: need 4*M, prefer 3*M + M*NB)
 3341: *
 3342:                      CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
 3343:      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
 3344:                      IWORK = IE + M
 3345: *
 3346: *                    Perform bidiagonal QR iteration, computing left
 3347: *                    singular vectors of A in U and computing right
 3348: *                    singular vectors of A in VT
 3349: *                    (Workspace: need BDSPAC)
 3350: *
 3351:                      CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
 3352:      $                            LDVT, U, LDU, DUM, 1, WORK( IWORK ),
 3353:      $                            INFO )
 3354: *
 3355:                   END IF
 3356: *
 3357:                END IF
 3358: *
 3359:             END IF
 3360: *
 3361:          ELSE
 3362: *
 3363: *           N .LT. MNTHR
 3364: *
 3365: *           Path 10t(N greater than M, but not much larger)
 3366: *           Reduce to bidiagonal form without LQ decomposition
 3367: *
 3368:             IE = 1
 3369:             ITAUQ = IE + M
 3370:             ITAUP = ITAUQ + M
 3371:             IWORK = ITAUP + M
 3372: *
 3373: *           Bidiagonalize A
 3374: *           (Workspace: need 3*M + N, prefer 3*M + (M + N)*NB)
 3375: *
 3376:             CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
 3377:      $                   WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
 3378:      $                   IERR )
 3379:             IF( WNTUAS ) THEN
 3380: *
 3381: *              If left singular vectors desired in U, copy result to U
 3382: *              and generate left bidiagonalizing vectors in U
 3383: *              (Workspace: need 4*M-1, prefer 3*M + (M-1)*NB)
 3384: *
 3385:                CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
 3386:                CALL DORGBR( 'Q', M, M, N, U, LDU, WORK( ITAUQ ),
 3387:      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
 3388:             END IF
 3389:             IF( WNTVAS ) THEN
 3390: *
 3391: *              If right singular vectors desired in VT, copy result to
 3392: *              VT and generate right bidiagonalizing vectors in VT
 3393: *              (Workspace: need 3*M + NRVT, prefer 3*M + NRVT*NB)
 3394: *
 3395:                CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
 3396:                IF( WNTVA )
 3397:      $            NRVT = N
 3398:                IF( WNTVS )
 3399:      $            NRVT = M
 3400:                CALL DORGBR( 'P', NRVT, N, M, VT, LDVT, WORK( ITAUP ),
 3401:      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
 3402:             END IF
 3403:             IF( WNTUO ) THEN
 3404: *
 3405: *              If left singular vectors desired in A, generate left
 3406: *              bidiagonalizing vectors in A
 3407: *              (Workspace: need 4*M-1, prefer 3*M + (M-1)*NB)
 3408: *
 3409:                CALL DORGBR( 'Q', M, M, N, A, LDA, WORK( ITAUQ ),
 3410:      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
 3411:             END IF
 3412:             IF( WNTVO ) THEN
 3413: *
 3414: *              If right singular vectors desired in A, generate right
 3415: *              bidiagonalizing vectors in A
 3416: *              (Workspace: need 4*M, prefer 3*M + M*NB)
 3417: *
 3418:                CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
 3419:      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
 3420:             END IF
 3421:             IWORK = IE + M
 3422:             IF( WNTUAS .OR. WNTUO )
 3423:      $         NRU = M
 3424:             IF( WNTUN )
 3425:      $         NRU = 0
 3426:             IF( WNTVAS .OR. WNTVO )
 3427:      $         NCVT = N
 3428:             IF( WNTVN )
 3429:      $         NCVT = 0
 3430:             IF( ( .NOT.WNTUO ) .AND. ( .NOT.WNTVO ) ) THEN
 3431: *
 3432: *              Perform bidiagonal QR iteration, if desired, computing
 3433: *              left singular vectors in U and computing right singular
 3434: *              vectors in VT
 3435: *              (Workspace: need BDSPAC)
 3436: *
 3437:                CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), VT,
 3438:      $                      LDVT, U, LDU, DUM, 1, WORK( IWORK ), INFO )
 3439:             ELSE IF( ( .NOT.WNTUO ) .AND. WNTVO ) THEN
 3440: *
 3441: *              Perform bidiagonal QR iteration, if desired, computing
 3442: *              left singular vectors in U and computing right singular
 3443: *              vectors in A
 3444: *              (Workspace: need BDSPAC)
 3445: *
 3446:                CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), A, LDA,
 3447:      $                      U, LDU, DUM, 1, WORK( IWORK ), INFO )
 3448:             ELSE
 3449: *
 3450: *              Perform bidiagonal QR iteration, if desired, computing
 3451: *              left singular vectors in A and computing right singular
 3452: *              vectors in VT
 3453: *              (Workspace: need BDSPAC)
 3454: *
 3455:                CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), VT,
 3456:      $                      LDVT, A, LDA, DUM, 1, WORK( IWORK ), INFO )
 3457:             END IF
 3458: *
 3459:          END IF
 3460: *
 3461:       END IF
 3462: *
 3463: *     If DBDSQR failed to converge, copy unconverged superdiagonals
 3464: *     to WORK( 2:MINMN )
 3465: *
 3466:       IF( INFO.NE.0 ) THEN
 3467:          IF( IE.GT.2 ) THEN
 3468:             DO 50 I = 1, MINMN - 1
 3469:                WORK( I+1 ) = WORK( I+IE-1 )
 3470:    50       CONTINUE
 3471:          END IF
 3472:          IF( IE.LT.2 ) THEN
 3473:             DO 60 I = MINMN - 1, 1, -1
 3474:                WORK( I+1 ) = WORK( I+IE-1 )
 3475:    60       CONTINUE
 3476:          END IF
 3477:       END IF
 3478: *
 3479: *     Undo scaling if necessary
 3480: *
 3481:       IF( ISCL.EQ.1 ) THEN
 3482:          IF( ANRM.GT.BIGNUM )
 3483:      $      CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
 3484:      $                   IERR )
 3485:          IF( INFO.NE.0 .AND. ANRM.GT.BIGNUM )
 3486:      $      CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN-1, 1, WORK( 2 ),
 3487:      $                   MINMN, IERR )
 3488:          IF( ANRM.LT.SMLNUM )
 3489:      $      CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
 3490:      $                   IERR )
 3491:          IF( INFO.NE.0 .AND. ANRM.LT.SMLNUM )
 3492:      $      CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN-1, 1, WORK( 2 ),
 3493:      $                   MINMN, IERR )
 3494:       END IF
 3495: *
 3496: *     Return optimal workspace in WORK(1)
 3497: *
 3498:       WORK( 1 ) = MAXWRK
 3499: *
 3500:       RETURN
 3501: *
 3502: *     End of DGESVD
 3503: *
 3504:       END

CVSweb interface <joel.bertrand@systella.fr>