📄 dgesdd.f
字号:
SUBROUTINE DGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, $ LWORK, 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 A( LDA, * ), S( * ), U( LDU, * ), $ VT( LDVT, * ), WORK( * )* ..* .. Common block to return operation count .. COMMON / LATIME / OPS, ITCNT* ..* .. Scalars in Common .. DOUBLE PRECISION ITCNT, OPS* ..** Purpose* =======** DGESDD computes the singular value decomposition (SVD) of a real* M-by-N matrix A, optionally computing the left and right singular* vectors. If singular vectors are desired, it uses a* divide-and-conquer algorithm.** The SVD is written** A = U * SIGMA * 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 orthogonal matrix, and* V is an N-by-N orthogonal 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**T, 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**T 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**T 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**T are returned in* the array VT;* otherwise, all columns of U are returned in the* array U and the first M rows of V**T are overwritten* in the array VT;* = 'N': no columns of U or rows of V**T 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) DOUBLE PRECISION 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**T (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) DOUBLE PRECISION 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* orthogonal 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) DOUBLE PRECISION array, dimension (LDVT,N)* If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the* N-by-N orthogonal matrix V**T;* if JOBZ = 'S', VT contains the first min(M,N) rows of* V**T (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) DOUBLE PRECISION 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 >= 3*min(M,N) + max(max(M,N),6*min(M,N)).* If JOBZ = 'O',* LWORK >= 3*min(M,N)*min(M,N) + * max(max(M,N),5*min(M,N)*min(M,N)+4*min(M,N)).* If JOBZ = 'S' or 'A'* LWORK >= 3*min(M,N)*min(M,N) +* max(max(M,N),4*min(M,N)*min(M,N)+4*min(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.** 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: DBDSDC did not converge, updating process failed.** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters .. DOUBLE PRECISION ZERO, ONE PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars .. LOGICAL LQUERY, WNTQA, WNTQAS, WNTQN, WNTQO, WNTQS INTEGER BDSPAC, BLK, CHUNK, I, IE, IERR, IL, $ IR, ISCL, ITAU, ITAUP, ITAUQ, IU, IVT, LDWKVT, $ LDWRKL, LDWRKR, LDWRKU, MAXWRK, MINMN, MINWRK, $ MNTHR, NB, NWORK, WRKBL DOUBLE PRECISION ANRM, BIGNUM, EPS, SMLNUM* ..* .. Local Arrays .. INTEGER IDUM( 1 ) DOUBLE PRECISION DUM( 1 )* ..* .. External Subroutines .. EXTERNAL DBDSDC, DGEBRD, DGELQF, DGEMM, DGEQRF, DLACPY, $ DLASCL, DLASET, DORGBR, DORGLQ, DORGQR, DORMBR, $ XERBLA* ..* .. External Functions .. LOGICAL LSAME INTEGER ILAENV DOUBLE PRECISION DLAMCH, DLANGE, DOPBL3, DOPLA, DOPLA2 EXTERNAL DLAMCH, DLANGE, DOPBL3, DOPLA, DOPLA2, ILAENV, $ LSAME* ..* .. Intrinsic Functions .. INTRINSIC DBLE, INT, MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input arguments* INFO = 0 MINMN = MIN( M, N ) MNTHR = INT( MINMN*11.0D0 / 6.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.* 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** Compute space needed for DBDSDC* IF( WNTQN ) THEN BDSPAC = 7*N ELSE BDSPAC = 3*N*N + 4*N END IF IF( M.GE.MNTHR ) THEN IF( WNTQN ) THEN** Path 1 (M much larger than N, JOBZ='N')* WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, $ -1 ) WRKBL = MAX( WRKBL, 3*N+2*N* $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) MAXWRK = MAX( WRKBL, BDSPAC+N ) MINWRK = BDSPAC + N ELSE IF( WNTQO ) THEN** Path 2 (M much larger than N, JOBZ='O')* WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M, $ N, N, -1 ) ) WRKBL = MAX( WRKBL, 3*N+2*N* $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) WRKBL = MAX( WRKBL, 3*N+N* $ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) ) WRKBL = MAX( WRKBL, 3*N+N* $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) ) WRKBL = MAX( WRKBL, BDSPAC+3*N ) MAXWRK = WRKBL + 2*N*N MINWRK = BDSPAC + 2*N*N + 3*N ELSE IF( WNTQS ) THEN** Path 3 (M much larger than N, JOBZ='S')* WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M, $ N, N, -1 ) ) WRKBL = MAX( WRKBL, 3*N+2*N* $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) WRKBL = MAX( WRKBL, 3*N+N* $ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) ) WRKBL = MAX( WRKBL, 3*N+N* $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) ) WRKBL = MAX( WRKBL, BDSPAC+3*N ) MAXWRK = WRKBL + N*N MINWRK = BDSPAC + N*N + 3*N ELSE IF( WNTQA ) THEN** Path 4 (M much larger than N, JOBZ='A')* WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M, $ M, N, -1 ) ) WRKBL = MAX( WRKBL, 3*N+2*N* $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) WRKBL = MAX( WRKBL, 3*N+N* $ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) ) WRKBL = MAX( WRKBL, 3*N+N* $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) ) WRKBL = MAX( WRKBL, BDSPAC+3*N ) MAXWRK = WRKBL + N*N MINWRK = BDSPAC + N*N + 3*N END IF ELSE** Path 5 (M at least N, but not much larger)* WRKBL = 3*N + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, -1, $ -1 ) IF( WNTQN ) THEN MAXWRK = MAX( WRKBL, BDSPAC+3*N ) MINWRK = 3*N + MAX( M, BDSPAC ) ELSE IF( WNTQO ) THEN WRKBL = MAX( WRKBL, 3*N+N* $ ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) ) WRKBL = MAX( WRKBL, 3*N+N* $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) ) WRKBL = MAX( WRKBL, BDSPAC+3*N ) MAXWRK = WRKBL + M*N MINWRK = 3*N + MAX( M, N*N+BDSPAC ) ELSE IF( WNTQS ) THEN WRKBL = MAX( WRKBL, 3*N+N* $ ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) ) WRKBL = MAX( WRKBL, 3*N+N* $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) ) MAXWRK = MAX( WRKBL, BDSPAC+3*N ) MINWRK = 3*N + MAX( M, BDSPAC ) ELSE IF( WNTQA ) THEN WRKBL = MAX( WRKBL, 3*N+M* $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) ) WRKBL = MAX( WRKBL, 3*N+N* $ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) ) MAXWRK = MAX( MAXWRK, BDSPAC+3*N ) MINWRK = 3*N + MAX( M, BDSPAC ) END IF END IF ELSE** Compute space needed for DBDSDC* IF( WNTQN ) THEN BDSPAC = 7*M ELSE BDSPAC = 3*M*M + 4*M END IF IF( N.GE.MNTHR ) THEN IF( WNTQN ) THEN** Path 1t (N much larger than M, JOBZ='N')* WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, $ -1 ) WRKBL = MAX( WRKBL, 3*M+2*M* $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) MAXWRK = MAX( WRKBL, BDSPAC+M ) MINWRK = BDSPAC + M ELSE IF( WNTQO ) THEN** Path 2t (N much larger than M, JOBZ='O')* WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M, $ N, M, -1 ) ) WRKBL = MAX( WRKBL, 3*M+2*M* $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) ) WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) ) WRKBL = MAX( WRKBL, BDSPAC+3*M ) MAXWRK = WRKBL + 2*M*M MINWRK = BDSPAC + 2*M*M + 3*M ELSE IF( WNTQS ) THEN** Path 3t (N much larger than M, JOBZ='S')*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -