Annotation of rpl/lapack/lapack/dgesvd.f, revision 1.20

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

CVSweb interface <joel.bertrand@systella.fr>