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