1: *> \brief <b> ZGESVDX computes the singular value decomposition (SVD) for GE matrices</b>
2: *
3: * =========== DOCUMENTATION ===========
4: *
5: * Online html documentation available at
6: * http://www.netlib.org/lapack/explore-html/
7: *
8: *> \htmlonly
9: *> Download ZGESVDX + dependencies
10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zgesvdx.f">
11: *> [TGZ]</a>
12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zgesvdx.f">
13: *> [ZIP]</a>
14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgesvdx.f">
15: *> [TXT]</a>
16: *> \endhtmlonly
17: *
18: * Definition:
19: * ===========
20: *
21: * SUBROUTINE CGESVDX( JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU,
22: * $ IL, IU, NS, S, U, LDU, VT, LDVT, WORK,
23: * $ LWORK, RWORK, IWORK, INFO )
24: *
25: *
26: * .. Scalar Arguments ..
27: * CHARACTER JOBU, JOBVT, RANGE
28: * INTEGER IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
29: * DOUBLE PRECISION VL, VU
30: * ..
31: * .. Array Arguments ..
32: * INTEGER IWORK( * )
33: * DOUBLE PRECISION S( * ), RWORK( * )
34: * COMPLEX*16 A( LDA, * ), U( LDU, * ), VT( LDVT, * ),
35: * $ WORK( * )
36: * ..
37: *
38: *
39: * Purpose
40: * =======
41: *
42: * ZGESVDX computes the singular value decomposition (SVD) of a complex
43: * M-by-N matrix A, optionally computing the left and/or right singular
44: * vectors. The SVD is written
45: *
46: * A = U * SIGMA * transpose(V)
47: *
48: * where SIGMA is an M-by-N matrix which is zero except for its
49: * min(m,n) diagonal elements, U is an M-by-M unitary matrix, and
50: * V is an N-by-N unitary matrix. The diagonal elements of SIGMA
51: * are the singular values of A; they are real and non-negative, and
52: * are returned in descending order. The first min(m,n) columns of
53: * U and V are the left and right singular vectors of A.
54: *
55: * ZGESVDX uses an eigenvalue problem for obtaining the SVD, which
56: * allows for the computation of a subset of singular values and
57: * vectors. See DBDSVDX for details.
58: *
59: * Note that the routine returns V**T, not V.
60: *
61: * Arguments:
62: * ==========
63: *
64: *> \param[in] JOBU
65: *> \verbatim
66: *> JOBU is CHARACTER*1
67: *> Specifies options for computing all or part of the matrix U:
68: *> = 'V': the first min(m,n) columns of U (the left singular
69: *> vectors) or as specified by RANGE are returned in
70: *> the array U;
71: *> = 'N': no columns of U (no left singular vectors) are
72: *> computed.
73: *> \endverbatim
74: *>
75: *> \param[in] JOBVT
76: *> \verbatim
77: *> JOBVT is CHARACTER*1
78: *> Specifies options for computing all or part of the matrix
79: *> V**T:
80: *> = 'V': the first min(m,n) rows of V**T (the right singular
81: *> vectors) or as specified by RANGE are returned in
82: *> the array VT;
83: *> = 'N': no rows of V**T (no right singular vectors) are
84: *> computed.
85: *> \endverbatim
86: *>
87: *> \param[in] RANGE
88: *> \verbatim
89: *> RANGE is CHARACTER*1
90: *> = 'A': all singular values will be found.
91: *> = 'V': all singular values in the half-open interval (VL,VU]
92: *> will be found.
93: *> = 'I': the IL-th through IU-th singular values will be found.
94: *> \endverbatim
95: *>
96: *> \param[in] M
97: *> \verbatim
98: *> M is INTEGER
99: *> The number of rows of the input matrix A. M >= 0.
100: *> \endverbatim
101: *>
102: *> \param[in] N
103: *> \verbatim
104: *> N is INTEGER
105: *> The number of columns of the input matrix A. N >= 0.
106: *> \endverbatim
107: *>
108: *> \param[in,out] A
109: *> \verbatim
110: *> A is COMPLEX array, dimension (LDA,N)
111: *> On entry, the M-by-N matrix A.
112: *> On exit, the contents of A are destroyed.
113: *> \endverbatim
114: *>
115: *> \param[in] LDA
116: *> \verbatim
117: *> LDA is INTEGER
118: *> The leading dimension of the array A. LDA >= max(1,M).
119: *> \endverbatim
120: *>
121: *> \param[in] VL
122: *> \verbatim
123: *> VL is DOUBLE PRECISION
124: *> VL >=0.
125: *> \endverbatim
126: *>
127: *> \param[in] VU
128: *> \verbatim
129: *> VU is DOUBLE PRECISION
130: *> If RANGE='V', the lower and upper bounds of the interval to
131: *> be searched for singular values. VU > VL.
132: *> Not referenced if RANGE = 'A' or 'I'.
133: *> \endverbatim
134: *>
135: *> \param[in] IL
136: *> \verbatim
137: *> IL is INTEGER
138: *> \endverbatim
139: *>
140: *> \param[in] IU
141: *> \verbatim
142: *> IU is INTEGER
143: *> If RANGE='I', the indices (in ascending order) of the
144: *> smallest and largest singular values to be returned.
145: *> 1 <= IL <= IU <= min(M,N), if min(M,N) > 0.
146: *> Not referenced if RANGE = 'A' or 'V'.
147: *> \endverbatim
148: *>
149: *> \param[out] NS
150: *> \verbatim
151: *> NS is INTEGER
152: *> The total number of singular values found,
153: *> 0 <= NS <= min(M,N).
154: *> If RANGE = 'A', NS = min(M,N); if RANGE = 'I', NS = IU-IL+1.
155: *> \endverbatim
156: *>
157: *> \param[out] S
158: *> \verbatim
159: *> S is DOUBLE PRECISION array, dimension (min(M,N))
160: *> The singular values of A, sorted so that S(i) >= S(i+1).
161: *> \endverbatim
162: *>
163: *> \param[out] U
164: *> \verbatim
165: *> U is COMPLEX*16 array, dimension (LDU,UCOL)
166: *> If JOBU = 'V', U contains columns of U (the left singular
167: *> vectors, stored columnwise) as specified by RANGE; if
168: *> JOBU = 'N', U is not referenced.
169: *> Note: The user must ensure that UCOL >= NS; if RANGE = 'V',
170: *> the exact value of NS is not known ILQFin advance and an upper
171: *> bound must be used.
172: *> \endverbatim
173: *>
174: *> \param[in] LDU
175: *> \verbatim
176: *> LDU is INTEGER
177: *> The leading dimension of the array U. LDU >= 1; if
178: *> JOBU = 'V', LDU >= M.
179: *> \endverbatim
180: *>
181: *> \param[out] VT
182: *> \verbatim
183: *> VT is COMPLEX*16 array, dimension (LDVT,N)
184: *> If JOBVT = 'V', VT contains the rows of V**T (the right singular
185: *> vectors, stored rowwise) as specified by RANGE; if JOBVT = 'N',
186: *> VT is not referenced.
187: *> Note: The user must ensure that LDVT >= NS; if RANGE = 'V',
188: *> the exact value of NS is not known in advance and an upper
189: *> bound must be used.
190: *> \endverbatim
191: *>
192: *> \param[in] LDVT
193: *> \verbatim
194: *> LDVT is INTEGER
195: *> The leading dimension of the array VT. LDVT >= 1; if
196: *> JOBVT = 'V', LDVT >= NS (see above).
197: *> \endverbatim
198: *>
199: *> \param[out] WORK
200: *> \verbatim
201: *> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
202: *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
203: *> \endverbatim
204: *>
205: *> \param[in] LWORK
206: *> \verbatim
207: *> LWORK is INTEGER
208: *> The dimension of the array WORK.
209: *> LWORK >= MAX(1,MIN(M,N)*(MIN(M,N)+4)) for the paths (see
210: *> comments inside the code):
211: *> - PATH 1 (M much larger than N)
212: *> - PATH 1t (N much larger than M)
213: *> LWORK >= MAX(1,MIN(M,N)*2+MAX(M,N)) for the other paths.
214: *> For good performance, LWORK should generally be larger.
215: *>
216: *> If LWORK = -1, then a workspace query is assumed; the routine
217: *> only calculates the optimal size of the WORK array, returns
218: *> this value as the first entry of the WORK array, and no error
219: *> message related to LWORK is issued by XERBLA.
220: *> \endverbatim
221: *>
222: *> \param[out] RWORK
223: *> \verbatim
224: *> RWORK is DOUBLE PRECISION array, dimension (MAX(1,LRWORK))
225: *> LRWORK >= MIN(M,N)*(MIN(M,N)*2+15*MIN(M,N)).
226: *> \endverbatim
227: *>
228: *> \param[out] IWORK
229: *> \verbatim
230: *> IWORK is INTEGER array, dimension (12*MIN(M,N))
231: *> If INFO = 0, the first NS elements of IWORK are zero. If INFO > 0,
232: *> then IWORK contains the indices of the eigenvectors that failed
233: *> to converge in DBDSVDX/DSTEVX.
234: *> \endverbatim
235: *>
236: *> \param[out] INFO
237: *> \verbatim
238: *> INFO is INTEGER
239: *> = 0: successful exit
240: *> < 0: if INFO = -i, the i-th argument had an illegal value
241: *> > 0: if INFO = i, then i eigenvectors failed to converge
242: *> in DBDSVDX/DSTEVX.
243: *> if INFO = N*2 + 1, an internal error occurred in
244: *> DBDSVDX
245: *> \endverbatim
246: *
247: * Authors:
248: * ========
249: *
250: *> \author Univ. of Tennessee
251: *> \author Univ. of California Berkeley
252: *> \author Univ. of Colorado Denver
253: *> \author NAG Ltd.
254: *
255: *> \date November 2015
256: *
257: *> \ingroup complex16GEsing
258: *
259: * =====================================================================
260: SUBROUTINE ZGESVDX( JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU,
261: $ IL, IU, NS, S, U, LDU, VT, LDVT, WORK,
262: $ LWORK, RWORK, IWORK, INFO )
263: *
264: * -- LAPACK driver routine (version 3.6.0) --
265: * -- LAPACK is a software package provided by Univ. of Tennessee, --
266: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
267: * November 2015
268: *
269: * .. Scalar Arguments ..
270: CHARACTER JOBU, JOBVT, RANGE
271: INTEGER IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
272: DOUBLE PRECISION VL, VU
273: * ..
274: * .. Array Arguments ..
275: INTEGER IWORK( * )
276: DOUBLE PRECISION S( * ), RWORK( * )
277: COMPLEX*16 A( LDA, * ), U( LDU, * ), VT( LDVT, * ),
278: $ WORK( * )
279: * ..
280: *
281: * =====================================================================
282: *
283: * .. Parameters ..
284: COMPLEX*16 CZERO, CONE
285: PARAMETER ( CZERO = ( 0.0D0, 0.0D0 ),
286: $ CONE = ( 1.0D0, 0.0D0 ) )
287: DOUBLE PRECISION ZERO, ONE
288: PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
289: * ..
290: * .. Local Scalars ..
291: CHARACTER JOBZ, RNGTGK
292: LOGICAL ALLS, INDS, LQUERY, VALS, WANTU, WANTVT
293: INTEGER I, ID, IE, IERR, ILQF, ILTGK, IQRF, ISCL,
294: $ ITAU, ITAUP, ITAUQ, ITEMP, ITGKZ, IUTGK,
295: $ J, K, MAXWRK, MINMN, MINWRK, MNTHR
296: DOUBLE PRECISION ABSTOL, ANRM, BIGNUM, EPS, SMLNUM
297: * ..
298: * .. Local Arrays ..
299: DOUBLE PRECISION DUM( 1 )
300: * ..
301: * .. External Subroutines ..
302: EXTERNAL ZGEBRD, ZGELQF, ZGEQRF, ZLASCL, ZLASET,
303: $ DLASCL, XERBLA
304: * ..
305: * .. External Functions ..
306: LOGICAL LSAME
307: INTEGER ILAENV
308: DOUBLE PRECISION DLAMCH, ZLANGE
309: EXTERNAL LSAME, ILAENV, DLAMCH, ZLANGE
310: * ..
311: * .. Intrinsic Functions ..
312: INTRINSIC MAX, MIN, SQRT
313: * ..
314: * .. Executable Statements ..
315: *
316: * Test the input arguments.
317: *
318: NS = 0
319: INFO = 0
320: ABSTOL = 2*DLAMCH('S')
321: LQUERY = ( LWORK.EQ.-1 )
322: MINMN = MIN( M, N )
323:
324: WANTU = LSAME( JOBU, 'V' )
325: WANTVT = LSAME( JOBVT, 'V' )
326: IF( WANTU .OR. WANTVT ) THEN
327: JOBZ = 'V'
328: ELSE
329: JOBZ = 'N'
330: END IF
331: ALLS = LSAME( RANGE, 'A' )
332: VALS = LSAME( RANGE, 'V' )
333: INDS = LSAME( RANGE, 'I' )
334: *
335: INFO = 0
336: IF( .NOT.LSAME( JOBU, 'V' ) .AND.
337: $ .NOT.LSAME( JOBU, 'N' ) ) THEN
338: INFO = -1
339: ELSE IF( .NOT.LSAME( JOBVT, 'V' ) .AND.
340: $ .NOT.LSAME( JOBVT, 'N' ) ) THEN
341: INFO = -2
342: ELSE IF( .NOT.( ALLS .OR. VALS .OR. INDS ) ) THEN
343: INFO = -3
344: ELSE IF( M.LT.0 ) THEN
345: INFO = -4
346: ELSE IF( N.LT.0 ) THEN
347: INFO = -5
348: ELSE IF( M.GT.LDA ) THEN
349: INFO = -7
350: ELSE IF( MINMN.GT.0 ) THEN
351: IF( VALS ) THEN
352: IF( VL.LT.ZERO ) THEN
353: INFO = -8
354: ELSE IF( VU.LE.VL ) THEN
355: INFO = -9
356: END IF
357: ELSE IF( INDS ) THEN
358: IF( IL.LT.1 .OR. IL.GT.MAX( 1, MINMN ) ) THEN
359: INFO = -10
360: ELSE IF( IU.LT.MIN( MINMN, IL ) .OR. IU.GT.MINMN ) THEN
361: INFO = -11
362: END IF
363: END IF
364: IF( INFO.EQ.0 ) THEN
365: IF( WANTU .AND. LDU.LT.M ) THEN
366: INFO = -15
367: ELSE IF( WANTVT .AND. LDVT.LT.MINMN ) THEN
368: INFO = -16
369: END IF
370: END IF
371: END IF
372: *
373: * Compute workspace
374: * (Note: Comments in the code beginning "Workspace:" describe the
375: * minimal amount of workspace needed at that point in the code,
376: * as well as the preferred amount for good performance.
377: * NB refers to the optimal block size for the immediately
378: * following subroutine, as returned by ILAENV.)
379: *
380: IF( INFO.EQ.0 ) THEN
381: MINWRK = 1
382: MAXWRK = 1
383: IF( MINMN.GT.0 ) THEN
384: IF( M.GE.N ) THEN
385: MNTHR = ILAENV( 6, 'ZGESVD', JOBU // JOBVT, M, N, 0, 0 )
386: IF( M.GE.MNTHR ) THEN
387: *
388: * Path 1 (M much larger than N)
389: *
390: MAXWRK = N + N*
391: $ ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
392: MAXWRK = MAX( MAXWRK, N*N + N + 2*N*
393: $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
394: MINWRK = N*(N+4)
395: ELSE
396: *
397: * Path 2 (M at least N, but not much larger)
398: *
399: MAXWRK = 2*N + ( M+N )*
400: $ ILAENV( 1, 'ZGEBRD', ' ', M, N, -1, -1 )
401: MINWRK = 2*N + M
402: END IF
403: ELSE
404: MNTHR = ILAENV( 6, 'ZGESVD', JOBU // JOBVT, M, N, 0, 0 )
405: IF( N.GE.MNTHR ) THEN
406: *
407: * Path 1t (N much larger than M)
408: *
409: MAXWRK = M + M*
410: $ ILAENV( 1, 'ZGELQF', ' ', M, N, -1, -1 )
411: MAXWRK = MAX( MAXWRK, M*M + M + 2*M*
412: $ ILAENV( 1, 'ZGEBRD', ' ', M, M, -1, -1 ) )
413: MINWRK = M*(M+4)
414: ELSE
415: *
416: * Path 2t (N greater than M, but not much larger)
417: *
418: MAXWRK = M*(M*2+19) + ( M+N )*
419: $ ILAENV( 1, 'ZGEBRD', ' ', M, N, -1, -1 )
420: MINWRK = 2*M + N
421: END IF
422: END IF
423: END IF
424: MAXWRK = MAX( MAXWRK, MINWRK )
425: WORK( 1 ) = DCMPLX( DBLE( MAXWRK ), ZERO )
426: *
427: IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
428: INFO = -19
429: END IF
430: END IF
431: *
432: IF( INFO.NE.0 ) THEN
433: CALL XERBLA( 'ZGESVDX', -INFO )
434: RETURN
435: ELSE IF( LQUERY ) THEN
436: RETURN
437: END IF
438: *
439: * Quick return if possible
440: *
441: IF( M.EQ.0 .OR. N.EQ.0 ) THEN
442: RETURN
443: END IF
444: *
445: * Set singular values indices accord to RANGE='A'.
446: *
447: ALLS = LSAME( RANGE, 'A' )
448: INDS = LSAME( RANGE, 'I' )
449: IF( ALLS ) THEN
450: RNGTGK = 'I'
451: ILTGK = 1
452: IUTGK = MIN( M, N )
453: ELSE IF( INDS ) THEN
454: RNGTGK = 'I'
455: ILTGK = IL
456: IUTGK = IU
457: ELSE
458: RNGTGK = 'V'
459: ILTGK = 0
460: IUTGK = 0
461: END IF
462: *
463: * Get machine constants
464: *
465: EPS = DLAMCH( 'P' )
466: SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPS
467: BIGNUM = ONE / SMLNUM
468: *
469: * Scale A if max element outside range [SMLNUM,BIGNUM]
470: *
471: ANRM = ZLANGE( 'M', M, N, A, LDA, DUM )
472: ISCL = 0
473: IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
474: ISCL = 1
475: CALL ZLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
476: ELSE IF( ANRM.GT.BIGNUM ) THEN
477: ISCL = 1
478: CALL ZLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
479: END IF
480: *
481: IF( M.GE.N ) THEN
482: *
483: * A has at least as many rows as columns. If A has sufficiently
484: * more rows than columns, first reduce A using the QR
485: * decomposition.
486: *
487: IF( M.GE.MNTHR ) THEN
488: *
489: * Path 1 (M much larger than N):
490: * A = Q * R = Q * ( QB * B * PB**T )
491: * = Q * ( QB * ( UB * S * VB**T ) * PB**T )
492: * U = Q * QB * UB; V**T = VB**T * PB**T
493: *
494: * Compute A=Q*R
495: * (Workspace: need 2*N, prefer N+N*NB)
496: *
497: ITAU = 1
498: ITEMP = ITAU + N
499: CALL ZGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( ITEMP ),
500: $ LWORK-ITEMP+1, INFO )
501: *
502: * Copy R into WORK and bidiagonalize it:
503: * (Workspace: need N*N+3*N, prefer N*N+N+2*N*NB)
504: *
505: IQRF = ITEMP
506: ITAUQ = ITEMP + N*N
507: ITAUP = ITAUQ + N
508: ITEMP = ITAUP + N
509: ID = 1
510: IE = ID + N
511: ITGKZ = IE + N
512: CALL ZLACPY( 'U', N, N, A, LDA, WORK( IQRF ), N )
513: CALL ZLASET( 'L', N-1, N-1, CZERO, CZERO,
514: $ WORK( IQRF+1 ), N )
515: CALL ZGEBRD( N, N, WORK( IQRF ), N, RWORK( ID ),
516: $ RWORK( IE ), WORK( ITAUQ ), WORK( ITAUP ),
517: $ WORK( ITEMP ), LWORK-ITEMP+1, INFO )
518: ITEMP = ITGKZ + N*(N*2+1)
519: *
520: * Solve eigenvalue problem TGK*Z=Z*S.
521: * (Workspace: need 2*N*N+14*N)
522: *
523: CALL DBDSVDX( 'U', JOBZ, RNGTGK, N, RWORK( ID ),
524: $ RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S,
525: $ RWORK( ITGKZ ), N*2, RWORK( ITEMP ),
526: $ IWORK, INFO)
527: *
528: * If needed, compute left singular vectors.
529: *
530: IF( WANTU ) THEN
531: K = ITGKZ
532: DO I = 1, NS
533: DO J = 1, N
534: U( J, I ) = DCMPLX( RWORK( K ), ZERO )
535: K = K + 1
536: END DO
537: K = K + N
538: END DO
539: CALL ZLASET( 'A', M-N, N, CZERO, CZERO, U( N+1,1 ), LDU )
540: *
541: * Call ZUNMBR to compute QB*UB.
542: * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
543: *
544: CALL ZUNMBR( 'Q', 'L', 'N', N, NS, N, WORK( IQRF ), N,
545: $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
546: $ LWORK-ITEMP+1, INFO )
547: *
548: * Call ZUNMQR to compute Q*(QB*UB).
549: * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
550: *
551: CALL ZUNMQR( 'L', 'N', M, NS, N, A, LDA,
552: $ WORK( ITAU ), U, LDU, WORK( ITEMP ),
553: $ LWORK-ITEMP+1, INFO )
554: END IF
555: *
556: * If needed, compute right singular vectors.
557: *
558: IF( WANTVT) THEN
559: K = ITGKZ + N
560: DO I = 1, NS
561: DO J = 1, N
562: VT( I, J ) = DCMPLX( RWORK( K ), ZERO )
563: K = K + 1
564: END DO
565: K = K + N
566: END DO
567: *
568: * Call ZUNMBR to compute VB**T * PB**T
569: * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
570: *
571: CALL ZUNMBR( 'P', 'R', 'C', NS, N, N, WORK( IQRF ), N,
572: $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
573: $ LWORK-ITEMP+1, INFO )
574: END IF
575: ELSE
576: *
577: * Path 2 (M at least N, but not much larger)
578: * Reduce A to bidiagonal form without QR decomposition
579: * A = QB * B * PB**T = QB * ( UB * S * VB**T ) * PB**T
580: * U = QB * UB; V**T = VB**T * PB**T
581: *
582: * Bidiagonalize A
583: * (Workspace: need 2*N+M, prefer 2*N+(M+N)*NB)
584: *
585: ITAUQ = 1
586: ITAUP = ITAUQ + N
587: ITEMP = ITAUP + N
588: ID = 1
589: IE = ID + N
590: ITGKZ = IE + N
591: CALL ZGEBRD( M, N, A, LDA, RWORK( ID ), RWORK( IE ),
592: $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
593: $ LWORK-ITEMP+1, INFO )
594: ITEMP = ITGKZ + N*(N*2+1)
595: *
596: * Solve eigenvalue problem TGK*Z=Z*S.
597: * (Workspace: need 2*N*N+14*N)
598: *
599: CALL DBDSVDX( 'U', JOBZ, RNGTGK, N, RWORK( ID ),
600: $ RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S,
601: $ RWORK( ITGKZ ), N*2, RWORK( ITEMP ),
602: $ IWORK, INFO)
603: *
604: * If needed, compute left singular vectors.
605: *
606: IF( WANTU ) THEN
607: K = ITGKZ
608: DO I = 1, NS
609: DO J = 1, N
610: U( J, I ) = DCMPLX( RWORK( K ), ZERO )
611: K = K + 1
612: END DO
613: K = K + N
614: END DO
615: CALL ZLASET( 'A', M-N, N, CZERO, CZERO, U( N+1,1 ), LDU )
616: *
617: * Call ZUNMBR to compute QB*UB.
618: * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
619: *
620: CALL ZUNMBR( 'Q', 'L', 'N', M, NS, N, A, LDA,
621: $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
622: $ LWORK-ITEMP+1, IERR )
623: END IF
624: *
625: * If needed, compute right singular vectors.
626: *
627: IF( WANTVT) THEN
628: K = ITGKZ + N
629: DO I = 1, NS
630: DO J = 1, N
631: VT( I, J ) = DCMPLX( RWORK( K ), ZERO )
632: K = K + 1
633: END DO
634: K = K + N
635: END DO
636: *
637: * Call ZUNMBR to compute VB**T * PB**T
638: * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
639: *
640: CALL ZUNMBR( 'P', 'R', 'C', NS, N, N, A, LDA,
641: $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
642: $ LWORK-ITEMP+1, IERR )
643: END IF
644: END IF
645: ELSE
646: *
647: * A has more columns than rows. If A has sufficiently more
648: * columns than rows, first reduce A using the LQ decomposition.
649: *
650: IF( N.GE.MNTHR ) THEN
651: *
652: * Path 1t (N much larger than M):
653: * A = L * Q = ( QB * B * PB**T ) * Q
654: * = ( QB * ( UB * S * VB**T ) * PB**T ) * Q
655: * U = QB * UB ; V**T = VB**T * PB**T * Q
656: *
657: * Compute A=L*Q
658: * (Workspace: need 2*M, prefer M+M*NB)
659: *
660: ITAU = 1
661: ITEMP = ITAU + M
662: CALL ZGELQF( M, N, A, LDA, WORK( ITAU ), WORK( ITEMP ),
663: $ LWORK-ITEMP+1, INFO )
664:
665: * Copy L into WORK and bidiagonalize it:
666: * (Workspace in WORK( ITEMP ): need M*M+3*M, prefer M*M+M+2*M*NB)
667: *
668: ILQF = ITEMP
669: ITAUQ = ILQF + M*M
670: ITAUP = ITAUQ + M
671: ITEMP = ITAUP + M
672: ID = 1
673: IE = ID + M
674: ITGKZ = IE + M
675: CALL ZLACPY( 'L', M, M, A, LDA, WORK( ILQF ), M )
676: CALL ZLASET( 'U', M-1, M-1, CZERO, CZERO,
677: $ WORK( ILQF+M ), M )
678: CALL ZGEBRD( M, M, WORK( ILQF ), M, RWORK( ID ),
679: $ RWORK( IE ), WORK( ITAUQ ), WORK( ITAUP ),
680: $ WORK( ITEMP ), LWORK-ITEMP+1, INFO )
681: ITEMP = ITGKZ + M*(M*2+1)
682: *
683: * Solve eigenvalue problem TGK*Z=Z*S.
684: * (Workspace: need 2*M*M+14*M)
685: *
686: CALL DBDSVDX( 'U', JOBZ, RNGTGK, M, RWORK( ID ),
687: $ RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S,
688: $ RWORK( ITGKZ ), M*2, RWORK( ITEMP ),
689: $ IWORK, INFO)
690: *
691: * If needed, compute left singular vectors.
692: *
693: IF( WANTU ) THEN
694: K = ITGKZ
695: DO I = 1, NS
696: DO J = 1, M
697: U( J, I ) = DCMPLX( RWORK( K ), ZERO )
698: K = K + 1
699: END DO
700: K = K + M
701: END DO
702: *
703: * Call ZUNMBR to compute QB*UB.
704: * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
705: *
706: CALL ZUNMBR( 'Q', 'L', 'N', M, NS, M, WORK( ILQF ), M,
707: $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
708: $ LWORK-ITEMP+1, INFO )
709: END IF
710: *
711: * If needed, compute right singular vectors.
712: *
713: IF( WANTVT) THEN
714: K = ITGKZ + M
715: DO I = 1, NS
716: DO J = 1, M
717: VT( I, J ) = DCMPLX( RWORK( K ), ZERO )
718: K = K + 1
719: END DO
720: K = K + M
721: END DO
722: CALL ZLASET( 'A', M, N-M, CZERO, CZERO,
723: $ VT( 1,M+1 ), LDVT )
724: *
725: * Call ZUNMBR to compute (VB**T)*(PB**T)
726: * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
727: *
728: CALL ZUNMBR( 'P', 'R', 'C', NS, M, M, WORK( ILQF ), M,
729: $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
730: $ LWORK-ITEMP+1, INFO )
731: *
732: * Call ZUNMLQ to compute ((VB**T)*(PB**T))*Q.
733: * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
734: *
735: CALL ZUNMLQ( 'R', 'N', NS, N, M, A, LDA,
736: $ WORK( ITAU ), VT, LDVT, WORK( ITEMP ),
737: $ LWORK-ITEMP+1, INFO )
738: END IF
739: ELSE
740: *
741: * Path 2t (N greater than M, but not much larger)
742: * Reduce to bidiagonal form without LQ decomposition
743: * A = QB * B * PB**T = QB * ( UB * S * VB**T ) * PB**T
744: * U = QB * UB; V**T = VB**T * PB**T
745: *
746: * Bidiagonalize A
747: * (Workspace: need 2*M+N, prefer 2*M+(M+N)*NB)
748: *
749: ITAUQ = 1
750: ITAUP = ITAUQ + M
751: ITEMP = ITAUP + M
752: ID = 1
753: IE = ID + M
754: ITGKZ = IE + M
755: CALL ZGEBRD( M, N, A, LDA, RWORK( ID ), RWORK( IE ),
756: $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
757: $ LWORK-ITEMP+1, INFO )
758: ITEMP = ITGKZ + M*(M*2+1)
759: *
760: * Solve eigenvalue problem TGK*Z=Z*S.
761: * (Workspace: need 2*M*M+14*M)
762: *
763: CALL DBDSVDX( 'L', JOBZ, RNGTGK, M, RWORK( ID ),
764: $ RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S,
765: $ RWORK( ITGKZ ), M*2, RWORK( ITEMP ),
766: $ IWORK, INFO)
767: *
768: * If needed, compute left singular vectors.
769: *
770: IF( WANTU ) THEN
771: K = ITGKZ
772: DO I = 1, NS
773: DO J = 1, M
774: U( J, I ) = DCMPLX( RWORK( K ), ZERO )
775: K = K + 1
776: END DO
777: K = K + M
778: END DO
779: *
780: * Call ZUNMBR to compute QB*UB.
781: * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
782: *
783: CALL ZUNMBR( 'Q', 'L', 'N', M, NS, N, A, LDA,
784: $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
785: $ LWORK-ITEMP+1, INFO )
786: END IF
787: *
788: * If needed, compute right singular vectors.
789: *
790: IF( WANTVT) THEN
791: K = ITGKZ + M
792: DO I = 1, NS
793: DO J = 1, M
794: VT( I, J ) = DCMPLX( RWORK( K ), ZERO )
795: K = K + 1
796: END DO
797: K = K + M
798: END DO
799: CALL ZLASET( 'A', M, N-M, CZERO, CZERO,
800: $ VT( 1,M+1 ), LDVT )
801: *
802: * Call ZUNMBR to compute VB**T * PB**T
803: * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
804: *
805: CALL ZUNMBR( 'P', 'R', 'C', NS, N, M, A, LDA,
806: $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
807: $ LWORK-ITEMP+1, INFO )
808: END IF
809: END IF
810: END IF
811: *
812: * Undo scaling if necessary
813: *
814: IF( ISCL.EQ.1 ) THEN
815: IF( ANRM.GT.BIGNUM )
816: $ CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1,
817: $ S, MINMN, INFO )
818: IF( ANRM.LT.SMLNUM )
819: $ CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1,
820: $ S, MINMN, INFO )
821: END IF
822: *
823: * Return optimal workspace in WORK(1)
824: *
825: WORK( 1 ) = DCMPLX( DBLE( MAXWRK ), ZERO )
826: *
827: RETURN
828: *
829: * End of ZGESVDX
830: *
831: END
CVSweb interface <joel.bertrand@systella.fr>