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