LAPACK 3.3.1
Linear Algebra PACKage

dgesvd.f

Go to the documentation of this file.
00001       SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT,
00002      $                   WORK, LWORK, INFO )
00003 *
00004 *  -- LAPACK driver routine (version 3.3.1) --
00005 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00006 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00007 *  -- April 2011                                                      --
00008 *
00009 *     .. Scalar Arguments ..
00010       CHARACTER          JOBU, JOBVT
00011       INTEGER            INFO, LDA, LDU, LDVT, LWORK, M, N
00012 *     ..
00013 *     .. Array Arguments ..
00014       DOUBLE PRECISION   A( LDA, * ), S( * ), U( LDU, * ),
00015      $                   VT( LDVT, * ), WORK( * )
00016 *     ..
00017 *
00018 *  Purpose
00019 *  =======
00020 *
00021 *  DGESVD computes the singular value decomposition (SVD) of a real
00022 *  M-by-N matrix A, optionally computing the left and/or right singular
00023 *  vectors. The SVD is written
00024 *
00025 *       A = U * SIGMA * transpose(V)
00026 *
00027 *  where SIGMA is an M-by-N matrix which is zero except for its
00028 *  min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
00029 *  V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
00030 *  are the singular values of A; they are real and non-negative, and
00031 *  are returned in descending order.  The first min(m,n) columns of
00032 *  U and V are the left and right singular vectors of A.
00033 *
00034 *  Note that the routine returns V**T, not V.
00035 *
00036 *  Arguments
00037 *  =========
00038 *
00039 *  JOBU    (input) CHARACTER*1
00040 *          Specifies options for computing all or part of the matrix U:
00041 *          = 'A':  all M columns of U are returned in array U:
00042 *          = 'S':  the first min(m,n) columns of U (the left singular
00043 *                  vectors) are returned in the array U;
00044 *          = 'O':  the first min(m,n) columns of U (the left singular
00045 *                  vectors) are overwritten on the array A;
00046 *          = 'N':  no columns of U (no left singular vectors) are
00047 *                  computed.
00048 *
00049 *  JOBVT   (input) CHARACTER*1
00050 *          Specifies options for computing all or part of the matrix
00051 *          V**T:
00052 *          = 'A':  all N rows of V**T are returned in the array VT;
00053 *          = 'S':  the first min(m,n) rows of V**T (the right singular
00054 *                  vectors) are returned in the array VT;
00055 *          = 'O':  the first min(m,n) rows of V**T (the right singular
00056 *                  vectors) are overwritten on the array A;
00057 *          = 'N':  no rows of V**T (no right singular vectors) are
00058 *                  computed.
00059 *
00060 *          JOBVT and JOBU cannot both be 'O'.
00061 *
00062 *  M       (input) INTEGER
00063 *          The number of rows of the input matrix A.  M >= 0.
00064 *
00065 *  N       (input) INTEGER
00066 *          The number of columns of the input matrix A.  N >= 0.
00067 *
00068 *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
00069 *          On entry, the M-by-N matrix A.
00070 *          On exit,
00071 *          if JOBU = 'O',  A is overwritten with the first min(m,n)
00072 *                          columns of U (the left singular vectors,
00073 *                          stored columnwise);
00074 *          if JOBVT = 'O', A is overwritten with the first min(m,n)
00075 *                          rows of V**T (the right singular vectors,
00076 *                          stored rowwise);
00077 *          if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A
00078 *                          are destroyed.
00079 *
00080 *  LDA     (input) INTEGER
00081 *          The leading dimension of the array A.  LDA >= max(1,M).
00082 *
00083 *  S       (output) DOUBLE PRECISION array, dimension (min(M,N))
00084 *          The singular values of A, sorted so that S(i) >= S(i+1).
00085 *
00086 *  U       (output) DOUBLE PRECISION array, dimension (LDU,UCOL)
00087 *          (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'.
00088 *          If JOBU = 'A', U contains the M-by-M orthogonal matrix U;
00089 *          if JOBU = 'S', U contains the first min(m,n) columns of U
00090 *          (the left singular vectors, stored columnwise);
00091 *          if JOBU = 'N' or 'O', U is not referenced.
00092 *
00093 *  LDU     (input) INTEGER
00094 *          The leading dimension of the array U.  LDU >= 1; if
00095 *          JOBU = 'S' or 'A', LDU >= M.
00096 *
00097 *  VT      (output) DOUBLE PRECISION array, dimension (LDVT,N)
00098 *          If JOBVT = 'A', VT contains the N-by-N orthogonal matrix
00099 *          V**T;
00100 *          if JOBVT = 'S', VT contains the first min(m,n) rows of
00101 *          V**T (the right singular vectors, stored rowwise);
00102 *          if JOBVT = 'N' or 'O', VT is not referenced.
00103 *
00104 *  LDVT    (input) INTEGER
00105 *          The leading dimension of the array VT.  LDVT >= 1; if
00106 *          JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N).
00107 *
00108 *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
00109 *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
00110 *          if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged
00111 *          superdiagonal elements of an upper bidiagonal matrix B
00112 *          whose diagonal is in S (not necessarily sorted). B
00113 *          satisfies A = U * B * VT, so it has the same singular values
00114 *          as A, and singular vectors related by U and VT.
00115 *
00116 *  LWORK   (input) INTEGER
00117 *          The dimension of the array WORK.
00118 *          LWORK >= MAX(1,5*MIN(M,N)) for the paths (see comments inside code):
00119 *             - PATH 1  (M much larger than N, JOBU='N') 
00120 *             - PATH 1t (N much larger than M, JOBVT='N')
00121 *          LWORK >= MAX(1,3*MIN(M,N)+MAX(M,N),5*MIN(M,N)) for the other paths
00122 *          For good performance, LWORK should generally be larger.
00123 *
00124 *          If LWORK = -1, then a workspace query is assumed; the routine
00125 *          only calculates the optimal size of the WORK array, returns
00126 *          this value as the first entry of the WORK array, and no error
00127 *          message related to LWORK is issued by XERBLA.
00128 *
00129 *  INFO    (output) INTEGER
00130 *          = 0:  successful exit.
00131 *          < 0:  if INFO = -i, the i-th argument had an illegal value.
00132 *          > 0:  if DBDSQR did not converge, INFO specifies how many
00133 *                superdiagonals of an intermediate bidiagonal form B
00134 *                did not converge to zero. See the description of WORK
00135 *                above for details.
00136 *
00137 *  =====================================================================
00138 *
00139 *     .. Parameters ..
00140       DOUBLE PRECISION   ZERO, ONE
00141       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
00142 *     ..
00143 *     .. Local Scalars ..
00144       LOGICAL            LQUERY, WNTUA, WNTUAS, WNTUN, WNTUO, WNTUS,
00145      $                   WNTVA, WNTVAS, WNTVN, WNTVO, WNTVS
00146       INTEGER            BDSPAC, BLK, CHUNK, I, IE, IERR, IR, ISCL,
00147      $                   ITAU, ITAUP, ITAUQ, IU, IWORK, LDWRKR, LDWRKU,
00148      $                   MAXWRK, MINMN, MINWRK, MNTHR, NCU, NCVT, NRU,
00149      $                   NRVT, WRKBL
00150       DOUBLE PRECISION   ANRM, BIGNUM, EPS, SMLNUM
00151 *     ..
00152 *     .. Local Arrays ..
00153       DOUBLE PRECISION   DUM( 1 )
00154 *     ..
00155 *     .. External Subroutines ..
00156       EXTERNAL           DBDSQR, DGEBRD, DGELQF, DGEMM, DGEQRF, DLACPY,
00157      $                   DLASCL, DLASET, DORGBR, DORGLQ, DORGQR, DORMBR,
00158      $                   XERBLA
00159 *     ..
00160 *     .. External Functions ..
00161       LOGICAL            LSAME
00162       INTEGER            ILAENV
00163       DOUBLE PRECISION   DLAMCH, DLANGE
00164       EXTERNAL           LSAME, ILAENV, DLAMCH, DLANGE
00165 *     ..
00166 *     .. Intrinsic Functions ..
00167       INTRINSIC          MAX, MIN, SQRT
00168 *     ..
00169 *     .. Executable Statements ..
00170 *
00171 *     Test the input arguments
00172 *
00173       INFO = 0
00174       MINMN = MIN( M, N )
00175       WNTUA = LSAME( JOBU, 'A' )
00176       WNTUS = LSAME( JOBU, 'S' )
00177       WNTUAS = WNTUA .OR. WNTUS
00178       WNTUO = LSAME( JOBU, 'O' )
00179       WNTUN = LSAME( JOBU, 'N' )
00180       WNTVA = LSAME( JOBVT, 'A' )
00181       WNTVS = LSAME( JOBVT, 'S' )
00182       WNTVAS = WNTVA .OR. WNTVS
00183       WNTVO = LSAME( JOBVT, 'O' )
00184       WNTVN = LSAME( JOBVT, 'N' )
00185       LQUERY = ( LWORK.EQ.-1 )
00186 *
00187       IF( .NOT.( WNTUA .OR. WNTUS .OR. WNTUO .OR. WNTUN ) ) THEN
00188          INFO = -1
00189       ELSE IF( .NOT.( WNTVA .OR. WNTVS .OR. WNTVO .OR. WNTVN ) .OR.
00190      $         ( WNTVO .AND. WNTUO ) ) THEN
00191          INFO = -2
00192       ELSE IF( M.LT.0 ) THEN
00193          INFO = -3
00194       ELSE IF( N.LT.0 ) THEN
00195          INFO = -4
00196       ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
00197          INFO = -6
00198       ELSE IF( LDU.LT.1 .OR. ( WNTUAS .AND. LDU.LT.M ) ) THEN
00199          INFO = -9
00200       ELSE IF( LDVT.LT.1 .OR. ( WNTVA .AND. LDVT.LT.N ) .OR.
00201      $         ( WNTVS .AND. LDVT.LT.MINMN ) ) THEN
00202          INFO = -11
00203       END IF
00204 *
00205 *     Compute workspace
00206 *      (Note: Comments in the code beginning "Workspace:" describe the
00207 *       minimal amount of workspace needed at that point in the code,
00208 *       as well as the preferred amount for good performance.
00209 *       NB refers to the optimal block size for the immediately
00210 *       following subroutine, as returned by ILAENV.)
00211 *
00212       IF( INFO.EQ.0 ) THEN
00213          MINWRK = 1
00214          MAXWRK = 1
00215          IF( M.GE.N .AND. MINMN.GT.0 ) THEN
00216 *
00217 *           Compute space needed for DBDSQR
00218 *
00219             MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
00220             BDSPAC = 5*N
00221             IF( M.GE.MNTHR ) THEN
00222                IF( WNTUN ) THEN
00223 *
00224 *                 Path 1 (M much larger than N, JOBU='N')
00225 *
00226                   MAXWRK = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1,
00227      $                     -1 )
00228                   MAXWRK = MAX( MAXWRK, 3*N+2*N*
00229      $                     ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
00230                   IF( WNTVO .OR. WNTVAS )
00231      $               MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*
00232      $                        ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
00233                   MAXWRK = MAX( MAXWRK, BDSPAC )
00234                   MINWRK = MAX( 4*N, BDSPAC )
00235                ELSE IF( WNTUO .AND. WNTVN ) THEN
00236 *
00237 *                 Path 2 (M much larger than N, JOBU='O', JOBVT='N')
00238 *
00239                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
00240                   WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
00241      $                    N, N, -1 ) )
00242                   WRKBL = MAX( WRKBL, 3*N+2*N*
00243      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
00244                   WRKBL = MAX( WRKBL, 3*N+N*
00245      $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
00246                   WRKBL = MAX( WRKBL, BDSPAC )
00247                   MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )
00248                   MINWRK = MAX( 3*N+M, BDSPAC )
00249                ELSE IF( WNTUO .AND. WNTVAS ) THEN
00250 *
00251 *                 Path 3 (M much larger than N, JOBU='O', JOBVT='S' or
00252 *                 'A')
00253 *
00254                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
00255                   WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
00256      $                    N, N, -1 ) )
00257                   WRKBL = MAX( WRKBL, 3*N+2*N*
00258      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
00259                   WRKBL = MAX( WRKBL, 3*N+N*
00260      $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
00261                   WRKBL = MAX( WRKBL, 3*N+( N-1 )*
00262      $                    ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
00263                   WRKBL = MAX( WRKBL, BDSPAC )
00264                   MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )
00265                   MINWRK = MAX( 3*N+M, BDSPAC )
00266                ELSE IF( WNTUS .AND. WNTVN ) THEN
00267 *
00268 *                 Path 4 (M much larger than N, JOBU='S', JOBVT='N')
00269 *
00270                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
00271                   WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
00272      $                    N, N, -1 ) )
00273                   WRKBL = MAX( WRKBL, 3*N+2*N*
00274      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
00275                   WRKBL = MAX( WRKBL, 3*N+N*
00276      $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
00277                   WRKBL = MAX( WRKBL, BDSPAC )
00278                   MAXWRK = N*N + WRKBL
00279                   MINWRK = MAX( 3*N+M, BDSPAC )
00280                ELSE IF( WNTUS .AND. WNTVO ) THEN
00281 *
00282 *                 Path 5 (M much larger than N, JOBU='S', JOBVT='O')
00283 *
00284                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
00285                   WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
00286      $                    N, N, -1 ) )
00287                   WRKBL = MAX( WRKBL, 3*N+2*N*
00288      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
00289                   WRKBL = MAX( WRKBL, 3*N+N*
00290      $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
00291                   WRKBL = MAX( WRKBL, 3*N+( N-1 )*
00292      $                    ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
00293                   WRKBL = MAX( WRKBL, BDSPAC )
00294                   MAXWRK = 2*N*N + WRKBL
00295                   MINWRK = MAX( 3*N+M, BDSPAC )
00296                ELSE IF( WNTUS .AND. WNTVAS ) THEN
00297 *
00298 *                 Path 6 (M much larger than N, JOBU='S', JOBVT='S' or
00299 *                 'A')
00300 *
00301                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
00302                   WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
00303      $                    N, N, -1 ) )
00304                   WRKBL = MAX( WRKBL, 3*N+2*N*
00305      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
00306                   WRKBL = MAX( WRKBL, 3*N+N*
00307      $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
00308                   WRKBL = MAX( WRKBL, 3*N+( N-1 )*
00309      $                    ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
00310                   WRKBL = MAX( WRKBL, BDSPAC )
00311                   MAXWRK = N*N + WRKBL
00312                   MINWRK = MAX( 3*N+M, BDSPAC )
00313                ELSE IF( WNTUA .AND. WNTVN ) THEN
00314 *
00315 *                 Path 7 (M much larger than N, JOBU='A', JOBVT='N')
00316 *
00317                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
00318                   WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
00319      $                    M, N, -1 ) )
00320                   WRKBL = MAX( WRKBL, 3*N+2*N*
00321      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
00322                   WRKBL = MAX( WRKBL, 3*N+N*
00323      $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
00324                   WRKBL = MAX( WRKBL, BDSPAC )
00325                   MAXWRK = N*N + WRKBL
00326                   MINWRK = MAX( 3*N+M, BDSPAC )
00327                ELSE IF( WNTUA .AND. WNTVO ) THEN
00328 *
00329 *                 Path 8 (M much larger than N, JOBU='A', JOBVT='O')
00330 *
00331                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
00332                   WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
00333      $                    M, N, -1 ) )
00334                   WRKBL = MAX( WRKBL, 3*N+2*N*
00335      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
00336                   WRKBL = MAX( WRKBL, 3*N+N*
00337      $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
00338                   WRKBL = MAX( WRKBL, 3*N+( N-1 )*
00339      $                    ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
00340                   WRKBL = MAX( WRKBL, BDSPAC )
00341                   MAXWRK = 2*N*N + WRKBL
00342                   MINWRK = MAX( 3*N+M, BDSPAC )
00343                ELSE IF( WNTUA .AND. WNTVAS ) THEN
00344 *
00345 *                 Path 9 (M much larger than N, JOBU='A', JOBVT='S' or
00346 *                 'A')
00347 *
00348                   WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
00349                   WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
00350      $                    M, N, -1 ) )
00351                   WRKBL = MAX( WRKBL, 3*N+2*N*
00352      $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
00353                   WRKBL = MAX( WRKBL, 3*N+N*
00354      $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
00355                   WRKBL = MAX( WRKBL, 3*N+( N-1 )*
00356      $                    ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
00357                   WRKBL = MAX( WRKBL, BDSPAC )
00358                   MAXWRK = N*N + WRKBL
00359                   MINWRK = MAX( 3*N+M, BDSPAC )
00360                END IF
00361             ELSE
00362 *
00363 *              Path 10 (M at least N, but not much larger)
00364 *
00365                MAXWRK = 3*N + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N,
00366      $                  -1, -1 )
00367                IF( WNTUS .OR. WNTUO )
00368      $            MAXWRK = MAX( MAXWRK, 3*N+N*
00369      $                     ILAENV( 1, 'DORGBR', 'Q', M, N, N, -1 ) )
00370                IF( WNTUA )
00371      $            MAXWRK = MAX( MAXWRK, 3*N+M*
00372      $                     ILAENV( 1, 'DORGBR', 'Q', M, M, N, -1 ) )
00373                IF( .NOT.WNTVN )
00374      $            MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*
00375      $                     ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
00376                MAXWRK = MAX( MAXWRK, BDSPAC )
00377                MINWRK = MAX( 3*N+M, BDSPAC )
00378             END IF
00379          ELSE IF( MINMN.GT.0 ) THEN
00380 *
00381 *           Compute space needed for DBDSQR
00382 *
00383             MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
00384             BDSPAC = 5*M
00385             IF( N.GE.MNTHR ) THEN
00386                IF( WNTVN ) THEN
00387 *
00388 *                 Path 1t(N much larger than M, JOBVT='N')
00389 *
00390                   MAXWRK = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1,
00391      $                     -1 )
00392                   MAXWRK = MAX( MAXWRK, 3*M+2*M*
00393      $                     ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
00394                   IF( WNTUO .OR. WNTUAS )
00395      $               MAXWRK = MAX( MAXWRK, 3*M+M*
00396      $                        ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
00397                   MAXWRK = MAX( MAXWRK, BDSPAC )
00398                   MINWRK = MAX( 4*M, BDSPAC )
00399                ELSE IF( WNTVO .AND. WNTUN ) THEN
00400 *
00401 *                 Path 2t(N much larger than M, JOBU='N', JOBVT='O')
00402 *
00403                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
00404                   WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
00405      $                    N, M, -1 ) )
00406                   WRKBL = MAX( WRKBL, 3*M+2*M*
00407      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
00408                   WRKBL = MAX( WRKBL, 3*M+( M-1 )*
00409      $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
00410                   WRKBL = MAX( WRKBL, BDSPAC )
00411                   MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )
00412                   MINWRK = MAX( 3*M+N, BDSPAC )
00413                ELSE IF( WNTVO .AND. WNTUAS ) THEN
00414 *
00415 *                 Path 3t(N much larger than M, JOBU='S' or 'A',
00416 *                 JOBVT='O')
00417 *
00418                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
00419                   WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
00420      $                    N, M, -1 ) )
00421                   WRKBL = MAX( WRKBL, 3*M+2*M*
00422      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
00423                   WRKBL = MAX( WRKBL, 3*M+( M-1 )*
00424      $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
00425                   WRKBL = MAX( WRKBL, 3*M+M*
00426      $                    ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
00427                   WRKBL = MAX( WRKBL, BDSPAC )
00428                   MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )
00429                   MINWRK = MAX( 3*M+N, BDSPAC )
00430                ELSE IF( WNTVS .AND. WNTUN ) THEN
00431 *
00432 *                 Path 4t(N much larger than M, JOBU='N', JOBVT='S')
00433 *
00434                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
00435                   WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
00436      $                    N, M, -1 ) )
00437                   WRKBL = MAX( WRKBL, 3*M+2*M*
00438      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
00439                   WRKBL = MAX( WRKBL, 3*M+( M-1 )*
00440      $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
00441                   WRKBL = MAX( WRKBL, BDSPAC )
00442                   MAXWRK = M*M + WRKBL
00443                   MINWRK = MAX( 3*M+N, BDSPAC )
00444                ELSE IF( WNTVS .AND. WNTUO ) THEN
00445 *
00446 *                 Path 5t(N much larger than M, JOBU='O', JOBVT='S')
00447 *
00448                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
00449                   WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
00450      $                    N, M, -1 ) )
00451                   WRKBL = MAX( WRKBL, 3*M+2*M*
00452      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
00453                   WRKBL = MAX( WRKBL, 3*M+( M-1 )*
00454      $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
00455                   WRKBL = MAX( WRKBL, 3*M+M*
00456      $                    ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
00457                   WRKBL = MAX( WRKBL, BDSPAC )
00458                   MAXWRK = 2*M*M + WRKBL
00459                   MINWRK = MAX( 3*M+N, BDSPAC )
00460                ELSE IF( WNTVS .AND. WNTUAS ) THEN
00461 *
00462 *                 Path 6t(N much larger than M, JOBU='S' or 'A',
00463 *                 JOBVT='S')
00464 *
00465                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
00466                   WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
00467      $                    N, M, -1 ) )
00468                   WRKBL = MAX( WRKBL, 3*M+2*M*
00469      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
00470                   WRKBL = MAX( WRKBL, 3*M+( M-1 )*
00471      $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
00472                   WRKBL = MAX( WRKBL, 3*M+M*
00473      $                    ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
00474                   WRKBL = MAX( WRKBL, BDSPAC )
00475                   MAXWRK = M*M + WRKBL
00476                   MINWRK = MAX( 3*M+N, BDSPAC )
00477                ELSE IF( WNTVA .AND. WNTUN ) THEN
00478 *
00479 *                 Path 7t(N much larger than M, JOBU='N', JOBVT='A')
00480 *
00481                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
00482                   WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
00483      $                    N, M, -1 ) )
00484                   WRKBL = MAX( WRKBL, 3*M+2*M*
00485      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
00486                   WRKBL = MAX( WRKBL, 3*M+( M-1 )*
00487      $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
00488                   WRKBL = MAX( WRKBL, BDSPAC )
00489                   MAXWRK = M*M + WRKBL
00490                   MINWRK = MAX( 3*M+N, BDSPAC )
00491                ELSE IF( WNTVA .AND. WNTUO ) THEN
00492 *
00493 *                 Path 8t(N much larger than M, JOBU='O', JOBVT='A')
00494 *
00495                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
00496                   WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
00497      $                    N, M, -1 ) )
00498                   WRKBL = MAX( WRKBL, 3*M+2*M*
00499      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
00500                   WRKBL = MAX( WRKBL, 3*M+( M-1 )*
00501      $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
00502                   WRKBL = MAX( WRKBL, 3*M+M*
00503      $                    ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
00504                   WRKBL = MAX( WRKBL, BDSPAC )
00505                   MAXWRK = 2*M*M + WRKBL
00506                   MINWRK = MAX( 3*M+N, BDSPAC )
00507                ELSE IF( WNTVA .AND. WNTUAS ) THEN
00508 *
00509 *                 Path 9t(N much larger than M, JOBU='S' or 'A',
00510 *                 JOBVT='A')
00511 *
00512                   WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
00513                   WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
00514      $                    N, M, -1 ) )
00515                   WRKBL = MAX( WRKBL, 3*M+2*M*
00516      $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
00517                   WRKBL = MAX( WRKBL, 3*M+( M-1 )*
00518      $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
00519                   WRKBL = MAX( WRKBL, 3*M+M*
00520      $                    ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
00521                   WRKBL = MAX( WRKBL, BDSPAC )
00522                   MAXWRK = M*M + WRKBL
00523                   MINWRK = MAX( 3*M+N, BDSPAC )
00524                END IF
00525             ELSE
00526 *
00527 *              Path 10t(N greater than M, but not much larger)
00528 *
00529                MAXWRK = 3*M + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N,
00530      $                  -1, -1 )
00531                IF( WNTVS .OR. WNTVO )
00532      $            MAXWRK = MAX( MAXWRK, 3*M+M*
00533      $                     ILAENV( 1, 'DORGBR', 'P', M, N, M, -1 ) )
00534                IF( WNTVA )
00535      $            MAXWRK = MAX( MAXWRK, 3*M+N*
00536      $                     ILAENV( 1, 'DORGBR', 'P', N, N, M, -1 ) )
00537                IF( .NOT.WNTUN )
00538      $            MAXWRK = MAX( MAXWRK, 3*M+( M-1 )*
00539      $                     ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
00540                MAXWRK = MAX( MAXWRK, BDSPAC )
00541                MINWRK = MAX( 3*M+N, BDSPAC )
00542             END IF
00543          END IF
00544          MAXWRK = MAX( MAXWRK, MINWRK )
00545          WORK( 1 ) = MAXWRK
00546 *
00547          IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
00548             INFO = -13
00549          END IF
00550       END IF
00551 *
00552       IF( INFO.NE.0 ) THEN
00553          CALL XERBLA( 'DGESVD', -INFO )
00554          RETURN
00555       ELSE IF( LQUERY ) THEN
00556          RETURN
00557       END IF
00558 *
00559 *     Quick return if possible
00560 *
00561       IF( M.EQ.0 .OR. N.EQ.0 ) THEN
00562          RETURN
00563       END IF
00564 *
00565 *     Get machine constants
00566 *
00567       EPS = DLAMCH( 'P' )
00568       SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPS
00569       BIGNUM = ONE / SMLNUM
00570 *
00571 *     Scale A if max element outside range [SMLNUM,BIGNUM]
00572 *
00573       ANRM = DLANGE( 'M', M, N, A, LDA, DUM )
00574       ISCL = 0
00575       IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00576          ISCL = 1
00577          CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, IERR )
00578       ELSE IF( ANRM.GT.BIGNUM ) THEN
00579          ISCL = 1
00580          CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, IERR )
00581       END IF
00582 *
00583       IF( M.GE.N ) THEN
00584 *
00585 *        A has at least as many rows as columns. If A has sufficiently
00586 *        more rows than columns, first reduce using the QR
00587 *        decomposition (if sufficient workspace available)
00588 *
00589          IF( M.GE.MNTHR ) THEN
00590 *
00591             IF( WNTUN ) THEN
00592 *
00593 *              Path 1 (M much larger than N, JOBU='N')
00594 *              No left singular vectors to be computed
00595 *
00596                ITAU = 1
00597                IWORK = ITAU + N
00598 *
00599 *              Compute A=Q*R
00600 *              (Workspace: need 2*N, prefer N+N*NB)
00601 *
00602                CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
00603      $                      LWORK-IWORK+1, IERR )
00604 *
00605 *              Zero out below R
00606 *
00607                CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
00608                IE = 1
00609                ITAUQ = IE + N
00610                ITAUP = ITAUQ + N
00611                IWORK = ITAUP + N
00612 *
00613 *              Bidiagonalize R in A
00614 *              (Workspace: need 4*N, prefer 3*N+2*N*NB)
00615 *
00616                CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
00617      $                      WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
00618      $                      IERR )
00619                NCVT = 0
00620                IF( WNTVO .OR. WNTVAS ) THEN
00621 *
00622 *                 If right singular vectors desired, generate P'.
00623 *                 (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
00624 *
00625                   CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
00626      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00627                   NCVT = N
00628                END IF
00629                IWORK = IE + N
00630 *
00631 *              Perform bidiagonal QR iteration, computing right
00632 *              singular vectors of A in A if desired
00633 *              (Workspace: need BDSPAC)
00634 *
00635                CALL DBDSQR( 'U', N, NCVT, 0, 0, S, WORK( IE ), A, LDA,
00636      $                      DUM, 1, DUM, 1, WORK( IWORK ), INFO )
00637 *
00638 *              If right singular vectors desired in VT, copy them there
00639 *
00640                IF( WNTVAS )
00641      $            CALL DLACPY( 'F', N, N, A, LDA, VT, LDVT )
00642 *
00643             ELSE IF( WNTUO .AND. WNTVN ) THEN
00644 *
00645 *              Path 2 (M much larger than N, JOBU='O', JOBVT='N')
00646 *              N left singular vectors to be overwritten on A and
00647 *              no right singular vectors to be computed
00648 *
00649                IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
00650 *
00651 *                 Sufficient workspace for a fast algorithm
00652 *
00653                   IR = 1
00654                   IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+LDA*N ) THEN
00655 *
00656 *                    WORK(IU) is LDA by N, WORK(IR) is LDA by N
00657 *
00658                      LDWRKU = LDA
00659                      LDWRKR = LDA
00660                   ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+N*N ) THEN
00661 *
00662 *                    WORK(IU) is LDA by N, WORK(IR) is N by N
00663 *
00664                      LDWRKU = LDA
00665                      LDWRKR = N
00666                   ELSE
00667 *
00668 *                    WORK(IU) is LDWRKU by N, WORK(IR) is N by N
00669 *
00670                      LDWRKU = ( LWORK-N*N-N ) / N
00671                      LDWRKR = N
00672                   END IF
00673                   ITAU = IR + LDWRKR*N
00674                   IWORK = ITAU + N
00675 *
00676 *                 Compute A=Q*R
00677 *                 (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00678 *
00679                   CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
00680      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00681 *
00682 *                 Copy R to WORK(IR) and zero out below it
00683 *
00684                   CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )
00685                   CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),
00686      $                         LDWRKR )
00687 *
00688 *                 Generate Q in A
00689 *                 (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00690 *
00691                   CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
00692      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00693                   IE = ITAU
00694                   ITAUQ = IE + N
00695                   ITAUP = ITAUQ + N
00696                   IWORK = ITAUP + N
00697 *
00698 *                 Bidiagonalize R in WORK(IR)
00699 *                 (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
00700 *
00701                   CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),
00702      $                         WORK( ITAUQ ), WORK( ITAUP ),
00703      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00704 *
00705 *                 Generate left vectors bidiagonalizing R
00706 *                 (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
00707 *
00708                   CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
00709      $                         WORK( ITAUQ ), WORK( IWORK ),
00710      $                         LWORK-IWORK+1, IERR )
00711                   IWORK = IE + N
00712 *
00713 *                 Perform bidiagonal QR iteration, computing left
00714 *                 singular vectors of R in WORK(IR)
00715 *                 (Workspace: need N*N+BDSPAC)
00716 *
00717                   CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM, 1,
00718      $                         WORK( IR ), LDWRKR, DUM, 1,
00719      $                         WORK( IWORK ), INFO )
00720                   IU = IE + N
00721 *
00722 *                 Multiply Q in A by left singular vectors of R in
00723 *                 WORK(IR), storing result in WORK(IU) and copying to A
00724 *                 (Workspace: need N*N+2*N, prefer N*N+M*N+N)
00725 *
00726                   DO 10 I = 1, M, LDWRKU
00727                      CHUNK = MIN( M-I+1, LDWRKU )
00728                      CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
00729      $                           LDA, WORK( IR ), LDWRKR, ZERO,
00730      $                           WORK( IU ), LDWRKU )
00731                      CALL DLACPY( 'F', CHUNK, N, WORK( IU ), LDWRKU,
00732      $                            A( I, 1 ), LDA )
00733    10             CONTINUE
00734 *
00735                ELSE
00736 *
00737 *                 Insufficient workspace for a fast algorithm
00738 *
00739                   IE = 1
00740                   ITAUQ = IE + N
00741                   ITAUP = ITAUQ + N
00742                   IWORK = ITAUP + N
00743 *
00744 *                 Bidiagonalize A
00745 *                 (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)
00746 *
00747                   CALL DGEBRD( M, N, A, LDA, S, WORK( IE ),
00748      $                         WORK( ITAUQ ), WORK( ITAUP ),
00749      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00750 *
00751 *                 Generate left vectors bidiagonalizing A
00752 *                 (Workspace: need 4*N, prefer 3*N+N*NB)
00753 *
00754                   CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),
00755      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00756                   IWORK = IE + N
00757 *
00758 *                 Perform bidiagonal QR iteration, computing left
00759 *                 singular vectors of A in A
00760 *                 (Workspace: need BDSPAC)
00761 *
00762                   CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM, 1,
00763      $                         A, LDA, DUM, 1, WORK( IWORK ), INFO )
00764 *
00765                END IF
00766 *
00767             ELSE IF( WNTUO .AND. WNTVAS ) THEN
00768 *
00769 *              Path 3 (M much larger than N, JOBU='O', JOBVT='S' or 'A')
00770 *              N left singular vectors to be overwritten on A and
00771 *              N right singular vectors to be computed in VT
00772 *
00773                IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
00774 *
00775 *                 Sufficient workspace for a fast algorithm
00776 *
00777                   IR = 1
00778                   IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+LDA*N ) THEN
00779 *
00780 *                    WORK(IU) is LDA by N and WORK(IR) is LDA by N
00781 *
00782                      LDWRKU = LDA
00783                      LDWRKR = LDA
00784                   ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+N*N ) THEN
00785 *
00786 *                    WORK(IU) is LDA by N and WORK(IR) is N by N
00787 *
00788                      LDWRKU = LDA
00789                      LDWRKR = N
00790                   ELSE
00791 *
00792 *                    WORK(IU) is LDWRKU by N and WORK(IR) is N by N
00793 *
00794                      LDWRKU = ( LWORK-N*N-N ) / N
00795                      LDWRKR = N
00796                   END IF
00797                   ITAU = IR + LDWRKR*N
00798                   IWORK = ITAU + N
00799 *
00800 *                 Compute A=Q*R
00801 *                 (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00802 *
00803                   CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
00804      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00805 *
00806 *                 Copy R to VT, zeroing out below it
00807 *
00808                   CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
00809                   IF( N.GT.1 )
00810      $               CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
00811      $                            VT( 2, 1 ), LDVT )
00812 *
00813 *                 Generate Q in A
00814 *                 (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00815 *
00816                   CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
00817      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00818                   IE = ITAU
00819                   ITAUQ = IE + N
00820                   ITAUP = ITAUQ + N
00821                   IWORK = ITAUP + N
00822 *
00823 *                 Bidiagonalize R in VT, copying result to WORK(IR)
00824 *                 (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
00825 *
00826                   CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
00827      $                         WORK( ITAUQ ), WORK( ITAUP ),
00828      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00829                   CALL DLACPY( 'L', N, N, VT, LDVT, WORK( IR ), LDWRKR )
00830 *
00831 *                 Generate left vectors bidiagonalizing R in WORK(IR)
00832 *                 (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
00833 *
00834                   CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
00835      $                         WORK( ITAUQ ), WORK( IWORK ),
00836      $                         LWORK-IWORK+1, IERR )
00837 *
00838 *                 Generate right vectors bidiagonalizing R in VT
00839 *                 (Workspace: need N*N+4*N-1, prefer N*N+3*N+(N-1)*NB)
00840 *
00841                   CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
00842      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00843                   IWORK = IE + N
00844 *
00845 *                 Perform bidiagonal QR iteration, computing left
00846 *                 singular vectors of R in WORK(IR) and computing right
00847 *                 singular vectors of R in VT
00848 *                 (Workspace: need N*N+BDSPAC)
00849 *
00850                   CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT, LDVT,
00851      $                         WORK( IR ), LDWRKR, DUM, 1,
00852      $                         WORK( IWORK ), INFO )
00853                   IU = IE + N
00854 *
00855 *                 Multiply Q in A by left singular vectors of R in
00856 *                 WORK(IR), storing result in WORK(IU) and copying to A
00857 *                 (Workspace: need N*N+2*N, prefer N*N+M*N+N)
00858 *
00859                   DO 20 I = 1, M, LDWRKU
00860                      CHUNK = MIN( M-I+1, LDWRKU )
00861                      CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
00862      $                           LDA, WORK( IR ), LDWRKR, ZERO,
00863      $                           WORK( IU ), LDWRKU )
00864                      CALL DLACPY( 'F', CHUNK, N, WORK( IU ), LDWRKU,
00865      $                            A( I, 1 ), LDA )
00866    20             CONTINUE
00867 *
00868                ELSE
00869 *
00870 *                 Insufficient workspace for a fast algorithm
00871 *
00872                   ITAU = 1
00873                   IWORK = ITAU + N
00874 *
00875 *                 Compute A=Q*R
00876 *                 (Workspace: need 2*N, prefer N+N*NB)
00877 *
00878                   CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
00879      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00880 *
00881 *                 Copy R to VT, zeroing out below it
00882 *
00883                   CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
00884                   IF( N.GT.1 )
00885      $               CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
00886      $                            VT( 2, 1 ), LDVT )
00887 *
00888 *                 Generate Q in A
00889 *                 (Workspace: need 2*N, prefer N+N*NB)
00890 *
00891                   CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
00892      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00893                   IE = ITAU
00894                   ITAUQ = IE + N
00895                   ITAUP = ITAUQ + N
00896                   IWORK = ITAUP + N
00897 *
00898 *                 Bidiagonalize R in VT
00899 *                 (Workspace: need 4*N, prefer 3*N+2*N*NB)
00900 *
00901                   CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
00902      $                         WORK( ITAUQ ), WORK( ITAUP ),
00903      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00904 *
00905 *                 Multiply Q in A by left vectors bidiagonalizing R
00906 *                 (Workspace: need 3*N+M, prefer 3*N+M*NB)
00907 *
00908                   CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,
00909      $                         WORK( ITAUQ ), A, LDA, WORK( IWORK ),
00910      $                         LWORK-IWORK+1, IERR )
00911 *
00912 *                 Generate right vectors bidiagonalizing R in VT
00913 *                 (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
00914 *
00915                   CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
00916      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
00917                   IWORK = IE + N
00918 *
00919 *                 Perform bidiagonal QR iteration, computing left
00920 *                 singular vectors of A in A and computing right
00921 *                 singular vectors of A in VT
00922 *                 (Workspace: need BDSPAC)
00923 *
00924                   CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT, LDVT,
00925      $                         A, LDA, DUM, 1, WORK( IWORK ), INFO )
00926 *
00927                END IF
00928 *
00929             ELSE IF( WNTUS ) THEN
00930 *
00931                IF( WNTVN ) THEN
00932 *
00933 *                 Path 4 (M much larger than N, JOBU='S', JOBVT='N')
00934 *                 N left singular vectors to be computed in U and
00935 *                 no right singular vectors to be computed
00936 *
00937                   IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
00938 *
00939 *                    Sufficient workspace for a fast algorithm
00940 *
00941                      IR = 1
00942                      IF( LWORK.GE.WRKBL+LDA*N ) THEN
00943 *
00944 *                       WORK(IR) is LDA by N
00945 *
00946                         LDWRKR = LDA
00947                      ELSE
00948 *
00949 *                       WORK(IR) is N by N
00950 *
00951                         LDWRKR = N
00952                      END IF
00953                      ITAU = IR + LDWRKR*N
00954                      IWORK = ITAU + N
00955 *
00956 *                    Compute A=Q*R
00957 *                    (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00958 *
00959                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
00960      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
00961 *
00962 *                    Copy R to WORK(IR), zeroing out below it
00963 *
00964                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ),
00965      $                            LDWRKR )
00966                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
00967      $                            WORK( IR+1 ), LDWRKR )
00968 *
00969 *                    Generate Q in A
00970 *                    (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00971 *
00972                      CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
00973      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
00974                      IE = ITAU
00975                      ITAUQ = IE + N
00976                      ITAUP = ITAUQ + N
00977                      IWORK = ITAUP + N
00978 *
00979 *                    Bidiagonalize R in WORK(IR)
00980 *                    (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
00981 *
00982                      CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S,
00983      $                            WORK( IE ), WORK( ITAUQ ),
00984      $                            WORK( ITAUP ), WORK( IWORK ),
00985      $                            LWORK-IWORK+1, IERR )
00986 *
00987 *                    Generate left vectors bidiagonalizing R in WORK(IR)
00988 *                    (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
00989 *
00990                      CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
00991      $                            WORK( ITAUQ ), WORK( IWORK ),
00992      $                            LWORK-IWORK+1, IERR )
00993                      IWORK = IE + N
00994 *
00995 *                    Perform bidiagonal QR iteration, computing left
00996 *                    singular vectors of R in WORK(IR)
00997 *                    (Workspace: need N*N+BDSPAC)
00998 *
00999                      CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM,
01000      $                            1, WORK( IR ), LDWRKR, DUM, 1,
01001      $                            WORK( IWORK ), INFO )
01002 *
01003 *                    Multiply Q in A by left singular vectors of R in
01004 *                    WORK(IR), storing result in U
01005 *                    (Workspace: need N*N)
01006 *
01007                      CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,
01008      $                           WORK( IR ), LDWRKR, ZERO, U, LDU )
01009 *
01010                   ELSE
01011 *
01012 *                    Insufficient workspace for a fast algorithm
01013 *
01014                      ITAU = 1
01015                      IWORK = ITAU + N
01016 *
01017 *                    Compute A=Q*R, copying result to U
01018 *                    (Workspace: need 2*N, prefer N+N*NB)
01019 *
01020                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
01021      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01022                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
01023 *
01024 *                    Generate Q in U
01025 *                    (Workspace: need 2*N, prefer N+N*NB)
01026 *
01027                      CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),
01028      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01029                      IE = ITAU
01030                      ITAUQ = IE + N
01031                      ITAUP = ITAUQ + N
01032                      IWORK = ITAUP + N
01033 *
01034 *                    Zero out below R in A
01035 *
01036                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),
01037      $                            LDA )
01038 *
01039 *                    Bidiagonalize R in A
01040 *                    (Workspace: need 4*N, prefer 3*N+2*N*NB)
01041 *
01042                      CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
01043      $                            WORK( ITAUQ ), WORK( ITAUP ),
01044      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01045 *
01046 *                    Multiply Q in U by left vectors bidiagonalizing R
01047 *                    (Workspace: need 3*N+M, prefer 3*N+M*NB)
01048 *
01049                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
01050      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
01051      $                            LWORK-IWORK+1, IERR )
01052                      IWORK = IE + N
01053 *
01054 *                    Perform bidiagonal QR iteration, computing left
01055 *                    singular vectors of A in U
01056 *                    (Workspace: need BDSPAC)
01057 *
01058                      CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM,
01059      $                            1, U, LDU, DUM, 1, WORK( IWORK ),
01060      $                            INFO )
01061 *
01062                   END IF
01063 *
01064                ELSE IF( WNTVO ) THEN
01065 *
01066 *                 Path 5 (M much larger than N, JOBU='S', JOBVT='O')
01067 *                 N left singular vectors to be computed in U and
01068 *                 N right singular vectors to be overwritten on A
01069 *
01070                   IF( LWORK.GE.2*N*N+MAX( 4*N, BDSPAC ) ) THEN
01071 *
01072 *                    Sufficient workspace for a fast algorithm
01073 *
01074                      IU = 1
01075                      IF( LWORK.GE.WRKBL+2*LDA*N ) THEN
01076 *
01077 *                       WORK(IU) is LDA by N and WORK(IR) is LDA by N
01078 *
01079                         LDWRKU = LDA
01080                         IR = IU + LDWRKU*N
01081                         LDWRKR = LDA
01082                      ELSE IF( LWORK.GE.WRKBL+( LDA+N )*N ) THEN
01083 *
01084 *                       WORK(IU) is LDA by N and WORK(IR) is N by N
01085 *
01086                         LDWRKU = LDA
01087                         IR = IU + LDWRKU*N
01088                         LDWRKR = N
01089                      ELSE
01090 *
01091 *                       WORK(IU) is N by N and WORK(IR) is N by N
01092 *
01093                         LDWRKU = N
01094                         IR = IU + LDWRKU*N
01095                         LDWRKR = N
01096                      END IF
01097                      ITAU = IR + LDWRKR*N
01098                      IWORK = ITAU + N
01099 *
01100 *                    Compute A=Q*R
01101 *                    (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB)
01102 *
01103                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
01104      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01105 *
01106 *                    Copy R to WORK(IU), zeroing out below it
01107 *
01108                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
01109      $                            LDWRKU )
01110                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
01111      $                            WORK( IU+1 ), LDWRKU )
01112 *
01113 *                    Generate Q in A
01114 *                    (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB)
01115 *
01116                      CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
01117      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01118                      IE = ITAU
01119                      ITAUQ = IE + N
01120                      ITAUP = ITAUQ + N
01121                      IWORK = ITAUP + N
01122 *
01123 *                    Bidiagonalize R in WORK(IU), copying result to
01124 *                    WORK(IR)
01125 *                    (Workspace: need 2*N*N+4*N,
01126 *                                prefer 2*N*N+3*N+2*N*NB)
01127 *
01128                      CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
01129      $                            WORK( IE ), WORK( ITAUQ ),
01130      $                            WORK( ITAUP ), WORK( IWORK ),
01131      $                            LWORK-IWORK+1, IERR )
01132                      CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU,
01133      $                            WORK( IR ), LDWRKR )
01134 *
01135 *                    Generate left bidiagonalizing vectors in WORK(IU)
01136 *                    (Workspace: need 2*N*N+4*N, prefer 2*N*N+3*N+N*NB)
01137 *
01138                      CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
01139      $                            WORK( ITAUQ ), WORK( IWORK ),
01140      $                            LWORK-IWORK+1, IERR )
01141 *
01142 *                    Generate right bidiagonalizing vectors in WORK(IR)
01143 *                    (Workspace: need 2*N*N+4*N-1,
01144 *                                prefer 2*N*N+3*N+(N-1)*NB)
01145 *
01146                      CALL DORGBR( 'P', N, N, N, WORK( IR ), LDWRKR,
01147      $                            WORK( ITAUP ), WORK( IWORK ),
01148      $                            LWORK-IWORK+1, IERR )
01149                      IWORK = IE + N
01150 *
01151 *                    Perform bidiagonal QR iteration, computing left
01152 *                    singular vectors of R in WORK(IU) and computing
01153 *                    right singular vectors of R in WORK(IR)
01154 *                    (Workspace: need 2*N*N+BDSPAC)
01155 *
01156                      CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ),
01157      $                            WORK( IR ), LDWRKR, WORK( IU ),
01158      $                            LDWRKU, DUM, 1, WORK( IWORK ), INFO )
01159 *
01160 *                    Multiply Q in A by left singular vectors of R in
01161 *                    WORK(IU), storing result in U
01162 *                    (Workspace: need N*N)
01163 *
01164                      CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,
01165      $                           WORK( IU ), LDWRKU, ZERO, U, LDU )
01166 *
01167 *                    Copy right singular vectors of R to A
01168 *                    (Workspace: need N*N)
01169 *
01170                      CALL DLACPY( 'F', N, N, WORK( IR ), LDWRKR, A,
01171      $                            LDA )
01172 *
01173                   ELSE
01174 *
01175 *                    Insufficient workspace for a fast algorithm
01176 *
01177                      ITAU = 1
01178                      IWORK = ITAU + N
01179 *
01180 *                    Compute A=Q*R, copying result to U
01181 *                    (Workspace: need 2*N, prefer N+N*NB)
01182 *
01183                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
01184      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01185                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
01186 *
01187 *                    Generate Q in U
01188 *                    (Workspace: need 2*N, prefer N+N*NB)
01189 *
01190                      CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),
01191      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01192                      IE = ITAU
01193                      ITAUQ = IE + N
01194                      ITAUP = ITAUQ + N
01195                      IWORK = ITAUP + N
01196 *
01197 *                    Zero out below R in A
01198 *
01199                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),
01200      $                            LDA )
01201 *
01202 *                    Bidiagonalize R in A
01203 *                    (Workspace: need 4*N, prefer 3*N+2*N*NB)
01204 *
01205                      CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
01206      $                            WORK( ITAUQ ), WORK( ITAUP ),
01207      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01208 *
01209 *                    Multiply Q in U by left vectors bidiagonalizing R
01210 *                    (Workspace: need 3*N+M, prefer 3*N+M*NB)
01211 *
01212                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
01213      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
01214      $                            LWORK-IWORK+1, IERR )
01215 *
01216 *                    Generate right vectors bidiagonalizing R in A
01217 *                    (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
01218 *
01219                      CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
01220      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01221                      IWORK = IE + N
01222 *
01223 *                    Perform bidiagonal QR iteration, computing left
01224 *                    singular vectors of A in U and computing right
01225 *                    singular vectors of A in A
01226 *                    (Workspace: need BDSPAC)
01227 *
01228                      CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), A,
01229      $                            LDA, U, LDU, DUM, 1, WORK( IWORK ),
01230      $                            INFO )
01231 *
01232                   END IF
01233 *
01234                ELSE IF( WNTVAS ) THEN
01235 *
01236 *                 Path 6 (M much larger than N, JOBU='S', JOBVT='S'
01237 *                         or 'A')
01238 *                 N left singular vectors to be computed in U and
01239 *                 N right singular vectors to be computed in VT
01240 *
01241                   IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
01242 *
01243 *                    Sufficient workspace for a fast algorithm
01244 *
01245                      IU = 1
01246                      IF( LWORK.GE.WRKBL+LDA*N ) THEN
01247 *
01248 *                       WORK(IU) is LDA by N
01249 *
01250                         LDWRKU = LDA
01251                      ELSE
01252 *
01253 *                       WORK(IU) is N by N
01254 *
01255                         LDWRKU = N
01256                      END IF
01257                      ITAU = IU + LDWRKU*N
01258                      IWORK = ITAU + N
01259 *
01260 *                    Compute A=Q*R
01261 *                    (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
01262 *
01263                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
01264      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01265 *
01266 *                    Copy R to WORK(IU), zeroing out below it
01267 *
01268                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
01269      $                            LDWRKU )
01270                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
01271      $                            WORK( IU+1 ), LDWRKU )
01272 *
01273 *                    Generate Q in A
01274 *                    (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
01275 *
01276                      CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
01277      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01278                      IE = ITAU
01279                      ITAUQ = IE + N
01280                      ITAUP = ITAUQ + N
01281                      IWORK = ITAUP + N
01282 *
01283 *                    Bidiagonalize R in WORK(IU), copying result to VT
01284 *                    (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
01285 *
01286                      CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
01287      $                            WORK( IE ), WORK( ITAUQ ),
01288      $                            WORK( ITAUP ), WORK( IWORK ),
01289      $                            LWORK-IWORK+1, IERR )
01290                      CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, VT,
01291      $                            LDVT )
01292 *
01293 *                    Generate left bidiagonalizing vectors in WORK(IU)
01294 *                    (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
01295 *
01296                      CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
01297      $                            WORK( ITAUQ ), WORK( IWORK ),
01298      $                            LWORK-IWORK+1, IERR )
01299 *
01300 *                    Generate right bidiagonalizing vectors in VT
01301 *                    (Workspace: need N*N+4*N-1,
01302 *                                prefer N*N+3*N+(N-1)*NB)
01303 *
01304                      CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
01305      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01306                      IWORK = IE + N
01307 *
01308 *                    Perform bidiagonal QR iteration, computing left
01309 *                    singular vectors of R in WORK(IU) and computing
01310 *                    right singular vectors of R in VT
01311 *                    (Workspace: need N*N+BDSPAC)
01312 *
01313                      CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT,
01314      $                            LDVT, WORK( IU ), LDWRKU, DUM, 1,
01315      $                            WORK( IWORK ), INFO )
01316 *
01317 *                    Multiply Q in A by left singular vectors of R in
01318 *                    WORK(IU), storing result in U
01319 *                    (Workspace: need N*N)
01320 *
01321                      CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,
01322      $                           WORK( IU ), LDWRKU, ZERO, U, LDU )
01323 *
01324                   ELSE
01325 *
01326 *                    Insufficient workspace for a fast algorithm
01327 *
01328                      ITAU = 1
01329                      IWORK = ITAU + N
01330 *
01331 *                    Compute A=Q*R, copying result to U
01332 *                    (Workspace: need 2*N, prefer N+N*NB)
01333 *
01334                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
01335      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01336                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
01337 *
01338 *                    Generate Q in U
01339 *                    (Workspace: need 2*N, prefer N+N*NB)
01340 *
01341                      CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),
01342      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01343 *
01344 *                    Copy R to VT, zeroing out below it
01345 *
01346                      CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
01347                      IF( N.GT.1 )
01348      $                  CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
01349      $                               VT( 2, 1 ), LDVT )
01350                      IE = ITAU
01351                      ITAUQ = IE + N
01352                      ITAUP = ITAUQ + N
01353                      IWORK = ITAUP + N
01354 *
01355 *                    Bidiagonalize R in VT
01356 *                    (Workspace: need 4*N, prefer 3*N+2*N*NB)
01357 *
01358                      CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
01359      $                            WORK( ITAUQ ), WORK( ITAUP ),
01360      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01361 *
01362 *                    Multiply Q in U by left bidiagonalizing vectors
01363 *                    in VT
01364 *                    (Workspace: need 3*N+M, prefer 3*N+M*NB)
01365 *
01366                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,
01367      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
01368      $                            LWORK-IWORK+1, IERR )
01369 *
01370 *                    Generate right bidiagonalizing vectors in VT
01371 *                    (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
01372 *
01373                      CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
01374      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01375                      IWORK = IE + N
01376 *
01377 *                    Perform bidiagonal QR iteration, computing left
01378 *                    singular vectors of A in U and computing right
01379 *                    singular vectors of A in VT
01380 *                    (Workspace: need BDSPAC)
01381 *
01382                      CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT,
01383      $                            LDVT, U, LDU, DUM, 1, WORK( IWORK ),
01384      $                            INFO )
01385 *
01386                   END IF
01387 *
01388                END IF
01389 *
01390             ELSE IF( WNTUA ) THEN
01391 *
01392                IF( WNTVN ) THEN
01393 *
01394 *                 Path 7 (M much larger than N, JOBU='A', JOBVT='N')
01395 *                 M left singular vectors to be computed in U and
01396 *                 no right singular vectors to be computed
01397 *
01398                   IF( LWORK.GE.N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN
01399 *
01400 *                    Sufficient workspace for a fast algorithm
01401 *
01402                      IR = 1
01403                      IF( LWORK.GE.WRKBL+LDA*N ) THEN
01404 *
01405 *                       WORK(IR) is LDA by N
01406 *
01407                         LDWRKR = LDA
01408                      ELSE
01409 *
01410 *                       WORK(IR) is N by N
01411 *
01412                         LDWRKR = N
01413                      END IF
01414                      ITAU = IR + LDWRKR*N
01415                      IWORK = ITAU + N
01416 *
01417 *                    Compute A=Q*R, copying result to U
01418 *                    (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
01419 *
01420                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
01421      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01422                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
01423 *
01424 *                    Copy R to WORK(IR), zeroing out below it
01425 *
01426                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ),
01427      $                            LDWRKR )
01428                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
01429      $                            WORK( IR+1 ), LDWRKR )
01430 *
01431 *                    Generate Q in U
01432 *                    (Workspace: need N*N+N+M, prefer N*N+N+M*NB)
01433 *
01434                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
01435      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01436                      IE = ITAU
01437                      ITAUQ = IE + N
01438                      ITAUP = ITAUQ + N
01439                      IWORK = ITAUP + N
01440 *
01441 *                    Bidiagonalize R in WORK(IR)
01442 *                    (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
01443 *
01444                      CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S,
01445      $                            WORK( IE ), WORK( ITAUQ ),
01446      $                            WORK( ITAUP ), WORK( IWORK ),
01447      $                            LWORK-IWORK+1, IERR )
01448 *
01449 *                    Generate left bidiagonalizing vectors in WORK(IR)
01450 *                    (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
01451 *
01452                      CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
01453      $                            WORK( ITAUQ ), WORK( IWORK ),
01454      $                            LWORK-IWORK+1, IERR )
01455                      IWORK = IE + N
01456 *
01457 *                    Perform bidiagonal QR iteration, computing left
01458 *                    singular vectors of R in WORK(IR)
01459 *                    (Workspace: need N*N+BDSPAC)
01460 *
01461                      CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM,
01462      $                            1, WORK( IR ), LDWRKR, DUM, 1,
01463      $                            WORK( IWORK ), INFO )
01464 *
01465 *                    Multiply Q in U by left singular vectors of R in
01466 *                    WORK(IR), storing result in A
01467 *                    (Workspace: need N*N)
01468 *
01469                      CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,
01470      $                           WORK( IR ), LDWRKR, ZERO, A, LDA )
01471 *
01472 *                    Copy left singular vectors of A from A to U
01473 *
01474                      CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
01475 *
01476                   ELSE
01477 *
01478 *                    Insufficient workspace for a fast algorithm
01479 *
01480                      ITAU = 1
01481                      IWORK = ITAU + N
01482 *
01483 *                    Compute A=Q*R, copying result to U
01484 *                    (Workspace: need 2*N, prefer N+N*NB)
01485 *
01486                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
01487      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01488                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
01489 *
01490 *                    Generate Q in U
01491 *                    (Workspace: need N+M, prefer N+M*NB)
01492 *
01493                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
01494      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01495                      IE = ITAU
01496                      ITAUQ = IE + N
01497                      ITAUP = ITAUQ + N
01498                      IWORK = ITAUP + N
01499 *
01500 *                    Zero out below R in A
01501 *
01502                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),
01503      $                            LDA )
01504 *
01505 *                    Bidiagonalize R in A
01506 *                    (Workspace: need 4*N, prefer 3*N+2*N*NB)
01507 *
01508                      CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
01509      $                            WORK( ITAUQ ), WORK( ITAUP ),
01510      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01511 *
01512 *                    Multiply Q in U by left bidiagonalizing vectors
01513 *                    in A
01514 *                    (Workspace: need 3*N+M, prefer 3*N+M*NB)
01515 *
01516                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
01517      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
01518      $                            LWORK-IWORK+1, IERR )
01519                      IWORK = IE + N
01520 *
01521 *                    Perform bidiagonal QR iteration, computing left
01522 *                    singular vectors of A in U
01523 *                    (Workspace: need BDSPAC)
01524 *
01525                      CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM,
01526      $                            1, U, LDU, DUM, 1, WORK( IWORK ),
01527      $                            INFO )
01528 *
01529                   END IF
01530 *
01531                ELSE IF( WNTVO ) THEN
01532 *
01533 *                 Path 8 (M much larger than N, JOBU='A', JOBVT='O')
01534 *                 M left singular vectors to be computed in U and
01535 *                 N right singular vectors to be overwritten on A
01536 *
01537                   IF( LWORK.GE.2*N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN
01538 *
01539 *                    Sufficient workspace for a fast algorithm
01540 *
01541                      IU = 1
01542                      IF( LWORK.GE.WRKBL+2*LDA*N ) THEN
01543 *
01544 *                       WORK(IU) is LDA by N and WORK(IR) is LDA by N
01545 *
01546                         LDWRKU = LDA
01547                         IR = IU + LDWRKU*N
01548                         LDWRKR = LDA
01549                      ELSE IF( LWORK.GE.WRKBL+( LDA+N )*N ) THEN
01550 *
01551 *                       WORK(IU) is LDA by N and WORK(IR) is N by N
01552 *
01553                         LDWRKU = LDA
01554                         IR = IU + LDWRKU*N
01555                         LDWRKR = N
01556                      ELSE
01557 *
01558 *                       WORK(IU) is N by N and WORK(IR) is N by N
01559 *
01560                         LDWRKU = N
01561                         IR = IU + LDWRKU*N
01562                         LDWRKR = N
01563                      END IF
01564                      ITAU = IR + LDWRKR*N
01565                      IWORK = ITAU + N
01566 *
01567 *                    Compute A=Q*R, copying result to U
01568 *                    (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB)
01569 *
01570                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
01571      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01572                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
01573 *
01574 *                    Generate Q in U
01575 *                    (Workspace: need 2*N*N+N+M, prefer 2*N*N+N+M*NB)
01576 *
01577                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
01578      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01579 *
01580 *                    Copy R to WORK(IU), zeroing out below it
01581 *
01582                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
01583      $                            LDWRKU )
01584                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
01585      $                            WORK( IU+1 ), LDWRKU )
01586                      IE = ITAU
01587                      ITAUQ = IE + N
01588                      ITAUP = ITAUQ + N
01589                      IWORK = ITAUP + N
01590 *
01591 *                    Bidiagonalize R in WORK(IU), copying result to
01592 *                    WORK(IR)
01593 *                    (Workspace: need 2*N*N+4*N,
01594 *                                prefer 2*N*N+3*N+2*N*NB)
01595 *
01596                      CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
01597      $                            WORK( IE ), WORK( ITAUQ ),
01598      $                            WORK( ITAUP ), WORK( IWORK ),
01599      $                            LWORK-IWORK+1, IERR )
01600                      CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU,
01601      $                            WORK( IR ), LDWRKR )
01602 *
01603 *                    Generate left bidiagonalizing vectors in WORK(IU)
01604 *                    (Workspace: need 2*N*N+4*N, prefer 2*N*N+3*N+N*NB)
01605 *
01606                      CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
01607      $                            WORK( ITAUQ ), WORK( IWORK ),
01608      $                            LWORK-IWORK+1, IERR )
01609 *
01610 *                    Generate right bidiagonalizing vectors in WORK(IR)
01611 *                    (Workspace: need 2*N*N+4*N-1,
01612 *                                prefer 2*N*N+3*N+(N-1)*NB)
01613 *
01614                      CALL DORGBR( 'P', N, N, N, WORK( IR ), LDWRKR,
01615      $                            WORK( ITAUP ), WORK( IWORK ),
01616      $                            LWORK-IWORK+1, IERR )
01617                      IWORK = IE + N
01618 *
01619 *                    Perform bidiagonal QR iteration, computing left
01620 *                    singular vectors of R in WORK(IU) and computing
01621 *                    right singular vectors of R in WORK(IR)
01622 *                    (Workspace: need 2*N*N+BDSPAC)
01623 *
01624                      CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ),
01625      $                            WORK( IR ), LDWRKR, WORK( IU ),
01626      $                            LDWRKU, DUM, 1, WORK( IWORK ), INFO )
01627 *
01628 *                    Multiply Q in U by left singular vectors of R in
01629 *                    WORK(IU), storing result in A
01630 *                    (Workspace: need N*N)
01631 *
01632                      CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,
01633      $                           WORK( IU ), LDWRKU, ZERO, A, LDA )
01634 *
01635 *                    Copy left singular vectors of A from A to U
01636 *
01637                      CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
01638 *
01639 *                    Copy right singular vectors of R from WORK(IR) to A
01640 *
01641                      CALL DLACPY( 'F', N, N, WORK( IR ), LDWRKR, A,
01642      $                            LDA )
01643 *
01644                   ELSE
01645 *
01646 *                    Insufficient workspace for a fast algorithm
01647 *
01648                      ITAU = 1
01649                      IWORK = ITAU + N
01650 *
01651 *                    Compute A=Q*R, copying result to U
01652 *                    (Workspace: need 2*N, prefer N+N*NB)
01653 *
01654                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
01655      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01656                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
01657 *
01658 *                    Generate Q in U
01659 *                    (Workspace: need N+M, prefer N+M*NB)
01660 *
01661                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
01662      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01663                      IE = ITAU
01664                      ITAUQ = IE + N
01665                      ITAUP = ITAUQ + N
01666                      IWORK = ITAUP + N
01667 *
01668 *                    Zero out below R in A
01669 *
01670                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),
01671      $                            LDA )
01672 *
01673 *                    Bidiagonalize R in A
01674 *                    (Workspace: need 4*N, prefer 3*N+2*N*NB)
01675 *
01676                      CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
01677      $                            WORK( ITAUQ ), WORK( ITAUP ),
01678      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01679 *
01680 *                    Multiply Q in U by left bidiagonalizing vectors
01681 *                    in A
01682 *                    (Workspace: need 3*N+M, prefer 3*N+M*NB)
01683 *
01684                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
01685      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
01686      $                            LWORK-IWORK+1, IERR )
01687 *
01688 *                    Generate right bidiagonalizing vectors in A
01689 *                    (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
01690 *
01691                      CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
01692      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01693                      IWORK = IE + N
01694 *
01695 *                    Perform bidiagonal QR iteration, computing left
01696 *                    singular vectors of A in U and computing right
01697 *                    singular vectors of A in A
01698 *                    (Workspace: need BDSPAC)
01699 *
01700                      CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), A,
01701      $                            LDA, U, LDU, DUM, 1, WORK( IWORK ),
01702      $                            INFO )
01703 *
01704                   END IF
01705 *
01706                ELSE IF( WNTVAS ) THEN
01707 *
01708 *                 Path 9 (M much larger than N, JOBU='A', JOBVT='S'
01709 *                         or 'A')
01710 *                 M left singular vectors to be computed in U and
01711 *                 N right singular vectors to be computed in VT
01712 *
01713                   IF( LWORK.GE.N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN
01714 *
01715 *                    Sufficient workspace for a fast algorithm
01716 *
01717                      IU = 1
01718                      IF( LWORK.GE.WRKBL+LDA*N ) THEN
01719 *
01720 *                       WORK(IU) is LDA by N
01721 *
01722                         LDWRKU = LDA
01723                      ELSE
01724 *
01725 *                       WORK(IU) is N by N
01726 *
01727                         LDWRKU = N
01728                      END IF
01729                      ITAU = IU + LDWRKU*N
01730                      IWORK = ITAU + N
01731 *
01732 *                    Compute A=Q*R, copying result to U
01733 *                    (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
01734 *
01735                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
01736      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01737                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
01738 *
01739 *                    Generate Q in U
01740 *                    (Workspace: need N*N+N+M, prefer N*N+N+M*NB)
01741 *
01742                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
01743      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01744 *
01745 *                    Copy R to WORK(IU), zeroing out below it
01746 *
01747                      CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
01748      $                            LDWRKU )
01749                      CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
01750      $                            WORK( IU+1 ), LDWRKU )
01751                      IE = ITAU
01752                      ITAUQ = IE + N
01753                      ITAUP = ITAUQ + N
01754                      IWORK = ITAUP + N
01755 *
01756 *                    Bidiagonalize R in WORK(IU), copying result to VT
01757 *                    (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
01758 *
01759                      CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
01760      $                            WORK( IE ), WORK( ITAUQ ),
01761      $                            WORK( ITAUP ), WORK( IWORK ),
01762      $                            LWORK-IWORK+1, IERR )
01763                      CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, VT,
01764      $                            LDVT )
01765 *
01766 *                    Generate left bidiagonalizing vectors in WORK(IU)
01767 *                    (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
01768 *
01769                      CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
01770      $                            WORK( ITAUQ ), WORK( IWORK ),
01771      $                            LWORK-IWORK+1, IERR )
01772 *
01773 *                    Generate right bidiagonalizing vectors in VT
01774 *                    (Workspace: need N*N+4*N-1,
01775 *                                prefer N*N+3*N+(N-1)*NB)
01776 *
01777                      CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
01778      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01779                      IWORK = IE + N
01780 *
01781 *                    Perform bidiagonal QR iteration, computing left
01782 *                    singular vectors of R in WORK(IU) and computing
01783 *                    right singular vectors of R in VT
01784 *                    (Workspace: need N*N+BDSPAC)
01785 *
01786                      CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT,
01787      $                            LDVT, WORK( IU ), LDWRKU, DUM, 1,
01788      $                            WORK( IWORK ), INFO )
01789 *
01790 *                    Multiply Q in U by left singular vectors of R in
01791 *                    WORK(IU), storing result in A
01792 *                    (Workspace: need N*N)
01793 *
01794                      CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,
01795      $                           WORK( IU ), LDWRKU, ZERO, A, LDA )
01796 *
01797 *                    Copy left singular vectors of A from A to U
01798 *
01799                      CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
01800 *
01801                   ELSE
01802 *
01803 *                    Insufficient workspace for a fast algorithm
01804 *
01805                      ITAU = 1
01806                      IWORK = ITAU + N
01807 *
01808 *                    Compute A=Q*R, copying result to U
01809 *                    (Workspace: need 2*N, prefer N+N*NB)
01810 *
01811                      CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
01812      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01813                      CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
01814 *
01815 *                    Generate Q in U
01816 *                    (Workspace: need N+M, prefer N+M*NB)
01817 *
01818                      CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
01819      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01820 *
01821 *                    Copy R from A to VT, zeroing out below it
01822 *
01823                      CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
01824                      IF( N.GT.1 )
01825      $                  CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
01826      $                               VT( 2, 1 ), LDVT )
01827                      IE = ITAU
01828                      ITAUQ = IE + N
01829                      ITAUP = ITAUQ + N
01830                      IWORK = ITAUP + N
01831 *
01832 *                    Bidiagonalize R in VT
01833 *                    (Workspace: need 4*N, prefer 3*N+2*N*NB)
01834 *
01835                      CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
01836      $                            WORK( ITAUQ ), WORK( ITAUP ),
01837      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01838 *
01839 *                    Multiply Q in U by left bidiagonalizing vectors
01840 *                    in VT
01841 *                    (Workspace: need 3*N+M, prefer 3*N+M*NB)
01842 *
01843                      CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,
01844      $                            WORK( ITAUQ ), U, LDU, WORK( IWORK ),
01845      $                            LWORK-IWORK+1, IERR )
01846 *
01847 *                    Generate right bidiagonalizing vectors in VT
01848 *                    (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
01849 *
01850                      CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
01851      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
01852                      IWORK = IE + N
01853 *
01854 *                    Perform bidiagonal QR iteration, computing left
01855 *                    singular vectors of A in U and computing right
01856 *                    singular vectors of A in VT
01857 *                    (Workspace: need BDSPAC)
01858 *
01859                      CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT,
01860      $                            LDVT, U, LDU, DUM, 1, WORK( IWORK ),
01861      $                            INFO )
01862 *
01863                   END IF
01864 *
01865                END IF
01866 *
01867             END IF
01868 *
01869          ELSE
01870 *
01871 *           M .LT. MNTHR
01872 *
01873 *           Path 10 (M at least N, but not much larger)
01874 *           Reduce to bidiagonal form without QR decomposition
01875 *
01876             IE = 1
01877             ITAUQ = IE + N
01878             ITAUP = ITAUQ + N
01879             IWORK = ITAUP + N
01880 *
01881 *           Bidiagonalize A
01882 *           (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)
01883 *
01884             CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
01885      $                   WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
01886      $                   IERR )
01887             IF( WNTUAS ) THEN
01888 *
01889 *              If left singular vectors desired in U, copy result to U
01890 *              and generate left bidiagonalizing vectors in U
01891 *              (Workspace: need 3*N+NCU, prefer 3*N+NCU*NB)
01892 *
01893                CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
01894                IF( WNTUS )
01895      $            NCU = N
01896                IF( WNTUA )
01897      $            NCU = M
01898                CALL DORGBR( 'Q', M, NCU, N, U, LDU, WORK( ITAUQ ),
01899      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
01900             END IF
01901             IF( WNTVAS ) THEN
01902 *
01903 *              If right singular vectors desired in VT, copy result to
01904 *              VT and generate right bidiagonalizing vectors in VT
01905 *              (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
01906 *
01907                CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
01908                CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
01909      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
01910             END IF
01911             IF( WNTUO ) THEN
01912 *
01913 *              If left singular vectors desired in A, generate left
01914 *              bidiagonalizing vectors in A
01915 *              (Workspace: need 4*N, prefer 3*N+N*NB)
01916 *
01917                CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),
01918      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
01919             END IF
01920             IF( WNTVO ) THEN
01921 *
01922 *              If right singular vectors desired in A, generate right
01923 *              bidiagonalizing vectors in A
01924 *              (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
01925 *
01926                CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
01927      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
01928             END IF
01929             IWORK = IE + N
01930             IF( WNTUAS .OR. WNTUO )
01931      $         NRU = M
01932             IF( WNTUN )
01933      $         NRU = 0
01934             IF( WNTVAS .OR. WNTVO )
01935      $         NCVT = N
01936             IF( WNTVN )
01937      $         NCVT = 0
01938             IF( ( .NOT.WNTUO ) .AND. ( .NOT.WNTVO ) ) THEN
01939 *
01940 *              Perform bidiagonal QR iteration, if desired, computing
01941 *              left singular vectors in U and computing right singular
01942 *              vectors in VT
01943 *              (Workspace: need BDSPAC)
01944 *
01945                CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), VT,
01946      $                      LDVT, U, LDU, DUM, 1, WORK( IWORK ), INFO )
01947             ELSE IF( ( .NOT.WNTUO ) .AND. WNTVO ) THEN
01948 *
01949 *              Perform bidiagonal QR iteration, if desired, computing
01950 *              left singular vectors in U and computing right singular
01951 *              vectors in A
01952 *              (Workspace: need BDSPAC)
01953 *
01954                CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), A, LDA,
01955      $                      U, LDU, DUM, 1, WORK( IWORK ), INFO )
01956             ELSE
01957 *
01958 *              Perform bidiagonal QR iteration, if desired, computing
01959 *              left singular vectors in A and computing right singular
01960 *              vectors in VT
01961 *              (Workspace: need BDSPAC)
01962 *
01963                CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), VT,
01964      $                      LDVT, A, LDA, DUM, 1, WORK( IWORK ), INFO )
01965             END IF
01966 *
01967          END IF
01968 *
01969       ELSE
01970 *
01971 *        A has more columns than rows. If A has sufficiently more
01972 *        columns than rows, first reduce using the LQ decomposition (if
01973 *        sufficient workspace available)
01974 *
01975          IF( N.GE.MNTHR ) THEN
01976 *
01977             IF( WNTVN ) THEN
01978 *
01979 *              Path 1t(N much larger than M, JOBVT='N')
01980 *              No right singular vectors to be computed
01981 *
01982                ITAU = 1
01983                IWORK = ITAU + M
01984 *
01985 *              Compute A=L*Q
01986 *              (Workspace: need 2*M, prefer M+M*NB)
01987 *
01988                CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
01989      $                      LWORK-IWORK+1, IERR )
01990 *
01991 *              Zero out above L
01992 *
01993                CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )
01994                IE = 1
01995                ITAUQ = IE + M
01996                ITAUP = ITAUQ + M
01997                IWORK = ITAUP + M
01998 *
01999 *              Bidiagonalize L in A
02000 *              (Workspace: need 4*M, prefer 3*M+2*M*NB)
02001 *
02002                CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
02003      $                      WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
02004      $                      IERR )
02005                IF( WNTUO .OR. WNTUAS ) THEN
02006 *
02007 *                 If left singular vectors desired, generate Q
02008 *                 (Workspace: need 4*M, prefer 3*M+M*NB)
02009 *
02010                   CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),
02011      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02012                END IF
02013                IWORK = IE + M
02014                NRU = 0
02015                IF( WNTUO .OR. WNTUAS )
02016      $            NRU = M
02017 *
02018 *              Perform bidiagonal QR iteration, computing left singular
02019 *              vectors of A in A if desired
02020 *              (Workspace: need BDSPAC)
02021 *
02022                CALL DBDSQR( 'U', M, 0, NRU, 0, S, WORK( IE ), DUM, 1, A,
02023      $                      LDA, DUM, 1, WORK( IWORK ), INFO )
02024 *
02025 *              If left singular vectors desired in U, copy them there
02026 *
02027                IF( WNTUAS )
02028      $            CALL DLACPY( 'F', M, M, A, LDA, U, LDU )
02029 *
02030             ELSE IF( WNTVO .AND. WNTUN ) THEN
02031 *
02032 *              Path 2t(N much larger than M, JOBU='N', JOBVT='O')
02033 *              M right singular vectors to be overwritten on A and
02034 *              no left singular vectors to be computed
02035 *
02036                IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
02037 *
02038 *                 Sufficient workspace for a fast algorithm
02039 *
02040                   IR = 1
02041                   IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+LDA*M ) THEN
02042 *
02043 *                    WORK(IU) is LDA by N and WORK(IR) is LDA by M
02044 *
02045                      LDWRKU = LDA
02046                      CHUNK = N
02047                      LDWRKR = LDA
02048                   ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+M*M ) THEN
02049 *
02050 *                    WORK(IU) is LDA by N and WORK(IR) is M by M
02051 *
02052                      LDWRKU = LDA
02053                      CHUNK = N
02054                      LDWRKR = M
02055                   ELSE
02056 *
02057 *                    WORK(IU) is M by CHUNK and WORK(IR) is M by M
02058 *
02059                      LDWRKU = M
02060                      CHUNK = ( LWORK-M*M-M ) / M
02061                      LDWRKR = M
02062                   END IF
02063                   ITAU = IR + LDWRKR*M
02064                   IWORK = ITAU + M
02065 *
02066 *                 Compute A=L*Q
02067 *                 (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
02068 *
02069                   CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02070      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02071 *
02072 *                 Copy L to WORK(IR) and zero out above it
02073 *
02074                   CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ), LDWRKR )
02075                   CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
02076      $                         WORK( IR+LDWRKR ), LDWRKR )
02077 *
02078 *                 Generate Q in A
02079 *                 (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
02080 *
02081                   CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
02082      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02083                   IE = ITAU
02084                   ITAUQ = IE + M
02085                   ITAUP = ITAUQ + M
02086                   IWORK = ITAUP + M
02087 *
02088 *                 Bidiagonalize L in WORK(IR)
02089 *                 (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
02090 *
02091                   CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S, WORK( IE ),
02092      $                         WORK( ITAUQ ), WORK( ITAUP ),
02093      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02094 *
02095 *                 Generate right vectors bidiagonalizing L
02096 *                 (Workspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB)
02097 *
02098                   CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
02099      $                         WORK( ITAUP ), WORK( IWORK ),
02100      $                         LWORK-IWORK+1, IERR )
02101                   IWORK = IE + M
02102 *
02103 *                 Perform bidiagonal QR iteration, computing right
02104 *                 singular vectors of L in WORK(IR)
02105 *                 (Workspace: need M*M+BDSPAC)
02106 *
02107                   CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),
02108      $                         WORK( IR ), LDWRKR, DUM, 1, DUM, 1,
02109      $                         WORK( IWORK ), INFO )
02110                   IU = IE + M
02111 *
02112 *                 Multiply right singular vectors of L in WORK(IR) by Q
02113 *                 in A, storing result in WORK(IU) and copying to A
02114 *                 (Workspace: need M*M+2*M, prefer M*M+M*N+M)
02115 *
02116                   DO 30 I = 1, N, CHUNK
02117                      BLK = MIN( N-I+1, CHUNK )
02118                      CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IR ),
02119      $                           LDWRKR, A( 1, I ), LDA, ZERO,
02120      $                           WORK( IU ), LDWRKU )
02121                      CALL DLACPY( 'F', M, BLK, WORK( IU ), LDWRKU,
02122      $                            A( 1, I ), LDA )
02123    30             CONTINUE
02124 *
02125                ELSE
02126 *
02127 *                 Insufficient workspace for a fast algorithm
02128 *
02129                   IE = 1
02130                   ITAUQ = IE + M
02131                   ITAUP = ITAUQ + M
02132                   IWORK = ITAUP + M
02133 *
02134 *                 Bidiagonalize A
02135 *                 (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
02136 *
02137                   CALL DGEBRD( M, N, A, LDA, S, WORK( IE ),
02138      $                         WORK( ITAUQ ), WORK( ITAUP ),
02139      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02140 *
02141 *                 Generate right vectors bidiagonalizing A
02142 *                 (Workspace: need 4*M, prefer 3*M+M*NB)
02143 *
02144                   CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
02145      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02146                   IWORK = IE + M
02147 *
02148 *                 Perform bidiagonal QR iteration, computing right
02149 *                 singular vectors of A in A
02150 *                 (Workspace: need BDSPAC)
02151 *
02152                   CALL DBDSQR( 'L', M, N, 0, 0, S, WORK( IE ), A, LDA,
02153      $                         DUM, 1, DUM, 1, WORK( IWORK ), INFO )
02154 *
02155                END IF
02156 *
02157             ELSE IF( WNTVO .AND. WNTUAS ) THEN
02158 *
02159 *              Path 3t(N much larger than M, JOBU='S' or 'A', JOBVT='O')
02160 *              M right singular vectors to be overwritten on A and
02161 *              M left singular vectors to be computed in U
02162 *
02163                IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
02164 *
02165 *                 Sufficient workspace for a fast algorithm
02166 *
02167                   IR = 1
02168                   IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+LDA*M ) THEN
02169 *
02170 *                    WORK(IU) is LDA by N and WORK(IR) is LDA by M
02171 *
02172                      LDWRKU = LDA
02173                      CHUNK = N
02174                      LDWRKR = LDA
02175                   ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+M*M ) THEN
02176 *
02177 *                    WORK(IU) is LDA by N and WORK(IR) is M by M
02178 *
02179                      LDWRKU = LDA
02180                      CHUNK = N
02181                      LDWRKR = M
02182                   ELSE
02183 *
02184 *                    WORK(IU) is M by CHUNK and WORK(IR) is M by M
02185 *
02186                      LDWRKU = M
02187                      CHUNK = ( LWORK-M*M-M ) / M
02188                      LDWRKR = M
02189                   END IF
02190                   ITAU = IR + LDWRKR*M
02191                   IWORK = ITAU + M
02192 *
02193 *                 Compute A=L*Q
02194 *                 (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
02195 *
02196                   CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02197      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02198 *
02199 *                 Copy L to U, zeroing about above it
02200 *
02201                   CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
02202                   CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
02203      $                         LDU )
02204 *
02205 *                 Generate Q in A
02206 *                 (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
02207 *
02208                   CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
02209      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02210                   IE = ITAU
02211                   ITAUQ = IE + M
02212                   ITAUP = ITAUQ + M
02213                   IWORK = ITAUP + M
02214 *
02215 *                 Bidiagonalize L in U, copying result to WORK(IR)
02216 *                 (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
02217 *
02218                   CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
02219      $                         WORK( ITAUQ ), WORK( ITAUP ),
02220      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02221                   CALL DLACPY( 'U', M, M, U, LDU, WORK( IR ), LDWRKR )
02222 *
02223 *                 Generate right vectors bidiagonalizing L in WORK(IR)
02224 *                 (Workspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB)
02225 *
02226                   CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
02227      $                         WORK( ITAUP ), WORK( IWORK ),
02228      $                         LWORK-IWORK+1, IERR )
02229 *
02230 *                 Generate left vectors bidiagonalizing L in U
02231 *                 (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB)
02232 *
02233                   CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
02234      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02235                   IWORK = IE + M
02236 *
02237 *                 Perform bidiagonal QR iteration, computing left
02238 *                 singular vectors of L in U, and computing right
02239 *                 singular vectors of L in WORK(IR)
02240 *                 (Workspace: need M*M+BDSPAC)
02241 *
02242                   CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
02243      $                         WORK( IR ), LDWRKR, U, LDU, DUM, 1,
02244      $                         WORK( IWORK ), INFO )
02245                   IU = IE + M
02246 *
02247 *                 Multiply right singular vectors of L in WORK(IR) by Q
02248 *                 in A, storing result in WORK(IU) and copying to A
02249 *                 (Workspace: need M*M+2*M, prefer M*M+M*N+M))
02250 *
02251                   DO 40 I = 1, N, CHUNK
02252                      BLK = MIN( N-I+1, CHUNK )
02253                      CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IR ),
02254      $                           LDWRKR, A( 1, I ), LDA, ZERO,
02255      $                           WORK( IU ), LDWRKU )
02256                      CALL DLACPY( 'F', M, BLK, WORK( IU ), LDWRKU,
02257      $                            A( 1, I ), LDA )
02258    40             CONTINUE
02259 *
02260                ELSE
02261 *
02262 *                 Insufficient workspace for a fast algorithm
02263 *
02264                   ITAU = 1
02265                   IWORK = ITAU + M
02266 *
02267 *                 Compute A=L*Q
02268 *                 (Workspace: need 2*M, prefer M+M*NB)
02269 *
02270                   CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02271      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02272 *
02273 *                 Copy L to U, zeroing out above it
02274 *
02275                   CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
02276                   CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
02277      $                         LDU )
02278 *
02279 *                 Generate Q in A
02280 *                 (Workspace: need 2*M, prefer M+M*NB)
02281 *
02282                   CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
02283      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02284                   IE = ITAU
02285                   ITAUQ = IE + M
02286                   ITAUP = ITAUQ + M
02287                   IWORK = ITAUP + M
02288 *
02289 *                 Bidiagonalize L in U
02290 *                 (Workspace: need 4*M, prefer 3*M+2*M*NB)
02291 *
02292                   CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
02293      $                         WORK( ITAUQ ), WORK( ITAUP ),
02294      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02295 *
02296 *                 Multiply right vectors bidiagonalizing L by Q in A
02297 *                 (Workspace: need 3*M+N, prefer 3*M+N*NB)
02298 *
02299                   CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,
02300      $                         WORK( ITAUP ), A, LDA, WORK( IWORK ),
02301      $                         LWORK-IWORK+1, IERR )
02302 *
02303 *                 Generate left vectors bidiagonalizing L in U
02304 *                 (Workspace: need 4*M, prefer 3*M+M*NB)
02305 *
02306                   CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
02307      $                         WORK( IWORK ), LWORK-IWORK+1, IERR )
02308                   IWORK = IE + M
02309 *
02310 *                 Perform bidiagonal QR iteration, computing left
02311 *                 singular vectors of A in U and computing right
02312 *                 singular vectors of A in A
02313 *                 (Workspace: need BDSPAC)
02314 *
02315                   CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), A, LDA,
02316      $                         U, LDU, DUM, 1, WORK( IWORK ), INFO )
02317 *
02318                END IF
02319 *
02320             ELSE IF( WNTVS ) THEN
02321 *
02322                IF( WNTUN ) THEN
02323 *
02324 *                 Path 4t(N much larger than M, JOBU='N', JOBVT='S')
02325 *                 M right singular vectors to be computed in VT and
02326 *                 no left singular vectors to be computed
02327 *
02328                   IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
02329 *
02330 *                    Sufficient workspace for a fast algorithm
02331 *
02332                      IR = 1
02333                      IF( LWORK.GE.WRKBL+LDA*M ) THEN
02334 *
02335 *                       WORK(IR) is LDA by M
02336 *
02337                         LDWRKR = LDA
02338                      ELSE
02339 *
02340 *                       WORK(IR) is M by M
02341 *
02342                         LDWRKR = M
02343                      END IF
02344                      ITAU = IR + LDWRKR*M
02345                      IWORK = ITAU + M
02346 *
02347 *                    Compute A=L*Q
02348 *                    (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
02349 *
02350                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02351      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02352 *
02353 *                    Copy L to WORK(IR), zeroing out above it
02354 *
02355                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ),
02356      $                            LDWRKR )
02357                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
02358      $                            WORK( IR+LDWRKR ), LDWRKR )
02359 *
02360 *                    Generate Q in A
02361 *                    (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
02362 *
02363                      CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
02364      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02365                      IE = ITAU
02366                      ITAUQ = IE + M
02367                      ITAUP = ITAUQ + M
02368                      IWORK = ITAUP + M
02369 *
02370 *                    Bidiagonalize L in WORK(IR)
02371 *                    (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
02372 *
02373                      CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S,
02374      $                            WORK( IE ), WORK( ITAUQ ),
02375      $                            WORK( ITAUP ), WORK( IWORK ),
02376      $                            LWORK-IWORK+1, IERR )
02377 *
02378 *                    Generate right vectors bidiagonalizing L in
02379 *                    WORK(IR)
02380 *                    (Workspace: need M*M+4*M, prefer M*M+3*M+(M-1)*NB)
02381 *
02382                      CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
02383      $                            WORK( ITAUP ), WORK( IWORK ),
02384      $                            LWORK-IWORK+1, IERR )
02385                      IWORK = IE + M
02386 *
02387 *                    Perform bidiagonal QR iteration, computing right
02388 *                    singular vectors of L in WORK(IR)
02389 *                    (Workspace: need M*M+BDSPAC)
02390 *
02391                      CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),
02392      $                            WORK( IR ), LDWRKR, DUM, 1, DUM, 1,
02393      $                            WORK( IWORK ), INFO )
02394 *
02395 *                    Multiply right singular vectors of L in WORK(IR) by
02396 *                    Q in A, storing result in VT
02397 *                    (Workspace: need M*M)
02398 *
02399                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IR ),
02400      $                           LDWRKR, A, LDA, ZERO, VT, LDVT )
02401 *
02402                   ELSE
02403 *
02404 *                    Insufficient workspace for a fast algorithm
02405 *
02406                      ITAU = 1
02407                      IWORK = ITAU + M
02408 *
02409 *                    Compute A=L*Q
02410 *                    (Workspace: need 2*M, prefer M+M*NB)
02411 *
02412                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02413      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02414 *
02415 *                    Copy result to VT
02416 *
02417                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
02418 *
02419 *                    Generate Q in VT
02420 *                    (Workspace: need 2*M, prefer M+M*NB)
02421 *
02422                      CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),
02423      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02424                      IE = ITAU
02425                      ITAUQ = IE + M
02426                      ITAUP = ITAUQ + M
02427                      IWORK = ITAUP + M
02428 *
02429 *                    Zero out above L in A
02430 *
02431                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
02432      $                            LDA )
02433 *
02434 *                    Bidiagonalize L in A
02435 *                    (Workspace: need 4*M, prefer 3*M+2*M*NB)
02436 *
02437                      CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
02438      $                            WORK( ITAUQ ), WORK( ITAUP ),
02439      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02440 *
02441 *                    Multiply right vectors bidiagonalizing L by Q in VT
02442 *                    (Workspace: need 3*M+N, prefer 3*M+N*NB)
02443 *
02444                      CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
02445      $                            WORK( ITAUP ), VT, LDVT,
02446      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02447                      IWORK = IE + M
02448 *
02449 *                    Perform bidiagonal QR iteration, computing right
02450 *                    singular vectors of A in VT
02451 *                    (Workspace: need BDSPAC)
02452 *
02453                      CALL DBDSQR( 'U', M, N, 0, 0, S, WORK( IE ), VT,
02454      $                            LDVT, DUM, 1, DUM, 1, WORK( IWORK ),
02455      $                            INFO )
02456 *
02457                   END IF
02458 *
02459                ELSE IF( WNTUO ) THEN
02460 *
02461 *                 Path 5t(N much larger than M, JOBU='O', JOBVT='S')
02462 *                 M right singular vectors to be computed in VT and
02463 *                 M left singular vectors to be overwritten on A
02464 *
02465                   IF( LWORK.GE.2*M*M+MAX( 4*M, BDSPAC ) ) THEN
02466 *
02467 *                    Sufficient workspace for a fast algorithm
02468 *
02469                      IU = 1
02470                      IF( LWORK.GE.WRKBL+2*LDA*M ) THEN
02471 *
02472 *                       WORK(IU) is LDA by M and WORK(IR) is LDA by M
02473 *
02474                         LDWRKU = LDA
02475                         IR = IU + LDWRKU*M
02476                         LDWRKR = LDA
02477                      ELSE IF( LWORK.GE.WRKBL+( LDA+M )*M ) THEN
02478 *
02479 *                       WORK(IU) is LDA by M and WORK(IR) is M by M
02480 *
02481                         LDWRKU = LDA
02482                         IR = IU + LDWRKU*M
02483                         LDWRKR = M
02484                      ELSE
02485 *
02486 *                       WORK(IU) is M by M and WORK(IR) is M by M
02487 *
02488                         LDWRKU = M
02489                         IR = IU + LDWRKU*M
02490                         LDWRKR = M
02491                      END IF
02492                      ITAU = IR + LDWRKR*M
02493                      IWORK = ITAU + M
02494 *
02495 *                    Compute A=L*Q
02496 *                    (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB)
02497 *
02498                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02499      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02500 *
02501 *                    Copy L to WORK(IU), zeroing out below it
02502 *
02503                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
02504      $                            LDWRKU )
02505                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
02506      $                            WORK( IU+LDWRKU ), LDWRKU )
02507 *
02508 *                    Generate Q in A
02509 *                    (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB)
02510 *
02511                      CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
02512      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02513                      IE = ITAU
02514                      ITAUQ = IE + M
02515                      ITAUP = ITAUQ + M
02516                      IWORK = ITAUP + M
02517 *
02518 *                    Bidiagonalize L in WORK(IU), copying result to
02519 *                    WORK(IR)
02520 *                    (Workspace: need 2*M*M+4*M,
02521 *                                prefer 2*M*M+3*M+2*M*NB)
02522 *
02523                      CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
02524      $                            WORK( IE ), WORK( ITAUQ ),
02525      $                            WORK( ITAUP ), WORK( IWORK ),
02526      $                            LWORK-IWORK+1, IERR )
02527                      CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU,
02528      $                            WORK( IR ), LDWRKR )
02529 *
02530 *                    Generate right bidiagonalizing vectors in WORK(IU)
02531 *                    (Workspace: need 2*M*M+4*M-1,
02532 *                                prefer 2*M*M+3*M+(M-1)*NB)
02533 *
02534                      CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
02535      $                            WORK( ITAUP ), WORK( IWORK ),
02536      $                            LWORK-IWORK+1, IERR )
02537 *
02538 *                    Generate left bidiagonalizing vectors in WORK(IR)
02539 *                    (Workspace: need 2*M*M+4*M, prefer 2*M*M+3*M+M*NB)
02540 *
02541                      CALL DORGBR( 'Q', M, M, M, WORK( IR ), LDWRKR,
02542      $                            WORK( ITAUQ ), WORK( IWORK ),
02543      $                            LWORK-IWORK+1, IERR )
02544                      IWORK = IE + M
02545 *
02546 *                    Perform bidiagonal QR iteration, computing left
02547 *                    singular vectors of L in WORK(IR) and computing
02548 *                    right singular vectors of L in WORK(IU)
02549 *                    (Workspace: need 2*M*M+BDSPAC)
02550 *
02551                      CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
02552      $                            WORK( IU ), LDWRKU, WORK( IR ),
02553      $                            LDWRKR, DUM, 1, WORK( IWORK ), INFO )
02554 *
02555 *                    Multiply right singular vectors of L in WORK(IU) by
02556 *                    Q in A, storing result in VT
02557 *                    (Workspace: need M*M)
02558 *
02559                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
02560      $                           LDWRKU, A, LDA, ZERO, VT, LDVT )
02561 *
02562 *                    Copy left singular vectors of L to A
02563 *                    (Workspace: need M*M)
02564 *
02565                      CALL DLACPY( 'F', M, M, WORK( IR ), LDWRKR, A,
02566      $                            LDA )
02567 *
02568                   ELSE
02569 *
02570 *                    Insufficient workspace for a fast algorithm
02571 *
02572                      ITAU = 1
02573                      IWORK = ITAU + M
02574 *
02575 *                    Compute A=L*Q, copying result to VT
02576 *                    (Workspace: need 2*M, prefer M+M*NB)
02577 *
02578                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02579      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02580                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
02581 *
02582 *                    Generate Q in VT
02583 *                    (Workspace: need 2*M, prefer M+M*NB)
02584 *
02585                      CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),
02586      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02587                      IE = ITAU
02588                      ITAUQ = IE + M
02589                      ITAUP = ITAUQ + M
02590                      IWORK = ITAUP + M
02591 *
02592 *                    Zero out above L in A
02593 *
02594                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
02595      $                            LDA )
02596 *
02597 *                    Bidiagonalize L in A
02598 *                    (Workspace: need 4*M, prefer 3*M+2*M*NB)
02599 *
02600                      CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
02601      $                            WORK( ITAUQ ), WORK( ITAUP ),
02602      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02603 *
02604 *                    Multiply right vectors bidiagonalizing L by Q in VT
02605 *                    (Workspace: need 3*M+N, prefer 3*M+N*NB)
02606 *
02607                      CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
02608      $                            WORK( ITAUP ), VT, LDVT,
02609      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02610 *
02611 *                    Generate left bidiagonalizing vectors of L in A
02612 *                    (Workspace: need 4*M, prefer 3*M+M*NB)
02613 *
02614                      CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),
02615      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02616                      IWORK = IE + M
02617 *
02618 *                    Perform bidiagonal QR iteration, compute left
02619 *                    singular vectors of A in A and compute right
02620 *                    singular vectors of A in VT
02621 *                    (Workspace: need BDSPAC)
02622 *
02623                      CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
02624      $                            LDVT, A, LDA, DUM, 1, WORK( IWORK ),
02625      $                            INFO )
02626 *
02627                   END IF
02628 *
02629                ELSE IF( WNTUAS ) THEN
02630 *
02631 *                 Path 6t(N much larger than M, JOBU='S' or 'A',
02632 *                         JOBVT='S')
02633 *                 M right singular vectors to be computed in VT and
02634 *                 M left singular vectors to be computed in U
02635 *
02636                   IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
02637 *
02638 *                    Sufficient workspace for a fast algorithm
02639 *
02640                      IU = 1
02641                      IF( LWORK.GE.WRKBL+LDA*M ) THEN
02642 *
02643 *                       WORK(IU) is LDA by N
02644 *
02645                         LDWRKU = LDA
02646                      ELSE
02647 *
02648 *                       WORK(IU) is LDA by M
02649 *
02650                         LDWRKU = M
02651                      END IF
02652                      ITAU = IU + LDWRKU*M
02653                      IWORK = ITAU + M
02654 *
02655 *                    Compute A=L*Q
02656 *                    (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
02657 *
02658                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02659      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02660 *
02661 *                    Copy L to WORK(IU), zeroing out above it
02662 *
02663                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
02664      $                            LDWRKU )
02665                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
02666      $                            WORK( IU+LDWRKU ), LDWRKU )
02667 *
02668 *                    Generate Q in A
02669 *                    (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
02670 *
02671                      CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
02672      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02673                      IE = ITAU
02674                      ITAUQ = IE + M
02675                      ITAUP = ITAUQ + M
02676                      IWORK = ITAUP + M
02677 *
02678 *                    Bidiagonalize L in WORK(IU), copying result to U
02679 *                    (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
02680 *
02681                      CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
02682      $                            WORK( IE ), WORK( ITAUQ ),
02683      $                            WORK( ITAUP ), WORK( IWORK ),
02684      $                            LWORK-IWORK+1, IERR )
02685                      CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, U,
02686      $                            LDU )
02687 *
02688 *                    Generate right bidiagonalizing vectors in WORK(IU)
02689 *                    (Workspace: need M*M+4*M-1,
02690 *                                prefer M*M+3*M+(M-1)*NB)
02691 *
02692                      CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
02693      $                            WORK( ITAUP ), WORK( IWORK ),
02694      $                            LWORK-IWORK+1, IERR )
02695 *
02696 *                    Generate left bidiagonalizing vectors in U
02697 *                    (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB)
02698 *
02699                      CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
02700      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02701                      IWORK = IE + M
02702 *
02703 *                    Perform bidiagonal QR iteration, computing left
02704 *                    singular vectors of L in U and computing right
02705 *                    singular vectors of L in WORK(IU)
02706 *                    (Workspace: need M*M+BDSPAC)
02707 *
02708                      CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
02709      $                            WORK( IU ), LDWRKU, U, LDU, DUM, 1,
02710      $                            WORK( IWORK ), INFO )
02711 *
02712 *                    Multiply right singular vectors of L in WORK(IU) by
02713 *                    Q in A, storing result in VT
02714 *                    (Workspace: need M*M)
02715 *
02716                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
02717      $                           LDWRKU, A, LDA, ZERO, VT, LDVT )
02718 *
02719                   ELSE
02720 *
02721 *                    Insufficient workspace for a fast algorithm
02722 *
02723                      ITAU = 1
02724                      IWORK = ITAU + M
02725 *
02726 *                    Compute A=L*Q, copying result to VT
02727 *                    (Workspace: need 2*M, prefer M+M*NB)
02728 *
02729                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02730      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02731                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
02732 *
02733 *                    Generate Q in VT
02734 *                    (Workspace: need 2*M, prefer M+M*NB)
02735 *
02736                      CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),
02737      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02738 *
02739 *                    Copy L to U, zeroing out above it
02740 *
02741                      CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
02742                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
02743      $                            LDU )
02744                      IE = ITAU
02745                      ITAUQ = IE + M
02746                      ITAUP = ITAUQ + M
02747                      IWORK = ITAUP + M
02748 *
02749 *                    Bidiagonalize L in U
02750 *                    (Workspace: need 4*M, prefer 3*M+2*M*NB)
02751 *
02752                      CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
02753      $                            WORK( ITAUQ ), WORK( ITAUP ),
02754      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02755 *
02756 *                    Multiply right bidiagonalizing vectors in U by Q
02757 *                    in VT
02758 *                    (Workspace: need 3*M+N, prefer 3*M+N*NB)
02759 *
02760                      CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,
02761      $                            WORK( ITAUP ), VT, LDVT,
02762      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02763 *
02764 *                    Generate left bidiagonalizing vectors in U
02765 *                    (Workspace: need 4*M, prefer 3*M+M*NB)
02766 *
02767                      CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
02768      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02769                      IWORK = IE + M
02770 *
02771 *                    Perform bidiagonal QR iteration, computing left
02772 *                    singular vectors of A in U and computing right
02773 *                    singular vectors of A in VT
02774 *                    (Workspace: need BDSPAC)
02775 *
02776                      CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
02777      $                            LDVT, U, LDU, DUM, 1, WORK( IWORK ),
02778      $                            INFO )
02779 *
02780                   END IF
02781 *
02782                END IF
02783 *
02784             ELSE IF( WNTVA ) THEN
02785 *
02786                IF( WNTUN ) THEN
02787 *
02788 *                 Path 7t(N much larger than M, JOBU='N', JOBVT='A')
02789 *                 N right singular vectors to be computed in VT and
02790 *                 no left singular vectors to be computed
02791 *
02792                   IF( LWORK.GE.M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN
02793 *
02794 *                    Sufficient workspace for a fast algorithm
02795 *
02796                      IR = 1
02797                      IF( LWORK.GE.WRKBL+LDA*M ) THEN
02798 *
02799 *                       WORK(IR) is LDA by M
02800 *
02801                         LDWRKR = LDA
02802                      ELSE
02803 *
02804 *                       WORK(IR) is M by M
02805 *
02806                         LDWRKR = M
02807                      END IF
02808                      ITAU = IR + LDWRKR*M
02809                      IWORK = ITAU + M
02810 *
02811 *                    Compute A=L*Q, copying result to VT
02812 *                    (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
02813 *
02814                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02815      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02816                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
02817 *
02818 *                    Copy L to WORK(IR), zeroing out above it
02819 *
02820                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ),
02821      $                            LDWRKR )
02822                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
02823      $                            WORK( IR+LDWRKR ), LDWRKR )
02824 *
02825 *                    Generate Q in VT
02826 *                    (Workspace: need M*M+M+N, prefer M*M+M+N*NB)
02827 *
02828                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
02829      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02830                      IE = ITAU
02831                      ITAUQ = IE + M
02832                      ITAUP = ITAUQ + M
02833                      IWORK = ITAUP + M
02834 *
02835 *                    Bidiagonalize L in WORK(IR)
02836 *                    (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
02837 *
02838                      CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S,
02839      $                            WORK( IE ), WORK( ITAUQ ),
02840      $                            WORK( ITAUP ), WORK( IWORK ),
02841      $                            LWORK-IWORK+1, IERR )
02842 *
02843 *                    Generate right bidiagonalizing vectors in WORK(IR)
02844 *                    (Workspace: need M*M+4*M-1,
02845 *                                prefer M*M+3*M+(M-1)*NB)
02846 *
02847                      CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
02848      $                            WORK( ITAUP ), WORK( IWORK ),
02849      $                            LWORK-IWORK+1, IERR )
02850                      IWORK = IE + M
02851 *
02852 *                    Perform bidiagonal QR iteration, computing right
02853 *                    singular vectors of L in WORK(IR)
02854 *                    (Workspace: need M*M+BDSPAC)
02855 *
02856                      CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),
02857      $                            WORK( IR ), LDWRKR, DUM, 1, DUM, 1,
02858      $                            WORK( IWORK ), INFO )
02859 *
02860 *                    Multiply right singular vectors of L in WORK(IR) by
02861 *                    Q in VT, storing result in A
02862 *                    (Workspace: need M*M)
02863 *
02864                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IR ),
02865      $                           LDWRKR, VT, LDVT, ZERO, A, LDA )
02866 *
02867 *                    Copy right singular vectors of A from A to VT
02868 *
02869                      CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
02870 *
02871                   ELSE
02872 *
02873 *                    Insufficient workspace for a fast algorithm
02874 *
02875                      ITAU = 1
02876                      IWORK = ITAU + M
02877 *
02878 *                    Compute A=L*Q, copying result to VT
02879 *                    (Workspace: need 2*M, prefer M+M*NB)
02880 *
02881                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02882      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02883                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
02884 *
02885 *                    Generate Q in VT
02886 *                    (Workspace: need M+N, prefer M+N*NB)
02887 *
02888                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
02889      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02890                      IE = ITAU
02891                      ITAUQ = IE + M
02892                      ITAUP = ITAUQ + M
02893                      IWORK = ITAUP + M
02894 *
02895 *                    Zero out above L in A
02896 *
02897                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
02898      $                            LDA )
02899 *
02900 *                    Bidiagonalize L in A
02901 *                    (Workspace: need 4*M, prefer 3*M+2*M*NB)
02902 *
02903                      CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
02904      $                            WORK( ITAUQ ), WORK( ITAUP ),
02905      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02906 *
02907 *                    Multiply right bidiagonalizing vectors in A by Q
02908 *                    in VT
02909 *                    (Workspace: need 3*M+N, prefer 3*M+N*NB)
02910 *
02911                      CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
02912      $                            WORK( ITAUP ), VT, LDVT,
02913      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02914                      IWORK = IE + M
02915 *
02916 *                    Perform bidiagonal QR iteration, computing right
02917 *                    singular vectors of A in VT
02918 *                    (Workspace: need BDSPAC)
02919 *
02920                      CALL DBDSQR( 'U', M, N, 0, 0, S, WORK( IE ), VT,
02921      $                            LDVT, DUM, 1, DUM, 1, WORK( IWORK ),
02922      $                            INFO )
02923 *
02924                   END IF
02925 *
02926                ELSE IF( WNTUO ) THEN
02927 *
02928 *                 Path 8t(N much larger than M, JOBU='O', JOBVT='A')
02929 *                 N right singular vectors to be computed in VT and
02930 *                 M left singular vectors to be overwritten on A
02931 *
02932                   IF( LWORK.GE.2*M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN
02933 *
02934 *                    Sufficient workspace for a fast algorithm
02935 *
02936                      IU = 1
02937                      IF( LWORK.GE.WRKBL+2*LDA*M ) THEN
02938 *
02939 *                       WORK(IU) is LDA by M and WORK(IR) is LDA by M
02940 *
02941                         LDWRKU = LDA
02942                         IR = IU + LDWRKU*M
02943                         LDWRKR = LDA
02944                      ELSE IF( LWORK.GE.WRKBL+( LDA+M )*M ) THEN
02945 *
02946 *                       WORK(IU) is LDA by M and WORK(IR) is M by M
02947 *
02948                         LDWRKU = LDA
02949                         IR = IU + LDWRKU*M
02950                         LDWRKR = M
02951                      ELSE
02952 *
02953 *                       WORK(IU) is M by M and WORK(IR) is M by M
02954 *
02955                         LDWRKU = M
02956                         IR = IU + LDWRKU*M
02957                         LDWRKR = M
02958                      END IF
02959                      ITAU = IR + LDWRKR*M
02960                      IWORK = ITAU + M
02961 *
02962 *                    Compute A=L*Q, copying result to VT
02963 *                    (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB)
02964 *
02965                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
02966      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02967                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
02968 *
02969 *                    Generate Q in VT
02970 *                    (Workspace: need 2*M*M+M+N, prefer 2*M*M+M+N*NB)
02971 *
02972                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
02973      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
02974 *
02975 *                    Copy L to WORK(IU), zeroing out above it
02976 *
02977                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
02978      $                            LDWRKU )
02979                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
02980      $                            WORK( IU+LDWRKU ), LDWRKU )
02981                      IE = ITAU
02982                      ITAUQ = IE + M
02983                      ITAUP = ITAUQ + M
02984                      IWORK = ITAUP + M
02985 *
02986 *                    Bidiagonalize L in WORK(IU), copying result to
02987 *                    WORK(IR)
02988 *                    (Workspace: need 2*M*M+4*M,
02989 *                                prefer 2*M*M+3*M+2*M*NB)
02990 *
02991                      CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
02992      $                            WORK( IE ), WORK( ITAUQ ),
02993      $                            WORK( ITAUP ), WORK( IWORK ),
02994      $                            LWORK-IWORK+1, IERR )
02995                      CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU,
02996      $                            WORK( IR ), LDWRKR )
02997 *
02998 *                    Generate right bidiagonalizing vectors in WORK(IU)
02999 *                    (Workspace: need 2*M*M+4*M-1,
03000 *                                prefer 2*M*M+3*M+(M-1)*NB)
03001 *
03002                      CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
03003      $                            WORK( ITAUP ), WORK( IWORK ),
03004      $                            LWORK-IWORK+1, IERR )
03005 *
03006 *                    Generate left bidiagonalizing vectors in WORK(IR)
03007 *                    (Workspace: need 2*M*M+4*M, prefer 2*M*M+3*M+M*NB)
03008 *
03009                      CALL DORGBR( 'Q', M, M, M, WORK( IR ), LDWRKR,
03010      $                            WORK( ITAUQ ), WORK( IWORK ),
03011      $                            LWORK-IWORK+1, IERR )
03012                      IWORK = IE + M
03013 *
03014 *                    Perform bidiagonal QR iteration, computing left
03015 *                    singular vectors of L in WORK(IR) and computing
03016 *                    right singular vectors of L in WORK(IU)
03017 *                    (Workspace: need 2*M*M+BDSPAC)
03018 *
03019                      CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
03020      $                            WORK( IU ), LDWRKU, WORK( IR ),
03021      $                            LDWRKR, DUM, 1, WORK( IWORK ), INFO )
03022 *
03023 *                    Multiply right singular vectors of L in WORK(IU) by
03024 *                    Q in VT, storing result in A
03025 *                    (Workspace: need M*M)
03026 *
03027                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
03028      $                           LDWRKU, VT, LDVT, ZERO, A, LDA )
03029 *
03030 *                    Copy right singular vectors of A from A to VT
03031 *
03032                      CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
03033 *
03034 *                    Copy left singular vectors of A from WORK(IR) to A
03035 *
03036                      CALL DLACPY( 'F', M, M, WORK( IR ), LDWRKR, A,
03037      $                            LDA )
03038 *
03039                   ELSE
03040 *
03041 *                    Insufficient workspace for a fast algorithm
03042 *
03043                      ITAU = 1
03044                      IWORK = ITAU + M
03045 *
03046 *                    Compute A=L*Q, copying result to VT
03047 *                    (Workspace: need 2*M, prefer M+M*NB)
03048 *
03049                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
03050      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03051                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
03052 *
03053 *                    Generate Q in VT
03054 *                    (Workspace: need M+N, prefer M+N*NB)
03055 *
03056                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
03057      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03058                      IE = ITAU
03059                      ITAUQ = IE + M
03060                      ITAUP = ITAUQ + M
03061                      IWORK = ITAUP + M
03062 *
03063 *                    Zero out above L in A
03064 *
03065                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
03066      $                            LDA )
03067 *
03068 *                    Bidiagonalize L in A
03069 *                    (Workspace: need 4*M, prefer 3*M+2*M*NB)
03070 *
03071                      CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
03072      $                            WORK( ITAUQ ), WORK( ITAUP ),
03073      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03074 *
03075 *                    Multiply right bidiagonalizing vectors in A by Q
03076 *                    in VT
03077 *                    (Workspace: need 3*M+N, prefer 3*M+N*NB)
03078 *
03079                      CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
03080      $                            WORK( ITAUP ), VT, LDVT,
03081      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03082 *
03083 *                    Generate left bidiagonalizing vectors in A
03084 *                    (Workspace: need 4*M, prefer 3*M+M*NB)
03085 *
03086                      CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),
03087      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03088                      IWORK = IE + M
03089 *
03090 *                    Perform bidiagonal QR iteration, computing left
03091 *                    singular vectors of A in A and computing right
03092 *                    singular vectors of A in VT
03093 *                    (Workspace: need BDSPAC)
03094 *
03095                      CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
03096      $                            LDVT, A, LDA, DUM, 1, WORK( IWORK ),
03097      $                            INFO )
03098 *
03099                   END IF
03100 *
03101                ELSE IF( WNTUAS ) THEN
03102 *
03103 *                 Path 9t(N much larger than M, JOBU='S' or 'A',
03104 *                         JOBVT='A')
03105 *                 N right singular vectors to be computed in VT and
03106 *                 M left singular vectors to be computed in U
03107 *
03108                   IF( LWORK.GE.M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN
03109 *
03110 *                    Sufficient workspace for a fast algorithm
03111 *
03112                      IU = 1
03113                      IF( LWORK.GE.WRKBL+LDA*M ) THEN
03114 *
03115 *                       WORK(IU) is LDA by M
03116 *
03117                         LDWRKU = LDA
03118                      ELSE
03119 *
03120 *                       WORK(IU) is M by M
03121 *
03122                         LDWRKU = M
03123                      END IF
03124                      ITAU = IU + LDWRKU*M
03125                      IWORK = ITAU + M
03126 *
03127 *                    Compute A=L*Q, copying result to VT
03128 *                    (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
03129 *
03130                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
03131      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03132                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
03133 *
03134 *                    Generate Q in VT
03135 *                    (Workspace: need M*M+M+N, prefer M*M+M+N*NB)
03136 *
03137                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
03138      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03139 *
03140 *                    Copy L to WORK(IU), zeroing out above it
03141 *
03142                      CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
03143      $                            LDWRKU )
03144                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
03145      $                            WORK( IU+LDWRKU ), LDWRKU )
03146                      IE = ITAU
03147                      ITAUQ = IE + M
03148                      ITAUP = ITAUQ + M
03149                      IWORK = ITAUP + M
03150 *
03151 *                    Bidiagonalize L in WORK(IU), copying result to U
03152 *                    (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
03153 *
03154                      CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
03155      $                            WORK( IE ), WORK( ITAUQ ),
03156      $                            WORK( ITAUP ), WORK( IWORK ),
03157      $                            LWORK-IWORK+1, IERR )
03158                      CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, U,
03159      $                            LDU )
03160 *
03161 *                    Generate right bidiagonalizing vectors in WORK(IU)
03162 *                    (Workspace: need M*M+4*M, prefer M*M+3*M+(M-1)*NB)
03163 *
03164                      CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
03165      $                            WORK( ITAUP ), WORK( IWORK ),
03166      $                            LWORK-IWORK+1, IERR )
03167 *
03168 *                    Generate left bidiagonalizing vectors in U
03169 *                    (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB)
03170 *
03171                      CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
03172      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03173                      IWORK = IE + M
03174 *
03175 *                    Perform bidiagonal QR iteration, computing left
03176 *                    singular vectors of L in U and computing right
03177 *                    singular vectors of L in WORK(IU)
03178 *                    (Workspace: need M*M+BDSPAC)
03179 *
03180                      CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
03181      $                            WORK( IU ), LDWRKU, U, LDU, DUM, 1,
03182      $                            WORK( IWORK ), INFO )
03183 *
03184 *                    Multiply right singular vectors of L in WORK(IU) by
03185 *                    Q in VT, storing result in A
03186 *                    (Workspace: need M*M)
03187 *
03188                      CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
03189      $                           LDWRKU, VT, LDVT, ZERO, A, LDA )
03190 *
03191 *                    Copy right singular vectors of A from A to VT
03192 *
03193                      CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
03194 *
03195                   ELSE
03196 *
03197 *                    Insufficient workspace for a fast algorithm
03198 *
03199                      ITAU = 1
03200                      IWORK = ITAU + M
03201 *
03202 *                    Compute A=L*Q, copying result to VT
03203 *                    (Workspace: need 2*M, prefer M+M*NB)
03204 *
03205                      CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
03206      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03207                      CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
03208 *
03209 *                    Generate Q in VT
03210 *                    (Workspace: need M+N, prefer M+N*NB)
03211 *
03212                      CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
03213      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03214 *
03215 *                    Copy L to U, zeroing out above it
03216 *
03217                      CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
03218                      CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
03219      $                            LDU )
03220                      IE = ITAU
03221                      ITAUQ = IE + M
03222                      ITAUP = ITAUQ + M
03223                      IWORK = ITAUP + M
03224 *
03225 *                    Bidiagonalize L in U
03226 *                    (Workspace: need 4*M, prefer 3*M+2*M*NB)
03227 *
03228                      CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
03229      $                            WORK( ITAUQ ), WORK( ITAUP ),
03230      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03231 *
03232 *                    Multiply right bidiagonalizing vectors in U by Q
03233 *                    in VT
03234 *                    (Workspace: need 3*M+N, prefer 3*M+N*NB)
03235 *
03236                      CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,
03237      $                            WORK( ITAUP ), VT, LDVT,
03238      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03239 *
03240 *                    Generate left bidiagonalizing vectors in U
03241 *                    (Workspace: need 4*M, prefer 3*M+M*NB)
03242 *
03243                      CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
03244      $                            WORK( IWORK ), LWORK-IWORK+1, IERR )
03245                      IWORK = IE + M
03246 *
03247 *                    Perform bidiagonal QR iteration, computing left
03248 *                    singular vectors of A in U and computing right
03249 *                    singular vectors of A in VT
03250 *                    (Workspace: need BDSPAC)
03251 *
03252                      CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
03253      $                            LDVT, U, LDU, DUM, 1, WORK( IWORK ),
03254      $                            INFO )
03255 *
03256                   END IF
03257 *
03258                END IF
03259 *
03260             END IF
03261 *
03262          ELSE
03263 *
03264 *           N .LT. MNTHR
03265 *
03266 *           Path 10t(N greater than M, but not much larger)
03267 *           Reduce to bidiagonal form without LQ decomposition
03268 *
03269             IE = 1
03270             ITAUQ = IE + M
03271             ITAUP = ITAUQ + M
03272             IWORK = ITAUP + M
03273 *
03274 *           Bidiagonalize A
03275 *           (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
03276 *
03277             CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
03278      $                   WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
03279      $                   IERR )
03280             IF( WNTUAS ) THEN
03281 *
03282 *              If left singular vectors desired in U, copy result to U
03283 *              and generate left bidiagonalizing vectors in U
03284 *              (Workspace: need 4*M-1, prefer 3*M+(M-1)*NB)
03285 *
03286                CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
03287                CALL DORGBR( 'Q', M, M, N, U, LDU, WORK( ITAUQ ),
03288      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
03289             END IF
03290             IF( WNTVAS ) THEN
03291 *
03292 *              If right singular vectors desired in VT, copy result to
03293 *              VT and generate right bidiagonalizing vectors in VT
03294 *              (Workspace: need 3*M+NRVT, prefer 3*M+NRVT*NB)
03295 *
03296                CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
03297                IF( WNTVA )
03298      $            NRVT = N
03299                IF( WNTVS )
03300      $            NRVT = M
03301                CALL DORGBR( 'P', NRVT, N, M, VT, LDVT, WORK( ITAUP ),
03302      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
03303             END IF
03304             IF( WNTUO ) THEN
03305 *
03306 *              If left singular vectors desired in A, generate left
03307 *              bidiagonalizing vectors in A
03308 *              (Workspace: need 4*M-1, prefer 3*M+(M-1)*NB)
03309 *
03310                CALL DORGBR( 'Q', M, M, N, A, LDA, WORK( ITAUQ ),
03311      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
03312             END IF
03313             IF( WNTVO ) THEN
03314 *
03315 *              If right singular vectors desired in A, generate right
03316 *              bidiagonalizing vectors in A
03317 *              (Workspace: need 4*M, prefer 3*M+M*NB)
03318 *
03319                CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
03320      $                      WORK( IWORK ), LWORK-IWORK+1, IERR )
03321             END IF
03322             IWORK = IE + M
03323             IF( WNTUAS .OR. WNTUO )
03324      $         NRU = M
03325             IF( WNTUN )
03326      $         NRU = 0
03327             IF( WNTVAS .OR. WNTVO )
03328      $         NCVT = N
03329             IF( WNTVN )
03330      $         NCVT = 0
03331             IF( ( .NOT.WNTUO ) .AND. ( .NOT.WNTVO ) ) THEN
03332 *
03333 *              Perform bidiagonal QR iteration, if desired, computing
03334 *              left singular vectors in U and computing right singular
03335 *              vectors in VT
03336 *              (Workspace: need BDSPAC)
03337 *
03338                CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), VT,
03339      $                      LDVT, U, LDU, DUM, 1, WORK( IWORK ), INFO )
03340             ELSE IF( ( .NOT.WNTUO ) .AND. WNTVO ) THEN
03341 *
03342 *              Perform bidiagonal QR iteration, if desired, computing
03343 *              left singular vectors in U and computing right singular
03344 *              vectors in A
03345 *              (Workspace: need BDSPAC)
03346 *
03347                CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), A, LDA,
03348      $                      U, LDU, DUM, 1, WORK( IWORK ), INFO )
03349             ELSE
03350 *
03351 *              Perform bidiagonal QR iteration, if desired, computing
03352 *              left singular vectors in A and computing right singular
03353 *              vectors in VT
03354 *              (Workspace: need BDSPAC)
03355 *
03356                CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), VT,
03357      $                      LDVT, A, LDA, DUM, 1, WORK( IWORK ), INFO )
03358             END IF
03359 *
03360          END IF
03361 *
03362       END IF
03363 *
03364 *     If DBDSQR failed to converge, copy unconverged superdiagonals
03365 *     to WORK( 2:MINMN )
03366 *
03367       IF( INFO.NE.0 ) THEN
03368          IF( IE.GT.2 ) THEN
03369             DO 50 I = 1, MINMN - 1
03370                WORK( I+1 ) = WORK( I+IE-1 )
03371    50       CONTINUE
03372          END IF
03373          IF( IE.LT.2 ) THEN
03374             DO 60 I = MINMN - 1, 1, -1
03375                WORK( I+1 ) = WORK( I+IE-1 )
03376    60       CONTINUE
03377          END IF
03378       END IF
03379 *
03380 *     Undo scaling if necessary
03381 *
03382       IF( ISCL.EQ.1 ) THEN
03383          IF( ANRM.GT.BIGNUM )
03384      $      CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
03385      $                   IERR )
03386          IF( INFO.NE.0 .AND. ANRM.GT.BIGNUM )
03387      $      CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN-1, 1, WORK( 2 ),
03388      $                   MINMN, IERR )
03389          IF( ANRM.LT.SMLNUM )
03390      $      CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
03391      $                   IERR )
03392          IF( INFO.NE.0 .AND. ANRM.LT.SMLNUM )
03393      $      CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN-1, 1, WORK( 2 ),
03394      $                   MINMN, IERR )
03395       END IF
03396 *
03397 *     Return optimal workspace in WORK(1)
03398 *
03399       WORK( 1 ) = MAXWRK
03400 *
03401       RETURN
03402 *
03403 *     End of DGESVD
03404 *
03405       END
 All Files Functions