Annotation of rpl/lapack/lapack/dgesvd.f, revision 1.1
1.1 ! bertrand 1: SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT,
! 2: $ WORK, LWORK, INFO )
! 3: *
! 4: * -- LAPACK driver routine (version 3.2) --
! 5: * -- LAPACK is a software package provided by Univ. of Tennessee, --
! 6: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
! 7: * November 2006
! 8: *
! 9: * .. Scalar Arguments ..
! 10: CHARACTER JOBU, JOBVT
! 11: INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N
! 12: * ..
! 13: * .. Array Arguments ..
! 14: DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ),
! 15: $ VT( LDVT, * ), WORK( * )
! 16: * ..
! 17: *
! 18: * Purpose
! 19: * =======
! 20: *
! 21: * DGESVD computes the singular value decomposition (SVD) of a real
! 22: * M-by-N matrix A, optionally computing the left and/or right singular
! 23: * vectors. The SVD is written
! 24: *
! 25: * A = U * SIGMA * transpose(V)
! 26: *
! 27: * where SIGMA is an M-by-N matrix which is zero except for its
! 28: * min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
! 29: * V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA
! 30: * are the singular values of A; they are real and non-negative, and
! 31: * are returned in descending order. The first min(m,n) columns of
! 32: * U and V are the left and right singular vectors of A.
! 33: *
! 34: * Note that the routine returns V**T, not V.
! 35: *
! 36: * Arguments
! 37: * =========
! 38: *
! 39: * JOBU (input) CHARACTER*1
! 40: * Specifies options for computing all or part of the matrix U:
! 41: * = 'A': all M columns of U are returned in array U:
! 42: * = 'S': the first min(m,n) columns of U (the left singular
! 43: * vectors) are returned in the array U;
! 44: * = 'O': the first min(m,n) columns of U (the left singular
! 45: * vectors) are overwritten on the array A;
! 46: * = 'N': no columns of U (no left singular vectors) are
! 47: * computed.
! 48: *
! 49: * JOBVT (input) CHARACTER*1
! 50: * Specifies options for computing all or part of the matrix
! 51: * V**T:
! 52: * = 'A': all N rows of V**T are returned in the array VT;
! 53: * = 'S': the first min(m,n) rows of V**T (the right singular
! 54: * vectors) are returned in the array VT;
! 55: * = 'O': the first min(m,n) rows of V**T (the right singular
! 56: * vectors) are overwritten on the array A;
! 57: * = 'N': no rows of V**T (no right singular vectors) are
! 58: * computed.
! 59: *
! 60: * JOBVT and JOBU cannot both be 'O'.
! 61: *
! 62: * M (input) INTEGER
! 63: * The number of rows of the input matrix A. M >= 0.
! 64: *
! 65: * N (input) INTEGER
! 66: * The number of columns of the input matrix A. N >= 0.
! 67: *
! 68: * A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
! 69: * On entry, the M-by-N matrix A.
! 70: * On exit,
! 71: * if JOBU = 'O', A is overwritten with the first min(m,n)
! 72: * columns of U (the left singular vectors,
! 73: * stored columnwise);
! 74: * if JOBVT = 'O', A is overwritten with the first min(m,n)
! 75: * rows of V**T (the right singular vectors,
! 76: * stored rowwise);
! 77: * if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A
! 78: * are destroyed.
! 79: *
! 80: * LDA (input) INTEGER
! 81: * The leading dimension of the array A. LDA >= max(1,M).
! 82: *
! 83: * S (output) DOUBLE PRECISION array, dimension (min(M,N))
! 84: * The singular values of A, sorted so that S(i) >= S(i+1).
! 85: *
! 86: * U (output) DOUBLE PRECISION array, dimension (LDU,UCOL)
! 87: * (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'.
! 88: * If JOBU = 'A', U contains the M-by-M orthogonal matrix U;
! 89: * if JOBU = 'S', U contains the first min(m,n) columns of U
! 90: * (the left singular vectors, stored columnwise);
! 91: * if JOBU = 'N' or 'O', U is not referenced.
! 92: *
! 93: * LDU (input) INTEGER
! 94: * The leading dimension of the array U. LDU >= 1; if
! 95: * JOBU = 'S' or 'A', LDU >= M.
! 96: *
! 97: * VT (output) DOUBLE PRECISION array, dimension (LDVT,N)
! 98: * If JOBVT = 'A', VT contains the N-by-N orthogonal matrix
! 99: * V**T;
! 100: * if JOBVT = 'S', VT contains the first min(m,n) rows of
! 101: * V**T (the right singular vectors, stored rowwise);
! 102: * if JOBVT = 'N' or 'O', VT is not referenced.
! 103: *
! 104: * LDVT (input) INTEGER
! 105: * The leading dimension of the array VT. LDVT >= 1; if
! 106: * JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N).
! 107: *
! 108: * WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
! 109: * On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
! 110: * if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged
! 111: * superdiagonal elements of an upper bidiagonal matrix B
! 112: * whose diagonal is in S (not necessarily sorted). B
! 113: * satisfies A = U * B * VT, so it has the same singular values
! 114: * as A, and singular vectors related by U and VT.
! 115: *
! 116: * LWORK (input) INTEGER
! 117: * The dimension of the array WORK.
! 118: * LWORK >= MAX(1,3*MIN(M,N)+MAX(M,N),5*MIN(M,N)).
! 119: * For good performance, LWORK should generally be larger.
! 120: *
! 121: * If LWORK = -1, then a workspace query is assumed; the routine
! 122: * only calculates the optimal size of the WORK array, returns
! 123: * this value as the first entry of the WORK array, and no error
! 124: * message related to LWORK is issued by XERBLA.
! 125: *
! 126: * INFO (output) INTEGER
! 127: * = 0: successful exit.
! 128: * < 0: if INFO = -i, the i-th argument had an illegal value.
! 129: * > 0: if DBDSQR did not converge, INFO specifies how many
! 130: * superdiagonals of an intermediate bidiagonal form B
! 131: * did not converge to zero. See the description of WORK
! 132: * above for details.
! 133: *
! 134: * =====================================================================
! 135: *
! 136: * .. Parameters ..
! 137: DOUBLE PRECISION ZERO, ONE
! 138: PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
! 139: * ..
! 140: * .. Local Scalars ..
! 141: LOGICAL LQUERY, WNTUA, WNTUAS, WNTUN, WNTUO, WNTUS,
! 142: $ WNTVA, WNTVAS, WNTVN, WNTVO, WNTVS
! 143: INTEGER BDSPAC, BLK, CHUNK, I, IE, IERR, IR, ISCL,
! 144: $ ITAU, ITAUP, ITAUQ, IU, IWORK, LDWRKR, LDWRKU,
! 145: $ MAXWRK, MINMN, MINWRK, MNTHR, NCU, NCVT, NRU,
! 146: $ NRVT, WRKBL
! 147: DOUBLE PRECISION ANRM, BIGNUM, EPS, SMLNUM
! 148: * ..
! 149: * .. Local Arrays ..
! 150: DOUBLE PRECISION DUM( 1 )
! 151: * ..
! 152: * .. External Subroutines ..
! 153: EXTERNAL DBDSQR, DGEBRD, DGELQF, DGEMM, DGEQRF, DLACPY,
! 154: $ DLASCL, DLASET, DORGBR, DORGLQ, DORGQR, DORMBR,
! 155: $ XERBLA
! 156: * ..
! 157: * .. External Functions ..
! 158: LOGICAL LSAME
! 159: INTEGER ILAENV
! 160: DOUBLE PRECISION DLAMCH, DLANGE
! 161: EXTERNAL LSAME, ILAENV, DLAMCH, DLANGE
! 162: * ..
! 163: * .. Intrinsic Functions ..
! 164: INTRINSIC MAX, MIN, SQRT
! 165: * ..
! 166: * .. Executable Statements ..
! 167: *
! 168: * Test the input arguments
! 169: *
! 170: INFO = 0
! 171: MINMN = MIN( M, N )
! 172: WNTUA = LSAME( JOBU, 'A' )
! 173: WNTUS = LSAME( JOBU, 'S' )
! 174: WNTUAS = WNTUA .OR. WNTUS
! 175: WNTUO = LSAME( JOBU, 'O' )
! 176: WNTUN = LSAME( JOBU, 'N' )
! 177: WNTVA = LSAME( JOBVT, 'A' )
! 178: WNTVS = LSAME( JOBVT, 'S' )
! 179: WNTVAS = WNTVA .OR. WNTVS
! 180: WNTVO = LSAME( JOBVT, 'O' )
! 181: WNTVN = LSAME( JOBVT, 'N' )
! 182: LQUERY = ( LWORK.EQ.-1 )
! 183: *
! 184: IF( .NOT.( WNTUA .OR. WNTUS .OR. WNTUO .OR. WNTUN ) ) THEN
! 185: INFO = -1
! 186: ELSE IF( .NOT.( WNTVA .OR. WNTVS .OR. WNTVO .OR. WNTVN ) .OR.
! 187: $ ( WNTVO .AND. WNTUO ) ) THEN
! 188: INFO = -2
! 189: ELSE IF( M.LT.0 ) THEN
! 190: INFO = -3
! 191: ELSE IF( N.LT.0 ) THEN
! 192: INFO = -4
! 193: ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
! 194: INFO = -6
! 195: ELSE IF( LDU.LT.1 .OR. ( WNTUAS .AND. LDU.LT.M ) ) THEN
! 196: INFO = -9
! 197: ELSE IF( LDVT.LT.1 .OR. ( WNTVA .AND. LDVT.LT.N ) .OR.
! 198: $ ( WNTVS .AND. LDVT.LT.MINMN ) ) THEN
! 199: INFO = -11
! 200: END IF
! 201: *
! 202: * Compute workspace
! 203: * (Note: Comments in the code beginning "Workspace:" describe the
! 204: * minimal amount of workspace needed at that point in the code,
! 205: * as well as the preferred amount for good performance.
! 206: * NB refers to the optimal block size for the immediately
! 207: * following subroutine, as returned by ILAENV.)
! 208: *
! 209: IF( INFO.EQ.0 ) THEN
! 210: MINWRK = 1
! 211: MAXWRK = 1
! 212: IF( M.GE.N .AND. MINMN.GT.0 ) THEN
! 213: *
! 214: * Compute space needed for DBDSQR
! 215: *
! 216: MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
! 217: BDSPAC = 5*N
! 218: IF( M.GE.MNTHR ) THEN
! 219: IF( WNTUN ) THEN
! 220: *
! 221: * Path 1 (M much larger than N, JOBU='N')
! 222: *
! 223: MAXWRK = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1,
! 224: $ -1 )
! 225: MAXWRK = MAX( MAXWRK, 3*N+2*N*
! 226: $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
! 227: IF( WNTVO .OR. WNTVAS )
! 228: $ MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*
! 229: $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
! 230: MAXWRK = MAX( MAXWRK, BDSPAC )
! 231: MINWRK = MAX( 4*N, BDSPAC )
! 232: ELSE IF( WNTUO .AND. WNTVN ) THEN
! 233: *
! 234: * Path 2 (M much larger than N, JOBU='O', JOBVT='N')
! 235: *
! 236: WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
! 237: WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
! 238: $ N, N, -1 ) )
! 239: WRKBL = MAX( WRKBL, 3*N+2*N*
! 240: $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
! 241: WRKBL = MAX( WRKBL, 3*N+N*
! 242: $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
! 243: WRKBL = MAX( WRKBL, BDSPAC )
! 244: MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )
! 245: MINWRK = MAX( 3*N+M, BDSPAC )
! 246: ELSE IF( WNTUO .AND. WNTVAS ) THEN
! 247: *
! 248: * Path 3 (M much larger than N, JOBU='O', JOBVT='S' or
! 249: * 'A')
! 250: *
! 251: WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
! 252: WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
! 253: $ N, N, -1 ) )
! 254: WRKBL = MAX( WRKBL, 3*N+2*N*
! 255: $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
! 256: WRKBL = MAX( WRKBL, 3*N+N*
! 257: $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
! 258: WRKBL = MAX( WRKBL, 3*N+( N-1 )*
! 259: $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
! 260: WRKBL = MAX( WRKBL, BDSPAC )
! 261: MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )
! 262: MINWRK = MAX( 3*N+M, BDSPAC )
! 263: ELSE IF( WNTUS .AND. WNTVN ) THEN
! 264: *
! 265: * Path 4 (M much larger than N, JOBU='S', JOBVT='N')
! 266: *
! 267: WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
! 268: WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
! 269: $ N, N, -1 ) )
! 270: WRKBL = MAX( WRKBL, 3*N+2*N*
! 271: $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
! 272: WRKBL = MAX( WRKBL, 3*N+N*
! 273: $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
! 274: WRKBL = MAX( WRKBL, BDSPAC )
! 275: MAXWRK = N*N + WRKBL
! 276: MINWRK = MAX( 3*N+M, BDSPAC )
! 277: ELSE IF( WNTUS .AND. WNTVO ) THEN
! 278: *
! 279: * Path 5 (M much larger than N, JOBU='S', JOBVT='O')
! 280: *
! 281: WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
! 282: WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
! 283: $ N, N, -1 ) )
! 284: WRKBL = MAX( WRKBL, 3*N+2*N*
! 285: $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
! 286: WRKBL = MAX( WRKBL, 3*N+N*
! 287: $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
! 288: WRKBL = MAX( WRKBL, 3*N+( N-1 )*
! 289: $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
! 290: WRKBL = MAX( WRKBL, BDSPAC )
! 291: MAXWRK = 2*N*N + WRKBL
! 292: MINWRK = MAX( 3*N+M, BDSPAC )
! 293: ELSE IF( WNTUS .AND. WNTVAS ) THEN
! 294: *
! 295: * Path 6 (M much larger than N, JOBU='S', JOBVT='S' or
! 296: * 'A')
! 297: *
! 298: WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
! 299: WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
! 300: $ N, N, -1 ) )
! 301: WRKBL = MAX( WRKBL, 3*N+2*N*
! 302: $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
! 303: WRKBL = MAX( WRKBL, 3*N+N*
! 304: $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
! 305: WRKBL = MAX( WRKBL, 3*N+( N-1 )*
! 306: $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
! 307: WRKBL = MAX( WRKBL, BDSPAC )
! 308: MAXWRK = N*N + WRKBL
! 309: MINWRK = MAX( 3*N+M, BDSPAC )
! 310: ELSE IF( WNTUA .AND. WNTVN ) THEN
! 311: *
! 312: * Path 7 (M much larger than N, JOBU='A', JOBVT='N')
! 313: *
! 314: WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
! 315: WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
! 316: $ M, N, -1 ) )
! 317: WRKBL = MAX( WRKBL, 3*N+2*N*
! 318: $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
! 319: WRKBL = MAX( WRKBL, 3*N+N*
! 320: $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
! 321: WRKBL = MAX( WRKBL, BDSPAC )
! 322: MAXWRK = N*N + WRKBL
! 323: MINWRK = MAX( 3*N+M, BDSPAC )
! 324: ELSE IF( WNTUA .AND. WNTVO ) THEN
! 325: *
! 326: * Path 8 (M much larger than N, JOBU='A', JOBVT='O')
! 327: *
! 328: WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
! 329: WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
! 330: $ M, N, -1 ) )
! 331: WRKBL = MAX( WRKBL, 3*N+2*N*
! 332: $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
! 333: WRKBL = MAX( WRKBL, 3*N+N*
! 334: $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
! 335: WRKBL = MAX( WRKBL, 3*N+( N-1 )*
! 336: $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
! 337: WRKBL = MAX( WRKBL, BDSPAC )
! 338: MAXWRK = 2*N*N + WRKBL
! 339: MINWRK = MAX( 3*N+M, BDSPAC )
! 340: ELSE IF( WNTUA .AND. WNTVAS ) THEN
! 341: *
! 342: * Path 9 (M much larger than N, JOBU='A', JOBVT='S' or
! 343: * 'A')
! 344: *
! 345: WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
! 346: WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
! 347: $ M, N, -1 ) )
! 348: WRKBL = MAX( WRKBL, 3*N+2*N*
! 349: $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
! 350: WRKBL = MAX( WRKBL, 3*N+N*
! 351: $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
! 352: WRKBL = MAX( WRKBL, 3*N+( N-1 )*
! 353: $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
! 354: WRKBL = MAX( WRKBL, BDSPAC )
! 355: MAXWRK = N*N + WRKBL
! 356: MINWRK = MAX( 3*N+M, BDSPAC )
! 357: END IF
! 358: ELSE
! 359: *
! 360: * Path 10 (M at least N, but not much larger)
! 361: *
! 362: MAXWRK = 3*N + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N,
! 363: $ -1, -1 )
! 364: IF( WNTUS .OR. WNTUO )
! 365: $ MAXWRK = MAX( MAXWRK, 3*N+N*
! 366: $ ILAENV( 1, 'DORGBR', 'Q', M, N, N, -1 ) )
! 367: IF( WNTUA )
! 368: $ MAXWRK = MAX( MAXWRK, 3*N+M*
! 369: $ ILAENV( 1, 'DORGBR', 'Q', M, M, N, -1 ) )
! 370: IF( .NOT.WNTVN )
! 371: $ MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*
! 372: $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
! 373: MAXWRK = MAX( MAXWRK, BDSPAC )
! 374: MINWRK = MAX( 3*N+M, BDSPAC )
! 375: END IF
! 376: ELSE IF( MINMN.GT.0 ) THEN
! 377: *
! 378: * Compute space needed for DBDSQR
! 379: *
! 380: MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
! 381: BDSPAC = 5*M
! 382: IF( N.GE.MNTHR ) THEN
! 383: IF( WNTVN ) THEN
! 384: *
! 385: * Path 1t(N much larger than M, JOBVT='N')
! 386: *
! 387: MAXWRK = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1,
! 388: $ -1 )
! 389: MAXWRK = MAX( MAXWRK, 3*M+2*M*
! 390: $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
! 391: IF( WNTUO .OR. WNTUAS )
! 392: $ MAXWRK = MAX( MAXWRK, 3*M+M*
! 393: $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
! 394: MAXWRK = MAX( MAXWRK, BDSPAC )
! 395: MINWRK = MAX( 4*M, BDSPAC )
! 396: ELSE IF( WNTVO .AND. WNTUN ) THEN
! 397: *
! 398: * Path 2t(N much larger than M, JOBU='N', JOBVT='O')
! 399: *
! 400: WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
! 401: WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
! 402: $ N, M, -1 ) )
! 403: WRKBL = MAX( WRKBL, 3*M+2*M*
! 404: $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
! 405: WRKBL = MAX( WRKBL, 3*M+( M-1 )*
! 406: $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
! 407: WRKBL = MAX( WRKBL, BDSPAC )
! 408: MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )
! 409: MINWRK = MAX( 3*M+N, BDSPAC )
! 410: ELSE IF( WNTVO .AND. WNTUAS ) THEN
! 411: *
! 412: * Path 3t(N much larger than M, JOBU='S' or 'A',
! 413: * JOBVT='O')
! 414: *
! 415: WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
! 416: WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
! 417: $ N, M, -1 ) )
! 418: WRKBL = MAX( WRKBL, 3*M+2*M*
! 419: $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
! 420: WRKBL = MAX( WRKBL, 3*M+( M-1 )*
! 421: $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
! 422: WRKBL = MAX( WRKBL, 3*M+M*
! 423: $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
! 424: WRKBL = MAX( WRKBL, BDSPAC )
! 425: MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )
! 426: MINWRK = MAX( 3*M+N, BDSPAC )
! 427: ELSE IF( WNTVS .AND. WNTUN ) THEN
! 428: *
! 429: * Path 4t(N much larger than M, JOBU='N', JOBVT='S')
! 430: *
! 431: WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
! 432: WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
! 433: $ N, M, -1 ) )
! 434: WRKBL = MAX( WRKBL, 3*M+2*M*
! 435: $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
! 436: WRKBL = MAX( WRKBL, 3*M+( M-1 )*
! 437: $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
! 438: WRKBL = MAX( WRKBL, BDSPAC )
! 439: MAXWRK = M*M + WRKBL
! 440: MINWRK = MAX( 3*M+N, BDSPAC )
! 441: ELSE IF( WNTVS .AND. WNTUO ) THEN
! 442: *
! 443: * Path 5t(N much larger than M, JOBU='O', JOBVT='S')
! 444: *
! 445: WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
! 446: WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
! 447: $ N, M, -1 ) )
! 448: WRKBL = MAX( WRKBL, 3*M+2*M*
! 449: $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
! 450: WRKBL = MAX( WRKBL, 3*M+( M-1 )*
! 451: $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
! 452: WRKBL = MAX( WRKBL, 3*M+M*
! 453: $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
! 454: WRKBL = MAX( WRKBL, BDSPAC )
! 455: MAXWRK = 2*M*M + WRKBL
! 456: MINWRK = MAX( 3*M+N, BDSPAC )
! 457: ELSE IF( WNTVS .AND. WNTUAS ) THEN
! 458: *
! 459: * Path 6t(N much larger than M, JOBU='S' or 'A',
! 460: * JOBVT='S')
! 461: *
! 462: WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
! 463: WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
! 464: $ N, M, -1 ) )
! 465: WRKBL = MAX( WRKBL, 3*M+2*M*
! 466: $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
! 467: WRKBL = MAX( WRKBL, 3*M+( M-1 )*
! 468: $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
! 469: WRKBL = MAX( WRKBL, 3*M+M*
! 470: $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
! 471: WRKBL = MAX( WRKBL, BDSPAC )
! 472: MAXWRK = M*M + WRKBL
! 473: MINWRK = MAX( 3*M+N, BDSPAC )
! 474: ELSE IF( WNTVA .AND. WNTUN ) THEN
! 475: *
! 476: * Path 7t(N much larger than M, JOBU='N', JOBVT='A')
! 477: *
! 478: WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
! 479: WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
! 480: $ N, M, -1 ) )
! 481: WRKBL = MAX( WRKBL, 3*M+2*M*
! 482: $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
! 483: WRKBL = MAX( WRKBL, 3*M+( M-1 )*
! 484: $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
! 485: WRKBL = MAX( WRKBL, BDSPAC )
! 486: MAXWRK = M*M + WRKBL
! 487: MINWRK = MAX( 3*M+N, BDSPAC )
! 488: ELSE IF( WNTVA .AND. WNTUO ) THEN
! 489: *
! 490: * Path 8t(N much larger than M, JOBU='O', JOBVT='A')
! 491: *
! 492: WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
! 493: WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
! 494: $ N, M, -1 ) )
! 495: WRKBL = MAX( WRKBL, 3*M+2*M*
! 496: $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
! 497: WRKBL = MAX( WRKBL, 3*M+( M-1 )*
! 498: $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
! 499: WRKBL = MAX( WRKBL, 3*M+M*
! 500: $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
! 501: WRKBL = MAX( WRKBL, BDSPAC )
! 502: MAXWRK = 2*M*M + WRKBL
! 503: MINWRK = MAX( 3*M+N, BDSPAC )
! 504: ELSE IF( WNTVA .AND. WNTUAS ) THEN
! 505: *
! 506: * Path 9t(N much larger than M, JOBU='S' or 'A',
! 507: * JOBVT='A')
! 508: *
! 509: WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
! 510: WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
! 511: $ N, M, -1 ) )
! 512: WRKBL = MAX( WRKBL, 3*M+2*M*
! 513: $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
! 514: WRKBL = MAX( WRKBL, 3*M+( M-1 )*
! 515: $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
! 516: WRKBL = MAX( WRKBL, 3*M+M*
! 517: $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
! 518: WRKBL = MAX( WRKBL, BDSPAC )
! 519: MAXWRK = M*M + WRKBL
! 520: MINWRK = MAX( 3*M+N, BDSPAC )
! 521: END IF
! 522: ELSE
! 523: *
! 524: * Path 10t(N greater than M, but not much larger)
! 525: *
! 526: MAXWRK = 3*M + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N,
! 527: $ -1, -1 )
! 528: IF( WNTVS .OR. WNTVO )
! 529: $ MAXWRK = MAX( MAXWRK, 3*M+M*
! 530: $ ILAENV( 1, 'DORGBR', 'P', M, N, M, -1 ) )
! 531: IF( WNTVA )
! 532: $ MAXWRK = MAX( MAXWRK, 3*M+N*
! 533: $ ILAENV( 1, 'DORGBR', 'P', N, N, M, -1 ) )
! 534: IF( .NOT.WNTUN )
! 535: $ MAXWRK = MAX( MAXWRK, 3*M+( M-1 )*
! 536: $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
! 537: MAXWRK = MAX( MAXWRK, BDSPAC )
! 538: MINWRK = MAX( 3*M+N, BDSPAC )
! 539: END IF
! 540: END IF
! 541: MAXWRK = MAX( MAXWRK, MINWRK )
! 542: WORK( 1 ) = MAXWRK
! 543: *
! 544: IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
! 545: INFO = -13
! 546: END IF
! 547: END IF
! 548: *
! 549: IF( INFO.NE.0 ) THEN
! 550: CALL XERBLA( 'DGESVD', -INFO )
! 551: RETURN
! 552: ELSE IF( LQUERY ) THEN
! 553: RETURN
! 554: END IF
! 555: *
! 556: * Quick return if possible
! 557: *
! 558: IF( M.EQ.0 .OR. N.EQ.0 ) THEN
! 559: RETURN
! 560: END IF
! 561: *
! 562: * Get machine constants
! 563: *
! 564: EPS = DLAMCH( 'P' )
! 565: SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPS
! 566: BIGNUM = ONE / SMLNUM
! 567: *
! 568: * Scale A if max element outside range [SMLNUM,BIGNUM]
! 569: *
! 570: ANRM = DLANGE( 'M', M, N, A, LDA, DUM )
! 571: ISCL = 0
! 572: IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
! 573: ISCL = 1
! 574: CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, IERR )
! 575: ELSE IF( ANRM.GT.BIGNUM ) THEN
! 576: ISCL = 1
! 577: CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, IERR )
! 578: END IF
! 579: *
! 580: IF( M.GE.N ) THEN
! 581: *
! 582: * A has at least as many rows as columns. If A has sufficiently
! 583: * more rows than columns, first reduce using the QR
! 584: * decomposition (if sufficient workspace available)
! 585: *
! 586: IF( M.GE.MNTHR ) THEN
! 587: *
! 588: IF( WNTUN ) THEN
! 589: *
! 590: * Path 1 (M much larger than N, JOBU='N')
! 591: * No left singular vectors to be computed
! 592: *
! 593: ITAU = 1
! 594: IWORK = ITAU + N
! 595: *
! 596: * Compute A=Q*R
! 597: * (Workspace: need 2*N, prefer N+N*NB)
! 598: *
! 599: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
! 600: $ LWORK-IWORK+1, IERR )
! 601: *
! 602: * Zero out below R
! 603: *
! 604: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )
! 605: IE = 1
! 606: ITAUQ = IE + N
! 607: ITAUP = ITAUQ + N
! 608: IWORK = ITAUP + N
! 609: *
! 610: * Bidiagonalize R in A
! 611: * (Workspace: need 4*N, prefer 3*N+2*N*NB)
! 612: *
! 613: CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
! 614: $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
! 615: $ IERR )
! 616: NCVT = 0
! 617: IF( WNTVO .OR. WNTVAS ) THEN
! 618: *
! 619: * If right singular vectors desired, generate P'.
! 620: * (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
! 621: *
! 622: CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
! 623: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 624: NCVT = N
! 625: END IF
! 626: IWORK = IE + N
! 627: *
! 628: * Perform bidiagonal QR iteration, computing right
! 629: * singular vectors of A in A if desired
! 630: * (Workspace: need BDSPAC)
! 631: *
! 632: CALL DBDSQR( 'U', N, NCVT, 0, 0, S, WORK( IE ), A, LDA,
! 633: $ DUM, 1, DUM, 1, WORK( IWORK ), INFO )
! 634: *
! 635: * If right singular vectors desired in VT, copy them there
! 636: *
! 637: IF( WNTVAS )
! 638: $ CALL DLACPY( 'F', N, N, A, LDA, VT, LDVT )
! 639: *
! 640: ELSE IF( WNTUO .AND. WNTVN ) THEN
! 641: *
! 642: * Path 2 (M much larger than N, JOBU='O', JOBVT='N')
! 643: * N left singular vectors to be overwritten on A and
! 644: * no right singular vectors to be computed
! 645: *
! 646: IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
! 647: *
! 648: * Sufficient workspace for a fast algorithm
! 649: *
! 650: IR = 1
! 651: IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+LDA*N ) THEN
! 652: *
! 653: * WORK(IU) is LDA by N, WORK(IR) is LDA by N
! 654: *
! 655: LDWRKU = LDA
! 656: LDWRKR = LDA
! 657: ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+N*N ) THEN
! 658: *
! 659: * WORK(IU) is LDA by N, WORK(IR) is N by N
! 660: *
! 661: LDWRKU = LDA
! 662: LDWRKR = N
! 663: ELSE
! 664: *
! 665: * WORK(IU) is LDWRKU by N, WORK(IR) is N by N
! 666: *
! 667: LDWRKU = ( LWORK-N*N-N ) / N
! 668: LDWRKR = N
! 669: END IF
! 670: ITAU = IR + LDWRKR*N
! 671: IWORK = ITAU + N
! 672: *
! 673: * Compute A=Q*R
! 674: * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
! 675: *
! 676: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 677: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 678: *
! 679: * Copy R to WORK(IR) and zero out below it
! 680: *
! 681: CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )
! 682: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),
! 683: $ LDWRKR )
! 684: *
! 685: * Generate Q in A
! 686: * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
! 687: *
! 688: CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
! 689: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 690: IE = ITAU
! 691: ITAUQ = IE + N
! 692: ITAUP = ITAUQ + N
! 693: IWORK = ITAUP + N
! 694: *
! 695: * Bidiagonalize R in WORK(IR)
! 696: * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
! 697: *
! 698: CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),
! 699: $ WORK( ITAUQ ), WORK( ITAUP ),
! 700: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 701: *
! 702: * Generate left vectors bidiagonalizing R
! 703: * (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
! 704: *
! 705: CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
! 706: $ WORK( ITAUQ ), WORK( IWORK ),
! 707: $ LWORK-IWORK+1, IERR )
! 708: IWORK = IE + N
! 709: *
! 710: * Perform bidiagonal QR iteration, computing left
! 711: * singular vectors of R in WORK(IR)
! 712: * (Workspace: need N*N+BDSPAC)
! 713: *
! 714: CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM, 1,
! 715: $ WORK( IR ), LDWRKR, DUM, 1,
! 716: $ WORK( IWORK ), INFO )
! 717: IU = IE + N
! 718: *
! 719: * Multiply Q in A by left singular vectors of R in
! 720: * WORK(IR), storing result in WORK(IU) and copying to A
! 721: * (Workspace: need N*N+2*N, prefer N*N+M*N+N)
! 722: *
! 723: DO 10 I = 1, M, LDWRKU
! 724: CHUNK = MIN( M-I+1, LDWRKU )
! 725: CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
! 726: $ LDA, WORK( IR ), LDWRKR, ZERO,
! 727: $ WORK( IU ), LDWRKU )
! 728: CALL DLACPY( 'F', CHUNK, N, WORK( IU ), LDWRKU,
! 729: $ A( I, 1 ), LDA )
! 730: 10 CONTINUE
! 731: *
! 732: ELSE
! 733: *
! 734: * Insufficient workspace for a fast algorithm
! 735: *
! 736: IE = 1
! 737: ITAUQ = IE + N
! 738: ITAUP = ITAUQ + N
! 739: IWORK = ITAUP + N
! 740: *
! 741: * Bidiagonalize A
! 742: * (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)
! 743: *
! 744: CALL DGEBRD( M, N, A, LDA, S, WORK( IE ),
! 745: $ WORK( ITAUQ ), WORK( ITAUP ),
! 746: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 747: *
! 748: * Generate left vectors bidiagonalizing A
! 749: * (Workspace: need 4*N, prefer 3*N+N*NB)
! 750: *
! 751: CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),
! 752: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 753: IWORK = IE + N
! 754: *
! 755: * Perform bidiagonal QR iteration, computing left
! 756: * singular vectors of A in A
! 757: * (Workspace: need BDSPAC)
! 758: *
! 759: CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM, 1,
! 760: $ A, LDA, DUM, 1, WORK( IWORK ), INFO )
! 761: *
! 762: END IF
! 763: *
! 764: ELSE IF( WNTUO .AND. WNTVAS ) THEN
! 765: *
! 766: * Path 3 (M much larger than N, JOBU='O', JOBVT='S' or 'A')
! 767: * N left singular vectors to be overwritten on A and
! 768: * N right singular vectors to be computed in VT
! 769: *
! 770: IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
! 771: *
! 772: * Sufficient workspace for a fast algorithm
! 773: *
! 774: IR = 1
! 775: IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+LDA*N ) THEN
! 776: *
! 777: * WORK(IU) is LDA by N and WORK(IR) is LDA by N
! 778: *
! 779: LDWRKU = LDA
! 780: LDWRKR = LDA
! 781: ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+N*N ) THEN
! 782: *
! 783: * WORK(IU) is LDA by N and WORK(IR) is N by N
! 784: *
! 785: LDWRKU = LDA
! 786: LDWRKR = N
! 787: ELSE
! 788: *
! 789: * WORK(IU) is LDWRKU by N and WORK(IR) is N by N
! 790: *
! 791: LDWRKU = ( LWORK-N*N-N ) / N
! 792: LDWRKR = N
! 793: END IF
! 794: ITAU = IR + LDWRKR*N
! 795: IWORK = ITAU + N
! 796: *
! 797: * Compute A=Q*R
! 798: * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
! 799: *
! 800: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 801: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 802: *
! 803: * Copy R to VT, zeroing out below it
! 804: *
! 805: CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
! 806: IF( N.GT.1 )
! 807: $ CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
! 808: $ VT( 2, 1 ), LDVT )
! 809: *
! 810: * Generate Q in A
! 811: * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
! 812: *
! 813: CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
! 814: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 815: IE = ITAU
! 816: ITAUQ = IE + N
! 817: ITAUP = ITAUQ + N
! 818: IWORK = ITAUP + N
! 819: *
! 820: * Bidiagonalize R in VT, copying result to WORK(IR)
! 821: * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
! 822: *
! 823: CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
! 824: $ WORK( ITAUQ ), WORK( ITAUP ),
! 825: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 826: CALL DLACPY( 'L', N, N, VT, LDVT, WORK( IR ), LDWRKR )
! 827: *
! 828: * Generate left vectors bidiagonalizing R in WORK(IR)
! 829: * (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
! 830: *
! 831: CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
! 832: $ WORK( ITAUQ ), WORK( IWORK ),
! 833: $ LWORK-IWORK+1, IERR )
! 834: *
! 835: * Generate right vectors bidiagonalizing R in VT
! 836: * (Workspace: need N*N+4*N-1, prefer N*N+3*N+(N-1)*NB)
! 837: *
! 838: CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
! 839: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 840: IWORK = IE + N
! 841: *
! 842: * Perform bidiagonal QR iteration, computing left
! 843: * singular vectors of R in WORK(IR) and computing right
! 844: * singular vectors of R in VT
! 845: * (Workspace: need N*N+BDSPAC)
! 846: *
! 847: CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT, LDVT,
! 848: $ WORK( IR ), LDWRKR, DUM, 1,
! 849: $ WORK( IWORK ), INFO )
! 850: IU = IE + N
! 851: *
! 852: * Multiply Q in A by left singular vectors of R in
! 853: * WORK(IR), storing result in WORK(IU) and copying to A
! 854: * (Workspace: need N*N+2*N, prefer N*N+M*N+N)
! 855: *
! 856: DO 20 I = 1, M, LDWRKU
! 857: CHUNK = MIN( M-I+1, LDWRKU )
! 858: CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),
! 859: $ LDA, WORK( IR ), LDWRKR, ZERO,
! 860: $ WORK( IU ), LDWRKU )
! 861: CALL DLACPY( 'F', CHUNK, N, WORK( IU ), LDWRKU,
! 862: $ A( I, 1 ), LDA )
! 863: 20 CONTINUE
! 864: *
! 865: ELSE
! 866: *
! 867: * Insufficient workspace for a fast algorithm
! 868: *
! 869: ITAU = 1
! 870: IWORK = ITAU + N
! 871: *
! 872: * Compute A=Q*R
! 873: * (Workspace: need 2*N, prefer N+N*NB)
! 874: *
! 875: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 876: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 877: *
! 878: * Copy R to VT, zeroing out below it
! 879: *
! 880: CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
! 881: IF( N.GT.1 )
! 882: $ CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
! 883: $ VT( 2, 1 ), LDVT )
! 884: *
! 885: * Generate Q in A
! 886: * (Workspace: need 2*N, prefer N+N*NB)
! 887: *
! 888: CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
! 889: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 890: IE = ITAU
! 891: ITAUQ = IE + N
! 892: ITAUP = ITAUQ + N
! 893: IWORK = ITAUP + N
! 894: *
! 895: * Bidiagonalize R in VT
! 896: * (Workspace: need 4*N, prefer 3*N+2*N*NB)
! 897: *
! 898: CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
! 899: $ WORK( ITAUQ ), WORK( ITAUP ),
! 900: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 901: *
! 902: * Multiply Q in A by left vectors bidiagonalizing R
! 903: * (Workspace: need 3*N+M, prefer 3*N+M*NB)
! 904: *
! 905: CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,
! 906: $ WORK( ITAUQ ), A, LDA, WORK( IWORK ),
! 907: $ LWORK-IWORK+1, IERR )
! 908: *
! 909: * Generate right vectors bidiagonalizing R in VT
! 910: * (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
! 911: *
! 912: CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
! 913: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 914: IWORK = IE + N
! 915: *
! 916: * Perform bidiagonal QR iteration, computing left
! 917: * singular vectors of A in A and computing right
! 918: * singular vectors of A in VT
! 919: * (Workspace: need BDSPAC)
! 920: *
! 921: CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT, LDVT,
! 922: $ A, LDA, DUM, 1, WORK( IWORK ), INFO )
! 923: *
! 924: END IF
! 925: *
! 926: ELSE IF( WNTUS ) THEN
! 927: *
! 928: IF( WNTVN ) THEN
! 929: *
! 930: * Path 4 (M much larger than N, JOBU='S', JOBVT='N')
! 931: * N left singular vectors to be computed in U and
! 932: * no right singular vectors to be computed
! 933: *
! 934: IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
! 935: *
! 936: * Sufficient workspace for a fast algorithm
! 937: *
! 938: IR = 1
! 939: IF( LWORK.GE.WRKBL+LDA*N ) THEN
! 940: *
! 941: * WORK(IR) is LDA by N
! 942: *
! 943: LDWRKR = LDA
! 944: ELSE
! 945: *
! 946: * WORK(IR) is N by N
! 947: *
! 948: LDWRKR = N
! 949: END IF
! 950: ITAU = IR + LDWRKR*N
! 951: IWORK = ITAU + N
! 952: *
! 953: * Compute A=Q*R
! 954: * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
! 955: *
! 956: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 957: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 958: *
! 959: * Copy R to WORK(IR), zeroing out below it
! 960: *
! 961: CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ),
! 962: $ LDWRKR )
! 963: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
! 964: $ WORK( IR+1 ), LDWRKR )
! 965: *
! 966: * Generate Q in A
! 967: * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
! 968: *
! 969: CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
! 970: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 971: IE = ITAU
! 972: ITAUQ = IE + N
! 973: ITAUP = ITAUQ + N
! 974: IWORK = ITAUP + N
! 975: *
! 976: * Bidiagonalize R in WORK(IR)
! 977: * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
! 978: *
! 979: CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S,
! 980: $ WORK( IE ), WORK( ITAUQ ),
! 981: $ WORK( ITAUP ), WORK( IWORK ),
! 982: $ LWORK-IWORK+1, IERR )
! 983: *
! 984: * Generate left vectors bidiagonalizing R in WORK(IR)
! 985: * (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
! 986: *
! 987: CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
! 988: $ WORK( ITAUQ ), WORK( IWORK ),
! 989: $ LWORK-IWORK+1, IERR )
! 990: IWORK = IE + N
! 991: *
! 992: * Perform bidiagonal QR iteration, computing left
! 993: * singular vectors of R in WORK(IR)
! 994: * (Workspace: need N*N+BDSPAC)
! 995: *
! 996: CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM,
! 997: $ 1, WORK( IR ), LDWRKR, DUM, 1,
! 998: $ WORK( IWORK ), INFO )
! 999: *
! 1000: * Multiply Q in A by left singular vectors of R in
! 1001: * WORK(IR), storing result in U
! 1002: * (Workspace: need N*N)
! 1003: *
! 1004: CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,
! 1005: $ WORK( IR ), LDWRKR, ZERO, U, LDU )
! 1006: *
! 1007: ELSE
! 1008: *
! 1009: * Insufficient workspace for a fast algorithm
! 1010: *
! 1011: ITAU = 1
! 1012: IWORK = ITAU + N
! 1013: *
! 1014: * Compute A=Q*R, copying result to U
! 1015: * (Workspace: need 2*N, prefer N+N*NB)
! 1016: *
! 1017: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 1018: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1019: CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
! 1020: *
! 1021: * Generate Q in U
! 1022: * (Workspace: need 2*N, prefer N+N*NB)
! 1023: *
! 1024: CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),
! 1025: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1026: IE = ITAU
! 1027: ITAUQ = IE + N
! 1028: ITAUP = ITAUQ + N
! 1029: IWORK = ITAUP + N
! 1030: *
! 1031: * Zero out below R in A
! 1032: *
! 1033: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),
! 1034: $ LDA )
! 1035: *
! 1036: * Bidiagonalize R in A
! 1037: * (Workspace: need 4*N, prefer 3*N+2*N*NB)
! 1038: *
! 1039: CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
! 1040: $ WORK( ITAUQ ), WORK( ITAUP ),
! 1041: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1042: *
! 1043: * Multiply Q in U by left vectors bidiagonalizing R
! 1044: * (Workspace: need 3*N+M, prefer 3*N+M*NB)
! 1045: *
! 1046: CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
! 1047: $ WORK( ITAUQ ), U, LDU, WORK( IWORK ),
! 1048: $ LWORK-IWORK+1, IERR )
! 1049: IWORK = IE + N
! 1050: *
! 1051: * Perform bidiagonal QR iteration, computing left
! 1052: * singular vectors of A in U
! 1053: * (Workspace: need BDSPAC)
! 1054: *
! 1055: CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM,
! 1056: $ 1, U, LDU, DUM, 1, WORK( IWORK ),
! 1057: $ INFO )
! 1058: *
! 1059: END IF
! 1060: *
! 1061: ELSE IF( WNTVO ) THEN
! 1062: *
! 1063: * Path 5 (M much larger than N, JOBU='S', JOBVT='O')
! 1064: * N left singular vectors to be computed in U and
! 1065: * N right singular vectors to be overwritten on A
! 1066: *
! 1067: IF( LWORK.GE.2*N*N+MAX( 4*N, BDSPAC ) ) THEN
! 1068: *
! 1069: * Sufficient workspace for a fast algorithm
! 1070: *
! 1071: IU = 1
! 1072: IF( LWORK.GE.WRKBL+2*LDA*N ) THEN
! 1073: *
! 1074: * WORK(IU) is LDA by N and WORK(IR) is LDA by N
! 1075: *
! 1076: LDWRKU = LDA
! 1077: IR = IU + LDWRKU*N
! 1078: LDWRKR = LDA
! 1079: ELSE IF( LWORK.GE.WRKBL+( LDA+N )*N ) THEN
! 1080: *
! 1081: * WORK(IU) is LDA by N and WORK(IR) is N by N
! 1082: *
! 1083: LDWRKU = LDA
! 1084: IR = IU + LDWRKU*N
! 1085: LDWRKR = N
! 1086: ELSE
! 1087: *
! 1088: * WORK(IU) is N by N and WORK(IR) is N by N
! 1089: *
! 1090: LDWRKU = N
! 1091: IR = IU + LDWRKU*N
! 1092: LDWRKR = N
! 1093: END IF
! 1094: ITAU = IR + LDWRKR*N
! 1095: IWORK = ITAU + N
! 1096: *
! 1097: * Compute A=Q*R
! 1098: * (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB)
! 1099: *
! 1100: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 1101: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1102: *
! 1103: * Copy R to WORK(IU), zeroing out below it
! 1104: *
! 1105: CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
! 1106: $ LDWRKU )
! 1107: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
! 1108: $ WORK( IU+1 ), LDWRKU )
! 1109: *
! 1110: * Generate Q in A
! 1111: * (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB)
! 1112: *
! 1113: CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
! 1114: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1115: IE = ITAU
! 1116: ITAUQ = IE + N
! 1117: ITAUP = ITAUQ + N
! 1118: IWORK = ITAUP + N
! 1119: *
! 1120: * Bidiagonalize R in WORK(IU), copying result to
! 1121: * WORK(IR)
! 1122: * (Workspace: need 2*N*N+4*N,
! 1123: * prefer 2*N*N+3*N+2*N*NB)
! 1124: *
! 1125: CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
! 1126: $ WORK( IE ), WORK( ITAUQ ),
! 1127: $ WORK( ITAUP ), WORK( IWORK ),
! 1128: $ LWORK-IWORK+1, IERR )
! 1129: CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU,
! 1130: $ WORK( IR ), LDWRKR )
! 1131: *
! 1132: * Generate left bidiagonalizing vectors in WORK(IU)
! 1133: * (Workspace: need 2*N*N+4*N, prefer 2*N*N+3*N+N*NB)
! 1134: *
! 1135: CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
! 1136: $ WORK( ITAUQ ), WORK( IWORK ),
! 1137: $ LWORK-IWORK+1, IERR )
! 1138: *
! 1139: * Generate right bidiagonalizing vectors in WORK(IR)
! 1140: * (Workspace: need 2*N*N+4*N-1,
! 1141: * prefer 2*N*N+3*N+(N-1)*NB)
! 1142: *
! 1143: CALL DORGBR( 'P', N, N, N, WORK( IR ), LDWRKR,
! 1144: $ WORK( ITAUP ), WORK( IWORK ),
! 1145: $ LWORK-IWORK+1, IERR )
! 1146: IWORK = IE + N
! 1147: *
! 1148: * Perform bidiagonal QR iteration, computing left
! 1149: * singular vectors of R in WORK(IU) and computing
! 1150: * right singular vectors of R in WORK(IR)
! 1151: * (Workspace: need 2*N*N+BDSPAC)
! 1152: *
! 1153: CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ),
! 1154: $ WORK( IR ), LDWRKR, WORK( IU ),
! 1155: $ LDWRKU, DUM, 1, WORK( IWORK ), INFO )
! 1156: *
! 1157: * Multiply Q in A by left singular vectors of R in
! 1158: * WORK(IU), storing result in U
! 1159: * (Workspace: need N*N)
! 1160: *
! 1161: CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,
! 1162: $ WORK( IU ), LDWRKU, ZERO, U, LDU )
! 1163: *
! 1164: * Copy right singular vectors of R to A
! 1165: * (Workspace: need N*N)
! 1166: *
! 1167: CALL DLACPY( 'F', N, N, WORK( IR ), LDWRKR, A,
! 1168: $ LDA )
! 1169: *
! 1170: ELSE
! 1171: *
! 1172: * Insufficient workspace for a fast algorithm
! 1173: *
! 1174: ITAU = 1
! 1175: IWORK = ITAU + N
! 1176: *
! 1177: * Compute A=Q*R, copying result to U
! 1178: * (Workspace: need 2*N, prefer N+N*NB)
! 1179: *
! 1180: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 1181: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1182: CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
! 1183: *
! 1184: * Generate Q in U
! 1185: * (Workspace: need 2*N, prefer N+N*NB)
! 1186: *
! 1187: CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),
! 1188: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1189: IE = ITAU
! 1190: ITAUQ = IE + N
! 1191: ITAUP = ITAUQ + N
! 1192: IWORK = ITAUP + N
! 1193: *
! 1194: * Zero out below R in A
! 1195: *
! 1196: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),
! 1197: $ LDA )
! 1198: *
! 1199: * Bidiagonalize R in A
! 1200: * (Workspace: need 4*N, prefer 3*N+2*N*NB)
! 1201: *
! 1202: CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
! 1203: $ WORK( ITAUQ ), WORK( ITAUP ),
! 1204: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1205: *
! 1206: * Multiply Q in U by left vectors bidiagonalizing R
! 1207: * (Workspace: need 3*N+M, prefer 3*N+M*NB)
! 1208: *
! 1209: CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
! 1210: $ WORK( ITAUQ ), U, LDU, WORK( IWORK ),
! 1211: $ LWORK-IWORK+1, IERR )
! 1212: *
! 1213: * Generate right vectors bidiagonalizing R in A
! 1214: * (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
! 1215: *
! 1216: CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
! 1217: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1218: IWORK = IE + N
! 1219: *
! 1220: * Perform bidiagonal QR iteration, computing left
! 1221: * singular vectors of A in U and computing right
! 1222: * singular vectors of A in A
! 1223: * (Workspace: need BDSPAC)
! 1224: *
! 1225: CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), A,
! 1226: $ LDA, U, LDU, DUM, 1, WORK( IWORK ),
! 1227: $ INFO )
! 1228: *
! 1229: END IF
! 1230: *
! 1231: ELSE IF( WNTVAS ) THEN
! 1232: *
! 1233: * Path 6 (M much larger than N, JOBU='S', JOBVT='S'
! 1234: * or 'A')
! 1235: * N left singular vectors to be computed in U and
! 1236: * N right singular vectors to be computed in VT
! 1237: *
! 1238: IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN
! 1239: *
! 1240: * Sufficient workspace for a fast algorithm
! 1241: *
! 1242: IU = 1
! 1243: IF( LWORK.GE.WRKBL+LDA*N ) THEN
! 1244: *
! 1245: * WORK(IU) is LDA by N
! 1246: *
! 1247: LDWRKU = LDA
! 1248: ELSE
! 1249: *
! 1250: * WORK(IU) is N by N
! 1251: *
! 1252: LDWRKU = N
! 1253: END IF
! 1254: ITAU = IU + LDWRKU*N
! 1255: IWORK = ITAU + N
! 1256: *
! 1257: * Compute A=Q*R
! 1258: * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
! 1259: *
! 1260: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 1261: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1262: *
! 1263: * Copy R to WORK(IU), zeroing out below it
! 1264: *
! 1265: CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
! 1266: $ LDWRKU )
! 1267: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
! 1268: $ WORK( IU+1 ), LDWRKU )
! 1269: *
! 1270: * Generate Q in A
! 1271: * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
! 1272: *
! 1273: CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),
! 1274: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1275: IE = ITAU
! 1276: ITAUQ = IE + N
! 1277: ITAUP = ITAUQ + N
! 1278: IWORK = ITAUP + N
! 1279: *
! 1280: * Bidiagonalize R in WORK(IU), copying result to VT
! 1281: * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
! 1282: *
! 1283: CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
! 1284: $ WORK( IE ), WORK( ITAUQ ),
! 1285: $ WORK( ITAUP ), WORK( IWORK ),
! 1286: $ LWORK-IWORK+1, IERR )
! 1287: CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, VT,
! 1288: $ LDVT )
! 1289: *
! 1290: * Generate left bidiagonalizing vectors in WORK(IU)
! 1291: * (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
! 1292: *
! 1293: CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
! 1294: $ WORK( ITAUQ ), WORK( IWORK ),
! 1295: $ LWORK-IWORK+1, IERR )
! 1296: *
! 1297: * Generate right bidiagonalizing vectors in VT
! 1298: * (Workspace: need N*N+4*N-1,
! 1299: * prefer N*N+3*N+(N-1)*NB)
! 1300: *
! 1301: CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
! 1302: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1303: IWORK = IE + N
! 1304: *
! 1305: * Perform bidiagonal QR iteration, computing left
! 1306: * singular vectors of R in WORK(IU) and computing
! 1307: * right singular vectors of R in VT
! 1308: * (Workspace: need N*N+BDSPAC)
! 1309: *
! 1310: CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT,
! 1311: $ LDVT, WORK( IU ), LDWRKU, DUM, 1,
! 1312: $ WORK( IWORK ), INFO )
! 1313: *
! 1314: * Multiply Q in A by left singular vectors of R in
! 1315: * WORK(IU), storing result in U
! 1316: * (Workspace: need N*N)
! 1317: *
! 1318: CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,
! 1319: $ WORK( IU ), LDWRKU, ZERO, U, LDU )
! 1320: *
! 1321: ELSE
! 1322: *
! 1323: * Insufficient workspace for a fast algorithm
! 1324: *
! 1325: ITAU = 1
! 1326: IWORK = ITAU + N
! 1327: *
! 1328: * Compute A=Q*R, copying result to U
! 1329: * (Workspace: need 2*N, prefer N+N*NB)
! 1330: *
! 1331: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 1332: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1333: CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
! 1334: *
! 1335: * Generate Q in U
! 1336: * (Workspace: need 2*N, prefer N+N*NB)
! 1337: *
! 1338: CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),
! 1339: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1340: *
! 1341: * Copy R to VT, zeroing out below it
! 1342: *
! 1343: CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
! 1344: IF( N.GT.1 )
! 1345: $ CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
! 1346: $ VT( 2, 1 ), LDVT )
! 1347: IE = ITAU
! 1348: ITAUQ = IE + N
! 1349: ITAUP = ITAUQ + N
! 1350: IWORK = ITAUP + N
! 1351: *
! 1352: * Bidiagonalize R in VT
! 1353: * (Workspace: need 4*N, prefer 3*N+2*N*NB)
! 1354: *
! 1355: CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
! 1356: $ WORK( ITAUQ ), WORK( ITAUP ),
! 1357: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1358: *
! 1359: * Multiply Q in U by left bidiagonalizing vectors
! 1360: * in VT
! 1361: * (Workspace: need 3*N+M, prefer 3*N+M*NB)
! 1362: *
! 1363: CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,
! 1364: $ WORK( ITAUQ ), U, LDU, WORK( IWORK ),
! 1365: $ LWORK-IWORK+1, IERR )
! 1366: *
! 1367: * Generate right bidiagonalizing vectors in VT
! 1368: * (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
! 1369: *
! 1370: CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
! 1371: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1372: IWORK = IE + N
! 1373: *
! 1374: * Perform bidiagonal QR iteration, computing left
! 1375: * singular vectors of A in U and computing right
! 1376: * singular vectors of A in VT
! 1377: * (Workspace: need BDSPAC)
! 1378: *
! 1379: CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT,
! 1380: $ LDVT, U, LDU, DUM, 1, WORK( IWORK ),
! 1381: $ INFO )
! 1382: *
! 1383: END IF
! 1384: *
! 1385: END IF
! 1386: *
! 1387: ELSE IF( WNTUA ) THEN
! 1388: *
! 1389: IF( WNTVN ) THEN
! 1390: *
! 1391: * Path 7 (M much larger than N, JOBU='A', JOBVT='N')
! 1392: * M left singular vectors to be computed in U and
! 1393: * no right singular vectors to be computed
! 1394: *
! 1395: IF( LWORK.GE.N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN
! 1396: *
! 1397: * Sufficient workspace for a fast algorithm
! 1398: *
! 1399: IR = 1
! 1400: IF( LWORK.GE.WRKBL+LDA*N ) THEN
! 1401: *
! 1402: * WORK(IR) is LDA by N
! 1403: *
! 1404: LDWRKR = LDA
! 1405: ELSE
! 1406: *
! 1407: * WORK(IR) is N by N
! 1408: *
! 1409: LDWRKR = N
! 1410: END IF
! 1411: ITAU = IR + LDWRKR*N
! 1412: IWORK = ITAU + N
! 1413: *
! 1414: * Compute A=Q*R, copying result to U
! 1415: * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
! 1416: *
! 1417: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 1418: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1419: CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
! 1420: *
! 1421: * Copy R to WORK(IR), zeroing out below it
! 1422: *
! 1423: CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ),
! 1424: $ LDWRKR )
! 1425: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
! 1426: $ WORK( IR+1 ), LDWRKR )
! 1427: *
! 1428: * Generate Q in U
! 1429: * (Workspace: need N*N+N+M, prefer N*N+N+M*NB)
! 1430: *
! 1431: CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
! 1432: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1433: IE = ITAU
! 1434: ITAUQ = IE + N
! 1435: ITAUP = ITAUQ + N
! 1436: IWORK = ITAUP + N
! 1437: *
! 1438: * Bidiagonalize R in WORK(IR)
! 1439: * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
! 1440: *
! 1441: CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S,
! 1442: $ WORK( IE ), WORK( ITAUQ ),
! 1443: $ WORK( ITAUP ), WORK( IWORK ),
! 1444: $ LWORK-IWORK+1, IERR )
! 1445: *
! 1446: * Generate left bidiagonalizing vectors in WORK(IR)
! 1447: * (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
! 1448: *
! 1449: CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,
! 1450: $ WORK( ITAUQ ), WORK( IWORK ),
! 1451: $ LWORK-IWORK+1, IERR )
! 1452: IWORK = IE + N
! 1453: *
! 1454: * Perform bidiagonal QR iteration, computing left
! 1455: * singular vectors of R in WORK(IR)
! 1456: * (Workspace: need N*N+BDSPAC)
! 1457: *
! 1458: CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM,
! 1459: $ 1, WORK( IR ), LDWRKR, DUM, 1,
! 1460: $ WORK( IWORK ), INFO )
! 1461: *
! 1462: * Multiply Q in U by left singular vectors of R in
! 1463: * WORK(IR), storing result in A
! 1464: * (Workspace: need N*N)
! 1465: *
! 1466: CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,
! 1467: $ WORK( IR ), LDWRKR, ZERO, A, LDA )
! 1468: *
! 1469: * Copy left singular vectors of A from A to U
! 1470: *
! 1471: CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
! 1472: *
! 1473: ELSE
! 1474: *
! 1475: * Insufficient workspace for a fast algorithm
! 1476: *
! 1477: ITAU = 1
! 1478: IWORK = ITAU + N
! 1479: *
! 1480: * Compute A=Q*R, copying result to U
! 1481: * (Workspace: need 2*N, prefer N+N*NB)
! 1482: *
! 1483: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 1484: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1485: CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
! 1486: *
! 1487: * Generate Q in U
! 1488: * (Workspace: need N+M, prefer N+M*NB)
! 1489: *
! 1490: CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
! 1491: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1492: IE = ITAU
! 1493: ITAUQ = IE + N
! 1494: ITAUP = ITAUQ + N
! 1495: IWORK = ITAUP + N
! 1496: *
! 1497: * Zero out below R in A
! 1498: *
! 1499: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),
! 1500: $ LDA )
! 1501: *
! 1502: * Bidiagonalize R in A
! 1503: * (Workspace: need 4*N, prefer 3*N+2*N*NB)
! 1504: *
! 1505: CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
! 1506: $ WORK( ITAUQ ), WORK( ITAUP ),
! 1507: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1508: *
! 1509: * Multiply Q in U by left bidiagonalizing vectors
! 1510: * in A
! 1511: * (Workspace: need 3*N+M, prefer 3*N+M*NB)
! 1512: *
! 1513: CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
! 1514: $ WORK( ITAUQ ), U, LDU, WORK( IWORK ),
! 1515: $ LWORK-IWORK+1, IERR )
! 1516: IWORK = IE + N
! 1517: *
! 1518: * Perform bidiagonal QR iteration, computing left
! 1519: * singular vectors of A in U
! 1520: * (Workspace: need BDSPAC)
! 1521: *
! 1522: CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM,
! 1523: $ 1, U, LDU, DUM, 1, WORK( IWORK ),
! 1524: $ INFO )
! 1525: *
! 1526: END IF
! 1527: *
! 1528: ELSE IF( WNTVO ) THEN
! 1529: *
! 1530: * Path 8 (M much larger than N, JOBU='A', JOBVT='O')
! 1531: * M left singular vectors to be computed in U and
! 1532: * N right singular vectors to be overwritten on A
! 1533: *
! 1534: IF( LWORK.GE.2*N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN
! 1535: *
! 1536: * Sufficient workspace for a fast algorithm
! 1537: *
! 1538: IU = 1
! 1539: IF( LWORK.GE.WRKBL+2*LDA*N ) THEN
! 1540: *
! 1541: * WORK(IU) is LDA by N and WORK(IR) is LDA by N
! 1542: *
! 1543: LDWRKU = LDA
! 1544: IR = IU + LDWRKU*N
! 1545: LDWRKR = LDA
! 1546: ELSE IF( LWORK.GE.WRKBL+( LDA+N )*N ) THEN
! 1547: *
! 1548: * WORK(IU) is LDA by N and WORK(IR) is N by N
! 1549: *
! 1550: LDWRKU = LDA
! 1551: IR = IU + LDWRKU*N
! 1552: LDWRKR = N
! 1553: ELSE
! 1554: *
! 1555: * WORK(IU) is N by N and WORK(IR) is N by N
! 1556: *
! 1557: LDWRKU = N
! 1558: IR = IU + LDWRKU*N
! 1559: LDWRKR = N
! 1560: END IF
! 1561: ITAU = IR + LDWRKR*N
! 1562: IWORK = ITAU + N
! 1563: *
! 1564: * Compute A=Q*R, copying result to U
! 1565: * (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB)
! 1566: *
! 1567: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 1568: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1569: CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
! 1570: *
! 1571: * Generate Q in U
! 1572: * (Workspace: need 2*N*N+N+M, prefer 2*N*N+N+M*NB)
! 1573: *
! 1574: CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
! 1575: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1576: *
! 1577: * Copy R to WORK(IU), zeroing out below it
! 1578: *
! 1579: CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
! 1580: $ LDWRKU )
! 1581: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
! 1582: $ WORK( IU+1 ), LDWRKU )
! 1583: IE = ITAU
! 1584: ITAUQ = IE + N
! 1585: ITAUP = ITAUQ + N
! 1586: IWORK = ITAUP + N
! 1587: *
! 1588: * Bidiagonalize R in WORK(IU), copying result to
! 1589: * WORK(IR)
! 1590: * (Workspace: need 2*N*N+4*N,
! 1591: * prefer 2*N*N+3*N+2*N*NB)
! 1592: *
! 1593: CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
! 1594: $ WORK( IE ), WORK( ITAUQ ),
! 1595: $ WORK( ITAUP ), WORK( IWORK ),
! 1596: $ LWORK-IWORK+1, IERR )
! 1597: CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU,
! 1598: $ WORK( IR ), LDWRKR )
! 1599: *
! 1600: * Generate left bidiagonalizing vectors in WORK(IU)
! 1601: * (Workspace: need 2*N*N+4*N, prefer 2*N*N+3*N+N*NB)
! 1602: *
! 1603: CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
! 1604: $ WORK( ITAUQ ), WORK( IWORK ),
! 1605: $ LWORK-IWORK+1, IERR )
! 1606: *
! 1607: * Generate right bidiagonalizing vectors in WORK(IR)
! 1608: * (Workspace: need 2*N*N+4*N-1,
! 1609: * prefer 2*N*N+3*N+(N-1)*NB)
! 1610: *
! 1611: CALL DORGBR( 'P', N, N, N, WORK( IR ), LDWRKR,
! 1612: $ WORK( ITAUP ), WORK( IWORK ),
! 1613: $ LWORK-IWORK+1, IERR )
! 1614: IWORK = IE + N
! 1615: *
! 1616: * Perform bidiagonal QR iteration, computing left
! 1617: * singular vectors of R in WORK(IU) and computing
! 1618: * right singular vectors of R in WORK(IR)
! 1619: * (Workspace: need 2*N*N+BDSPAC)
! 1620: *
! 1621: CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ),
! 1622: $ WORK( IR ), LDWRKR, WORK( IU ),
! 1623: $ LDWRKU, DUM, 1, WORK( IWORK ), INFO )
! 1624: *
! 1625: * Multiply Q in U by left singular vectors of R in
! 1626: * WORK(IU), storing result in A
! 1627: * (Workspace: need N*N)
! 1628: *
! 1629: CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,
! 1630: $ WORK( IU ), LDWRKU, ZERO, A, LDA )
! 1631: *
! 1632: * Copy left singular vectors of A from A to U
! 1633: *
! 1634: CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
! 1635: *
! 1636: * Copy right singular vectors of R from WORK(IR) to A
! 1637: *
! 1638: CALL DLACPY( 'F', N, N, WORK( IR ), LDWRKR, A,
! 1639: $ LDA )
! 1640: *
! 1641: ELSE
! 1642: *
! 1643: * Insufficient workspace for a fast algorithm
! 1644: *
! 1645: ITAU = 1
! 1646: IWORK = ITAU + N
! 1647: *
! 1648: * Compute A=Q*R, copying result to U
! 1649: * (Workspace: need 2*N, prefer N+N*NB)
! 1650: *
! 1651: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 1652: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1653: CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
! 1654: *
! 1655: * Generate Q in U
! 1656: * (Workspace: need N+M, prefer N+M*NB)
! 1657: *
! 1658: CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
! 1659: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1660: IE = ITAU
! 1661: ITAUQ = IE + N
! 1662: ITAUP = ITAUQ + N
! 1663: IWORK = ITAUP + N
! 1664: *
! 1665: * Zero out below R in A
! 1666: *
! 1667: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),
! 1668: $ LDA )
! 1669: *
! 1670: * Bidiagonalize R in A
! 1671: * (Workspace: need 4*N, prefer 3*N+2*N*NB)
! 1672: *
! 1673: CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),
! 1674: $ WORK( ITAUQ ), WORK( ITAUP ),
! 1675: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1676: *
! 1677: * Multiply Q in U by left bidiagonalizing vectors
! 1678: * in A
! 1679: * (Workspace: need 3*N+M, prefer 3*N+M*NB)
! 1680: *
! 1681: CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,
! 1682: $ WORK( ITAUQ ), U, LDU, WORK( IWORK ),
! 1683: $ LWORK-IWORK+1, IERR )
! 1684: *
! 1685: * Generate right bidiagonalizing vectors in A
! 1686: * (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
! 1687: *
! 1688: CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
! 1689: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1690: IWORK = IE + N
! 1691: *
! 1692: * Perform bidiagonal QR iteration, computing left
! 1693: * singular vectors of A in U and computing right
! 1694: * singular vectors of A in A
! 1695: * (Workspace: need BDSPAC)
! 1696: *
! 1697: CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), A,
! 1698: $ LDA, U, LDU, DUM, 1, WORK( IWORK ),
! 1699: $ INFO )
! 1700: *
! 1701: END IF
! 1702: *
! 1703: ELSE IF( WNTVAS ) THEN
! 1704: *
! 1705: * Path 9 (M much larger than N, JOBU='A', JOBVT='S'
! 1706: * or 'A')
! 1707: * M left singular vectors to be computed in U and
! 1708: * N right singular vectors to be computed in VT
! 1709: *
! 1710: IF( LWORK.GE.N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN
! 1711: *
! 1712: * Sufficient workspace for a fast algorithm
! 1713: *
! 1714: IU = 1
! 1715: IF( LWORK.GE.WRKBL+LDA*N ) THEN
! 1716: *
! 1717: * WORK(IU) is LDA by N
! 1718: *
! 1719: LDWRKU = LDA
! 1720: ELSE
! 1721: *
! 1722: * WORK(IU) is N by N
! 1723: *
! 1724: LDWRKU = N
! 1725: END IF
! 1726: ITAU = IU + LDWRKU*N
! 1727: IWORK = ITAU + N
! 1728: *
! 1729: * Compute A=Q*R, copying result to U
! 1730: * (Workspace: need N*N+2*N, prefer N*N+N+N*NB)
! 1731: *
! 1732: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 1733: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1734: CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
! 1735: *
! 1736: * Generate Q in U
! 1737: * (Workspace: need N*N+N+M, prefer N*N+N+M*NB)
! 1738: *
! 1739: CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
! 1740: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1741: *
! 1742: * Copy R to WORK(IU), zeroing out below it
! 1743: *
! 1744: CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),
! 1745: $ LDWRKU )
! 1746: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
! 1747: $ WORK( IU+1 ), LDWRKU )
! 1748: IE = ITAU
! 1749: ITAUQ = IE + N
! 1750: ITAUP = ITAUQ + N
! 1751: IWORK = ITAUP + N
! 1752: *
! 1753: * Bidiagonalize R in WORK(IU), copying result to VT
! 1754: * (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)
! 1755: *
! 1756: CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,
! 1757: $ WORK( IE ), WORK( ITAUQ ),
! 1758: $ WORK( ITAUP ), WORK( IWORK ),
! 1759: $ LWORK-IWORK+1, IERR )
! 1760: CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, VT,
! 1761: $ LDVT )
! 1762: *
! 1763: * Generate left bidiagonalizing vectors in WORK(IU)
! 1764: * (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)
! 1765: *
! 1766: CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,
! 1767: $ WORK( ITAUQ ), WORK( IWORK ),
! 1768: $ LWORK-IWORK+1, IERR )
! 1769: *
! 1770: * Generate right bidiagonalizing vectors in VT
! 1771: * (Workspace: need N*N+4*N-1,
! 1772: * prefer N*N+3*N+(N-1)*NB)
! 1773: *
! 1774: CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
! 1775: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1776: IWORK = IE + N
! 1777: *
! 1778: * Perform bidiagonal QR iteration, computing left
! 1779: * singular vectors of R in WORK(IU) and computing
! 1780: * right singular vectors of R in VT
! 1781: * (Workspace: need N*N+BDSPAC)
! 1782: *
! 1783: CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT,
! 1784: $ LDVT, WORK( IU ), LDWRKU, DUM, 1,
! 1785: $ WORK( IWORK ), INFO )
! 1786: *
! 1787: * Multiply Q in U by left singular vectors of R in
! 1788: * WORK(IU), storing result in A
! 1789: * (Workspace: need N*N)
! 1790: *
! 1791: CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,
! 1792: $ WORK( IU ), LDWRKU, ZERO, A, LDA )
! 1793: *
! 1794: * Copy left singular vectors of A from A to U
! 1795: *
! 1796: CALL DLACPY( 'F', M, N, A, LDA, U, LDU )
! 1797: *
! 1798: ELSE
! 1799: *
! 1800: * Insufficient workspace for a fast algorithm
! 1801: *
! 1802: ITAU = 1
! 1803: IWORK = ITAU + N
! 1804: *
! 1805: * Compute A=Q*R, copying result to U
! 1806: * (Workspace: need 2*N, prefer N+N*NB)
! 1807: *
! 1808: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),
! 1809: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1810: CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
! 1811: *
! 1812: * Generate Q in U
! 1813: * (Workspace: need N+M, prefer N+M*NB)
! 1814: *
! 1815: CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),
! 1816: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1817: *
! 1818: * Copy R from A to VT, zeroing out below it
! 1819: *
! 1820: CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
! 1821: IF( N.GT.1 )
! 1822: $ CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,
! 1823: $ VT( 2, 1 ), LDVT )
! 1824: IE = ITAU
! 1825: ITAUQ = IE + N
! 1826: ITAUP = ITAUQ + N
! 1827: IWORK = ITAUP + N
! 1828: *
! 1829: * Bidiagonalize R in VT
! 1830: * (Workspace: need 4*N, prefer 3*N+2*N*NB)
! 1831: *
! 1832: CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),
! 1833: $ WORK( ITAUQ ), WORK( ITAUP ),
! 1834: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1835: *
! 1836: * Multiply Q in U by left bidiagonalizing vectors
! 1837: * in VT
! 1838: * (Workspace: need 3*N+M, prefer 3*N+M*NB)
! 1839: *
! 1840: CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,
! 1841: $ WORK( ITAUQ ), U, LDU, WORK( IWORK ),
! 1842: $ LWORK-IWORK+1, IERR )
! 1843: *
! 1844: * Generate right bidiagonalizing vectors in VT
! 1845: * (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
! 1846: *
! 1847: CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
! 1848: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1849: IWORK = IE + N
! 1850: *
! 1851: * Perform bidiagonal QR iteration, computing left
! 1852: * singular vectors of A in U and computing right
! 1853: * singular vectors of A in VT
! 1854: * (Workspace: need BDSPAC)
! 1855: *
! 1856: CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT,
! 1857: $ LDVT, U, LDU, DUM, 1, WORK( IWORK ),
! 1858: $ INFO )
! 1859: *
! 1860: END IF
! 1861: *
! 1862: END IF
! 1863: *
! 1864: END IF
! 1865: *
! 1866: ELSE
! 1867: *
! 1868: * M .LT. MNTHR
! 1869: *
! 1870: * Path 10 (M at least N, but not much larger)
! 1871: * Reduce to bidiagonal form without QR decomposition
! 1872: *
! 1873: IE = 1
! 1874: ITAUQ = IE + N
! 1875: ITAUP = ITAUQ + N
! 1876: IWORK = ITAUP + N
! 1877: *
! 1878: * Bidiagonalize A
! 1879: * (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)
! 1880: *
! 1881: CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
! 1882: $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
! 1883: $ IERR )
! 1884: IF( WNTUAS ) THEN
! 1885: *
! 1886: * If left singular vectors desired in U, copy result to U
! 1887: * and generate left bidiagonalizing vectors in U
! 1888: * (Workspace: need 3*N+NCU, prefer 3*N+NCU*NB)
! 1889: *
! 1890: CALL DLACPY( 'L', M, N, A, LDA, U, LDU )
! 1891: IF( WNTUS )
! 1892: $ NCU = N
! 1893: IF( WNTUA )
! 1894: $ NCU = M
! 1895: CALL DORGBR( 'Q', M, NCU, N, U, LDU, WORK( ITAUQ ),
! 1896: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1897: END IF
! 1898: IF( WNTVAS ) THEN
! 1899: *
! 1900: * If right singular vectors desired in VT, copy result to
! 1901: * VT and generate right bidiagonalizing vectors in VT
! 1902: * (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
! 1903: *
! 1904: CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )
! 1905: CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),
! 1906: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1907: END IF
! 1908: IF( WNTUO ) THEN
! 1909: *
! 1910: * If left singular vectors desired in A, generate left
! 1911: * bidiagonalizing vectors in A
! 1912: * (Workspace: need 4*N, prefer 3*N+N*NB)
! 1913: *
! 1914: CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),
! 1915: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1916: END IF
! 1917: IF( WNTVO ) THEN
! 1918: *
! 1919: * If right singular vectors desired in A, generate right
! 1920: * bidiagonalizing vectors in A
! 1921: * (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)
! 1922: *
! 1923: CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),
! 1924: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 1925: END IF
! 1926: IWORK = IE + N
! 1927: IF( WNTUAS .OR. WNTUO )
! 1928: $ NRU = M
! 1929: IF( WNTUN )
! 1930: $ NRU = 0
! 1931: IF( WNTVAS .OR. WNTVO )
! 1932: $ NCVT = N
! 1933: IF( WNTVN )
! 1934: $ NCVT = 0
! 1935: IF( ( .NOT.WNTUO ) .AND. ( .NOT.WNTVO ) ) THEN
! 1936: *
! 1937: * Perform bidiagonal QR iteration, if desired, computing
! 1938: * left singular vectors in U and computing right singular
! 1939: * vectors in VT
! 1940: * (Workspace: need BDSPAC)
! 1941: *
! 1942: CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), VT,
! 1943: $ LDVT, U, LDU, DUM, 1, WORK( IWORK ), INFO )
! 1944: ELSE IF( ( .NOT.WNTUO ) .AND. WNTVO ) THEN
! 1945: *
! 1946: * Perform bidiagonal QR iteration, if desired, computing
! 1947: * left singular vectors in U and computing right singular
! 1948: * vectors in A
! 1949: * (Workspace: need BDSPAC)
! 1950: *
! 1951: CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), A, LDA,
! 1952: $ U, LDU, DUM, 1, WORK( IWORK ), INFO )
! 1953: ELSE
! 1954: *
! 1955: * Perform bidiagonal QR iteration, if desired, computing
! 1956: * left singular vectors in A and computing right singular
! 1957: * vectors in VT
! 1958: * (Workspace: need BDSPAC)
! 1959: *
! 1960: CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), VT,
! 1961: $ LDVT, A, LDA, DUM, 1, WORK( IWORK ), INFO )
! 1962: END IF
! 1963: *
! 1964: END IF
! 1965: *
! 1966: ELSE
! 1967: *
! 1968: * A has more columns than rows. If A has sufficiently more
! 1969: * columns than rows, first reduce using the LQ decomposition (if
! 1970: * sufficient workspace available)
! 1971: *
! 1972: IF( N.GE.MNTHR ) THEN
! 1973: *
! 1974: IF( WNTVN ) THEN
! 1975: *
! 1976: * Path 1t(N much larger than M, JOBVT='N')
! 1977: * No right singular vectors to be computed
! 1978: *
! 1979: ITAU = 1
! 1980: IWORK = ITAU + M
! 1981: *
! 1982: * Compute A=L*Q
! 1983: * (Workspace: need 2*M, prefer M+M*NB)
! 1984: *
! 1985: CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
! 1986: $ LWORK-IWORK+1, IERR )
! 1987: *
! 1988: * Zero out above L
! 1989: *
! 1990: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )
! 1991: IE = 1
! 1992: ITAUQ = IE + M
! 1993: ITAUP = ITAUQ + M
! 1994: IWORK = ITAUP + M
! 1995: *
! 1996: * Bidiagonalize L in A
! 1997: * (Workspace: need 4*M, prefer 3*M+2*M*NB)
! 1998: *
! 1999: CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
! 2000: $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
! 2001: $ IERR )
! 2002: IF( WNTUO .OR. WNTUAS ) THEN
! 2003: *
! 2004: * If left singular vectors desired, generate Q
! 2005: * (Workspace: need 4*M, prefer 3*M+M*NB)
! 2006: *
! 2007: CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),
! 2008: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2009: END IF
! 2010: IWORK = IE + M
! 2011: NRU = 0
! 2012: IF( WNTUO .OR. WNTUAS )
! 2013: $ NRU = M
! 2014: *
! 2015: * Perform bidiagonal QR iteration, computing left singular
! 2016: * vectors of A in A if desired
! 2017: * (Workspace: need BDSPAC)
! 2018: *
! 2019: CALL DBDSQR( 'U', M, 0, NRU, 0, S, WORK( IE ), DUM, 1, A,
! 2020: $ LDA, DUM, 1, WORK( IWORK ), INFO )
! 2021: *
! 2022: * If left singular vectors desired in U, copy them there
! 2023: *
! 2024: IF( WNTUAS )
! 2025: $ CALL DLACPY( 'F', M, M, A, LDA, U, LDU )
! 2026: *
! 2027: ELSE IF( WNTVO .AND. WNTUN ) THEN
! 2028: *
! 2029: * Path 2t(N much larger than M, JOBU='N', JOBVT='O')
! 2030: * M right singular vectors to be overwritten on A and
! 2031: * no left singular vectors to be computed
! 2032: *
! 2033: IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
! 2034: *
! 2035: * Sufficient workspace for a fast algorithm
! 2036: *
! 2037: IR = 1
! 2038: IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+LDA*M ) THEN
! 2039: *
! 2040: * WORK(IU) is LDA by N and WORK(IR) is LDA by M
! 2041: *
! 2042: LDWRKU = LDA
! 2043: CHUNK = N
! 2044: LDWRKR = LDA
! 2045: ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+M*M ) THEN
! 2046: *
! 2047: * WORK(IU) is LDA by N and WORK(IR) is M by M
! 2048: *
! 2049: LDWRKU = LDA
! 2050: CHUNK = N
! 2051: LDWRKR = M
! 2052: ELSE
! 2053: *
! 2054: * WORK(IU) is M by CHUNK and WORK(IR) is M by M
! 2055: *
! 2056: LDWRKU = M
! 2057: CHUNK = ( LWORK-M*M-M ) / M
! 2058: LDWRKR = M
! 2059: END IF
! 2060: ITAU = IR + LDWRKR*M
! 2061: IWORK = ITAU + M
! 2062: *
! 2063: * Compute A=L*Q
! 2064: * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
! 2065: *
! 2066: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2067: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2068: *
! 2069: * Copy L to WORK(IR) and zero out above it
! 2070: *
! 2071: CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ), LDWRKR )
! 2072: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
! 2073: $ WORK( IR+LDWRKR ), LDWRKR )
! 2074: *
! 2075: * Generate Q in A
! 2076: * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
! 2077: *
! 2078: CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
! 2079: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2080: IE = ITAU
! 2081: ITAUQ = IE + M
! 2082: ITAUP = ITAUQ + M
! 2083: IWORK = ITAUP + M
! 2084: *
! 2085: * Bidiagonalize L in WORK(IR)
! 2086: * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
! 2087: *
! 2088: CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S, WORK( IE ),
! 2089: $ WORK( ITAUQ ), WORK( ITAUP ),
! 2090: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2091: *
! 2092: * Generate right vectors bidiagonalizing L
! 2093: * (Workspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB)
! 2094: *
! 2095: CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
! 2096: $ WORK( ITAUP ), WORK( IWORK ),
! 2097: $ LWORK-IWORK+1, IERR )
! 2098: IWORK = IE + M
! 2099: *
! 2100: * Perform bidiagonal QR iteration, computing right
! 2101: * singular vectors of L in WORK(IR)
! 2102: * (Workspace: need M*M+BDSPAC)
! 2103: *
! 2104: CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),
! 2105: $ WORK( IR ), LDWRKR, DUM, 1, DUM, 1,
! 2106: $ WORK( IWORK ), INFO )
! 2107: IU = IE + M
! 2108: *
! 2109: * Multiply right singular vectors of L in WORK(IR) by Q
! 2110: * in A, storing result in WORK(IU) and copying to A
! 2111: * (Workspace: need M*M+2*M, prefer M*M+M*N+M)
! 2112: *
! 2113: DO 30 I = 1, N, CHUNK
! 2114: BLK = MIN( N-I+1, CHUNK )
! 2115: CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IR ),
! 2116: $ LDWRKR, A( 1, I ), LDA, ZERO,
! 2117: $ WORK( IU ), LDWRKU )
! 2118: CALL DLACPY( 'F', M, BLK, WORK( IU ), LDWRKU,
! 2119: $ A( 1, I ), LDA )
! 2120: 30 CONTINUE
! 2121: *
! 2122: ELSE
! 2123: *
! 2124: * Insufficient workspace for a fast algorithm
! 2125: *
! 2126: IE = 1
! 2127: ITAUQ = IE + M
! 2128: ITAUP = ITAUQ + M
! 2129: IWORK = ITAUP + M
! 2130: *
! 2131: * Bidiagonalize A
! 2132: * (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
! 2133: *
! 2134: CALL DGEBRD( M, N, A, LDA, S, WORK( IE ),
! 2135: $ WORK( ITAUQ ), WORK( ITAUP ),
! 2136: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2137: *
! 2138: * Generate right vectors bidiagonalizing A
! 2139: * (Workspace: need 4*M, prefer 3*M+M*NB)
! 2140: *
! 2141: CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
! 2142: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2143: IWORK = IE + M
! 2144: *
! 2145: * Perform bidiagonal QR iteration, computing right
! 2146: * singular vectors of A in A
! 2147: * (Workspace: need BDSPAC)
! 2148: *
! 2149: CALL DBDSQR( 'L', M, N, 0, 0, S, WORK( IE ), A, LDA,
! 2150: $ DUM, 1, DUM, 1, WORK( IWORK ), INFO )
! 2151: *
! 2152: END IF
! 2153: *
! 2154: ELSE IF( WNTVO .AND. WNTUAS ) THEN
! 2155: *
! 2156: * Path 3t(N much larger than M, JOBU='S' or 'A', JOBVT='O')
! 2157: * M right singular vectors to be overwritten on A and
! 2158: * M left singular vectors to be computed in U
! 2159: *
! 2160: IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
! 2161: *
! 2162: * Sufficient workspace for a fast algorithm
! 2163: *
! 2164: IR = 1
! 2165: IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+LDA*M ) THEN
! 2166: *
! 2167: * WORK(IU) is LDA by N and WORK(IR) is LDA by M
! 2168: *
! 2169: LDWRKU = LDA
! 2170: CHUNK = N
! 2171: LDWRKR = LDA
! 2172: ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+M*M ) THEN
! 2173: *
! 2174: * WORK(IU) is LDA by N and WORK(IR) is M by M
! 2175: *
! 2176: LDWRKU = LDA
! 2177: CHUNK = N
! 2178: LDWRKR = M
! 2179: ELSE
! 2180: *
! 2181: * WORK(IU) is M by CHUNK and WORK(IR) is M by M
! 2182: *
! 2183: LDWRKU = M
! 2184: CHUNK = ( LWORK-M*M-M ) / M
! 2185: LDWRKR = M
! 2186: END IF
! 2187: ITAU = IR + LDWRKR*M
! 2188: IWORK = ITAU + M
! 2189: *
! 2190: * Compute A=L*Q
! 2191: * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
! 2192: *
! 2193: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2194: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2195: *
! 2196: * Copy L to U, zeroing about above it
! 2197: *
! 2198: CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
! 2199: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
! 2200: $ LDU )
! 2201: *
! 2202: * Generate Q in A
! 2203: * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
! 2204: *
! 2205: CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
! 2206: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2207: IE = ITAU
! 2208: ITAUQ = IE + M
! 2209: ITAUP = ITAUQ + M
! 2210: IWORK = ITAUP + M
! 2211: *
! 2212: * Bidiagonalize L in U, copying result to WORK(IR)
! 2213: * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
! 2214: *
! 2215: CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
! 2216: $ WORK( ITAUQ ), WORK( ITAUP ),
! 2217: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2218: CALL DLACPY( 'U', M, M, U, LDU, WORK( IR ), LDWRKR )
! 2219: *
! 2220: * Generate right vectors bidiagonalizing L in WORK(IR)
! 2221: * (Workspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB)
! 2222: *
! 2223: CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
! 2224: $ WORK( ITAUP ), WORK( IWORK ),
! 2225: $ LWORK-IWORK+1, IERR )
! 2226: *
! 2227: * Generate left vectors bidiagonalizing L in U
! 2228: * (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB)
! 2229: *
! 2230: CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
! 2231: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2232: IWORK = IE + M
! 2233: *
! 2234: * Perform bidiagonal QR iteration, computing left
! 2235: * singular vectors of L in U, and computing right
! 2236: * singular vectors of L in WORK(IR)
! 2237: * (Workspace: need M*M+BDSPAC)
! 2238: *
! 2239: CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
! 2240: $ WORK( IR ), LDWRKR, U, LDU, DUM, 1,
! 2241: $ WORK( IWORK ), INFO )
! 2242: IU = IE + M
! 2243: *
! 2244: * Multiply right singular vectors of L in WORK(IR) by Q
! 2245: * in A, storing result in WORK(IU) and copying to A
! 2246: * (Workspace: need M*M+2*M, prefer M*M+M*N+M))
! 2247: *
! 2248: DO 40 I = 1, N, CHUNK
! 2249: BLK = MIN( N-I+1, CHUNK )
! 2250: CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IR ),
! 2251: $ LDWRKR, A( 1, I ), LDA, ZERO,
! 2252: $ WORK( IU ), LDWRKU )
! 2253: CALL DLACPY( 'F', M, BLK, WORK( IU ), LDWRKU,
! 2254: $ A( 1, I ), LDA )
! 2255: 40 CONTINUE
! 2256: *
! 2257: ELSE
! 2258: *
! 2259: * Insufficient workspace for a fast algorithm
! 2260: *
! 2261: ITAU = 1
! 2262: IWORK = ITAU + M
! 2263: *
! 2264: * Compute A=L*Q
! 2265: * (Workspace: need 2*M, prefer M+M*NB)
! 2266: *
! 2267: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2268: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2269: *
! 2270: * Copy L to U, zeroing out above it
! 2271: *
! 2272: CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
! 2273: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
! 2274: $ LDU )
! 2275: *
! 2276: * Generate Q in A
! 2277: * (Workspace: need 2*M, prefer M+M*NB)
! 2278: *
! 2279: CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
! 2280: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2281: IE = ITAU
! 2282: ITAUQ = IE + M
! 2283: ITAUP = ITAUQ + M
! 2284: IWORK = ITAUP + M
! 2285: *
! 2286: * Bidiagonalize L in U
! 2287: * (Workspace: need 4*M, prefer 3*M+2*M*NB)
! 2288: *
! 2289: CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
! 2290: $ WORK( ITAUQ ), WORK( ITAUP ),
! 2291: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2292: *
! 2293: * Multiply right vectors bidiagonalizing L by Q in A
! 2294: * (Workspace: need 3*M+N, prefer 3*M+N*NB)
! 2295: *
! 2296: CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,
! 2297: $ WORK( ITAUP ), A, LDA, WORK( IWORK ),
! 2298: $ LWORK-IWORK+1, IERR )
! 2299: *
! 2300: * Generate left vectors bidiagonalizing L in U
! 2301: * (Workspace: need 4*M, prefer 3*M+M*NB)
! 2302: *
! 2303: CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
! 2304: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2305: IWORK = IE + M
! 2306: *
! 2307: * Perform bidiagonal QR iteration, computing left
! 2308: * singular vectors of A in U and computing right
! 2309: * singular vectors of A in A
! 2310: * (Workspace: need BDSPAC)
! 2311: *
! 2312: CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), A, LDA,
! 2313: $ U, LDU, DUM, 1, WORK( IWORK ), INFO )
! 2314: *
! 2315: END IF
! 2316: *
! 2317: ELSE IF( WNTVS ) THEN
! 2318: *
! 2319: IF( WNTUN ) THEN
! 2320: *
! 2321: * Path 4t(N much larger than M, JOBU='N', JOBVT='S')
! 2322: * M right singular vectors to be computed in VT and
! 2323: * no left singular vectors to be computed
! 2324: *
! 2325: IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
! 2326: *
! 2327: * Sufficient workspace for a fast algorithm
! 2328: *
! 2329: IR = 1
! 2330: IF( LWORK.GE.WRKBL+LDA*M ) THEN
! 2331: *
! 2332: * WORK(IR) is LDA by M
! 2333: *
! 2334: LDWRKR = LDA
! 2335: ELSE
! 2336: *
! 2337: * WORK(IR) is M by M
! 2338: *
! 2339: LDWRKR = M
! 2340: END IF
! 2341: ITAU = IR + LDWRKR*M
! 2342: IWORK = ITAU + M
! 2343: *
! 2344: * Compute A=L*Q
! 2345: * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
! 2346: *
! 2347: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2348: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2349: *
! 2350: * Copy L to WORK(IR), zeroing out above it
! 2351: *
! 2352: CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ),
! 2353: $ LDWRKR )
! 2354: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
! 2355: $ WORK( IR+LDWRKR ), LDWRKR )
! 2356: *
! 2357: * Generate Q in A
! 2358: * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
! 2359: *
! 2360: CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
! 2361: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2362: IE = ITAU
! 2363: ITAUQ = IE + M
! 2364: ITAUP = ITAUQ + M
! 2365: IWORK = ITAUP + M
! 2366: *
! 2367: * Bidiagonalize L in WORK(IR)
! 2368: * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
! 2369: *
! 2370: CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S,
! 2371: $ WORK( IE ), WORK( ITAUQ ),
! 2372: $ WORK( ITAUP ), WORK( IWORK ),
! 2373: $ LWORK-IWORK+1, IERR )
! 2374: *
! 2375: * Generate right vectors bidiagonalizing L in
! 2376: * WORK(IR)
! 2377: * (Workspace: need M*M+4*M, prefer M*M+3*M+(M-1)*NB)
! 2378: *
! 2379: CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
! 2380: $ WORK( ITAUP ), WORK( IWORK ),
! 2381: $ LWORK-IWORK+1, IERR )
! 2382: IWORK = IE + M
! 2383: *
! 2384: * Perform bidiagonal QR iteration, computing right
! 2385: * singular vectors of L in WORK(IR)
! 2386: * (Workspace: need M*M+BDSPAC)
! 2387: *
! 2388: CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),
! 2389: $ WORK( IR ), LDWRKR, DUM, 1, DUM, 1,
! 2390: $ WORK( IWORK ), INFO )
! 2391: *
! 2392: * Multiply right singular vectors of L in WORK(IR) by
! 2393: * Q in A, storing result in VT
! 2394: * (Workspace: need M*M)
! 2395: *
! 2396: CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IR ),
! 2397: $ LDWRKR, A, LDA, ZERO, VT, LDVT )
! 2398: *
! 2399: ELSE
! 2400: *
! 2401: * Insufficient workspace for a fast algorithm
! 2402: *
! 2403: ITAU = 1
! 2404: IWORK = ITAU + M
! 2405: *
! 2406: * Compute A=L*Q
! 2407: * (Workspace: need 2*M, prefer M+M*NB)
! 2408: *
! 2409: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2410: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2411: *
! 2412: * Copy result to VT
! 2413: *
! 2414: CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
! 2415: *
! 2416: * Generate Q in VT
! 2417: * (Workspace: need 2*M, prefer M+M*NB)
! 2418: *
! 2419: CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),
! 2420: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2421: IE = ITAU
! 2422: ITAUQ = IE + M
! 2423: ITAUP = ITAUQ + M
! 2424: IWORK = ITAUP + M
! 2425: *
! 2426: * Zero out above L in A
! 2427: *
! 2428: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
! 2429: $ LDA )
! 2430: *
! 2431: * Bidiagonalize L in A
! 2432: * (Workspace: need 4*M, prefer 3*M+2*M*NB)
! 2433: *
! 2434: CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
! 2435: $ WORK( ITAUQ ), WORK( ITAUP ),
! 2436: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2437: *
! 2438: * Multiply right vectors bidiagonalizing L by Q in VT
! 2439: * (Workspace: need 3*M+N, prefer 3*M+N*NB)
! 2440: *
! 2441: CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
! 2442: $ WORK( ITAUP ), VT, LDVT,
! 2443: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2444: IWORK = IE + M
! 2445: *
! 2446: * Perform bidiagonal QR iteration, computing right
! 2447: * singular vectors of A in VT
! 2448: * (Workspace: need BDSPAC)
! 2449: *
! 2450: CALL DBDSQR( 'U', M, N, 0, 0, S, WORK( IE ), VT,
! 2451: $ LDVT, DUM, 1, DUM, 1, WORK( IWORK ),
! 2452: $ INFO )
! 2453: *
! 2454: END IF
! 2455: *
! 2456: ELSE IF( WNTUO ) THEN
! 2457: *
! 2458: * Path 5t(N much larger than M, JOBU='O', JOBVT='S')
! 2459: * M right singular vectors to be computed in VT and
! 2460: * M left singular vectors to be overwritten on A
! 2461: *
! 2462: IF( LWORK.GE.2*M*M+MAX( 4*M, BDSPAC ) ) THEN
! 2463: *
! 2464: * Sufficient workspace for a fast algorithm
! 2465: *
! 2466: IU = 1
! 2467: IF( LWORK.GE.WRKBL+2*LDA*M ) THEN
! 2468: *
! 2469: * WORK(IU) is LDA by M and WORK(IR) is LDA by M
! 2470: *
! 2471: LDWRKU = LDA
! 2472: IR = IU + LDWRKU*M
! 2473: LDWRKR = LDA
! 2474: ELSE IF( LWORK.GE.WRKBL+( LDA+M )*M ) THEN
! 2475: *
! 2476: * WORK(IU) is LDA by M and WORK(IR) is M by M
! 2477: *
! 2478: LDWRKU = LDA
! 2479: IR = IU + LDWRKU*M
! 2480: LDWRKR = M
! 2481: ELSE
! 2482: *
! 2483: * WORK(IU) is M by M and WORK(IR) is M by M
! 2484: *
! 2485: LDWRKU = M
! 2486: IR = IU + LDWRKU*M
! 2487: LDWRKR = M
! 2488: END IF
! 2489: ITAU = IR + LDWRKR*M
! 2490: IWORK = ITAU + M
! 2491: *
! 2492: * Compute A=L*Q
! 2493: * (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB)
! 2494: *
! 2495: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2496: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2497: *
! 2498: * Copy L to WORK(IU), zeroing out below it
! 2499: *
! 2500: CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
! 2501: $ LDWRKU )
! 2502: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
! 2503: $ WORK( IU+LDWRKU ), LDWRKU )
! 2504: *
! 2505: * Generate Q in A
! 2506: * (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB)
! 2507: *
! 2508: CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
! 2509: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2510: IE = ITAU
! 2511: ITAUQ = IE + M
! 2512: ITAUP = ITAUQ + M
! 2513: IWORK = ITAUP + M
! 2514: *
! 2515: * Bidiagonalize L in WORK(IU), copying result to
! 2516: * WORK(IR)
! 2517: * (Workspace: need 2*M*M+4*M,
! 2518: * prefer 2*M*M+3*M+2*M*NB)
! 2519: *
! 2520: CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
! 2521: $ WORK( IE ), WORK( ITAUQ ),
! 2522: $ WORK( ITAUP ), WORK( IWORK ),
! 2523: $ LWORK-IWORK+1, IERR )
! 2524: CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU,
! 2525: $ WORK( IR ), LDWRKR )
! 2526: *
! 2527: * Generate right bidiagonalizing vectors in WORK(IU)
! 2528: * (Workspace: need 2*M*M+4*M-1,
! 2529: * prefer 2*M*M+3*M+(M-1)*NB)
! 2530: *
! 2531: CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
! 2532: $ WORK( ITAUP ), WORK( IWORK ),
! 2533: $ LWORK-IWORK+1, IERR )
! 2534: *
! 2535: * Generate left bidiagonalizing vectors in WORK(IR)
! 2536: * (Workspace: need 2*M*M+4*M, prefer 2*M*M+3*M+M*NB)
! 2537: *
! 2538: CALL DORGBR( 'Q', M, M, M, WORK( IR ), LDWRKR,
! 2539: $ WORK( ITAUQ ), WORK( IWORK ),
! 2540: $ LWORK-IWORK+1, IERR )
! 2541: IWORK = IE + M
! 2542: *
! 2543: * Perform bidiagonal QR iteration, computing left
! 2544: * singular vectors of L in WORK(IR) and computing
! 2545: * right singular vectors of L in WORK(IU)
! 2546: * (Workspace: need 2*M*M+BDSPAC)
! 2547: *
! 2548: CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
! 2549: $ WORK( IU ), LDWRKU, WORK( IR ),
! 2550: $ LDWRKR, DUM, 1, WORK( IWORK ), INFO )
! 2551: *
! 2552: * Multiply right singular vectors of L in WORK(IU) by
! 2553: * Q in A, storing result in VT
! 2554: * (Workspace: need M*M)
! 2555: *
! 2556: CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
! 2557: $ LDWRKU, A, LDA, ZERO, VT, LDVT )
! 2558: *
! 2559: * Copy left singular vectors of L to A
! 2560: * (Workspace: need M*M)
! 2561: *
! 2562: CALL DLACPY( 'F', M, M, WORK( IR ), LDWRKR, A,
! 2563: $ LDA )
! 2564: *
! 2565: ELSE
! 2566: *
! 2567: * Insufficient workspace for a fast algorithm
! 2568: *
! 2569: ITAU = 1
! 2570: IWORK = ITAU + M
! 2571: *
! 2572: * Compute A=L*Q, copying result to VT
! 2573: * (Workspace: need 2*M, prefer M+M*NB)
! 2574: *
! 2575: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2576: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2577: CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
! 2578: *
! 2579: * Generate Q in VT
! 2580: * (Workspace: need 2*M, prefer M+M*NB)
! 2581: *
! 2582: CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),
! 2583: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2584: IE = ITAU
! 2585: ITAUQ = IE + M
! 2586: ITAUP = ITAUQ + M
! 2587: IWORK = ITAUP + M
! 2588: *
! 2589: * Zero out above L in A
! 2590: *
! 2591: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
! 2592: $ LDA )
! 2593: *
! 2594: * Bidiagonalize L in A
! 2595: * (Workspace: need 4*M, prefer 3*M+2*M*NB)
! 2596: *
! 2597: CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
! 2598: $ WORK( ITAUQ ), WORK( ITAUP ),
! 2599: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2600: *
! 2601: * Multiply right vectors bidiagonalizing L by Q in VT
! 2602: * (Workspace: need 3*M+N, prefer 3*M+N*NB)
! 2603: *
! 2604: CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
! 2605: $ WORK( ITAUP ), VT, LDVT,
! 2606: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2607: *
! 2608: * Generate left bidiagonalizing vectors of L in A
! 2609: * (Workspace: need 4*M, prefer 3*M+M*NB)
! 2610: *
! 2611: CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),
! 2612: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2613: IWORK = IE + M
! 2614: *
! 2615: * Perform bidiagonal QR iteration, compute left
! 2616: * singular vectors of A in A and compute right
! 2617: * singular vectors of A in VT
! 2618: * (Workspace: need BDSPAC)
! 2619: *
! 2620: CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
! 2621: $ LDVT, A, LDA, DUM, 1, WORK( IWORK ),
! 2622: $ INFO )
! 2623: *
! 2624: END IF
! 2625: *
! 2626: ELSE IF( WNTUAS ) THEN
! 2627: *
! 2628: * Path 6t(N much larger than M, JOBU='S' or 'A',
! 2629: * JOBVT='S')
! 2630: * M right singular vectors to be computed in VT and
! 2631: * M left singular vectors to be computed in U
! 2632: *
! 2633: IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN
! 2634: *
! 2635: * Sufficient workspace for a fast algorithm
! 2636: *
! 2637: IU = 1
! 2638: IF( LWORK.GE.WRKBL+LDA*M ) THEN
! 2639: *
! 2640: * WORK(IU) is LDA by N
! 2641: *
! 2642: LDWRKU = LDA
! 2643: ELSE
! 2644: *
! 2645: * WORK(IU) is LDA by M
! 2646: *
! 2647: LDWRKU = M
! 2648: END IF
! 2649: ITAU = IU + LDWRKU*M
! 2650: IWORK = ITAU + M
! 2651: *
! 2652: * Compute A=L*Q
! 2653: * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
! 2654: *
! 2655: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2656: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2657: *
! 2658: * Copy L to WORK(IU), zeroing out above it
! 2659: *
! 2660: CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
! 2661: $ LDWRKU )
! 2662: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
! 2663: $ WORK( IU+LDWRKU ), LDWRKU )
! 2664: *
! 2665: * Generate Q in A
! 2666: * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
! 2667: *
! 2668: CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),
! 2669: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2670: IE = ITAU
! 2671: ITAUQ = IE + M
! 2672: ITAUP = ITAUQ + M
! 2673: IWORK = ITAUP + M
! 2674: *
! 2675: * Bidiagonalize L in WORK(IU), copying result to U
! 2676: * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
! 2677: *
! 2678: CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
! 2679: $ WORK( IE ), WORK( ITAUQ ),
! 2680: $ WORK( ITAUP ), WORK( IWORK ),
! 2681: $ LWORK-IWORK+1, IERR )
! 2682: CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, U,
! 2683: $ LDU )
! 2684: *
! 2685: * Generate right bidiagonalizing vectors in WORK(IU)
! 2686: * (Workspace: need M*M+4*M-1,
! 2687: * prefer M*M+3*M+(M-1)*NB)
! 2688: *
! 2689: CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
! 2690: $ WORK( ITAUP ), WORK( IWORK ),
! 2691: $ LWORK-IWORK+1, IERR )
! 2692: *
! 2693: * Generate left bidiagonalizing vectors in U
! 2694: * (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB)
! 2695: *
! 2696: CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
! 2697: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2698: IWORK = IE + M
! 2699: *
! 2700: * Perform bidiagonal QR iteration, computing left
! 2701: * singular vectors of L in U and computing right
! 2702: * singular vectors of L in WORK(IU)
! 2703: * (Workspace: need M*M+BDSPAC)
! 2704: *
! 2705: CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
! 2706: $ WORK( IU ), LDWRKU, U, LDU, DUM, 1,
! 2707: $ WORK( IWORK ), INFO )
! 2708: *
! 2709: * Multiply right singular vectors of L in WORK(IU) by
! 2710: * Q in A, storing result in VT
! 2711: * (Workspace: need M*M)
! 2712: *
! 2713: CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
! 2714: $ LDWRKU, A, LDA, ZERO, VT, LDVT )
! 2715: *
! 2716: ELSE
! 2717: *
! 2718: * Insufficient workspace for a fast algorithm
! 2719: *
! 2720: ITAU = 1
! 2721: IWORK = ITAU + M
! 2722: *
! 2723: * Compute A=L*Q, copying result to VT
! 2724: * (Workspace: need 2*M, prefer M+M*NB)
! 2725: *
! 2726: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2727: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2728: CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
! 2729: *
! 2730: * Generate Q in VT
! 2731: * (Workspace: need 2*M, prefer M+M*NB)
! 2732: *
! 2733: CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),
! 2734: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2735: *
! 2736: * Copy L to U, zeroing out above it
! 2737: *
! 2738: CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
! 2739: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
! 2740: $ LDU )
! 2741: IE = ITAU
! 2742: ITAUQ = IE + M
! 2743: ITAUP = ITAUQ + M
! 2744: IWORK = ITAUP + M
! 2745: *
! 2746: * Bidiagonalize L in U
! 2747: * (Workspace: need 4*M, prefer 3*M+2*M*NB)
! 2748: *
! 2749: CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
! 2750: $ WORK( ITAUQ ), WORK( ITAUP ),
! 2751: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2752: *
! 2753: * Multiply right bidiagonalizing vectors in U by Q
! 2754: * in VT
! 2755: * (Workspace: need 3*M+N, prefer 3*M+N*NB)
! 2756: *
! 2757: CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,
! 2758: $ WORK( ITAUP ), VT, LDVT,
! 2759: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2760: *
! 2761: * Generate left bidiagonalizing vectors in U
! 2762: * (Workspace: need 4*M, prefer 3*M+M*NB)
! 2763: *
! 2764: CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
! 2765: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2766: IWORK = IE + M
! 2767: *
! 2768: * Perform bidiagonal QR iteration, computing left
! 2769: * singular vectors of A in U and computing right
! 2770: * singular vectors of A in VT
! 2771: * (Workspace: need BDSPAC)
! 2772: *
! 2773: CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
! 2774: $ LDVT, U, LDU, DUM, 1, WORK( IWORK ),
! 2775: $ INFO )
! 2776: *
! 2777: END IF
! 2778: *
! 2779: END IF
! 2780: *
! 2781: ELSE IF( WNTVA ) THEN
! 2782: *
! 2783: IF( WNTUN ) THEN
! 2784: *
! 2785: * Path 7t(N much larger than M, JOBU='N', JOBVT='A')
! 2786: * N right singular vectors to be computed in VT and
! 2787: * no left singular vectors to be computed
! 2788: *
! 2789: IF( LWORK.GE.M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN
! 2790: *
! 2791: * Sufficient workspace for a fast algorithm
! 2792: *
! 2793: IR = 1
! 2794: IF( LWORK.GE.WRKBL+LDA*M ) THEN
! 2795: *
! 2796: * WORK(IR) is LDA by M
! 2797: *
! 2798: LDWRKR = LDA
! 2799: ELSE
! 2800: *
! 2801: * WORK(IR) is M by M
! 2802: *
! 2803: LDWRKR = M
! 2804: END IF
! 2805: ITAU = IR + LDWRKR*M
! 2806: IWORK = ITAU + M
! 2807: *
! 2808: * Compute A=L*Q, copying result to VT
! 2809: * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
! 2810: *
! 2811: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2812: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2813: CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
! 2814: *
! 2815: * Copy L to WORK(IR), zeroing out above it
! 2816: *
! 2817: CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ),
! 2818: $ LDWRKR )
! 2819: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
! 2820: $ WORK( IR+LDWRKR ), LDWRKR )
! 2821: *
! 2822: * Generate Q in VT
! 2823: * (Workspace: need M*M+M+N, prefer M*M+M+N*NB)
! 2824: *
! 2825: CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
! 2826: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2827: IE = ITAU
! 2828: ITAUQ = IE + M
! 2829: ITAUP = ITAUQ + M
! 2830: IWORK = ITAUP + M
! 2831: *
! 2832: * Bidiagonalize L in WORK(IR)
! 2833: * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
! 2834: *
! 2835: CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S,
! 2836: $ WORK( IE ), WORK( ITAUQ ),
! 2837: $ WORK( ITAUP ), WORK( IWORK ),
! 2838: $ LWORK-IWORK+1, IERR )
! 2839: *
! 2840: * Generate right bidiagonalizing vectors in WORK(IR)
! 2841: * (Workspace: need M*M+4*M-1,
! 2842: * prefer M*M+3*M+(M-1)*NB)
! 2843: *
! 2844: CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,
! 2845: $ WORK( ITAUP ), WORK( IWORK ),
! 2846: $ LWORK-IWORK+1, IERR )
! 2847: IWORK = IE + M
! 2848: *
! 2849: * Perform bidiagonal QR iteration, computing right
! 2850: * singular vectors of L in WORK(IR)
! 2851: * (Workspace: need M*M+BDSPAC)
! 2852: *
! 2853: CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),
! 2854: $ WORK( IR ), LDWRKR, DUM, 1, DUM, 1,
! 2855: $ WORK( IWORK ), INFO )
! 2856: *
! 2857: * Multiply right singular vectors of L in WORK(IR) by
! 2858: * Q in VT, storing result in A
! 2859: * (Workspace: need M*M)
! 2860: *
! 2861: CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IR ),
! 2862: $ LDWRKR, VT, LDVT, ZERO, A, LDA )
! 2863: *
! 2864: * Copy right singular vectors of A from A to VT
! 2865: *
! 2866: CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
! 2867: *
! 2868: ELSE
! 2869: *
! 2870: * Insufficient workspace for a fast algorithm
! 2871: *
! 2872: ITAU = 1
! 2873: IWORK = ITAU + M
! 2874: *
! 2875: * Compute A=L*Q, copying result to VT
! 2876: * (Workspace: need 2*M, prefer M+M*NB)
! 2877: *
! 2878: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2879: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2880: CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
! 2881: *
! 2882: * Generate Q in VT
! 2883: * (Workspace: need M+N, prefer M+N*NB)
! 2884: *
! 2885: CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
! 2886: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2887: IE = ITAU
! 2888: ITAUQ = IE + M
! 2889: ITAUP = ITAUQ + M
! 2890: IWORK = ITAUP + M
! 2891: *
! 2892: * Zero out above L in A
! 2893: *
! 2894: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
! 2895: $ LDA )
! 2896: *
! 2897: * Bidiagonalize L in A
! 2898: * (Workspace: need 4*M, prefer 3*M+2*M*NB)
! 2899: *
! 2900: CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
! 2901: $ WORK( ITAUQ ), WORK( ITAUP ),
! 2902: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2903: *
! 2904: * Multiply right bidiagonalizing vectors in A by Q
! 2905: * in VT
! 2906: * (Workspace: need 3*M+N, prefer 3*M+N*NB)
! 2907: *
! 2908: CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
! 2909: $ WORK( ITAUP ), VT, LDVT,
! 2910: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2911: IWORK = IE + M
! 2912: *
! 2913: * Perform bidiagonal QR iteration, computing right
! 2914: * singular vectors of A in VT
! 2915: * (Workspace: need BDSPAC)
! 2916: *
! 2917: CALL DBDSQR( 'U', M, N, 0, 0, S, WORK( IE ), VT,
! 2918: $ LDVT, DUM, 1, DUM, 1, WORK( IWORK ),
! 2919: $ INFO )
! 2920: *
! 2921: END IF
! 2922: *
! 2923: ELSE IF( WNTUO ) THEN
! 2924: *
! 2925: * Path 8t(N much larger than M, JOBU='O', JOBVT='A')
! 2926: * N right singular vectors to be computed in VT and
! 2927: * M left singular vectors to be overwritten on A
! 2928: *
! 2929: IF( LWORK.GE.2*M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN
! 2930: *
! 2931: * Sufficient workspace for a fast algorithm
! 2932: *
! 2933: IU = 1
! 2934: IF( LWORK.GE.WRKBL+2*LDA*M ) THEN
! 2935: *
! 2936: * WORK(IU) is LDA by M and WORK(IR) is LDA by M
! 2937: *
! 2938: LDWRKU = LDA
! 2939: IR = IU + LDWRKU*M
! 2940: LDWRKR = LDA
! 2941: ELSE IF( LWORK.GE.WRKBL+( LDA+M )*M ) THEN
! 2942: *
! 2943: * WORK(IU) is LDA by M and WORK(IR) is M by M
! 2944: *
! 2945: LDWRKU = LDA
! 2946: IR = IU + LDWRKU*M
! 2947: LDWRKR = M
! 2948: ELSE
! 2949: *
! 2950: * WORK(IU) is M by M and WORK(IR) is M by M
! 2951: *
! 2952: LDWRKU = M
! 2953: IR = IU + LDWRKU*M
! 2954: LDWRKR = M
! 2955: END IF
! 2956: ITAU = IR + LDWRKR*M
! 2957: IWORK = ITAU + M
! 2958: *
! 2959: * Compute A=L*Q, copying result to VT
! 2960: * (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB)
! 2961: *
! 2962: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 2963: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2964: CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
! 2965: *
! 2966: * Generate Q in VT
! 2967: * (Workspace: need 2*M*M+M+N, prefer 2*M*M+M+N*NB)
! 2968: *
! 2969: CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
! 2970: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 2971: *
! 2972: * Copy L to WORK(IU), zeroing out above it
! 2973: *
! 2974: CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
! 2975: $ LDWRKU )
! 2976: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
! 2977: $ WORK( IU+LDWRKU ), LDWRKU )
! 2978: IE = ITAU
! 2979: ITAUQ = IE + M
! 2980: ITAUP = ITAUQ + M
! 2981: IWORK = ITAUP + M
! 2982: *
! 2983: * Bidiagonalize L in WORK(IU), copying result to
! 2984: * WORK(IR)
! 2985: * (Workspace: need 2*M*M+4*M,
! 2986: * prefer 2*M*M+3*M+2*M*NB)
! 2987: *
! 2988: CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
! 2989: $ WORK( IE ), WORK( ITAUQ ),
! 2990: $ WORK( ITAUP ), WORK( IWORK ),
! 2991: $ LWORK-IWORK+1, IERR )
! 2992: CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU,
! 2993: $ WORK( IR ), LDWRKR )
! 2994: *
! 2995: * Generate right bidiagonalizing vectors in WORK(IU)
! 2996: * (Workspace: need 2*M*M+4*M-1,
! 2997: * prefer 2*M*M+3*M+(M-1)*NB)
! 2998: *
! 2999: CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
! 3000: $ WORK( ITAUP ), WORK( IWORK ),
! 3001: $ LWORK-IWORK+1, IERR )
! 3002: *
! 3003: * Generate left bidiagonalizing vectors in WORK(IR)
! 3004: * (Workspace: need 2*M*M+4*M, prefer 2*M*M+3*M+M*NB)
! 3005: *
! 3006: CALL DORGBR( 'Q', M, M, M, WORK( IR ), LDWRKR,
! 3007: $ WORK( ITAUQ ), WORK( IWORK ),
! 3008: $ LWORK-IWORK+1, IERR )
! 3009: IWORK = IE + M
! 3010: *
! 3011: * Perform bidiagonal QR iteration, computing left
! 3012: * singular vectors of L in WORK(IR) and computing
! 3013: * right singular vectors of L in WORK(IU)
! 3014: * (Workspace: need 2*M*M+BDSPAC)
! 3015: *
! 3016: CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
! 3017: $ WORK( IU ), LDWRKU, WORK( IR ),
! 3018: $ LDWRKR, DUM, 1, WORK( IWORK ), INFO )
! 3019: *
! 3020: * Multiply right singular vectors of L in WORK(IU) by
! 3021: * Q in VT, storing result in A
! 3022: * (Workspace: need M*M)
! 3023: *
! 3024: CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
! 3025: $ LDWRKU, VT, LDVT, ZERO, A, LDA )
! 3026: *
! 3027: * Copy right singular vectors of A from A to VT
! 3028: *
! 3029: CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
! 3030: *
! 3031: * Copy left singular vectors of A from WORK(IR) to A
! 3032: *
! 3033: CALL DLACPY( 'F', M, M, WORK( IR ), LDWRKR, A,
! 3034: $ LDA )
! 3035: *
! 3036: ELSE
! 3037: *
! 3038: * Insufficient workspace for a fast algorithm
! 3039: *
! 3040: ITAU = 1
! 3041: IWORK = ITAU + M
! 3042: *
! 3043: * Compute A=L*Q, copying result to VT
! 3044: * (Workspace: need 2*M, prefer M+M*NB)
! 3045: *
! 3046: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 3047: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3048: CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
! 3049: *
! 3050: * Generate Q in VT
! 3051: * (Workspace: need M+N, prefer M+N*NB)
! 3052: *
! 3053: CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
! 3054: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3055: IE = ITAU
! 3056: ITAUQ = IE + M
! 3057: ITAUP = ITAUQ + M
! 3058: IWORK = ITAUP + M
! 3059: *
! 3060: * Zero out above L in A
! 3061: *
! 3062: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),
! 3063: $ LDA )
! 3064: *
! 3065: * Bidiagonalize L in A
! 3066: * (Workspace: need 4*M, prefer 3*M+2*M*NB)
! 3067: *
! 3068: CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),
! 3069: $ WORK( ITAUQ ), WORK( ITAUP ),
! 3070: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3071: *
! 3072: * Multiply right bidiagonalizing vectors in A by Q
! 3073: * in VT
! 3074: * (Workspace: need 3*M+N, prefer 3*M+N*NB)
! 3075: *
! 3076: CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,
! 3077: $ WORK( ITAUP ), VT, LDVT,
! 3078: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3079: *
! 3080: * Generate left bidiagonalizing vectors in A
! 3081: * (Workspace: need 4*M, prefer 3*M+M*NB)
! 3082: *
! 3083: CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),
! 3084: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3085: IWORK = IE + M
! 3086: *
! 3087: * Perform bidiagonal QR iteration, computing left
! 3088: * singular vectors of A in A and computing right
! 3089: * singular vectors of A in VT
! 3090: * (Workspace: need BDSPAC)
! 3091: *
! 3092: CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
! 3093: $ LDVT, A, LDA, DUM, 1, WORK( IWORK ),
! 3094: $ INFO )
! 3095: *
! 3096: END IF
! 3097: *
! 3098: ELSE IF( WNTUAS ) THEN
! 3099: *
! 3100: * Path 9t(N much larger than M, JOBU='S' or 'A',
! 3101: * JOBVT='A')
! 3102: * N right singular vectors to be computed in VT and
! 3103: * M left singular vectors to be computed in U
! 3104: *
! 3105: IF( LWORK.GE.M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN
! 3106: *
! 3107: * Sufficient workspace for a fast algorithm
! 3108: *
! 3109: IU = 1
! 3110: IF( LWORK.GE.WRKBL+LDA*M ) THEN
! 3111: *
! 3112: * WORK(IU) is LDA by M
! 3113: *
! 3114: LDWRKU = LDA
! 3115: ELSE
! 3116: *
! 3117: * WORK(IU) is M by M
! 3118: *
! 3119: LDWRKU = M
! 3120: END IF
! 3121: ITAU = IU + LDWRKU*M
! 3122: IWORK = ITAU + M
! 3123: *
! 3124: * Compute A=L*Q, copying result to VT
! 3125: * (Workspace: need M*M+2*M, prefer M*M+M+M*NB)
! 3126: *
! 3127: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 3128: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3129: CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
! 3130: *
! 3131: * Generate Q in VT
! 3132: * (Workspace: need M*M+M+N, prefer M*M+M+N*NB)
! 3133: *
! 3134: CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
! 3135: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3136: *
! 3137: * Copy L to WORK(IU), zeroing out above it
! 3138: *
! 3139: CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),
! 3140: $ LDWRKU )
! 3141: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,
! 3142: $ WORK( IU+LDWRKU ), LDWRKU )
! 3143: IE = ITAU
! 3144: ITAUQ = IE + M
! 3145: ITAUP = ITAUQ + M
! 3146: IWORK = ITAUP + M
! 3147: *
! 3148: * Bidiagonalize L in WORK(IU), copying result to U
! 3149: * (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
! 3150: *
! 3151: CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,
! 3152: $ WORK( IE ), WORK( ITAUQ ),
! 3153: $ WORK( ITAUP ), WORK( IWORK ),
! 3154: $ LWORK-IWORK+1, IERR )
! 3155: CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, U,
! 3156: $ LDU )
! 3157: *
! 3158: * Generate right bidiagonalizing vectors in WORK(IU)
! 3159: * (Workspace: need M*M+4*M, prefer M*M+3*M+(M-1)*NB)
! 3160: *
! 3161: CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,
! 3162: $ WORK( ITAUP ), WORK( IWORK ),
! 3163: $ LWORK-IWORK+1, IERR )
! 3164: *
! 3165: * Generate left bidiagonalizing vectors in U
! 3166: * (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB)
! 3167: *
! 3168: CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
! 3169: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3170: IWORK = IE + M
! 3171: *
! 3172: * Perform bidiagonal QR iteration, computing left
! 3173: * singular vectors of L in U and computing right
! 3174: * singular vectors of L in WORK(IU)
! 3175: * (Workspace: need M*M+BDSPAC)
! 3176: *
! 3177: CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),
! 3178: $ WORK( IU ), LDWRKU, U, LDU, DUM, 1,
! 3179: $ WORK( IWORK ), INFO )
! 3180: *
! 3181: * Multiply right singular vectors of L in WORK(IU) by
! 3182: * Q in VT, storing result in A
! 3183: * (Workspace: need M*M)
! 3184: *
! 3185: CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),
! 3186: $ LDWRKU, VT, LDVT, ZERO, A, LDA )
! 3187: *
! 3188: * Copy right singular vectors of A from A to VT
! 3189: *
! 3190: CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )
! 3191: *
! 3192: ELSE
! 3193: *
! 3194: * Insufficient workspace for a fast algorithm
! 3195: *
! 3196: ITAU = 1
! 3197: IWORK = ITAU + M
! 3198: *
! 3199: * Compute A=L*Q, copying result to VT
! 3200: * (Workspace: need 2*M, prefer M+M*NB)
! 3201: *
! 3202: CALL DGELQF( M, N, A, LDA, WORK( ITAU ),
! 3203: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3204: CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
! 3205: *
! 3206: * Generate Q in VT
! 3207: * (Workspace: need M+N, prefer M+N*NB)
! 3208: *
! 3209: CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),
! 3210: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3211: *
! 3212: * Copy L to U, zeroing out above it
! 3213: *
! 3214: CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
! 3215: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),
! 3216: $ LDU )
! 3217: IE = ITAU
! 3218: ITAUQ = IE + M
! 3219: ITAUP = ITAUQ + M
! 3220: IWORK = ITAUP + M
! 3221: *
! 3222: * Bidiagonalize L in U
! 3223: * (Workspace: need 4*M, prefer 3*M+2*M*NB)
! 3224: *
! 3225: CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),
! 3226: $ WORK( ITAUQ ), WORK( ITAUP ),
! 3227: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3228: *
! 3229: * Multiply right bidiagonalizing vectors in U by Q
! 3230: * in VT
! 3231: * (Workspace: need 3*M+N, prefer 3*M+N*NB)
! 3232: *
! 3233: CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,
! 3234: $ WORK( ITAUP ), VT, LDVT,
! 3235: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3236: *
! 3237: * Generate left bidiagonalizing vectors in U
! 3238: * (Workspace: need 4*M, prefer 3*M+M*NB)
! 3239: *
! 3240: CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),
! 3241: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3242: IWORK = IE + M
! 3243: *
! 3244: * Perform bidiagonal QR iteration, computing left
! 3245: * singular vectors of A in U and computing right
! 3246: * singular vectors of A in VT
! 3247: * (Workspace: need BDSPAC)
! 3248: *
! 3249: CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,
! 3250: $ LDVT, U, LDU, DUM, 1, WORK( IWORK ),
! 3251: $ INFO )
! 3252: *
! 3253: END IF
! 3254: *
! 3255: END IF
! 3256: *
! 3257: END IF
! 3258: *
! 3259: ELSE
! 3260: *
! 3261: * N .LT. MNTHR
! 3262: *
! 3263: * Path 10t(N greater than M, but not much larger)
! 3264: * Reduce to bidiagonal form without LQ decomposition
! 3265: *
! 3266: IE = 1
! 3267: ITAUQ = IE + M
! 3268: ITAUP = ITAUQ + M
! 3269: IWORK = ITAUP + M
! 3270: *
! 3271: * Bidiagonalize A
! 3272: * (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)
! 3273: *
! 3274: CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),
! 3275: $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
! 3276: $ IERR )
! 3277: IF( WNTUAS ) THEN
! 3278: *
! 3279: * If left singular vectors desired in U, copy result to U
! 3280: * and generate left bidiagonalizing vectors in U
! 3281: * (Workspace: need 4*M-1, prefer 3*M+(M-1)*NB)
! 3282: *
! 3283: CALL DLACPY( 'L', M, M, A, LDA, U, LDU )
! 3284: CALL DORGBR( 'Q', M, M, N, U, LDU, WORK( ITAUQ ),
! 3285: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3286: END IF
! 3287: IF( WNTVAS ) THEN
! 3288: *
! 3289: * If right singular vectors desired in VT, copy result to
! 3290: * VT and generate right bidiagonalizing vectors in VT
! 3291: * (Workspace: need 3*M+NRVT, prefer 3*M+NRVT*NB)
! 3292: *
! 3293: CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )
! 3294: IF( WNTVA )
! 3295: $ NRVT = N
! 3296: IF( WNTVS )
! 3297: $ NRVT = M
! 3298: CALL DORGBR( 'P', NRVT, N, M, VT, LDVT, WORK( ITAUP ),
! 3299: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3300: END IF
! 3301: IF( WNTUO ) THEN
! 3302: *
! 3303: * If left singular vectors desired in A, generate left
! 3304: * bidiagonalizing vectors in A
! 3305: * (Workspace: need 4*M-1, prefer 3*M+(M-1)*NB)
! 3306: *
! 3307: CALL DORGBR( 'Q', M, M, N, A, LDA, WORK( ITAUQ ),
! 3308: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3309: END IF
! 3310: IF( WNTVO ) THEN
! 3311: *
! 3312: * If right singular vectors desired in A, generate right
! 3313: * bidiagonalizing vectors in A
! 3314: * (Workspace: need 4*M, prefer 3*M+M*NB)
! 3315: *
! 3316: CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),
! 3317: $ WORK( IWORK ), LWORK-IWORK+1, IERR )
! 3318: END IF
! 3319: IWORK = IE + M
! 3320: IF( WNTUAS .OR. WNTUO )
! 3321: $ NRU = M
! 3322: IF( WNTUN )
! 3323: $ NRU = 0
! 3324: IF( WNTVAS .OR. WNTVO )
! 3325: $ NCVT = N
! 3326: IF( WNTVN )
! 3327: $ NCVT = 0
! 3328: IF( ( .NOT.WNTUO ) .AND. ( .NOT.WNTVO ) ) THEN
! 3329: *
! 3330: * Perform bidiagonal QR iteration, if desired, computing
! 3331: * left singular vectors in U and computing right singular
! 3332: * vectors in VT
! 3333: * (Workspace: need BDSPAC)
! 3334: *
! 3335: CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), VT,
! 3336: $ LDVT, U, LDU, DUM, 1, WORK( IWORK ), INFO )
! 3337: ELSE IF( ( .NOT.WNTUO ) .AND. WNTVO ) THEN
! 3338: *
! 3339: * Perform bidiagonal QR iteration, if desired, computing
! 3340: * left singular vectors in U and computing right singular
! 3341: * vectors in A
! 3342: * (Workspace: need BDSPAC)
! 3343: *
! 3344: CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), A, LDA,
! 3345: $ U, LDU, DUM, 1, WORK( IWORK ), INFO )
! 3346: ELSE
! 3347: *
! 3348: * Perform bidiagonal QR iteration, if desired, computing
! 3349: * left singular vectors in A and computing right singular
! 3350: * vectors in VT
! 3351: * (Workspace: need BDSPAC)
! 3352: *
! 3353: CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), VT,
! 3354: $ LDVT, A, LDA, DUM, 1, WORK( IWORK ), INFO )
! 3355: END IF
! 3356: *
! 3357: END IF
! 3358: *
! 3359: END IF
! 3360: *
! 3361: * If DBDSQR failed to converge, copy unconverged superdiagonals
! 3362: * to WORK( 2:MINMN )
! 3363: *
! 3364: IF( INFO.NE.0 ) THEN
! 3365: IF( IE.GT.2 ) THEN
! 3366: DO 50 I = 1, MINMN - 1
! 3367: WORK( I+1 ) = WORK( I+IE-1 )
! 3368: 50 CONTINUE
! 3369: END IF
! 3370: IF( IE.LT.2 ) THEN
! 3371: DO 60 I = MINMN - 1, 1, -1
! 3372: WORK( I+1 ) = WORK( I+IE-1 )
! 3373: 60 CONTINUE
! 3374: END IF
! 3375: END IF
! 3376: *
! 3377: * Undo scaling if necessary
! 3378: *
! 3379: IF( ISCL.EQ.1 ) THEN
! 3380: IF( ANRM.GT.BIGNUM )
! 3381: $ CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,
! 3382: $ IERR )
! 3383: IF( INFO.NE.0 .AND. ANRM.GT.BIGNUM )
! 3384: $ CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN-1, 1, WORK( 2 ),
! 3385: $ MINMN, IERR )
! 3386: IF( ANRM.LT.SMLNUM )
! 3387: $ CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,
! 3388: $ IERR )
! 3389: IF( INFO.NE.0 .AND. ANRM.LT.SMLNUM )
! 3390: $ CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN-1, 1, WORK( 2 ),
! 3391: $ MINMN, IERR )
! 3392: END IF
! 3393: *
! 3394: * Return optimal workspace in WORK(1)
! 3395: *
! 3396: WORK( 1 ) = MAXWRK
! 3397: *
! 3398: RETURN
! 3399: *
! 3400: * End of DGESVD
! 3401: *
! 3402: END
CVSweb interface <joel.bertrand@systella.fr>