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