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