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