LAPACK 3.3.0

sgesdd.f

Go to the documentation of this file.
00001       SUBROUTINE SGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK,
00002      $                   LWORK, IWORK, INFO )
00003 *
00004 *  -- LAPACK driver routine (version 3.2.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 *     March 2009
00008 *
00009 *     .. Scalar Arguments ..
00010       CHARACTER          JOBZ
00011       INTEGER            INFO, LDA, LDU, LDVT, LWORK, M, N
00012 *     ..
00013 *     .. Array Arguments ..
00014       INTEGER            IWORK( * )
00015       REAL               A( LDA, * ), S( * ), U( LDU, * ),
00016      $                   VT( LDVT, * ), WORK( * )
00017 *     ..
00018 *
00019 *  Purpose
00020 *  =======
00021 *
00022 *  SGESDD computes the singular value decomposition (SVD) of a real
00023 *  M-by-N matrix A, optionally computing the left and right singular
00024 *  vectors.  If singular vectors are desired, it uses a
00025 *  divide-and-conquer algorithm.
00026 *
00027 *  The SVD is written
00028 *
00029 *       A = U * SIGMA * transpose(V)
00030 *
00031 *  where SIGMA is an M-by-N matrix which is zero except for its
00032 *  min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
00033 *  V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
00034 *  are the singular values of A; they are real and non-negative, and
00035 *  are returned in descending order.  The first min(m,n) columns of
00036 *  U and V are the left and right singular vectors of A.
00037 *
00038 *  Note that the routine returns VT = V**T, not V.
00039 *
00040 *  The divide and conquer algorithm makes very mild assumptions about
00041 *  floating point arithmetic. It will work on machines with a guard
00042 *  digit in add/subtract, or on those binary machines without guard
00043 *  digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
00044 *  Cray-2. It could conceivably fail on hexadecimal or decimal machines
00045 *  without guard digits, but we know of none.
00046 *
00047 *  Arguments
00048 *  =========
00049 *
00050 *  JOBZ    (input) CHARACTER*1
00051 *          Specifies options for computing all or part of the matrix U:
00052 *          = 'A':  all M columns of U and all N rows of V**T are
00053 *                  returned in the arrays U and VT;
00054 *          = 'S':  the first min(M,N) columns of U and the first
00055 *                  min(M,N) rows of V**T are returned in the arrays U
00056 *                  and VT;
00057 *          = 'O':  If M >= N, the first N columns of U are overwritten
00058 *                  on the array A and all rows of V**T are returned in
00059 *                  the array VT;
00060 *                  otherwise, all columns of U are returned in the
00061 *                  array U and the first M rows of V**T are overwritten
00062 *                  in the array A;
00063 *          = 'N':  no columns of U or rows of V**T are computed.
00064 *
00065 *  M       (input) INTEGER
00066 *          The number of rows of the input matrix A.  M >= 0.
00067 *
00068 *  N       (input) INTEGER
00069 *          The number of columns of the input matrix A.  N >= 0.
00070 *
00071 *  A       (input/output) REAL array, dimension (LDA,N)
00072 *          On entry, the M-by-N matrix A.
00073 *          On exit,
00074 *          if JOBZ = 'O',  A is overwritten with the first N columns
00075 *                          of U (the left singular vectors, stored
00076 *                          columnwise) if M >= N;
00077 *                          A is overwritten with the first M rows
00078 *                          of V**T (the right singular vectors, stored
00079 *                          rowwise) otherwise.
00080 *          if JOBZ .ne. 'O', the contents of A are destroyed.
00081 *
00082 *  LDA     (input) INTEGER
00083 *          The leading dimension of the array A.  LDA >= max(1,M).
00084 *
00085 *  S       (output) REAL array, dimension (min(M,N))
00086 *          The singular values of A, sorted so that S(i) >= S(i+1).
00087 *
00088 *  U       (output) REAL array, dimension (LDU,UCOL)
00089 *          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N;
00090 *          UCOL = min(M,N) if JOBZ = 'S'.
00091 *          If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M
00092 *          orthogonal matrix U;
00093 *          if JOBZ = 'S', U contains the first min(M,N) columns of U
00094 *          (the left singular vectors, stored columnwise);
00095 *          if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced.
00096 *
00097 *  LDU     (input) INTEGER
00098 *          The leading dimension of the array U.  LDU >= 1; if
00099 *          JOBZ = 'S' or 'A' or JOBZ = 'O' and M < N, LDU >= M.
00100 *
00101 *  VT      (output) REAL array, dimension (LDVT,N)
00102 *          If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the
00103 *          N-by-N orthogonal matrix V**T;
00104 *          if JOBZ = 'S', VT contains the first min(M,N) rows of
00105 *          V**T (the right singular vectors, stored rowwise);
00106 *          if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced.
00107 *
00108 *  LDVT    (input) INTEGER
00109 *          The leading dimension of the array VT.  LDVT >= 1; if
00110 *          JOBZ = 'A' or JOBZ = 'O' and M >= N, LDVT >= N;
00111 *          if JOBZ = 'S', LDVT >= min(M,N).
00112 *
00113 *  WORK    (workspace/output) REAL array, dimension (MAX(1,LWORK))
00114 *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
00115 *
00116 *  LWORK   (input) INTEGER
00117 *          The dimension of the array WORK. LWORK >= 1.
00118 *          If JOBZ = 'N',
00119 *            LWORK >= 3*min(M,N) + max(max(M,N),6*min(M,N)).
00120 *          If JOBZ = 'O',
00121 *            LWORK >= 3*min(M,N) + 
00122 *                     max(max(M,N),5*min(M,N)*min(M,N)+4*min(M,N)).
00123 *          If JOBZ = 'S' or 'A'
00124 *            LWORK >= 3*min(M,N) +
00125 *                     max(max(M,N),4*min(M,N)*min(M,N)+4*min(M,N)).
00126 *          For good performance, LWORK should generally be larger.
00127 *          If LWORK = -1 but other input arguments are legal, WORK(1)
00128 *          returns the optimal LWORK.
00129 *
00130 *  IWORK   (workspace) INTEGER array, dimension (8*min(M,N))
00131 *
00132 *  INFO    (output) INTEGER
00133 *          = 0:  successful exit.
00134 *          < 0:  if INFO = -i, the i-th argument had an illegal value.
00135 *          > 0:  SBDSDC did not converge, updating process failed.
00136 *
00137 *  Further Details
00138 *  ===============
00139 *
00140 *  Based on contributions by
00141 *     Ming Gu and Huan Ren, Computer Science Division, University of
00142 *     California at Berkeley, USA
00143 *
00144 *  =====================================================================
00145 *
00146 *     .. Parameters ..
00147       REAL               ZERO, ONE
00148       PARAMETER          ( ZERO = 0.0E0, ONE = 1.0E0 )
00149 *     ..
00150 *     .. Local Scalars ..
00151       LOGICAL            LQUERY, WNTQA, WNTQAS, WNTQN, WNTQO, WNTQS
00152       INTEGER            BDSPAC, BLK, CHUNK, I, IE, IERR, IL,
00153      $                   IR, ISCL, ITAU, ITAUP, ITAUQ, IU, IVT, LDWKVT,
00154      $                   LDWRKL, LDWRKR, LDWRKU, MAXWRK, MINMN, MINWRK,
00155      $                   MNTHR, NWORK, WRKBL
00156       REAL               ANRM, BIGNUM, EPS, SMLNUM
00157 *     ..
00158 *     .. Local Arrays ..
00159       INTEGER            IDUM( 1 )
00160       REAL               DUM( 1 )
00161 *     ..
00162 *     .. External Subroutines ..
00163       EXTERNAL           SBDSDC, SGEBRD, SGELQF, SGEMM, SGEQRF, SLACPY,
00164      $                   SLASCL, SLASET, SORGBR, SORGLQ, SORGQR, SORMBR,
00165      $                   XERBLA
00166 *     ..
00167 *     .. External Functions ..
00168       LOGICAL            LSAME
00169       INTEGER            ILAENV
00170       REAL               SLAMCH, SLANGE
00171       EXTERNAL           ILAENV, LSAME, SLAMCH, SLANGE
00172 *     ..
00173 *     .. Intrinsic Functions ..
00174       INTRINSIC          INT, MAX, MIN, SQRT
00175 *     ..
00176 *     .. Executable Statements ..
00177 *
00178 *     Test the input arguments
00179 *
00180       INFO = 0
00181       MINMN = MIN( M, N )
00182       WNTQA = LSAME( JOBZ, 'A' )
00183       WNTQS = LSAME( JOBZ, 'S' )
00184       WNTQAS = WNTQA .OR. WNTQS
00185       WNTQO = LSAME( JOBZ, 'O' )
00186       WNTQN = LSAME( JOBZ, 'N' )
00187       LQUERY = ( LWORK.EQ.-1 )
00188 *
00189       IF( .NOT.( WNTQA .OR. WNTQS .OR. WNTQO .OR. WNTQN ) ) THEN
00190          INFO = -1
00191       ELSE IF( M.LT.0 ) THEN
00192          INFO = -2
00193       ELSE IF( N.LT.0 ) THEN
00194          INFO = -3
00195       ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
00196          INFO = -5
00197       ELSE IF( LDU.LT.1 .OR. ( WNTQAS .AND. LDU.LT.M ) .OR.
00198      $         ( WNTQO .AND. M.LT.N .AND. LDU.LT.M ) ) THEN
00199          INFO = -8
00200       ELSE IF( LDVT.LT.1 .OR. ( WNTQA .AND. LDVT.LT.N ) .OR.
00201      $         ( WNTQS .AND. LDVT.LT.MINMN ) .OR.
00202      $         ( WNTQO .AND. M.GE.N .AND. LDVT.LT.N ) ) THEN
00203          INFO = -10
00204       END IF
00205 *
00206 *     Compute workspace
00207 *      (Note: Comments in the code beginning "Workspace:" describe the
00208 *       minimal amount of workspace needed at that point in the code,
00209 *       as well as the preferred amount for good performance.
00210 *       NB refers to the optimal block size for the immediately
00211 *       following subroutine, as returned by ILAENV.)
00212 *
00213       IF( INFO.EQ.0 ) THEN
00214          MINWRK = 1
00215          MAXWRK = 1
00216          IF( M.GE.N .AND. MINMN.GT.0 ) THEN
00217 *
00218 *           Compute space needed for SBDSDC
00219 *
00220             MNTHR = INT( MINMN*11.0E0 / 6.0E0 )
00221             IF( WNTQN ) THEN
00222                BDSPAC = 7*N
00223             ELSE
00224                BDSPAC = 3*N*N + 4*N
00225             END IF
00226             IF( M.GE.MNTHR ) THEN
00227                IF( WNTQN ) THEN
00228 *
00229 *                 Path 1 (M much larger than N, JOBZ='N')
00230 *
00231                   WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1,
00232      $                    -1 )
00233                   WRKBL = MAX( WRKBL, 3*N+2*N*
00234      $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
00235                   MAXWRK = MAX( WRKBL, BDSPAC+N )
00236                   MINWRK = BDSPAC + N
00237                ELSE IF( WNTQO ) THEN
00238 *
00239 *                 Path 2 (M much larger than N, JOBZ='O')
00240 *
00241                   WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
00242                   WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'SORGQR', ' ', M,
00243      $                    N, N, -1 ) )
00244                   WRKBL = MAX( WRKBL, 3*N+2*N*
00245      $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
00246                   WRKBL = MAX( WRKBL, 3*N+N*
00247      $                    ILAENV( 1, 'SORMBR', 'QLN', N, N, N, -1 ) )
00248                   WRKBL = MAX( WRKBL, 3*N+N*
00249      $                    ILAENV( 1, 'SORMBR', 'PRT', N, N, N, -1 ) )
00250                   WRKBL = MAX( WRKBL, BDSPAC+3*N )
00251                   MAXWRK = WRKBL + 2*N*N
00252                   MINWRK = BDSPAC + 2*N*N + 3*N
00253                ELSE IF( WNTQS ) THEN
00254 *
00255 *                 Path 3 (M much larger than N, JOBZ='S')
00256 *
00257                   WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
00258                   WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'SORGQR', ' ', M,
00259      $                    N, N, -1 ) )
00260                   WRKBL = MAX( WRKBL, 3*N+2*N*
00261      $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
00262                   WRKBL = MAX( WRKBL, 3*N+N*
00263      $                    ILAENV( 1, 'SORMBR', 'QLN', N, N, N, -1 ) )
00264                   WRKBL = MAX( WRKBL, 3*N+N*
00265      $                    ILAENV( 1, 'SORMBR', 'PRT', N, N, N, -1 ) )
00266                   WRKBL = MAX( WRKBL, BDSPAC+3*N )
00267                   MAXWRK = WRKBL + N*N
00268                   MINWRK = BDSPAC + N*N + 3*N
00269                ELSE IF( WNTQA ) THEN
00270 *
00271 *                 Path 4 (M much larger than N, JOBZ='A')
00272 *
00273                   WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
00274                   WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'SORGQR', ' ', M,
00275      $                    M, N, -1 ) )
00276                   WRKBL = MAX( WRKBL, 3*N+2*N*
00277      $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
00278                   WRKBL = MAX( WRKBL, 3*N+N*
00279      $                    ILAENV( 1, 'SORMBR', 'QLN', N, N, N, -1 ) )
00280                   WRKBL = MAX( WRKBL, 3*N+N*
00281      $                    ILAENV( 1, 'SORMBR', 'PRT', N, N, N, -1 ) )
00282                   WRKBL = MAX( WRKBL, BDSPAC+3*N )
00283                   MAXWRK = WRKBL + N*N
00284                   MINWRK = BDSPAC + N*N + 3*N
00285                END IF
00286             ELSE
00287 *
00288 *              Path 5 (M at least N, but not much larger)
00289 *
00290                WRKBL = 3*N + ( M+N )*ILAENV( 1, 'SGEBRD', ' ', M, N, -1,
00291      $                 -1 )
00292                IF( WNTQN ) THEN
00293                   MAXWRK = MAX( WRKBL, BDSPAC+3*N )
00294                   MINWRK = 3*N + MAX( M, BDSPAC )
00295                ELSE IF( WNTQO ) THEN
00296                   WRKBL = MAX( WRKBL, 3*N+N*
00297      $                    ILAENV( 1, 'SORMBR', 'QLN', M, N, N, -1 ) )
00298                   WRKBL = MAX( WRKBL, 3*N+N*
00299      $                    ILAENV( 1, 'SORMBR', 'PRT', N, N, N, -1 ) )
00300                   WRKBL = MAX( WRKBL, BDSPAC+3*N )
00301                   MAXWRK = WRKBL + M*N
00302                   MINWRK = 3*N + MAX( M, N*N+BDSPAC )
00303                ELSE IF( WNTQS ) THEN
00304                   WRKBL = MAX( WRKBL, 3*N+N*
00305      $                    ILAENV( 1, 'SORMBR', 'QLN', M, N, N, -1 ) )
00306                   WRKBL = MAX( WRKBL, 3*N+N*
00307      $                    ILAENV( 1, 'SORMBR', 'PRT', N, N, N, -1 ) )
00308                   MAXWRK = MAX( WRKBL, BDSPAC+3*N )
00309                   MINWRK = 3*N + MAX( M, BDSPAC )
00310                ELSE IF( WNTQA ) THEN
00311                   WRKBL = MAX( WRKBL, 3*N+M*
00312      $                    ILAENV( 1, 'SORMBR', 'QLN', M, M, N, -1 ) )
00313                   WRKBL = MAX( WRKBL, 3*N+N*
00314      $                    ILAENV( 1, 'SORMBR', 'PRT', N, N, N, -1 ) )
00315                   MAXWRK = MAX( MAXWRK, BDSPAC+3*N )
00316                   MINWRK = 3*N + MAX( M, BDSPAC )
00317                END IF
00318             END IF
00319          ELSE IF ( MINMN.GT.0 ) THEN
00320 *
00321 *           Compute space needed for SBDSDC
00322 *
00323             MNTHR = INT( MINMN*11.0E0 / 6.0E0 )
00324             IF( WNTQN ) THEN
00325                BDSPAC = 7*M
00326             ELSE
00327                BDSPAC = 3*M*M + 4*M
00328             END IF
00329             IF( N.GE.MNTHR ) THEN
00330                IF( WNTQN ) THEN
00331 *
00332 *                 Path 1t (N much larger than M, JOBZ='N')
00333 *
00334                   WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1,
00335      $                    -1 )
00336                   WRKBL = MAX( WRKBL, 3*M+2*M*
00337      $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
00338                   MAXWRK = MAX( WRKBL, BDSPAC+M )
00339                   MINWRK = BDSPAC + M
00340                ELSE IF( WNTQO ) THEN
00341 *
00342 *                 Path 2t (N much larger than M, JOBZ='O')
00343 *
00344                   WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
00345                   WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'SORGLQ', ' ', M,
00346      $                    N, M, -1 ) )
00347                   WRKBL = MAX( WRKBL, 3*M+2*M*
00348      $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
00349                   WRKBL = MAX( WRKBL, 3*M+M*
00350      $                    ILAENV( 1, 'SORMBR', 'QLN', M, M, M, -1 ) )
00351                   WRKBL = MAX( WRKBL, 3*M+M*
00352      $                    ILAENV( 1, 'SORMBR', 'PRT', M, M, M, -1 ) )
00353                   WRKBL = MAX( WRKBL, BDSPAC+3*M )
00354                   MAXWRK = WRKBL + 2*M*M
00355                   MINWRK = BDSPAC + 2*M*M + 3*M
00356                ELSE IF( WNTQS ) THEN
00357 *
00358 *                 Path 3t (N much larger than M, JOBZ='S')
00359 *
00360                   WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
00361                   WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'SORGLQ', ' ', M,
00362      $                    N, M, -1 ) )
00363                   WRKBL = MAX( WRKBL, 3*M+2*M*
00364      $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
00365                   WRKBL = MAX( WRKBL, 3*M+M*
00366      $                    ILAENV( 1, 'SORMBR', 'QLN', M, M, M, -1 ) )
00367                   WRKBL = MAX( WRKBL, 3*M+M*
00368      $                    ILAENV( 1, 'SORMBR', 'PRT', M, M, M, -1 ) )
00369                   WRKBL = MAX( WRKBL, BDSPAC+3*M )
00370                   MAXWRK = WRKBL + M*M
00371                   MINWRK = BDSPAC + M*M + 3*M
00372                ELSE IF( WNTQA ) THEN
00373 *
00374 *                 Path 4t (N much larger than M, JOBZ='A')
00375 *
00376                   WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
00377                   WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'SORGLQ', ' ', N,
00378      $                    N, M, -1 ) )
00379                   WRKBL = MAX( WRKBL, 3*M+2*M*
00380      $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
00381                   WRKBL = MAX( WRKBL, 3*M+M*
00382      $                    ILAENV( 1, 'SORMBR', 'QLN', M, M, M, -1 ) )
00383                   WRKBL = MAX( WRKBL, 3*M+M*
00384      $                    ILAENV( 1, 'SORMBR', 'PRT', M, M, M, -1 ) )
00385                   WRKBL = MAX( WRKBL, BDSPAC+3*M )
00386                   MAXWRK = WRKBL + M*M
00387                   MINWRK = BDSPAC + M*M + 3*M
00388                END IF
00389             ELSE
00390 *
00391 *              Path 5t (N greater than M, but not much larger)
00392 *
00393                WRKBL = 3*M + ( M+N )*ILAENV( 1, 'SGEBRD', ' ', M, N, -1,
00394      $                 -1 )
00395                IF( WNTQN ) THEN
00396                   MAXWRK = MAX( WRKBL, BDSPAC+3*M )
00397                   MINWRK = 3*M + MAX( N, BDSPAC )
00398                ELSE IF( WNTQO ) THEN
00399                   WRKBL = MAX( WRKBL, 3*M+M*
00400      $                    ILAENV( 1, 'SORMBR', 'QLN', M, M, N, -1 ) )
00401                   WRKBL = MAX( WRKBL, 3*M+M*
00402      $                    ILAENV( 1, 'SORMBR', 'PRT', M, N, M, -1 ) )
00403                   WRKBL = MAX( WRKBL, BDSPAC+3*M )
00404                   MAXWRK = WRKBL + M*N
00405                   MINWRK = 3*M + MAX( N, M*M+BDSPAC )
00406                ELSE IF( WNTQS ) THEN
00407                   WRKBL = MAX( WRKBL, 3*M+M*
00408      $                    ILAENV( 1, 'SORMBR', 'QLN', M, M, N, -1 ) )
00409                   WRKBL = MAX( WRKBL, 3*M+M*
00410      $                    ILAENV( 1, 'SORMBR', 'PRT', M, N, M, -1 ) )
00411                   MAXWRK = MAX( WRKBL, BDSPAC+3*M )
00412                   MINWRK = 3*M + MAX( N, BDSPAC )
00413                ELSE IF( WNTQA ) THEN
00414                   WRKBL = MAX( WRKBL, 3*M+M*
00415      $                    ILAENV( 1, 'SORMBR', 'QLN', M, M, N, -1 ) )
00416                   WRKBL = MAX( WRKBL, 3*M+M*
00417      $                    ILAENV( 1, 'SORMBR', 'PRT', N, N, M, -1 ) )
00418                   MAXWRK = MAX( WRKBL, BDSPAC+3*M )
00419                   MINWRK = 3*M + MAX( N, BDSPAC )
00420                END IF
00421             END IF
00422          END IF
00423          MAXWRK = MAX( MAXWRK, MINWRK )
00424          WORK( 1 ) = MAXWRK
00425 *
00426          IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
00427             INFO = -12
00428          END IF
00429       END IF
00430 *
00431       IF( INFO.NE.0 ) THEN
00432          CALL XERBLA( 'SGESDD', -INFO )
00433          RETURN
00434       ELSE IF( LQUERY ) THEN
00435          RETURN
00436       END IF
00437 *
00438 *     Quick return if possible
00439 *
00440       IF( M.EQ.0 .OR. N.EQ.0 ) THEN
00441          RETURN
00442       END IF
00443 *
00444 *     Get machine constants
00445 *
00446       EPS = SLAMCH( 'P' )
00447       SMLNUM = SQRT( SLAMCH( 'S' ) ) / EPS
00448       BIGNUM = ONE / SMLNUM
00449 *
00450 *     Scale A if max element outside range [SMLNUM,BIGNUM]
00451 *
00452       ANRM = SLANGE( 'M', M, N, A, LDA, DUM )
00453       ISCL = 0
00454       IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00455          ISCL = 1
00456          CALL SLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, IERR )
00457       ELSE IF( ANRM.GT.BIGNUM ) THEN
00458          ISCL = 1
00459          CALL SLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, IERR )
00460       END IF
00461 *
00462       IF( M.GE.N ) THEN
00463 *
00464 *        A has at least as many rows as columns. If A has sufficiently
00465 *        more rows than columns, first reduce using the QR
00466 *        decomposition (if sufficient workspace available)
00467 *
00468          IF( M.GE.MNTHR ) THEN
00469 *
00470             IF( WNTQN ) THEN
00471 *
00472 *              Path 1 (M much larger than N, JOBZ='N')
00473 *              No singular vectors to be computed
00474 *
00475                ITAU = 1
00476                NWORK = ITAU + N
00477 *
00478 *              Compute A=Q*R
00479 *              (Workspace: need 2*N, prefer N+N*NB)
00480 *
00481                CALL SGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
00482      $                      LWORK-NWORK+1, IERR )
00483 *
00484 *              Zero out below R
00485 *
00486                CALL SLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
00487                IE = 1
00488                ITAUQ = IE + N
00489                ITAUP = ITAUQ + N
00490                NWORK = ITAUP + N
00491 *
00492 *              Bidiagonalize R in A
00493 *              (Workspace: need 4*N, prefer 3*N+2*N*NB)
00494 *
00495                CALL SGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
00496      $                      WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
00497      $                      IERR )
00498                NWORK = IE + N
00499 *
00500 *              Perform bidiagonal SVD, computing singular values only
00501 *              (Workspace: need N+BDSPAC)
00502 *
00503                CALL SBDSDC( 'U', 'N', N, S, WORK( IE ), DUM, 1, DUM, 1,
00504      $                      DUM, IDUM, WORK( NWORK ), IWORK, INFO )
00505 *
00506             ELSE IF( WNTQO ) THEN
00507 *
00508 *              Path 2 (M much larger than N, JOBZ = 'O')
00509 *              N left singular vectors to be overwritten on A and
00510 *              N right singular vectors to be computed in VT
00511 *
00512                IR = 1
00513 *
00514 *              WORK(IR) is LDWRKR by N
00515 *
00516                IF( LWORK.GE.LDA*N+N*N+3*N+BDSPAC ) THEN
00517                   LDWRKR = LDA
00518                ELSE
00519                   LDWRKR = ( LWORK-N*N-3*N-BDSPAC ) / N
00520                END IF
00521                ITAU = IR + LDWRKR*N
00522                NWORK = ITAU + N
00523 *
00524 *              Compute A=Q*R
00525 *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00526 *
00527                CALL SGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
00528      $                      LWORK-NWORK+1, IERR )
00529 *
00530 *              Copy R to WORK(IR), zeroing out below it
00531 *
00532                CALL SLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )
00533                CALL SLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),
00534      $                      LDWRKR )
00535 *
00536 *              Generate Q in A
00537 *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00538 *
00539                CALL SORGQR( M, N, N, A, LDA, WORK( ITAU ),
00540      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
00541                IE = ITAU
00542                ITAUQ = IE + N
00543                ITAUP = ITAUQ + N
00544                NWORK = ITAUP + N
00545 *
00546 *              Bidiagonalize R in VT, copying result to WORK(IR)
00547 *              (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
00548 *
00549                CALL SGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),
00550      $                      WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
00551      $                      LWORK-NWORK+1, IERR )
00552 *
00553 *              WORK(IU) is N by N
00554 *
00555                IU = NWORK
00556                NWORK = IU + N*N
00557 *
00558 *              Perform bidiagonal SVD, computing left singular vectors
00559 *              of bidiagonal matrix in WORK(IU) and computing right
00560 *              singular vectors of bidiagonal matrix in VT
00561 *              (Workspace: need N+N*N+BDSPAC)
00562 *
00563                CALL SBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ), N,
00564      $                      VT, LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
00565      $                      INFO )
00566 *
00567 *              Overwrite WORK(IU) by left singular vectors of R
00568 *              and VT by right singular vectors of R
00569 *              (Workspace: need 2*N*N+3*N, prefer 2*N*N+2*N+N*NB)
00570 *
00571                CALL SORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR,
00572      $                      WORK( ITAUQ ), WORK( IU ), N, WORK( NWORK ),
00573      $                      LWORK-NWORK+1, IERR )
00574                CALL SORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR,
00575      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
00576      $                      LWORK-NWORK+1, IERR )
00577 *
00578 *              Multiply Q in A by left singular vectors of R in
00579 *              WORK(IU), storing result in WORK(IR) and copying to A
00580 *              (Workspace: need 2*N*N, prefer N*N+M*N)
00581 *
00582                DO 10 I = 1, M, LDWRKR
00583                   CHUNK = MIN( M-I+1, LDWRKR )
00584                   CALL SGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
00585      $                        LDA, WORK( IU ), N, ZERO, WORK( IR ),
00586      $                        LDWRKR )
00587                   CALL SLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR,
00588      $                         A( I, 1 ), LDA )
00589    10          CONTINUE
00590 *
00591             ELSE IF( WNTQS ) THEN
00592 *
00593 *              Path 3 (M much larger than N, JOBZ='S')
00594 *              N left singular vectors to be computed in U and
00595 *              N right singular vectors to be computed in VT
00596 *
00597                IR = 1
00598 *
00599 *              WORK(IR) is N by N
00600 *
00601                LDWRKR = N
00602                ITAU = IR + LDWRKR*N
00603                NWORK = ITAU + N
00604 *
00605 *              Compute A=Q*R
00606 *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00607 *
00608                CALL SGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
00609      $                      LWORK-NWORK+1, IERR )
00610 *
00611 *              Copy R to WORK(IR), zeroing out below it
00612 *
00613                CALL SLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )
00614                CALL SLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),
00615      $                      LDWRKR )
00616 *
00617 *              Generate Q in A
00618 *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00619 *
00620                CALL SORGQR( M, N, N, A, LDA, WORK( ITAU ),
00621      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
00622                IE = ITAU
00623                ITAUQ = IE + N
00624                ITAUP = ITAUQ + N
00625                NWORK = ITAUP + N
00626 *
00627 *              Bidiagonalize R in WORK(IR)
00628 *              (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
00629 *
00630                CALL SGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),
00631      $                      WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
00632      $                      LWORK-NWORK+1, IERR )
00633 *
00634 *              Perform bidiagonal SVD, computing left singular vectors
00635 *              of bidiagoal matrix in U and computing right singular
00636 *              vectors of bidiagonal matrix in VT
00637 *              (Workspace: need N+BDSPAC)
00638 *
00639                CALL SBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
00640      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
00641      $                      INFO )
00642 *
00643 *              Overwrite U by left singular vectors of R and VT
00644 *              by right singular vectors of R
00645 *              (Workspace: need N*N+3*N, prefer N*N+2*N+N*NB)
00646 *
00647                CALL SORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR,
00648      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
00649      $                      LWORK-NWORK+1, IERR )
00650 *
00651                CALL SORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR,
00652      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
00653      $                      LWORK-NWORK+1, IERR )
00654 *
00655 *              Multiply Q in A by left singular vectors of R in
00656 *              WORK(IR), storing result in U
00657 *              (Workspace: need N*N)
00658 *
00659                CALL SLACPY( 'F', N, N, U, LDU, WORK( IR ), LDWRKR )
00660                CALL SGEMM( 'N', 'N', M, N, N, ONE, A, LDA, WORK( IR ),
00661      $                     LDWRKR, ZERO, U, LDU )
00662 *
00663             ELSE IF( WNTQA ) THEN
00664 *
00665 *              Path 4 (M much larger than N, JOBZ='A')
00666 *              M left singular vectors to be computed in U and
00667 *              N right singular vectors to be computed in VT
00668 *
00669                IU = 1
00670 *
00671 *              WORK(IU) is N by N
00672 *
00673                LDWRKU = N
00674                ITAU = IU + LDWRKU*N
00675                NWORK = ITAU + N
00676 *
00677 *              Compute A=Q*R, copying result to U
00678 *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00679 *
00680                CALL SGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
00681      $                      LWORK-NWORK+1, IERR )
00682                CALL SLACPY( 'L', M, N, A, LDA, U, LDU )
00683 *
00684 *              Generate Q in U
00685 *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00686                CALL SORGQR( M, M, N, U, LDU, WORK( ITAU ),
00687      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
00688 *
00689 *              Produce R in A, zeroing out other entries
00690 *
00691                CALL SLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
00692                IE = ITAU
00693                ITAUQ = IE + N
00694                ITAUP = ITAUQ + N
00695                NWORK = ITAUP + N
00696 *
00697 *              Bidiagonalize R in A
00698 *              (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
00699 *
00700                CALL SGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
00701      $                      WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
00702      $                      IERR )
00703 *
00704 *              Perform bidiagonal SVD, computing left singular vectors
00705 *              of bidiagonal matrix in WORK(IU) and computing right
00706 *              singular vectors of bidiagonal matrix in VT
00707 *              (Workspace: need N+N*N+BDSPAC)
00708 *
00709                CALL SBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ), N,
00710      $                      VT, LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
00711      $                      INFO )
00712 *
00713 *              Overwrite WORK(IU) by left singular vectors of R and VT
00714 *              by right singular vectors of R
00715 *              (Workspace: need N*N+3*N, prefer N*N+2*N+N*NB)
00716 *
00717                CALL SORMBR( 'Q', 'L', 'N', N, N, N, A, LDA,
00718      $                      WORK( ITAUQ ), WORK( IU ), LDWRKU,
00719      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
00720                CALL SORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
00721      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
00722      $                      LWORK-NWORK+1, IERR )
00723 *
00724 *              Multiply Q in U by left singular vectors of R in
00725 *              WORK(IU), storing result in A
00726 *              (Workspace: need N*N)
00727 *
00728                CALL SGEMM( 'N', 'N', M, N, N, ONE, U, LDU, WORK( IU ),
00729      $                     LDWRKU, ZERO, A, LDA )
00730 *
00731 *              Copy left singular vectors of A from A to U
00732 *
00733                CALL SLACPY( 'F', M, N, A, LDA, U, LDU )
00734 *
00735             END IF
00736 *
00737          ELSE
00738 *
00739 *           M .LT. MNTHR
00740 *
00741 *           Path 5 (M at least N, but not much larger)
00742 *           Reduce to bidiagonal form without QR decomposition
00743 *
00744             IE = 1
00745             ITAUQ = IE + N
00746             ITAUP = ITAUQ + N
00747             NWORK = ITAUP + N
00748 *
00749 *           Bidiagonalize A
00750 *           (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)
00751 *
00752             CALL SGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
00753      $                   WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
00754      $                   IERR )
00755             IF( WNTQN ) THEN
00756 *
00757 *              Perform bidiagonal SVD, only computing singular values
00758 *              (Workspace: need N+BDSPAC)
00759 *
00760                CALL SBDSDC( 'U', 'N', N, S, WORK( IE ), DUM, 1, DUM, 1,
00761      $                      DUM, IDUM, WORK( NWORK ), IWORK, INFO )
00762             ELSE IF( WNTQO ) THEN
00763                IU = NWORK
00764                IF( LWORK.GE.M*N+3*N+BDSPAC ) THEN
00765 *
00766 *                 WORK( IU ) is M by N
00767 *
00768                   LDWRKU = M
00769                   NWORK = IU + LDWRKU*N
00770                   CALL SLASET( 'F', M, N, ZERO, ZERO, WORK( IU ),
00771      $                         LDWRKU )
00772                ELSE
00773 *
00774 *                 WORK( IU ) is N by N
00775 *
00776                   LDWRKU = N
00777                   NWORK = IU + LDWRKU*N
00778 *
00779 *                 WORK(IR) is LDWRKR by N
00780 *
00781                   IR = NWORK
00782                   LDWRKR = ( LWORK-N*N-3*N ) / N
00783                END IF
00784                NWORK = IU + LDWRKU*N
00785 *
00786 *              Perform bidiagonal SVD, computing left singular vectors
00787 *              of bidiagonal matrix in WORK(IU) and computing right
00788 *              singular vectors of bidiagonal matrix in VT
00789 *              (Workspace: need N+N*N+BDSPAC)
00790 *
00791                CALL SBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ),
00792      $                      LDWRKU, VT, LDVT, DUM, IDUM, WORK( NWORK ),
00793      $                      IWORK, INFO )
00794 *
00795 *              Overwrite VT by right singular vectors of A
00796 *              (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00797 *
00798                CALL SORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
00799      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
00800      $                      LWORK-NWORK+1, IERR )
00801 *
00802                IF( LWORK.GE.M*N+3*N+BDSPAC ) THEN
00803 *
00804 *                 Overwrite WORK(IU) by left singular vectors of A
00805 *                 (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00806 *
00807                   CALL SORMBR( 'Q', 'L', 'N', M, N, N, A, LDA,
00808      $                         WORK( ITAUQ ), WORK( IU ), LDWRKU,
00809      $                         WORK( NWORK ), LWORK-NWORK+1, IERR )
00810 *
00811 *                 Copy left singular vectors of A from WORK(IU) to A
00812 *
00813                   CALL SLACPY( 'F', M, N, WORK( IU ), LDWRKU, A, LDA )
00814                ELSE
00815 *
00816 *                 Generate Q in A
00817 *                 (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
00818 *
00819                   CALL SORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),
00820      $                         WORK( NWORK ), LWORK-NWORK+1, IERR )
00821 *
00822 *                 Multiply Q in A by left singular vectors of
00823 *                 bidiagonal matrix in WORK(IU), storing result in
00824 *                 WORK(IR) and copying to A
00825 *                 (Workspace: need 2*N*N, prefer N*N+M*N)
00826 *
00827                   DO 20 I = 1, M, LDWRKR
00828                      CHUNK = MIN( M-I+1, LDWRKR )
00829                      CALL SGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
00830      $                           LDA, WORK( IU ), LDWRKU, ZERO,
00831      $                           WORK( IR ), LDWRKR )
00832                      CALL SLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR,
00833      $                            A( I, 1 ), LDA )
00834    20             CONTINUE
00835                END IF
00836 *
00837             ELSE IF( WNTQS ) THEN
00838 *
00839 *              Perform bidiagonal SVD, computing left singular vectors
00840 *              of bidiagonal matrix in U and computing right singular
00841 *              vectors of bidiagonal matrix in VT
00842 *              (Workspace: need N+BDSPAC)
00843 *
00844                CALL SLASET( 'F', M, N, ZERO, ZERO, U, LDU )
00845                CALL SBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
00846      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
00847      $                      INFO )
00848 *
00849 *              Overwrite U by left singular vectors of A and VT
00850 *              by right singular vectors of A
00851 *              (Workspace: need 3*N, prefer 2*N+N*NB)
00852 *
00853                CALL SORMBR( 'Q', 'L', 'N', M, N, N, A, LDA,
00854      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
00855      $                      LWORK-NWORK+1, IERR )
00856                CALL SORMBR( 'P', 'R', 'T', N, N, N, A, LDA,
00857      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
00858      $                      LWORK-NWORK+1, IERR )
00859             ELSE IF( WNTQA ) THEN
00860 *
00861 *              Perform bidiagonal SVD, computing left singular vectors
00862 *              of bidiagonal matrix in U and computing right singular
00863 *              vectors of bidiagonal matrix in VT
00864 *              (Workspace: need N+BDSPAC)
00865 *
00866                CALL SLASET( 'F', M, M, ZERO, ZERO, U, LDU )
00867                CALL SBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,
00868      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
00869      $                      INFO )
00870 *
00871 *              Set the right corner of U to identity matrix
00872 *
00873                IF( M.GT.N ) THEN
00874                   CALL SLASET( 'F', M-N, M-N, ZERO, ONE, U( N+1, N+1 ),
00875      $                         LDU )
00876                END IF
00877 *
00878 *              Overwrite U by left singular vectors of A and VT
00879 *              by right singular vectors of A
00880 *              (Workspace: need N*N+2*N+M, prefer N*N+2*N+M*NB)
00881 *
00882                CALL SORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
00883      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
00884      $                      LWORK-NWORK+1, IERR )
00885                CALL SORMBR( 'P', 'R', 'T', N, N, M, A, LDA,
00886      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
00887      $                      LWORK-NWORK+1, IERR )
00888             END IF
00889 *
00890          END IF
00891 *
00892       ELSE
00893 *
00894 *        A has more columns than rows. If A has sufficiently more
00895 *        columns than rows, first reduce using the LQ decomposition (if
00896 *        sufficient workspace available)
00897 *
00898          IF( N.GE.MNTHR ) THEN
00899 *
00900             IF( WNTQN ) THEN
00901 *
00902 *              Path 1t (N much larger than M, JOBZ='N')
00903 *              No singular vectors to be computed
00904 *
00905                ITAU = 1
00906                NWORK = ITAU + M
00907 *
00908 *              Compute A=L*Q
00909 *              (Workspace: need 2*M, prefer M+M*NB)
00910 *
00911                CALL SGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
00912      $                      LWORK-NWORK+1, IERR )
00913 *
00914 *              Zero out above L
00915 *
00916                CALL SLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )
00917                IE = 1
00918                ITAUQ = IE + M
00919                ITAUP = ITAUQ + M
00920                NWORK = ITAUP + M
00921 *
00922 *              Bidiagonalize L in A
00923 *              (Workspace: need 4*M, prefer 3*M+2*M*NB)
00924 *
00925                CALL SGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
00926      $                      WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
00927      $                      IERR )
00928                NWORK = IE + M
00929 *
00930 *              Perform bidiagonal SVD, computing singular values only
00931 *              (Workspace: need M+BDSPAC)
00932 *
00933                CALL SBDSDC( 'U', 'N', M, S, WORK( IE ), DUM, 1, DUM, 1,
00934      $                      DUM, IDUM, WORK( NWORK ), IWORK, INFO )
00935 *
00936             ELSE IF( WNTQO ) THEN
00937 *
00938 *              Path 2t (N much larger than M, JOBZ='O')
00939 *              M right singular vectors to be overwritten on A and
00940 *              M left singular vectors to be computed in U
00941 *
00942                IVT = 1
00943 *
00944 *              IVT is M by M
00945 *
00946                IL = IVT + M*M
00947                IF( LWORK.GE.M*N+M*M+3*M+BDSPAC ) THEN
00948 *
00949 *                 WORK(IL) is M by N
00950 *
00951                   LDWRKL = M
00952                   CHUNK = N
00953                ELSE
00954                   LDWRKL = M
00955                   CHUNK = ( LWORK-M*M ) / M
00956                END IF
00957                ITAU = IL + LDWRKL*M
00958                NWORK = ITAU + M
00959 *
00960 *              Compute A=L*Q
00961 *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
00962 *
00963                CALL SGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
00964      $                      LWORK-NWORK+1, IERR )
00965 *
00966 *              Copy L to WORK(IL), zeroing about above it
00967 *
00968                CALL SLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWRKL )
00969                CALL SLASET( 'U', M-1, M-1, ZERO, ZERO,
00970      $                      WORK( IL+LDWRKL ), LDWRKL )
00971 *
00972 *              Generate Q in A
00973 *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
00974 *
00975                CALL SORGLQ( M, N, M, A, LDA, WORK( ITAU ),
00976      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
00977                IE = ITAU
00978                ITAUQ = IE + M
00979                ITAUP = ITAUQ + M
00980                NWORK = ITAUP + M
00981 *
00982 *              Bidiagonalize L in WORK(IL)
00983 *              (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
00984 *
00985                CALL SGEBRD( M, M, WORK( IL ), LDWRKL, S, WORK( IE ),
00986      $                      WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
00987      $                      LWORK-NWORK+1, IERR )
00988 *
00989 *              Perform bidiagonal SVD, computing left singular vectors
00990 *              of bidiagonal matrix in U, and computing right singular
00991 *              vectors of bidiagonal matrix in WORK(IVT)
00992 *              (Workspace: need M+M*M+BDSPAC)
00993 *
00994                CALL SBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU,
00995      $                      WORK( IVT ), M, DUM, IDUM, WORK( NWORK ),
00996      $                      IWORK, INFO )
00997 *
00998 *              Overwrite U by left singular vectors of L and WORK(IVT)
00999 *              by right singular vectors of L
01000 *              (Workspace: need 2*M*M+3*M, prefer 2*M*M+2*M+M*NB)
01001 *
01002                CALL SORMBR( 'Q', 'L', 'N', M, M, M, WORK( IL ), LDWRKL,
01003      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
01004      $                      LWORK-NWORK+1, IERR )
01005                CALL SORMBR( 'P', 'R', 'T', M, M, M, WORK( IL ), LDWRKL,
01006      $                      WORK( ITAUP ), WORK( IVT ), M,
01007      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
01008 *
01009 *              Multiply right singular vectors of L in WORK(IVT) by Q
01010 *              in A, storing result in WORK(IL) and copying to A
01011 *              (Workspace: need 2*M*M, prefer M*M+M*N)
01012 *
01013                DO 30 I = 1, N, CHUNK
01014                   BLK = MIN( N-I+1, CHUNK )
01015                   CALL SGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IVT ), M,
01016      $                        A( 1, I ), LDA, ZERO, WORK( IL ), LDWRKL )
01017                   CALL SLACPY( 'F', M, BLK, WORK( IL ), LDWRKL,
01018      $                         A( 1, I ), LDA )
01019    30          CONTINUE
01020 *
01021             ELSE IF( WNTQS ) THEN
01022 *
01023 *              Path 3t (N much larger than M, JOBZ='S')
01024 *              M right singular vectors to be computed in VT and
01025 *              M left singular vectors to be computed in U
01026 *
01027                IL = 1
01028 *
01029 *              WORK(IL) is M by M
01030 *
01031                LDWRKL = M
01032                ITAU = IL + LDWRKL*M
01033                NWORK = ITAU + M
01034 *
01035 *              Compute A=L*Q
01036 *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
01037 *
01038                CALL SGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
01039      $                      LWORK-NWORK+1, IERR )
01040 *
01041 *              Copy L to WORK(IL), zeroing out above it
01042 *
01043                CALL SLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWRKL )
01044                CALL SLASET( 'U', M-1, M-1, ZERO, ZERO,
01045      $                      WORK( IL+LDWRKL ), LDWRKL )
01046 *
01047 *              Generate Q in A
01048 *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
01049 *
01050                CALL SORGLQ( M, N, M, A, LDA, WORK( ITAU ),
01051      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
01052                IE = ITAU
01053                ITAUQ = IE + M
01054                ITAUP = ITAUQ + M
01055                NWORK = ITAUP + M
01056 *
01057 *              Bidiagonalize L in WORK(IU), copying result to U
01058 *              (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
01059 *
01060                CALL SGEBRD( M, M, WORK( IL ), LDWRKL, S, WORK( IE ),
01061      $                      WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),
01062      $                      LWORK-NWORK+1, IERR )
01063 *
01064 *              Perform bidiagonal SVD, computing left singular vectors
01065 *              of bidiagonal matrix in U and computing right singular
01066 *              vectors of bidiagonal matrix in VT
01067 *              (Workspace: need M+BDSPAC)
01068 *
01069                CALL SBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU, VT,
01070      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
01071      $                      INFO )
01072 *
01073 *              Overwrite U by left singular vectors of L and VT
01074 *              by right singular vectors of L
01075 *              (Workspace: need M*M+3*M, prefer M*M+2*M+M*NB)
01076 *
01077                CALL SORMBR( 'Q', 'L', 'N', M, M, M, WORK( IL ), LDWRKL,
01078      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
01079      $                      LWORK-NWORK+1, IERR )
01080                CALL SORMBR( 'P', 'R', 'T', M, M, M, WORK( IL ), LDWRKL,
01081      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
01082      $                      LWORK-NWORK+1, IERR )
01083 *
01084 *              Multiply right singular vectors of L in WORK(IL) by
01085 *              Q in A, storing result in VT
01086 *              (Workspace: need M*M)
01087 *
01088                CALL SLACPY( 'F', M, M, VT, LDVT, WORK( IL ), LDWRKL )
01089                CALL SGEMM( 'N', 'N', M, N, M, ONE, WORK( IL ), LDWRKL,
01090      $                     A, LDA, ZERO, VT, LDVT )
01091 *
01092             ELSE IF( WNTQA ) THEN
01093 *
01094 *              Path 4t (N much larger than M, JOBZ='A')
01095 *              N right singular vectors to be computed in VT and
01096 *              M left singular vectors to be computed in U
01097 *
01098                IVT = 1
01099 *
01100 *              WORK(IVT) is M by M
01101 *
01102                LDWKVT = M
01103                ITAU = IVT + LDWKVT*M
01104                NWORK = ITAU + M
01105 *
01106 *              Compute A=L*Q, copying result to VT
01107 *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
01108 *
01109                CALL SGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),
01110      $                      LWORK-NWORK+1, IERR )
01111                CALL SLACPY( 'U', M, N, A, LDA, VT, LDVT )
01112 *
01113 *              Generate Q in VT
01114 *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
01115 *
01116                CALL SORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
01117      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
01118 *
01119 *              Produce L in A, zeroing out other entries
01120 *
01121                CALL SLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )
01122                IE = ITAU
01123                ITAUQ = IE + M
01124                ITAUP = ITAUQ + M
01125                NWORK = ITAUP + M
01126 *
01127 *              Bidiagonalize L in A
01128 *              (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
01129 *
01130                CALL SGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
01131      $                      WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
01132      $                      IERR )
01133 *
01134 *              Perform bidiagonal SVD, computing left singular vectors
01135 *              of bidiagonal matrix in U and computing right singular
01136 *              vectors of bidiagonal matrix in WORK(IVT)
01137 *              (Workspace: need M+M*M+BDSPAC)
01138 *
01139                CALL SBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU,
01140      $                      WORK( IVT ), LDWKVT, DUM, IDUM,
01141      $                      WORK( NWORK ), IWORK, INFO )
01142 *
01143 *              Overwrite U by left singular vectors of L and WORK(IVT)
01144 *              by right singular vectors of L
01145 *              (Workspace: need M*M+3*M, prefer M*M+2*M+M*NB)
01146 *
01147                CALL SORMBR( 'Q', 'L', 'N', M, M, M, A, LDA,
01148      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
01149      $                      LWORK-NWORK+1, IERR )
01150                CALL SORMBR( 'P', 'R', 'T', M, M, M, A, LDA,
01151      $                      WORK( ITAUP ), WORK( IVT ), LDWKVT,
01152      $                      WORK( NWORK ), LWORK-NWORK+1, IERR )
01153 *
01154 *              Multiply right singular vectors of L in WORK(IVT) by
01155 *              Q in VT, storing result in A
01156 *              (Workspace: need M*M)
01157 *
01158                CALL SGEMM( 'N', 'N', M, N, M, ONE, WORK( IVT ), LDWKVT,
01159      $                     VT, LDVT, ZERO, A, LDA )
01160 *
01161 *              Copy right singular vectors of A from A to VT
01162 *
01163                CALL SLACPY( 'F', M, N, A, LDA, VT, LDVT )
01164 *
01165             END IF
01166 *
01167          ELSE
01168 *
01169 *           N .LT. MNTHR
01170 *
01171 *           Path 5t (N greater than M, but not much larger)
01172 *           Reduce to bidiagonal form without LQ decomposition
01173 *
01174             IE = 1
01175             ITAUQ = IE + M
01176             ITAUP = ITAUQ + M
01177             NWORK = ITAUP + M
01178 *
01179 *           Bidiagonalize A
01180 *           (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
01181 *
01182             CALL SGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
01183      $                   WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,
01184      $                   IERR )
01185             IF( WNTQN ) THEN
01186 *
01187 *              Perform bidiagonal SVD, only computing singular values
01188 *              (Workspace: need M+BDSPAC)
01189 *
01190                CALL SBDSDC( 'L', 'N', M, S, WORK( IE ), DUM, 1, DUM, 1,
01191      $                      DUM, IDUM, WORK( NWORK ), IWORK, INFO )
01192             ELSE IF( WNTQO ) THEN
01193                LDWKVT = M
01194                IVT = NWORK
01195                IF( LWORK.GE.M*N+3*M+BDSPAC ) THEN
01196 *
01197 *                 WORK( IVT ) is M by N
01198 *
01199                   CALL SLASET( 'F', M, N, ZERO, ZERO, WORK( IVT ),
01200      $                         LDWKVT )
01201                   NWORK = IVT + LDWKVT*N
01202                ELSE
01203 *
01204 *                 WORK( IVT ) is M by M
01205 *
01206                   NWORK = IVT + LDWKVT*M
01207                   IL = NWORK
01208 *
01209 *                 WORK(IL) is M by CHUNK
01210 *
01211                   CHUNK = ( LWORK-M*M-3*M ) / M
01212                END IF
01213 *
01214 *              Perform bidiagonal SVD, computing left singular vectors
01215 *              of bidiagonal matrix in U and computing right singular
01216 *              vectors of bidiagonal matrix in WORK(IVT)
01217 *              (Workspace: need M*M+BDSPAC)
01218 *
01219                CALL SBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU,
01220      $                      WORK( IVT ), LDWKVT, DUM, IDUM,
01221      $                      WORK( NWORK ), IWORK, INFO )
01222 *
01223 *              Overwrite U by left singular vectors of A
01224 *              (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
01225 *
01226                CALL SORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
01227      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
01228      $                      LWORK-NWORK+1, IERR )
01229 *
01230                IF( LWORK.GE.M*N+3*M+BDSPAC ) THEN
01231 *
01232 *                 Overwrite WORK(IVT) by left singular vectors of A
01233 *                 (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
01234 *
01235                   CALL SORMBR( 'P', 'R', 'T', M, N, M, A, LDA,
01236      $                         WORK( ITAUP ), WORK( IVT ), LDWKVT,
01237      $                         WORK( NWORK ), LWORK-NWORK+1, IERR )
01238 *
01239 *                 Copy right singular vectors of A from WORK(IVT) to A
01240 *
01241                   CALL SLACPY( 'F', M, N, WORK( IVT ), LDWKVT, A, LDA )
01242                ELSE
01243 *
01244 *                 Generate P**T in A
01245 *                 (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
01246 *
01247                   CALL SORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
01248      $                         WORK( NWORK ), LWORK-NWORK+1, IERR )
01249 *
01250 *                 Multiply Q in A by right singular vectors of
01251 *                 bidiagonal matrix in WORK(IVT), storing result in
01252 *                 WORK(IL) and copying to A
01253 *                 (Workspace: need 2*M*M, prefer M*M+M*N)
01254 *
01255                   DO 40 I = 1, N, CHUNK
01256                      BLK = MIN( N-I+1, CHUNK )
01257                      CALL SGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IVT ),
01258      $                           LDWKVT, A( 1, I ), LDA, ZERO,
01259      $                           WORK( IL ), M )
01260                      CALL SLACPY( 'F', M, BLK, WORK( IL ), M, A( 1, I ),
01261      $                            LDA )
01262    40             CONTINUE
01263                END IF
01264             ELSE IF( WNTQS ) THEN
01265 *
01266 *              Perform bidiagonal SVD, computing left singular vectors
01267 *              of bidiagonal matrix in U and computing right singular
01268 *              vectors of bidiagonal matrix in VT
01269 *              (Workspace: need M+BDSPAC)
01270 *
01271                CALL SLASET( 'F', M, N, ZERO, ZERO, VT, LDVT )
01272                CALL SBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU, VT,
01273      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
01274      $                      INFO )
01275 *
01276 *              Overwrite U by left singular vectors of A and VT
01277 *              by right singular vectors of A
01278 *              (Workspace: need 3*M, prefer 2*M+M*NB)
01279 *
01280                CALL SORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
01281      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
01282      $                      LWORK-NWORK+1, IERR )
01283                CALL SORMBR( 'P', 'R', 'T', M, N, M, A, LDA,
01284      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
01285      $                      LWORK-NWORK+1, IERR )
01286             ELSE IF( WNTQA ) THEN
01287 *
01288 *              Perform bidiagonal SVD, computing left singular vectors
01289 *              of bidiagonal matrix in U and computing right singular
01290 *              vectors of bidiagonal matrix in VT
01291 *              (Workspace: need M+BDSPAC)
01292 *
01293                CALL SLASET( 'F', N, N, ZERO, ZERO, VT, LDVT )
01294                CALL SBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU, VT,
01295      $                      LDVT, DUM, IDUM, WORK( NWORK ), IWORK,
01296      $                      INFO )
01297 *
01298 *              Set the right corner of VT to identity matrix
01299 *
01300                IF( N.GT.M ) THEN
01301                   CALL SLASET( 'F', N-M, N-M, ZERO, ONE, VT( M+1, M+1 ),
01302      $                         LDVT )
01303                END IF
01304 *
01305 *              Overwrite U by left singular vectors of A and VT
01306 *              by right singular vectors of A
01307 *              (Workspace: need 2*M+N, prefer 2*M+N*NB)
01308 *
01309                CALL SORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,
01310      $                      WORK( ITAUQ ), U, LDU, WORK( NWORK ),
01311      $                      LWORK-NWORK+1, IERR )
01312                CALL SORMBR( 'P', 'R', 'T', N, N, M, A, LDA,
01313      $                      WORK( ITAUP ), VT, LDVT, WORK( NWORK ),
01314      $                      LWORK-NWORK+1, IERR )
01315             END IF
01316 *
01317          END IF
01318 *
01319       END IF
01320 *
01321 *     Undo scaling if necessary
01322 *
01323       IF( ISCL.EQ.1 ) THEN
01324          IF( ANRM.GT.BIGNUM )
01325      $      CALL SLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
01326      $                   IERR )
01327          IF( ANRM.LT.SMLNUM )
01328      $      CALL SLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
01329      $                   IERR )
01330       END IF
01331 *
01332 *     Return optimal workspace in WORK(1)
01333 *
01334       WORK( 1 ) = MAXWRK
01335 *
01336       RETURN
01337 *
01338 *     End of SGESDD
01339 *
01340       END
 All Files Functions