⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zbdsqr.f

📁 计算矩阵的经典开源库.全世界都在用它.相信你也不能例外.
💻 F
📖 第 1 页 / 共 2 页
字号:
      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 + -