📄 zgesdd.f
字号:
SUBROUTINE ZGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, $ LWORK, RWORK, IWORK, INFO )** -- LAPACK driver routine (instrumented to count ops, version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1999** .. Scalar Arguments .. CHARACTER JOBZ INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N* ..* .. Array Arguments .. INTEGER IWORK( * ) DOUBLE PRECISION RWORK( * ), S( * ) COMPLEX*16 A( LDA, * ), U( LDU, * ), VT( LDVT, * ), $ WORK( * )* ..* .. Common block to return operation count .. COMMON / LATIME / OPS, ITCNT* ..* .. Scalars in Common .. DOUBLE PRECISION ITCNT, OPS* ..** Purpose* =======** ZGESDD computes the singular value decomposition (SVD) of a complex* M-by-N matrix A, optionally computing the left and/or right singular* vectors, by using divide-and-conquer method. The SVD is written** A = U * SIGMA * conjugate-transpose(V)** where SIGMA is an M-by-N matrix which is zero except for its* min(m,n) diagonal elements, U is an M-by-M unitary matrix, and* V is an N-by-N unitary matrix. The diagonal elements of SIGMA* are the singular values of A; they are real and non-negative, and* are returned in descending order. The first min(m,n) columns of* U and V are the left and right singular vectors of A.** Note that the routine returns VT = V**H, not V.** The divide and conquer algorithm makes very mild assumptions about* floating point arithmetic. It will work on machines with a guard* digit in add/subtract, or on those binary machines without guard* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or* Cray-2. It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** Arguments* =========** JOBZ (input) CHARACTER*1* Specifies options for computing all or part of the matrix U:* = 'A': all M columns of U and all N rows of V**H are* returned in the arrays U and VT;* = 'S': the first min(M,N) columns of U and the first* min(M,N) rows of V**H are returned in the arrays U* and VT;* = 'O': If M >= N, the first N columns of U are overwritten* on the array A and all rows of V**H are returned in* the array VT;* otherwise, all columns of U are returned in the* array U and the first M rows of V**H are overwritten* in the array VT;* = 'N': no columns of U or rows of V**H are computed.** M (input) INTEGER* The number of rows of the input matrix A. M >= 0.** N (input) INTEGER* The number of columns of the input matrix A. N >= 0.** A (input/output) COMPLEX*16 array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit,* if JOBZ = 'O', A is overwritten with the first N columns* of U (the left singular vectors, stored* columnwise) if M >= N;* A is overwritten with the first M rows* of V**H (the right singular vectors, stored* rowwise) otherwise.* if JOBZ .ne. 'O', the contents of A are destroyed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** S (output) DOUBLE PRECISION array, dimension (min(M,N))* The singular values of A, sorted so that S(i) >= S(i+1).** U (output) COMPLEX*16 array, dimension (LDU,UCOL)* UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N;* UCOL = min(M,N) if JOBZ = 'S'.* If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M* unitary matrix U;* if JOBZ = 'S', U contains the first min(M,N) columns of U* (the left singular vectors, stored columnwise);* if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced.** LDU (input) INTEGER* The leading dimension of the array U. LDU >= 1; if* JOBZ = 'S' or 'A' or JOBZ = 'O' and M < N, LDU >= M.** VT (output) COMPLEX*16 array, dimension (LDVT,N)* If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the* N-by-N unitary matrix V**H;* if JOBZ = 'S', VT contains the first min(M,N) rows of* V**H (the right singular vectors, stored rowwise);* if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced.** LDVT (input) INTEGER* The leading dimension of the array VT. LDVT >= 1; if* JOBZ = 'A' or JOBZ = 'O' and M >= N, LDVT >= N;* if JOBZ = 'S', LDVT >= min(M,N).** WORK (workspace/output) COMPLEX*16 array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= 1.* if JOBZ = 'N', LWORK >= 2*min(M,N)+max(M,N).* if JOBZ = 'O',* LWORK >= 2*min(M,N)*min(M,N)+2*min(M,N)+max(M,N).* if JOBZ = 'S' or 'A',* LWORK >= min(M,N)*min(M,N)+2*min(M,N)+max(M,N).* For good performance, LWORK should generally be larger.* If LWORK < 0 but other input arguments are legal, WORK(1)* returns the optimal LWORK.** RWORK (workspace) DOUBLE PRECISION array, dimension (LRWORK)* If JOBZ = 'N', LRWORK >= 7*min(M,N).* Otherwise, LRWORK >= 5*min(M,N)*min(M,N) + 5*min(M,N)** IWORK (workspace) INTEGER array, dimension (8*min(M,N))** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: The updating process of DBDSDC did not converge.** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters .. COMPLEX*16 CZERO, CONE PARAMETER ( CZERO = ( 0.0D0, 0.0D0 ), $ CONE = ( 1.0D0, 0.0D0 ) ) DOUBLE PRECISION ZERO, ONE PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars .. LOGICAL LQUERY, WNTQA, WNTQAS, WNTQN, WNTQO, WNTQS INTEGER BLK, CHUNK, I, IE, IERR, IL, IR, IRU, IRVT, $ ISCL, ITAU, ITAUP, ITAUQ, IU, IVT, LDWKVT, $ LDWRKL, LDWRKR, LDWRKU, MAXWRK, MINMN, MINWRK, $ MNTHR1, MNTHR2, NB, NRWORK, NWORK, WRKBL DOUBLE PRECISION ANRM, BIGNUM, EPS, SMLNUM* ..* .. Local Arrays .. INTEGER IDUM( 1 ) DOUBLE PRECISION DUM( 1 )* ..* .. External Subroutines .. EXTERNAL DBDSDC, DLASCL, XERBLA, ZGEBRD, ZGELQF, ZGEMM, $ ZGEQRF, ZLACP2, ZLACPY, ZLACRM, ZLARCM, ZLASCL, $ ZLASET, ZUNGBR, ZUNGLQ, ZUNGQR, ZUNMBR* ..* .. External Functions .. LOGICAL LSAME INTEGER ILAENV DOUBLE PRECISION DLAMCH, DOPBL3, DOPLA, DOPLA2, ZLANGE EXTERNAL DLAMCH, DOPBL3, DOPLA, DOPLA2, ILAENV, LSAME, $ ZLANGE* ..* .. Intrinsic Functions .. INTRINSIC INT, MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input arguments* INFO = 0 MINMN = MIN( M, N ) MNTHR1 = INT( MINMN*17.0D0 / 9.0D0 ) MNTHR2 = INT( MINMN*5.0D0 / 3.0D0 ) WNTQA = LSAME( JOBZ, 'A' ) WNTQS = LSAME( JOBZ, 'S' ) WNTQAS = WNTQA .OR. WNTQS WNTQO = LSAME( JOBZ, 'O' ) WNTQN = LSAME( JOBZ, 'N' ) MINWRK = 1 MAXWRK = 1 LQUERY = ( LWORK.EQ.-1 )* IF( .NOT.( WNTQA .OR. WNTQS .OR. WNTQO .OR. WNTQN ) ) THEN INFO = -1 ELSE IF( M.LT.0 ) THEN INFO = -2 ELSE IF( N.LT.0 ) THEN INFO = -3 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN INFO = -5 ELSE IF( LDU.LT.1 .OR. ( WNTQAS .AND. LDU.LT.M ) .OR. $ ( WNTQO .AND. M.LT.N .AND. LDU.LT.M ) ) THEN INFO = -8 ELSE IF( LDVT.LT.1 .OR. ( WNTQA .AND. LDVT.LT.N ) .OR. $ ( WNTQS .AND. LDVT.LT.MINMN ) .OR. $ ( WNTQO .AND. M.GE.N .AND. LDVT.LT.N ) ) THEN INFO = -10 END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* CWorkspace refers to complex workspace, and RWorkspace to* real workspace. NB refers to the optimal block size for the* immediately following subroutine, as returned by ILAENV.)* IF( INFO.EQ.0 .AND. M.GT.0 .AND. N.GT.0 ) THEN IF( M.GE.N ) THEN** There is no complex work space needed for bidiagonal SVD* The real work space needed for bidiagonal SVD is BDSPAC,* BDSPAC = 3*N*N + 4*N* IF( M.GE.MNTHR1 ) THEN IF( WNTQN ) THEN** Path 1 (M much larger than N, JOBZ='N')* WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, $ -1 ) WRKBL = MAX( WRKBL, 2*N+2*N* $ ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) ) MAXWRK = WRKBL MINWRK = 3*N ELSE IF( WNTQO ) THEN** Path 2 (M much larger than N, JOBZ='O')* WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, -1 ) WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'ZUNGQR', ' ', M, $ N, N, -1 ) ) WRKBL = MAX( WRKBL, 2*N+2*N* $ ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) ) WRKBL = MAX( WRKBL, 2*N+N* $ ILAENV( 1, 'ZUNMBR', 'QLN', N, N, N, -1 ) ) WRKBL = MAX( WRKBL, 2*N+N* $ ILAENV( 1, 'ZUNMBR', 'PRC', N, N, N, -1 ) ) MAXWRK = M*N + N*N + WRKBL MINWRK = 2*N*N + 3*N ELSE IF( WNTQS ) THEN** Path 3 (M much larger than N, JOBZ='S')* WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, -1 ) WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'ZUNGQR', ' ', M, $ N, N, -1 ) ) WRKBL = MAX( WRKBL, 2*N+2*N* $ ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) ) WRKBL = MAX( WRKBL, 2*N+N* $ ILAENV( 1, 'ZUNMBR', 'QLN', N, N, N, -1 ) ) WRKBL = MAX( WRKBL, 2*N+N* $ ILAENV( 1, 'ZUNMBR', 'PRC', N, N, N, -1 ) ) MAXWRK = N*N + WRKBL MINWRK = N*N + 3*N ELSE IF( WNTQA ) THEN** Path 4 (M much larger than N, JOBZ='A')* WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, -1 ) WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'ZUNGQR', ' ', M, $ M, N, -1 ) ) WRKBL = MAX( WRKBL, 2*N+2*N* $ ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) ) WRKBL = MAX( WRKBL, 2*N+N* $ ILAENV( 1, 'ZUNMBR', 'QLN', N, N, N, -1 ) ) WRKBL = MAX( WRKBL, 2*N+N* $ ILAENV( 1, 'ZUNMBR', 'PRC', N, N, N, -1 ) ) MAXWRK = N*N + WRKBL MINWRK = N*N + 2*N + M END IF ELSE IF( M.GE.MNTHR2 ) THEN** Path 5 (M much larger than N, but not as much as MNTHR1)* MAXWRK = 2*N + ( M+N )*ILAENV( 1, 'ZGEBRD', ' ', M, N, $ -1, -1 ) MINWRK = 2*N + M IF( WNTQO ) THEN MAXWRK = MAX( MAXWRK, 2*N+N* $ ILAENV( 1, 'ZUNGBR', 'P', N, N, N, -1 ) ) MAXWRK = MAX( MAXWRK, 2*N+N* $ ILAENV( 1, 'ZUNGBR', 'Q', M, N, N, -1 ) ) MAXWRK = MAXWRK + M*N MINWRK = MINWRK + N*N ELSE IF( WNTQS ) THEN MAXWRK = MAX( MAXWRK, 2*N+N* $ ILAENV( 1, 'ZUNGBR', 'P', N, N, N, -1 ) ) MAXWRK = MAX( MAXWRK, 2*N+N* $ ILAENV( 1, 'ZUNGBR', 'Q', M, N, N, -1 ) ) ELSE IF( WNTQA ) THEN MAXWRK = MAX( MAXWRK, 2*N+N* $ ILAENV( 1, 'ZUNGBR', 'P', N, N, N, -1 ) ) MAXWRK = MAX( MAXWRK, 2*N+M* $ ILAENV( 1, 'ZUNGBR', 'Q', M, M, N, -1 ) ) END IF ELSE** Path 6 (M at least N, but not much larger)* MAXWRK = 2*N + ( M+N )*ILAENV( 1, 'ZGEBRD', ' ', M, N, $ -1, -1 ) MINWRK = 2*N + M IF( WNTQO ) THEN MAXWRK = MAX( MAXWRK, 2*N+N*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -