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