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

📄 slasd4.f

📁 计算矩阵的经典开源库.全世界都在用它.相信你也不能例外.
💻 F
📖 第 1 页 / 共 3 页
字号:
      SUBROUTINE SLASD4( N, I, D, Z, DELTA, RHO, SIGMA, WORK, INFO )**  -- LAPACK auxiliary routine (instrumented to count ops, version 3.0) --*     Univ. of Tennessee, Oak Ridge National Lab, Argonne National Lab,*     Courant Institute, NAG Ltd., and Rice University*     October 31, 1999**     .. Scalar Arguments ..      INTEGER            I, INFO, N      REAL               RHO, SIGMA*     ..*     .. Array Arguments ..      REAL               D( * ), DELTA( * ), WORK( * ), Z( * )*     ..*     .. Common block to return operation count ..      COMMON             / LATIME / OPS, ITCNT*     ..*     .. Scalars in Common ..      REAL               ITCNT, OPS*     ..**  Purpose*  =======**  This subroutine computes the square root of the I-th updated*  eigenvalue of a positive symmetric rank-one modification to*  a positive diagonal matrix whose entries are given as the squares*  of the corresponding entries in the array d, and that**         0 <= D(i) < D(j)  for  i < j**  and that RHO > 0. This is arranged by the calling routine, and is*  no loss in generality.  The rank-one modified system is thus**         diag( D ) * diag( D ) +  RHO *  Z * Z_transpose.**  where we assume the Euclidean norm of Z is 1.**  The method consists of approximating the rational functions in the*  secular equation by simpler interpolating rational functions.**  Arguments*  =========**  N      (input) INTEGER*         The length of all arrays.**  I      (input) INTEGER*         The index of the eigenvalue to be computed.  1 <= I <= N.**  D      (input) REAL array, dimension ( N )*         The original eigenvalues.  It is assumed that they are in*         order, 0 <= D(I) < D(J)  for I < J.**  Z      (input) REAL array, dimension ( N )*         The components of the updating vector.**  DELTA  (output) REAL array, dimension ( N )*         If N .ne. 1, DELTA contains (D(j) - sigma_I) in its  j-th*         component.  If N = 1, then DELTA(1) = 1.  The vector DELTA*         contains the information necessary to construct the*         (singular) eigenvectors.**  RHO    (input) REAL*         The scalar in the symmetric updating formula.**  SIGMA  (output) REAL*         The computed lambda_I, the I-th updated eigenvalue.**  WORK   (workspace) REAL array, dimension ( N )*         If N .ne. 1, WORK contains (D(j) + sigma_I) in its  j-th*         component.  If N = 1, then WORK( 1 ) = 1.**  INFO   (output) INTEGER*         = 0:  successful exit*         > 0:  if INFO = 1, the updating process failed.**  Internal Parameters*  ===================**  Logical variable ORGATI (origin-at-i?) is used for distinguishing*  whether D(i) or D(i+1) is treated as the origin.**            ORGATI = .true.    origin at i*            ORGATI = .false.   origin at i+1**  Logical variable SWTCH3 (switch-for-3-poles?) is for noting*  if we are working with THREE poles!**  MAXIT is the maximum number of iterations allowed for each*  eigenvalue.**  Further Details*  ===============**  Based on contributions by*     Ren-Cang Li, Computer Science Division, University of California*     at Berkeley, USA**  =====================================================================**     .. Parameters ..      INTEGER            MAXIT      PARAMETER          ( MAXIT = 20 )      REAL               ZERO, ONE, TWO, THREE, FOUR, EIGHT, TEN      PARAMETER          ( ZERO = 0.0E0, ONE = 1.0E0, TWO = 2.0E0,     $                   THREE = 3.0E0, FOUR = 4.0E0, EIGHT = 8.0E0,     $                   TEN = 10.0E0 )*     ..*     .. Local Scalars ..      LOGICAL            ORGATI, SWTCH, SWTCH3      INTEGER            II, IIM1, IIP1, IP1, ITER, J, NITER      REAL               A, B, C, DELSQ, DELSQ2, DPHI, DPSI, DTIIM,     $                   DTIIP, DTIPSQ, DTISQ, DTNSQ, DTNSQ1, DW, EPS,     $                   ERRETM, ETA, PHI, PREW, PSI, RHOINV, SG2LB,     $                   SG2UB, TAU, TEMP, TEMP1, TEMP2, W*     ..*     .. Local Arrays ..      REAL               DD( 3 ), ZZ( 3 )*     ..*     .. External Subroutines ..      EXTERNAL           SLAED6, SLASD5*     ..*     .. External Functions ..      REAL               SLAMCH      EXTERNAL           SLAMCH*     ..*     .. Intrinsic Functions ..      INTRINSIC          REAL, ABS, MAX, MIN, SQRT*     ..*     .. Executable Statements ..**     Since this routine is called in an inner loop, we do no argument*     checking.**     Quick return for N=1 and 2.*      INFO = 0      IF( N.EQ.1 ) THEN**        Presumably, I=1 upon entry*         OPS = OPS + REAL( 5 )         SIGMA = SQRT( D( 1 )*D( 1 )+RHO*Z( 1 )*Z( 1 ) )         DELTA( 1 ) = ONE         WORK( 1 ) = ONE         RETURN      END IF      IF( N.EQ.2 ) THEN         CALL SLASD5( I, D, Z, DELTA, RHO, SIGMA, WORK )         RETURN      END IF**     Compute machine epsilon*      EPS = SLAMCH( 'Epsilon' )      OPS = OPS + REAL( 1 )      RHOINV = ONE / RHO**     The case I = N*      IF( I.EQ.N ) THEN**        Initialize some basic variables*         II = N - 1         NITER = 1**        Calculate initial guess*         OPS = OPS + REAL( 1 )         TEMP = RHO / TWO**        If ||Z||_2 is not one, then TEMP should be set to*        RHO * ||Z||_2^2 / TWO*         OPS = OPS + REAL( 5 + 4*N )         TEMP1 = TEMP / ( D( N )+SQRT( D( N )*D( N )+TEMP ) )         DO 10 J = 1, N            WORK( J ) = D( J ) + D( N ) + TEMP1            DELTA( J ) = ( D( J )-D( N ) ) - TEMP1   10    CONTINUE*         PSI = ZERO         OPS = OPS + REAL( 4*( N-2 ) )         DO 20 J = 1, N - 2            PSI = PSI + Z( J )*Z( J ) / ( DELTA( J )*WORK( J ) )   20    CONTINUE*         OPS = OPS + REAL( 9 )         C = RHOINV + PSI         W = C + Z( II )*Z( II ) / ( DELTA( II )*WORK( II ) ) +     $       Z( N )*Z( N ) / ( DELTA( N )*WORK( N ) )*         IF( W.LE.ZERO ) THEN            OPS = OPS + REAL( 14 )            TEMP1 = SQRT( D( N )*D( N )+RHO )            TEMP = Z( N-1 )*Z( N-1 ) / ( ( D( N-1 )+TEMP1 )*     $             ( D( N )-D( N-1 )+RHO / ( D( N )+TEMP1 ) ) ) +     $             Z( N )*Z( N ) / RHO**           The following TAU is to approximate*           SIGMA_n^2 - D( N )*D( N )*            IF( C.LE.TEMP ) THEN               TAU = RHO            ELSE               OPS = OPS + REAL( 10 )               DELSQ = ( D( N )-D( N-1 ) )*( D( N )+D( N-1 ) )               A = -C*DELSQ + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N )               B = Z( N )*Z( N )*DELSQ               IF( A.LT.ZERO ) THEN                  OPS = OPS + REAL( 8 )                  TAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )               ELSE                  OPS = OPS + REAL( 8 )                  TAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )               END IF            END IF**           It can be proved that*               D(N)^2+RHO/2 <= SIGMA_n^2 < D(N)^2+TAU <= D(N)^2+RHO*         ELSE            OPS = OPS + REAL( 10 )            DELSQ = ( D( N )-D( N-1 ) )*( D( N )+D( N-1 ) )            A = -C*DELSQ + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N )            B = Z( N )*Z( N )*DELSQ**           The following TAU is to approximate*           SIGMA_n^2 - D( N )*D( N )*            IF( A.LT.ZERO ) THEN               OPS = OPS + REAL( 8 )               TAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )            ELSE               OPS = OPS + REAL( 8 )               TAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )            END IF**           It can be proved that*           D(N)^2 < D(N)^2+TAU < SIGMA(N)^2 < D(N)^2+RHO/2*         END IF**        The following ETA is to approximate SIGMA_n - D( N )*         OPS = OPS + REAL( 5 )         ETA = TAU / ( D( N )+SQRT( D( N )*D( N )+TAU ) )*         OPS = OPS + REAL( 1 + 4*N )         SIGMA = D( N ) + ETA         DO 30 J = 1, N            DELTA( J ) = ( D( J )-D( I ) ) - ETA            WORK( J ) = D( J ) + D( I ) + ETA   30    CONTINUE**        Evaluate PSI and the derivative DPSI*         DPSI = ZERO         PSI = ZERO         ERRETM = ZERO         OPS = OPS + REAL( II*7 )         DO 40 J = 1, II            TEMP = Z( J ) / ( DELTA( J )*WORK( J ) )            PSI = PSI + Z( J )*TEMP            DPSI = DPSI + TEMP*TEMP            ERRETM = ERRETM + PSI   40    CONTINUE         ERRETM = ABS( ERRETM )**        Evaluate PHI and the derivative DPHI*         OPS = OPS + REAL( 14 )         TEMP = Z( N ) / ( DELTA( N )*WORK( N ) )         PHI = Z( N )*TEMP         DPHI = TEMP*TEMP         ERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV +     $            ABS( TAU )*( DPSI+DPHI )*         W = RHOINV + PHI + PSI**        Test for convergence*         IF( ABS( W ).LE.EPS*ERRETM ) THEN            GO TO 240         END IF**        Calculate the new step*         NITER = NITER + 1         OPS = OPS + REAL( 14 )         DTNSQ1 = WORK( N-1 )*DELTA( N-1 )         DTNSQ = WORK( N )*DELTA( N )         C = W - DTNSQ1*DPSI - DTNSQ*DPHI         A = ( DTNSQ+DTNSQ1 )*W - DTNSQ*DTNSQ1*( DPSI+DPHI )         B = DTNSQ*DTNSQ1*W         IF( C.LT.ZERO )     $      C = ABS( C )         IF( C.EQ.ZERO ) THEN            OPS = OPS + REAL( 2 )            ETA = RHO - SIGMA*SIGMA         ELSE IF( A.GE.ZERO ) THEN            OPS = OPS + REAL( 8 )            ETA = ( A+SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )         ELSE            OPS = OPS + REAL( 8 )            ETA = TWO*B / ( A-SQRT( ABS( A*A-FOUR*B*C ) ) )         END IF**        Note, eta should be positive if w is negative, and*        eta should be negative otherwise. However,*        if for some reason caused by roundoff, eta*w > 0,*        we simply use one Newton step instead. This way*        will guarantee eta*w < 0.*         OPS = OPS + REAL( 1 )         IF( W*ETA.GT.ZERO ) THEN            OPS = OPS + REAL( 2 )            ETA = -W / ( DPSI+DPHI )         END IF         TEMP = ETA - DTNSQ         IF( TEMP.GT.RHO ) THEN            OPS = OPS + REAL( 1 )            ETA = RHO + DTNSQ         END IF*         OPS = OPS + REAL( 6 + 2*N + 1 )         TAU = TAU + ETA         ETA = ETA / ( SIGMA+SQRT( ETA+SIGMA*SIGMA ) )         DO 50 J = 1, N            DELTA( J ) = DELTA( J ) - ETA

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -