📄 zbdsqr.f
字号:
SUBROUTINE ZBDSQR( UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U, $ LDU, C, LDC, RWORK, INFO )** -- LAPACK routine (instrumented to count operations, 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 UPLO INTEGER INFO, LDC, LDU, LDVT, N, NCC, NCVT, NRU* ..* .. Array Arguments .. DOUBLE PRECISION D( * ), E( * ), RWORK( * ) COMPLEX*16 C( LDC, * ), U( LDU, * ), VT( LDVT, * )* ..* Common block to return operation count and iteration count* ITCNT is initialized to 0, OPS is only incremented* .. Common blocks .. COMMON / LATIME / OPS, ITCNT* ..* .. Scalars in Common .. DOUBLE PRECISION ITCNT, OPS* ..** Purpose* =======** ZBDSQR computes the singular value decomposition (SVD) of a real* N-by-N (upper or lower) bidiagonal matrix B: B = Q * S * P' (P'* denotes the transpose of P), where S is a diagonal matrix with* non-negative diagonal elements (the singular values of B), and Q* and P are orthogonal matrices.** The routine computes S, and optionally computes U * Q, P' * VT,* or Q' * C, for given complex input matrices U, VT, and C.** See "Computing Small Singular Values of Bidiagonal Matrices With* Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan,* LAPACK Working Note #3 (or SIAM J. Sci. Statist. Comput. vol. 11,* no. 5, pp. 873-912, Sept 1990) and* "Accurate singular values and differential qd algorithms," by* B. Parlett and V. Fernando, Technical Report CPAM-554, Mathematics* Department, University of California at Berkeley, July 1992* for a detailed description of the algorithm.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': B is upper bidiagonal;* = 'L': B is lower bidiagonal.** N (input) INTEGER* The order of the matrix B. N >= 0.** NCVT (input) INTEGER* The number of columns of the matrix VT. NCVT >= 0.** NRU (input) INTEGER* The number of rows of the matrix U. NRU >= 0.** NCC (input) INTEGER* The number of columns of the matrix C. NCC >= 0.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the n diagonal elements of the bidiagonal matrix B.* On exit, if INFO=0, the singular values of B in decreasing* order.** E (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the elements of E contain the* offdiagonal elements of of the bidiagonal matrix whose SVD* is desired. On normal exit (INFO = 0), E is destroyed.* If the algorithm does not converge (INFO > 0), D and E* will contain the diagonal and superdiagonal elements of a* bidiagonal matrix orthogonally equivalent to the one given* as input. E(N) is used for workspace.** VT (input/output) COMPLEX*16 array, dimension (LDVT, NCVT)* On entry, an N-by-NCVT matrix VT.* On exit, VT is overwritten by P' * VT.* VT is not referenced if NCVT = 0.** LDVT (input) INTEGER* The leading dimension of the array VT.* LDVT >= max(1,N) if NCVT > 0; LDVT >= 1 if NCVT = 0.** U (input/output) COMPLEX*16 array, dimension (LDU, N)* On entry, an NRU-by-N matrix U.* On exit, U is overwritten by U * Q.* U is not referenced if NRU = 0.** LDU (input) INTEGER* The leading dimension of the array U. LDU >= max(1,NRU).** C (input/output) COMPLEX*16 array, dimension (LDC, NCC)* On entry, an N-by-NCC matrix C.* On exit, C is overwritten by Q' * C.* C is not referenced if NCC = 0.** LDC (input) INTEGER* The leading dimension of the array C.* LDC >= max(1,N) if NCC > 0; LDC >=1 if NCC = 0.** RWORK (workspace) DOUBLE PRECISION array, dimension (4*N)** INFO (output) INTEGER* = 0: successful exit* < 0: If INFO = -i, the i-th argument had an illegal value* > 0: the algorithm did not converge; D and E contain the* elements of a bidiagonal matrix which is orthogonally* similar to the input matrix B; if INFO = i, i* elements of E have not converged to zero.** Internal Parameters* ===================** TOLMUL DOUBLE PRECISION, default = max(10,min(100,EPS**(-1/8)))* TOLMUL controls the convergence criterion of the QR loop.* If it is positive, TOLMUL*EPS is the desired relative* precision in the computed singular values.* If it is negative, abs(TOLMUL*EPS*sigma_max) is the* desired absolute accuracy in the computed singular* values (corresponds to relative accuracy* abs(TOLMUL*EPS) in the largest singular value.* abs(TOLMUL) should be between 1 and 1/EPS, and preferably* between 10 (for fast convergence) and .1/EPS* (for there to be some accuracy in the results).* Default is to lose at either one eighth or 2 of the* available decimal digits in each computed singular value* (whichever is smaller).** MAXITR INTEGER, default = 6* MAXITR controls the maximum number of passes of the* algorithm through its inner loop. The algorithms stops* (and so fails to converge) if the number of passes* through the inner loop exceeds MAXITR*N**2.** =====================================================================** .. Parameters .. DOUBLE PRECISION ZERO PARAMETER ( ZERO = 0.0D0 ) DOUBLE PRECISION ONE PARAMETER ( ONE = 1.0D0 ) DOUBLE PRECISION NEGONE PARAMETER ( NEGONE = -1.0D0 ) DOUBLE PRECISION HNDRTH PARAMETER ( HNDRTH = 0.01D0 ) DOUBLE PRECISION TEN PARAMETER ( TEN = 10.0D0 ) DOUBLE PRECISION HNDRD PARAMETER ( HNDRD = 100.0D0 ) DOUBLE PRECISION MEIGTH PARAMETER ( MEIGTH = -0.125D0 ) INTEGER MAXITR PARAMETER ( MAXITR = 6 )* ..* .. Local Scalars .. LOGICAL LOWER, ROTATE INTEGER I, IDIR, ISUB, ITER, J, LL, LLL, M, MAXIT, NM1, $ NM12, NM13, OLDLL, OLDM DOUBLE PRECISION ABSE, ABSS, COSL, COSR, CS, EPS, F, G, H, MU, $ OLDCS, OLDSN, R, SHIFT, SIGMN, SIGMX, SINL, $ SINR, SLL, SMAX, SMIN, SMINL, SMINLO, SMINOA, $ SN, THRESH, TOL, TOLMUL, UNFL* ..* .. External Functions .. LOGICAL LSAME DOUBLE PRECISION DLAMCH EXTERNAL LSAME, DLAMCH* ..* .. External Subroutines .. EXTERNAL DLARTG, DLAS2, DLASQ1, DLASV2, XERBLA, ZDROT, $ ZDSCAL, ZLASR, ZSWAP* ..* .. Intrinsic Functions .. INTRINSIC ABS, DBLE, MAX, MIN, SIGN, SQRT* ..* .. Executable Statements ..** Test the input parameters.* INFO = 0 LOWER = LSAME( UPLO, 'L' ) IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LOWER ) THEN INFO = -1 ELSE IF( N.LT.0 ) THEN INFO = -2 ELSE IF( NCVT.LT.0 ) THEN INFO = -3 ELSE IF( NRU.LT.0 ) THEN INFO = -4 ELSE IF( NCC.LT.0 ) THEN INFO = -5 ELSE IF( ( NCVT.EQ.0 .AND. LDVT.LT.1 ) .OR. $ ( NCVT.GT.0 .AND. LDVT.LT.MAX( 1, N ) ) ) THEN INFO = -9 ELSE IF( LDU.LT.MAX( 1, NRU ) ) THEN INFO = -11 ELSE IF( ( NCC.EQ.0 .AND. LDC.LT.1 ) .OR. $ ( NCC.GT.0 .AND. LDC.LT.MAX( 1, N ) ) ) THEN INFO = -13 END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'ZBDSQR', -INFO ) RETURN END IF IF( N.EQ.0 ) $ RETURN IF( N.EQ.1 ) $ GO TO 160** ROTATE is true if any singular vectors desired, false otherwise* ROTATE = ( NCVT.GT.0 ) .OR. ( NRU.GT.0 ) .OR. ( NCC.GT.0 )** If no singular vectors desired, use qd algorithm* IF( .NOT.ROTATE ) THEN CALL DLASQ1( N, D, E, RWORK, INFO ) RETURN END IF* NM1 = N - 1 NM12 = NM1 + NM1 NM13 = NM12 + NM1 IDIR = 0** Get machine constants* EPS = DLAMCH( 'Epsilon' ) UNFL = DLAMCH( 'Safe minimum' )** If matrix lower bidiagonal, rotate to be upper bidiagonal* by applying Givens rotations on the left* IF( LOWER ) THEN OPS = OPS + DBLE( N-1 )*( 8+12*( NRU+NCC ) ) DO 10 I = 1, N - 1 CALL DLARTG( D( I ), E( I ), CS, SN, R ) D( I ) = R E( I ) = SN*D( I+1 ) D( I+1 ) = CS*D( I+1 ) RWORK( I ) = CS RWORK( NM1+I ) = SN 10 CONTINUE** Update singular vectors if desired* IF( NRU.GT.0 ) $ CALL ZLASR( 'R', 'V', 'F', NRU, N, RWORK( 1 ), RWORK( N ), $ U, LDU ) IF( NCC.GT.0 ) $ CALL ZLASR( 'L', 'V', 'F', N, NCC, RWORK( 1 ), RWORK( N ), $ C, LDC ) END IF** Compute singular values to relative accuracy TOL* (By setting TOL to be negative, algorithm will compute* singular values to absolute accuracy ABS(TOL)*norm(input matrix))* OPS = OPS + 4 TOLMUL = MAX( TEN, MIN( HNDRD, EPS**MEIGTH ) ) TOL = TOLMUL*EPS** Compute approximate maximum, minimum singular values* SMAX = ZERO DO 20 I = 1, N SMAX = MAX( SMAX, ABS( D( I ) ) ) 20 CONTINUE DO 30 I = 1, N - 1 SMAX = MAX( SMAX, ABS( E( I ) ) ) 30 CONTINUE SMINL = ZERO IF( TOL.GE.ZERO ) THEN** Relative accuracy desired* SMINOA = ABS( D( 1 ) ) IF( SMINOA.EQ.ZERO ) $ GO TO 50 MU = SMINOA OPS = OPS + 3*N - 1 DO 40 I = 2, N MU = ABS( D( I ) )*( MU / ( MU+ABS( E( I-1 ) ) ) ) SMINOA = MIN( SMINOA, MU ) IF( SMINOA.EQ.ZERO ) $ GO TO 50 40 CONTINUE 50 CONTINUE SMINOA = SMINOA / SQRT( DBLE( N ) ) THRESH = MAX( TOL*SMINOA, MAXITR*N*N*UNFL ) ELSE** Absolute accuracy desired* THRESH = MAX( ABS( TOL )*SMAX, MAXITR*N*N*UNFL ) END IF** Prepare for main iteration loop for the singular values* (MAXIT is the maximum number of passes through the inner* loop permitted before nonconvergence signalled.)* MAXIT = MAXITR*N*N ITER = 0 OLDLL = -1 OLDM = -1** M points to last element of unconverged part of matrix* M = N** Begin main iteration loop* 60 CONTINUE** Check for convergence or exceeding iteration count* IF( M.LE.1 ) $ GO TO 160 IF( ITER.GT.MAXIT ) $ GO TO 200** Find diagonal block of matrix to work on* IF( TOL.LT.ZERO .AND. ABS( D( M ) ).LE.THRESH ) $ D( M ) = ZERO SMAX = ABS( D( M ) ) SMIN = SMAX DO 70 LLL = 1, M - 1 LL = M - LLL ABSS = ABS( D( LL ) ) ABSE = ABS( E( LL ) ) IF( TOL.LT.ZERO .AND. ABSS.LE.THRESH ) $ D( LL ) = ZERO IF( ABSE.LE.THRESH ) $ GO TO 80 SMIN = MIN( SMIN, ABSS ) SMAX = MAX( SMAX, ABSS, ABSE ) 70 CONTINUE LL = 0 GO TO 90 80 CONTINUE E( LL ) = ZERO** Matrix splits since E(LL) = 0* IF( LL.EQ.M-1 ) THEN** Convergence of bottom singular value, return to top of loop* M = M - 1 GO TO 60 END IF 90 CONTINUE LL = LL + 1** E(LL) through E(M-1) are nonzero, E(LL-1) is zero* IF( LL.EQ.M-1 ) THEN** 2 by 2 block, handle separately* OPS = OPS + 37 + 12*( NCVT+NRU+NCC ) CALL DLASV2( D( M-1 ), E( M-1 ), D( M ), SIGMN, SIGMX, SINR, $ COSR, SINL, COSL ) D( M-1 ) = SIGMX E( M-1 ) = ZERO D( M ) = SIGMN** Compute singular vectors, if desired* IF( NCVT.GT.0 ) $ CALL ZDROT( NCVT, VT( M-1, 1 ), LDVT, VT( M, 1 ), LDVT, $ COSR, SINR )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -