dtgevc.f

来自「计算矩阵的经典开源库.全世界都在用它.相信你也不能例外.」· F 代码 · 共 1,270 行 · 第 1/3 页

F
1,270
字号
*      IF( COMPL ) THEN         IEIG = 0**        Main loop over eigenvalues*         ILCPLX = .FALSE.         DO 220 JE = 1, N**           Skip this iteration if (a) HOWMNY='S' and SELECT=.FALSE., or*           (b) this would be the second of a complex pair.*           Check for complex eigenvalue, so as to be sure of which*           entry(-ies) of SELECT to look at.*            IF( ILCPLX ) THEN               ILCPLX = .FALSE.               GO TO 220            END IF            NW = 1            IF( JE.LT.N ) THEN               IF( A( JE+1, JE ).NE.ZERO ) THEN                  ILCPLX = .TRUE.                  NW = 2               END IF            END IF            IF( ILALL ) THEN               ILCOMP = .TRUE.            ELSE IF( ILCPLX ) THEN               ILCOMP = SELECT( JE ) .OR. SELECT( JE+1 )            ELSE               ILCOMP = SELECT( JE )            END IF            IF( .NOT.ILCOMP )     $         GO TO 220**           Decide if (a) singular pencil, (b) real eigenvalue, or*           (c) complex eigenvalue.*            IF( .NOT.ILCPLX ) THEN               IF( ABS( A( JE, JE ) ).LE.SAFMIN .AND.     $             ABS( B( JE, JE ) ).LE.SAFMIN ) THEN**                 Singular matrix pencil -- returns unit eigenvector*                  IEIG = IEIG + 1                  DO 60 JR = 1, N                     VL( JR, IEIG ) = ZERO   60             CONTINUE                  VL( IEIG, IEIG ) = ONE                  GO TO 220               END IF            END IF**           Clear vector*            DO 70 JR = 1, NW*N               WORK( 2*N+JR ) = ZERO   70       CONTINUE*                                                 T*           Compute coefficients in  ( a A - b B )  y = 0*              a  is  ACOEF*              b  is  BCOEFR + i*BCOEFI*            IF( .NOT.ILCPLX ) THEN**              Real eigenvalue*               TEMP = ONE / MAX( ABS( A( JE, JE ) )*ASCALE,     $                ABS( B( JE, JE ) )*BSCALE, SAFMIN )               SALFAR = ( TEMP*A( JE, JE ) )*ASCALE               SBETA = ( TEMP*B( JE, JE ) )*BSCALE               ACOEF = SBETA*ASCALE               BCOEFR = SALFAR*BSCALE               BCOEFI = ZERO**              Scale to avoid underflow*               SCALE = ONE               LSA = ABS( SBETA ).GE.SAFMIN .AND. ABS( ACOEF ).LT.SMALL               LSB = ABS( SALFAR ).GE.SAFMIN .AND. ABS( BCOEFR ).LT.     $               SMALL               IF( LSA )     $            SCALE = ( SMALL / ABS( SBETA ) )*MIN( ANORM, BIG )               IF( LSB )     $            SCALE = MAX( SCALE, ( SMALL / ABS( SALFAR ) )*     $                    MIN( BNORM, BIG ) )               IF( LSA .OR. LSB ) THEN                  SCALE = MIN( SCALE, ONE /     $                    ( SAFMIN*MAX( ONE, ABS( ACOEF ),     $                    ABS( BCOEFR ) ) ) )                  IF( LSA ) THEN                     ACOEF = ASCALE*( SCALE*SBETA )                  ELSE                     ACOEF = SCALE*ACOEF                  END IF                  IF( LSB ) THEN                     BCOEFR = BSCALE*( SCALE*SALFAR )                  ELSE                     BCOEFR = SCALE*BCOEFR                  END IF               END IF               ACOEFA = ABS( ACOEF )               BCOEFA = ABS( BCOEFR )**              First component is 1*               WORK( 2*N+JE ) = ONE               XMAX = ONE            ELSE**              Complex eigenvalue*               CALL DLAG2( A( JE, JE ), LDA, B( JE, JE ), LDB,     $                     SAFMIN*SAFETY, ACOEF, TEMP, BCOEFR, TEMP2,     $                     BCOEFI )               BCOEFI = -BCOEFI               IF( BCOEFI.EQ.ZERO ) THEN                  INFO = JE                  RETURN               END IF**              Scale to avoid over/underflow*               ACOEFA = ABS( ACOEF )               BCOEFA = ABS( BCOEFR ) + ABS( BCOEFI )               SCALE = ONE               IF( ACOEFA*ULP.LT.SAFMIN .AND. ACOEFA.GE.SAFMIN )     $            SCALE = ( SAFMIN / ULP ) / ACOEFA               IF( BCOEFA*ULP.LT.SAFMIN .AND. BCOEFA.GE.SAFMIN )     $            SCALE = MAX( SCALE, ( SAFMIN / ULP ) / BCOEFA )               IF( SAFMIN*ACOEFA.GT.ASCALE )     $            SCALE = ASCALE / ( SAFMIN*ACOEFA )               IF( SAFMIN*BCOEFA.GT.BSCALE )     $            SCALE = MIN( SCALE, BSCALE / ( SAFMIN*BCOEFA ) )               IF( SCALE.NE.ONE ) THEN                  ACOEF = SCALE*ACOEF                  ACOEFA = ABS( ACOEF )                  BCOEFR = SCALE*BCOEFR                  BCOEFI = SCALE*BCOEFI                  BCOEFA = ABS( BCOEFR ) + ABS( BCOEFI )               END IF**              Compute first two components of eigenvector*               TEMP = ACOEF*A( JE+1, JE )               TEMP2R = ACOEF*A( JE, JE ) - BCOEFR*B( JE, JE )               TEMP2I = -BCOEFI*B( JE, JE )               IF( ABS( TEMP ).GT.ABS( TEMP2R )+ABS( TEMP2I ) ) THEN                  WORK( 2*N+JE ) = ONE                  WORK( 3*N+JE ) = ZERO                  WORK( 2*N+JE+1 ) = -TEMP2R / TEMP                  WORK( 3*N+JE+1 ) = -TEMP2I / TEMP               ELSE                  WORK( 2*N+JE+1 ) = ONE                  WORK( 3*N+JE+1 ) = ZERO                  TEMP = ACOEF*A( JE, JE+1 )                  WORK( 2*N+JE ) = ( BCOEFR*B( JE+1, JE+1 )-ACOEF*     $                             A( JE+1, JE+1 ) ) / TEMP                  WORK( 3*N+JE ) = BCOEFI*B( JE+1, JE+1 ) / TEMP               END IF               XMAX = MAX( ABS( WORK( 2*N+JE ) )+ABS( WORK( 3*N+JE ) ),     $                ABS( WORK( 2*N+JE+1 ) )+ABS( WORK( 3*N+JE+1 ) ) )            END IF*            DMIN = MAX( ULP*ACOEFA*ANORM, ULP*BCOEFA*BNORM, SAFMIN )**                                           T*           Triangular solve of  (a A - b B)  y = 0**                                   T*           (rowwise in  (a A - b B) , or columnwise in (a A - b B) )*            IL2BY2 = .FALSE.*           ------------------- Begin Timing Code ----------------------            OPST = ZERO            IN2BY2 = 0*           -------------------- End Timing Code -----------------------*            DO 160 J = JE + NW, N*              ------------------- Begin Timing Code -------------------               OPSSCA = DBLE( NW*( J-JE )+1 )*              -------------------- End Timing Code --------------------               IF( IL2BY2 ) THEN                  IL2BY2 = .FALSE.                  GO TO 160               END IF*               NA = 1               BDIAG( 1 ) = B( J, J )               IF( J.LT.N ) THEN                  IF( A( J+1, J ).NE.ZERO ) THEN                     IL2BY2 = .TRUE.                     BDIAG( 2 ) = B( J+1, J+1 )                     NA = 2*                    ---------------- Begin Timing Code ----------------                     IN2BY2 = IN2BY2 + 1*                    ----------------- End Timing Code -----------------                  END IF               END IF**              Check whether scaling is necessary for dot products*               XSCALE = ONE / MAX( ONE, XMAX )               TEMP = MAX( WORK( J ), WORK( N+J ),     $                ACOEFA*WORK( J )+BCOEFA*WORK( N+J ) )               IF( IL2BY2 )     $            TEMP = MAX( TEMP, WORK( J+1 ), WORK( N+J+1 ),     $                   ACOEFA*WORK( J+1 )+BCOEFA*WORK( N+J+1 ) )               IF( TEMP.GT.BIGNUM*XSCALE ) THEN                  DO 90 JW = 0, NW - 1                     DO 80 JR = JE, J - 1                        WORK( ( JW+2 )*N+JR ) = XSCALE*     $                     WORK( ( JW+2 )*N+JR )   80                CONTINUE   90             CONTINUE                  XMAX = XMAX*XSCALE*                 ------------------ Begin Timing Code -----------------                  OPST = OPST + OPSSCA*                 ------------------- End Timing Code ------------------               END IF**              Compute dot products**                    j-1*              SUM = sum  conjg( a*A(k,j) - b*B(k,j) )*x(k)*                    k=je**              To reduce the op count, this is done as**              _        j-1                  _        j-1*              a*conjg( sum  A(k,j)*x(k) ) - b*conjg( sum  B(k,j)*x(k) )*                       k=je                          k=je**              which may cause underflow problems if A or B are close*              to underflow.  (E.g., less than SMALL.)***              A series of compiler directives to defeat vectorization*              for the next loop**$PL$ CMCHAR=' 'CDIR$          NEXTSCALARC$DIR          SCALARCDIR$          NEXT SCALARCVD$L          NOVECTORCDEC$          NOVECTORCVD$           NOVECTOR*VDIR          NOVECTOR*VOCL          LOOP,SCALARCIBM           PREFER SCALAR*$PL$ CMCHAR='*'*               DO 120 JW = 1, NW**$PL$ CMCHAR=' 'CDIR$             NEXTSCALARC$DIR             SCALARCDIR$             NEXT SCALARCVD$L             NOVECTORCDEC$             NOVECTORCVD$              NOVECTOR*VDIR             NOVECTOR*VOCL             LOOP,SCALARCIBM              PREFER SCALAR*$PL$ CMCHAR='*'*                  DO 110 JA = 1, NA                     SUMA( JA, JW ) = ZERO                     SUMB( JA, JW ) = ZERO*                     DO 100 JR = JE, J - 1                        SUMA( JA, JW ) = SUMA( JA, JW ) +     $                                   A( JR, J+JA-1 )*     $                                   WORK( ( JW+1 )*N+JR )                        SUMB( JA, JW ) = SUMB( JA, JW ) +     $                                   B( JR, J+JA-1 )*     $                                   WORK( ( JW+1 )*N+JR )  100                CONTINUE  110             CONTINUE  120          CONTINUE**$PL$ CMCHAR=' 'CDIR$          NEXTSCALARC$DIR          SCALARCDIR$          NEXT SCALARCVD$L          NOVECTORCDEC$          NOVECTORCVD$           NOVECTOR*VDIR          NOVECTOR*VOCL          LOOP,SCALARCIBM           PREFER SCALAR*$PL$ CMCHAR='*'*               DO 130 JA = 1, NA                  IF( ILCPLX ) THEN                     SUM( JA, 1 ) = -ACOEF*SUMA( JA, 1 ) +     $                              BCOEFR*SUMB( JA, 1 ) -     $                              BCOEFI*SUMB( JA, 2 )                     SUM( JA, 2 ) = -ACOEF*SUMA( JA, 2 ) +     $                              BCOEFR*SUMB( JA, 2 ) +     $                              BCOEFI*SUMB( JA, 1 )                  ELSE                     SUM( JA, 1 ) = -ACOEF*SUMA( JA, 1 ) +     $                              BCOEFR*SUMB( JA, 1 )                  END IF  130          CONTINUE**                                  T*              Solve  ( a A - b B )  y = SUM(,)*              with scaling and perturbation of the denominator*               CALL DLALN2( .TRUE., NA, NW, DMIN, ACOEF, A( J, J ), LDA,     $                      BDIAG( 1 ), BDIAG( 2 ), SUM, 2, BCOEFR,     $                      BCOEFI, WORK( 2*N+J ), N, SCALE, TEMP,     $                      IINFO )               IF( SCALE.LT.ONE ) THEN                  DO 150 JW = 0, NW - 1                     DO 140 JR = JE, J - 1                        WORK( ( JW+2 )*N+JR ) = SCALE*     $                     WORK( ( JW+2 )*N+JR )  140                CONTINUE  150             CONTINUE                  XMAX = SCALE*XMAX*                 ------------------ Begin Timing Code -----------------                  OPST = OPST + OPSSCA*                 ------------------- End Timing Code ------------------               END IF               XMAX = MAX( XMAX, TEMP )  160       CONTINUE**           Copy eigenvector to VL, back transforming if*           HOWMNY='B'.*            IEIG = IEIG + 1            IF( ILBACK ) THEN               DO 170 JW = 0, NW - 1                  CALL DGEMV( 'N', N, N+1-JE, ONE, VL( 1, JE ), LDVL,     $                        WORK( ( JW+2 )*N+JE ), 1, ZERO,     $                        WORK( ( JW+4 )*N+1 ), 1 )  170          CONTINUE               CALL DLACPY( ' ', N, NW, WORK( 4*N+1 ), N, VL( 1, JE ),     $                      LDVL )               IBEG = 1            ELSE               CALL DLACPY( ' ', N, NW, WORK( 2*N+1 ), N, VL( 1, IEIG ),     $                      LDVL )               IBEG = JE            END IF**           Scale eigenvector*            XMAX = ZERO            IF( ILCPLX ) THEN               DO 180 J = IBEG, N                  XMAX = MAX( XMAX, ABS( VL( J, IEIG ) )+     $                   ABS( VL( J, IEIG+1 ) ) )  180          CONTINUE            ELSE               DO 190 J = IBEG, N                  XMAX = MAX( XMAX, ABS( VL( J, IEIG ) ) )  190          CONTINUE            END IF*            IF( XMAX.GT.SAFMIN ) THEN               XSCALE = ONE / XMAX*               DO 210 JW = 0, NW - 1                  DO 200 JR = IBEG, N                     VL( JR, IEIG+JW ) = XSCALE*VL( JR, IEIG+JW )  200             CONTINUE  210          CONTINUE            END IF            IEIG = IEIG + NW - 1**           ------------------- Begin Timing Code ----------------------*           Opcounts for each eigenvector**                                Real                Complex*           Initialization       8--16               71--87**           Dot Prod (per iter)  4*NA*(J-JE) + 2     8*NA*(J-JE) + 2*                                + 6*NA + scaling    + 13*NA + scaling*           Solve (per iter)     NA*(5 + 7*(NA-1))   NA*(17 + 17*(NA-1))*                                + scaling           + scaling**           Back xform           2*N*(N+1-JE) - N    4*N*(N+1-JE) - 2*N*           Scaling (w/back x.)  N                   3*N*           Scaling (w/o back)   N - (JE-1)          3*N - 3*(JE-1)*            IF( .NOT.ILCPLX ) THEN               OPST = OPST + DBLE( 2*( N-JE )*( N+1-JE )+13*( N-JE )+8*     $                IN2BY2+12 )               IF( ILBACK ) THEN                  OPST = OPST + DBLE( 2*N*( N+1-JE ) )               ELSE                  OPST = OPST + DBLE( N+1-JE )               END IF            ELSE               OPST = OPST + DBLE( 32*( N-1-JE )+4*( N-JE )*( N+1-JE )+     $                24*IN2BY2+71 )               IF( ILBACK ) THEN                  OPST = OPST + DBLE( 4*N*( N+1-JE )+N )               ELSE                  OPST = OPST + DBLE( 3*( N+1-JE ) )               END IF            END IF            OPS = OPS + OPST**           -------------------- End Timing Code -----------------------*  220    CONTINUE      END IF**     Right eigenvectors*      IF( COMPR ) THEN         IEIG = IM + 1**        Main loop over eigenvalues*         ILCPLX = .FALSE.         DO 500 JE = N, 1, -1**           Skip this iteration if (a) HOWMNY='S' and SELECT=.FALSE., or

⌨️ 快捷键说明

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