1 *> \brief <b> CGESVDX computes the singular value decomposition (SVD) for GE matrices</b>
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download CGESVDX + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cgesvdx.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cgesvdx.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgesvdx.f">
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 )
26 * .. Scalar Arguments ..
27 * CHARACTER JOBU, JOBVT, RANGE
28 * INTEGER IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
31 * .. Array Arguments ..
33 * REAL S( * ), RWORK( * )
34 * COMPLEX A( LDA, * ), U( LDU, * ), VT( LDVT, * ),
44 *> CGESVDX computes the singular value decomposition (SVD) of a complex
45 *> M-by-N matrix A, optionally computing the left and/or right singular
46 *> vectors. The SVD is written
48 *> A = U * SIGMA * transpose(V)
50 *> where SIGMA is an M-by-N matrix which is zero except for its
51 *> min(m,n) diagonal elements, U is an M-by-M unitary matrix, and
52 *> V is an N-by-N unitary matrix. The diagonal elements of SIGMA
53 *> are the singular values of A; they are real and non-negative, and
54 *> are returned in descending order. The first min(m,n) columns of
55 *> U and V are the left and right singular vectors of A.
57 *> CGESVDX uses an eigenvalue problem for obtaining the SVD, which
58 *> allows for the computation of a subset of singular values and
59 *> vectors. See SBDSVDX for details.
61 *> Note that the routine returns V**T, not V.
69 *> JOBU is CHARACTER*1
70 *> Specifies options for computing all or part of the matrix U:
71 *> = 'V': the first min(m,n) columns of U (the left singular
72 *> vectors) or as specified by RANGE are returned in
74 *> = 'N': no columns of U (no left singular vectors) are
80 *> JOBVT is CHARACTER*1
81 *> Specifies options for computing all or part of the matrix
83 *> = 'V': the first min(m,n) rows of V**T (the right singular
84 *> vectors) or as specified by RANGE are returned in
86 *> = 'N': no rows of V**T (no right singular vectors) are
92 *> RANGE is CHARACTER*1
93 *> = 'A': all singular values will be found.
94 *> = 'V': all singular values in the half-open interval (VL,VU]
96 *> = 'I': the IL-th through IU-th singular values will be found.
102 *> The number of rows of the input matrix A. M >= 0.
108 *> The number of columns of the input matrix A. N >= 0.
113 *> A is COMPLEX array, dimension (LDA,N)
114 *> On entry, the M-by-N matrix A.
115 *> On exit, the contents of A are destroyed.
121 *> The leading dimension of the array A. LDA >= max(1,M).
133 *> If RANGE='V', the lower and upper bounds of the interval to
134 *> be searched for singular values. VU > VL.
135 *> Not referenced if RANGE = 'A' or 'I'.
146 *> If RANGE='I', the indices (in ascending order) of the
147 *> smallest and largest singular values to be returned.
148 *> 1 <= IL <= IU <= min(M,N), if min(M,N) > 0.
149 *> Not referenced if RANGE = 'A' or 'V'.
155 *> The total number of singular values found,
156 *> 0 <= NS <= min(M,N).
157 *> If RANGE = 'A', NS = min(M,N); if RANGE = 'I', NS = IU-IL+1.
162 *> S is REAL array, dimension (min(M,N))
163 *> The singular values of A, sorted so that S(i) >= S(i+1).
168 *> U is COMPLEX array, dimension (LDU,UCOL)
169 *> If JOBU = 'V', U contains columns of U (the left singular
170 *> vectors, stored columnwise) as specified by RANGE; if
171 *> JOBU = 'N', U is not referenced.
172 *> Note: The user must ensure that UCOL >= NS; if RANGE = 'V',
173 *> the exact value of NS is not known ILQFin advance and an upper
174 *> bound must be used.
180 *> The leading dimension of the array U. LDU >= 1; if
181 *> JOBU = 'V', LDU >= M.
186 *> VT is COMPLEX array, dimension (LDVT,N)
187 *> If JOBVT = 'V', VT contains the rows of V**T (the right singular
188 *> vectors, stored rowwise) as specified by RANGE; if JOBVT = 'N',
189 *> VT is not referenced.
190 *> Note: The user must ensure that LDVT >= NS; if RANGE = 'V',
191 *> the exact value of NS is not known in advance and an upper
192 *> bound must be used.
198 *> The leading dimension of the array VT. LDVT >= 1; if
199 *> JOBVT = 'V', LDVT >= NS (see above).
204 *> WORK is COMPLEX array, dimension (MAX(1,LWORK))
205 *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
211 *> The dimension of the array WORK.
212 *> LWORK >= MAX(1,MIN(M,N)*(MIN(M,N)+4)) for the paths (see
213 *> comments inside the code):
214 *> - PATH 1 (M much larger than N)
215 *> - PATH 1t (N much larger than M)
216 *> LWORK >= MAX(1,MIN(M,N)*2+MAX(M,N)) for the other paths.
217 *> For good performance, LWORK should generally be larger.
219 *> If LWORK = -1, then a workspace query is assumed; the routine
220 *> only calculates the optimal size of the WORK array, returns
221 *> this value as the first entry of the WORK array, and no error
222 *> message related to LWORK is issued by XERBLA.
227 *> RWORK is REAL array, dimension (MAX(1,LRWORK))
228 *> LRWORK >= MIN(M,N)*(MIN(M,N)*2+15*MIN(M,N)).
233 *> IWORK is INTEGER array, dimension (12*MIN(M,N))
234 *> If INFO = 0, the first NS elements of IWORK are zero. If INFO > 0,
235 *> then IWORK contains the indices of the eigenvectors that failed
236 *> to converge in SBDSVDX/SSTEVX.
242 *> = 0: successful exit
243 *> < 0: if INFO = -i, the i-th argument had an illegal value
244 *> > 0: if INFO = i, then i eigenvectors failed to converge
245 *> in SBDSVDX/SSTEVX.
246 *> if INFO = N*2 + 1, an internal error occurred in
253 *> \author Univ. of Tennessee
254 *> \author Univ. of California Berkeley
255 *> \author Univ. of Colorado Denver
258 *> \date November 2015
260 *> \ingroup complexGEsing
262 * =====================================================================
263 SUBROUTINE CGESVDX( JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU,
264 $ IL, IU, NS, S, U, LDU, VT, LDVT, WORK,
265 $ LWORK, RWORK, IWORK, INFO )
267 * -- LAPACK driver routine (version 3.6.0) --
268 * -- LAPACK is a software package provided by Univ. of Tennessee, --
269 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
272 * .. Scalar Arguments ..
273 CHARACTER JOBU, JOBVT, RANGE
274 INTEGER IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
277 * .. Array Arguments ..
279 REAL S( * ), RWORK( * )
280 COMPLEX A( LDA, * ), U( LDU, * ), VT( LDVT, * ),
284 * =====================================================================
288 PARAMETER ( CZERO = ( 0.0E0, 0.0E0 ),
289 $ CONE = ( 1.0E0, 0.0E0 ) )
291 PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 )
293 * .. Local Scalars ..
294 CHARACTER JOBZ, RNGTGK
295 LOGICAL ALLS, INDS, LQUERY, VALS, WANTU, WANTVT
296 INTEGER I, ID, IE, IERR, ILQF, ILTGK, IQRF, ISCL,
297 $ ITAU, ITAUP, ITAUQ, ITEMP, ITGKZ, IUTGK,
298 $ J, K, MAXWRK, MINMN, MINWRK, MNTHR
299 REAL ABSTOL, ANRM, BIGNUM, EPS, SMLNUM
304 * .. External Subroutines ..
305 EXTERNAL CGEBRD, CGELQF, CGEQRF, CLASCL, CLASET,
308 * .. External Functions ..
312 EXTERNAL LSAME, ILAENV, SLAMCH, CLANGE
314 * .. Intrinsic Functions ..
315 INTRINSIC MAX, MIN, SQRT
317 * .. Executable Statements ..
319 * Test the input arguments.
323 ABSTOL = 2*SLAMCH('S')
324 LQUERY = ( LWORK.EQ.-1 )
327 WANTU = LSAME( JOBU, 'V' )
328 WANTVT = LSAME( JOBVT, 'V' )
329 IF( WANTU .OR. WANTVT ) THEN
334 ALLS = LSAME( RANGE, 'A' )
335 VALS = LSAME( RANGE, 'V' )
336 INDS = LSAME( RANGE, 'I' )
339 IF( .NOT.LSAME( JOBU, 'V' ) .AND.
340 $ .NOT.LSAME( JOBU, 'N' ) ) THEN
342 ELSE IF( .NOT.LSAME( JOBVT, 'V' ) .AND.
343 $ .NOT.LSAME( JOBVT, 'N' ) ) THEN
345 ELSE IF( .NOT.( ALLS .OR. VALS .OR. INDS ) ) THEN
347 ELSE IF( M.LT.0 ) THEN
349 ELSE IF( N.LT.0 ) THEN
351 ELSE IF( M.GT.LDA ) THEN
353 ELSE IF( MINMN.GT.0 ) THEN
355 IF( VL.LT.ZERO ) THEN
357 ELSE IF( VU.LE.VL ) THEN
361 IF( IL.LT.1 .OR. IL.GT.MAX( 1, MINMN ) ) THEN
363 ELSE IF( IU.LT.MIN( MINMN, IL ) .OR. IU.GT.MINMN ) THEN
368 IF( WANTU .AND. LDU.LT.M ) THEN
370 ELSE IF( WANTVT .AND. LDVT.LT.MINMN ) THEN
377 * (Note: Comments in the code beginning "Workspace:" describe the
378 * minimal amount of workspace needed at that point in the code,
379 * as well as the preferred amount for good performance.
380 * NB refers to the optimal block size for the immediately
381 * following subroutine, as returned by ILAENV.)
386 IF( MINMN.GT.0 ) THEN
388 MNTHR = ILAENV( 6, 'CGESVD', JOBU // JOBVT, M, N, 0, 0 )
389 IF( M.GE.MNTHR ) THEN
391 * Path 1 (M much larger than N)
394 $ ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
395 MAXWRK = MAX( MAXWRK, N*N + N + 2*N*
396 $ ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
400 * Path 2 (M at least N, but not much larger)
402 MAXWRK = 2*N + ( M+N )*
403 $ ILAENV( 1, 'CGEBRD', ' ', M, N, -1, -1 )
407 MNTHR = ILAENV( 6, 'CGESVD', JOBU // JOBVT, M, N, 0, 0 )
408 IF( N.GE.MNTHR ) THEN
410 * Path 1t (N much larger than M)
413 $ ILAENV( 1, 'CGELQF', ' ', M, N, -1, -1 )
414 MAXWRK = MAX( MAXWRK, M*M + M + 2*M*
415 $ ILAENV( 1, 'CGEBRD', ' ', M, M, -1, -1 ) )
419 * Path 2t (N greater than M, but not much larger)
421 MAXWRK = M*(M*2+19) + ( M+N )*
422 $ ILAENV( 1, 'CGEBRD', ' ', M, N, -1, -1 )
427 MAXWRK = MAX( MAXWRK, MINWRK )
428 WORK( 1 ) = CMPLX( REAL( MAXWRK ), ZERO )
430 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
436 CALL XERBLA( 'CGESVDX', -INFO )
438 ELSE IF( LQUERY ) THEN
442 * Quick return if possible
444 IF( M.EQ.0 .OR. N.EQ.0 ) THEN
448 * Set singular values indices accord to RANGE='A'.
450 ALLS = LSAME( RANGE, 'A' )
451 INDS = LSAME( RANGE, 'I' )
466 * Get machine constants
469 SMLNUM = SQRT( SLAMCH( 'S' ) ) / EPS
470 BIGNUM = ONE / SMLNUM
472 * Scale A if max element outside range [SMLNUM,BIGNUM]
474 ANRM = CLANGE( 'M', M, N, A, LDA, DUM )
476 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
478 CALL CLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
479 ELSE IF( ANRM.GT.BIGNUM ) THEN
481 CALL CLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
486 * A has at least as many rows as columns. If A has sufficiently
487 * more rows than columns, first reduce A using the QR
490 IF( M.GE.MNTHR ) THEN
492 * Path 1 (M much larger than N):
493 * A = Q * R = Q * ( QB * B * PB**T )
494 * = Q * ( QB * ( UB * S * VB**T ) * PB**T )
495 * U = Q * QB * UB; V**T = VB**T * PB**T
498 * (Workspace: need 2*N, prefer N+N*NB)
502 CALL CGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( ITEMP ),
503 $ LWORK-ITEMP+1, INFO )
505 * Copy R into WORK and bidiagonalize it:
506 * (Workspace: need N*N+3*N, prefer N*N+N+2*N*NB)
515 CALL CLACPY( 'U', N, N, A, LDA, WORK( IQRF ), N )
516 CALL CLASET( 'L', N-1, N-1, CZERO, CZERO,
517 $ WORK( IQRF+1 ), N )
518 CALL CGEBRD( N, N, WORK( IQRF ), N, RWORK( ID ),
519 $ RWORK( IE ), WORK( ITAUQ ), WORK( ITAUP ),
520 $ WORK( ITEMP ), LWORK-ITEMP+1, INFO )
521 ITEMP = ITGKZ + N*(N*2+1)
523 * Solve eigenvalue problem TGK*Z=Z*S.
524 * (Workspace: need 2*N*N+14*N)
526 CALL SBDSVDX( 'U', JOBZ, RNGTGK, N, RWORK( ID ),
527 $ RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S,
528 $ RWORK( ITGKZ ), N*2, RWORK( ITEMP ),
531 * If needed, compute left singular vectors.
537 U( J, I ) = CMPLX( RWORK( K ), ZERO )
542 CALL CLASET( 'A', M-N, N, CZERO, CZERO, U( N+1,1 ), LDU )
544 * Call CUNMBR to compute QB*UB.
545 * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
547 CALL CUNMBR( 'Q', 'L', 'N', N, NS, N, WORK( IQRF ), N,
548 $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
549 $ LWORK-ITEMP+1, INFO )
551 * Call CUNMQR to compute Q*(QB*UB).
552 * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
554 CALL CUNMQR( 'L', 'N', M, NS, N, A, LDA,
555 $ WORK( ITAU ), U, LDU, WORK( ITEMP ),
556 $ LWORK-ITEMP+1, INFO )
559 * If needed, compute right singular vectors.
565 VT( I, J ) = CMPLX( RWORK( K ), ZERO )
571 * Call CUNMBR to compute VB**T * PB**T
572 * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
574 CALL CUNMBR( 'P', 'R', 'C', NS, N, N, WORK( IQRF ), N,
575 $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
576 $ LWORK-ITEMP+1, INFO )
580 * Path 2 (M at least N, but not much larger)
581 * Reduce A to bidiagonal form without QR decomposition
582 * A = QB * B * PB**T = QB * ( UB * S * VB**T ) * PB**T
583 * U = QB * UB; V**T = VB**T * PB**T
586 * (Workspace: need 2*N+M, prefer 2*N+(M+N)*NB)
594 CALL CGEBRD( M, N, A, LDA, RWORK( ID ), RWORK( IE ),
595 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
596 $ LWORK-ITEMP+1, INFO )
597 ITEMP = ITGKZ + N*(N*2+1)
599 * Solve eigenvalue problem TGK*Z=Z*S.
600 * (Workspace: need 2*N*N+14*N)
602 CALL SBDSVDX( 'U', JOBZ, RNGTGK, N, RWORK( ID ),
603 $ RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S,
604 $ RWORK( ITGKZ ), N*2, RWORK( ITEMP ),
607 * If needed, compute left singular vectors.
613 U( J, I ) = CMPLX( RWORK( K ), ZERO )
618 CALL CLASET( 'A', M-N, N, CZERO, CZERO, U( N+1,1 ), LDU )
620 * Call CUNMBR to compute QB*UB.
621 * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
623 CALL CUNMBR( 'Q', 'L', 'N', M, NS, N, A, LDA,
624 $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
625 $ LWORK-ITEMP+1, IERR )
628 * If needed, compute right singular vectors.
634 VT( I, J ) = CMPLX( RWORK( K ), ZERO )
640 * Call CUNMBR to compute VB**T * PB**T
641 * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
643 CALL CUNMBR( 'P', 'R', 'C', NS, N, N, A, LDA,
644 $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
645 $ LWORK-ITEMP+1, IERR )
650 * A has more columns than rows. If A has sufficiently more
651 * columns than rows, first reduce A using the LQ decomposition.
653 IF( N.GE.MNTHR ) THEN
655 * Path 1t (N much larger than M):
656 * A = L * Q = ( QB * B * PB**T ) * Q
657 * = ( QB * ( UB * S * VB**T ) * PB**T ) * Q
658 * U = QB * UB ; V**T = VB**T * PB**T * Q
661 * (Workspace: need 2*M, prefer M+M*NB)
665 CALL CGELQF( M, N, A, LDA, WORK( ITAU ), WORK( ITEMP ),
666 $ LWORK-ITEMP+1, INFO )
668 * Copy L into WORK and bidiagonalize it:
669 * (Workspace in WORK( ITEMP ): need M*M+3*M, prefer M*M+M+2*M*NB)
678 CALL CLACPY( 'L', M, M, A, LDA, WORK( ILQF ), M )
679 CALL CLASET( 'U', M-1, M-1, CZERO, CZERO,
680 $ WORK( ILQF+M ), M )
681 CALL CGEBRD( M, M, WORK( ILQF ), M, RWORK( ID ),
682 $ RWORK( IE ), WORK( ITAUQ ), WORK( ITAUP ),
683 $ WORK( ITEMP ), LWORK-ITEMP+1, INFO )
684 ITEMP = ITGKZ + M*(M*2+1)
686 * Solve eigenvalue problem TGK*Z=Z*S.
687 * (Workspace: need 2*M*M+14*M)
689 CALL SBDSVDX( 'U', JOBZ, RNGTGK, M, RWORK( ID ),
690 $ RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S,
691 $ RWORK( ITGKZ ), M*2, RWORK( ITEMP ),
694 * If needed, compute left singular vectors.
700 U( J, I ) = CMPLX( RWORK( K ), ZERO )
706 * Call CUNMBR to compute QB*UB.
707 * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
709 CALL CUNMBR( 'Q', 'L', 'N', M, NS, M, WORK( ILQF ), M,
710 $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
711 $ LWORK-ITEMP+1, INFO )
714 * If needed, compute right singular vectors.
720 VT( I, J ) = CMPLX( RWORK( K ), ZERO )
725 CALL CLASET( 'A', M, N-M, CZERO, CZERO,
726 $ VT( 1,M+1 ), LDVT )
728 * Call CUNMBR to compute (VB**T)*(PB**T)
729 * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
731 CALL CUNMBR( 'P', 'R', 'C', NS, M, M, WORK( ILQF ), M,
732 $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
733 $ LWORK-ITEMP+1, INFO )
735 * Call CUNMLQ to compute ((VB**T)*(PB**T))*Q.
736 * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
738 CALL CUNMLQ( 'R', 'N', NS, N, M, A, LDA,
739 $ WORK( ITAU ), VT, LDVT, WORK( ITEMP ),
740 $ LWORK-ITEMP+1, INFO )
744 * Path 2t (N greater than M, but not much larger)
745 * Reduce to bidiagonal form without LQ decomposition
746 * A = QB * B * PB**T = QB * ( UB * S * VB**T ) * PB**T
747 * U = QB * UB; V**T = VB**T * PB**T
750 * (Workspace: need 2*M+N, prefer 2*M+(M+N)*NB)
758 CALL CGEBRD( M, N, A, LDA, RWORK( ID ), RWORK( IE ),
759 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
760 $ LWORK-ITEMP+1, INFO )
761 ITEMP = ITGKZ + M*(M*2+1)
763 * Solve eigenvalue problem TGK*Z=Z*S.
764 * (Workspace: need 2*M*M+14*M)
766 CALL SBDSVDX( 'L', JOBZ, RNGTGK, M, RWORK( ID ),
767 $ RWORK( IE ), VL, VU, ILTGK, IUTGK, NS, S,
768 $ RWORK( ITGKZ ), M*2, RWORK( ITEMP ),
771 * If needed, compute left singular vectors.
777 U( J, I ) = CMPLX( RWORK( K ), ZERO )
783 * Call CUNMBR to compute QB*UB.
784 * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
786 CALL CUNMBR( 'Q', 'L', 'N', M, NS, N, A, LDA,
787 $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
788 $ LWORK-ITEMP+1, INFO )
791 * If needed, compute right singular vectors.
797 VT( I, J ) = CMPLX( RWORK( K ), ZERO )
802 CALL CLASET( 'A', M, N-M, CZERO, CZERO,
803 $ VT( 1,M+1 ), LDVT )
805 * Call CUNMBR to compute VB**T * PB**T
806 * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
808 CALL CUNMBR( 'P', 'R', 'C', NS, N, M, A, LDA,
809 $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
810 $ LWORK-ITEMP+1, INFO )
815 * Undo scaling if necessary
819 $ CALL SLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1,
822 $ CALL SLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1,
826 * Return optimal workspace in WORK(1)
828 WORK( 1 ) = CMPLX( REAL( MAXWRK ), ZERO )