cgeevx.f
来自「famous linear algebra library (LAPACK) p」· F 代码 · 共 533 行 · 第 1/2 页
F
533 行
IF( WANTVL ) THEN
CALL CHSEQR( 'S', 'V', N, 1, N, A, LDA, W, VL, LDVL,
$ WORK, -1, INFO )
ELSE IF( WANTVR ) THEN
CALL CHSEQR( 'S', 'V', N, 1, N, A, LDA, W, VR, LDVR,
$ WORK, -1, INFO )
ELSE
IF( WNTSNN ) THEN
CALL CHSEQR( 'E', 'N', N, 1, N, A, LDA, W, VR, LDVR,
$ WORK, -1, INFO )
ELSE
CALL CHSEQR( 'S', 'N', N, 1, N, A, LDA, W, VR, LDVR,
$ WORK, -1, INFO )
END IF
END IF
HSWORK = WORK( 1 )
*
IF( ( .NOT.WANTVL ) .AND. ( .NOT.WANTVR ) ) THEN
MINWRK = 2*N
IF( .NOT.( WNTSNN .OR. WNTSNE ) )
$ MINWRK = MAX( MINWRK, N*N + 2*N )
MAXWRK = MAX( MAXWRK, HSWORK )
IF( .NOT.( WNTSNN .OR. WNTSNE ) )
$ MAXWRK = MAX( MAXWRK, N*N + 2*N )
ELSE
MINWRK = 2*N
IF( .NOT.( WNTSNN .OR. WNTSNE ) )
$ MINWRK = MAX( MINWRK, N*N + 2*N )
MAXWRK = MAX( MAXWRK, HSWORK )
MAXWRK = MAX( MAXWRK, N + ( N - 1 )*ILAENV( 1, 'CUNGHR',
$ ' ', N, 1, N, -1 ) )
IF( .NOT.( WNTSNN .OR. WNTSNE ) )
$ MAXWRK = MAX( MAXWRK, N*N + 2*N )
MAXWRK = MAX( MAXWRK, 2*N )
END IF
MAXWRK = MAX( MAXWRK, MINWRK )
END IF
WORK( 1 ) = MAXWRK
*
IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
INFO = -20
END IF
END IF
*
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'CGEEVX', -INFO )
RETURN
ELSE IF( LQUERY ) THEN
RETURN
END IF
*
* Quick return if possible
*
IF( N.EQ.0 )
$ RETURN
*
* Get machine constants
*
EPS = SLAMCH( 'P' )
SMLNUM = SLAMCH( 'S' )
BIGNUM = ONE / SMLNUM
CALL SLABAD( SMLNUM, BIGNUM )
SMLNUM = SQRT( SMLNUM ) / EPS
BIGNUM = ONE / SMLNUM
*
* Scale A if max element outside range [SMLNUM,BIGNUM]
*
ICOND = 0
ANRM = CLANGE( 'M', N, N, A, LDA, DUM )
SCALEA = .FALSE.
IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
SCALEA = .TRUE.
CSCALE = SMLNUM
ELSE IF( ANRM.GT.BIGNUM ) THEN
SCALEA = .TRUE.
CSCALE = BIGNUM
END IF
IF( SCALEA )
$ CALL CLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )
*
* Balance the matrix and compute ABNRM
*
CALL CGEBAL( BALANC, N, A, LDA, ILO, IHI, SCALE, IERR )
ABNRM = CLANGE( '1', N, N, A, LDA, DUM )
IF( SCALEA ) THEN
DUM( 1 ) = ABNRM
CALL SLASCL( 'G', 0, 0, CSCALE, ANRM, 1, 1, DUM, 1, IERR )
ABNRM = DUM( 1 )
END IF
*
* Reduce to upper Hessenberg form
* (CWorkspace: need 2*N, prefer N+N*NB)
* (RWorkspace: none)
*
ITAU = 1
IWRK = ITAU + N
CALL CGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),
$ LWORK-IWRK+1, IERR )
*
IF( WANTVL ) THEN
*
* Want left eigenvectors
* Copy Householder vectors to VL
*
SIDE = 'L'
CALL CLACPY( 'L', N, N, A, LDA, VL, LDVL )
*
* Generate unitary matrix in VL
* (CWorkspace: need 2*N-1, prefer N+(N-1)*NB)
* (RWorkspace: none)
*
CALL CUNGHR( N, ILO, IHI, VL, LDVL, WORK( ITAU ), WORK( IWRK ),
$ LWORK-IWRK+1, IERR )
*
* Perform QR iteration, accumulating Schur vectors in VL
* (CWorkspace: need 1, prefer HSWORK (see comments) )
* (RWorkspace: none)
*
IWRK = ITAU
CALL CHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, W, VL, LDVL,
$ WORK( IWRK ), LWORK-IWRK+1, INFO )
*
IF( WANTVR ) THEN
*
* Want left and right eigenvectors
* Copy Schur vectors to VR
*
SIDE = 'B'
CALL CLACPY( 'F', N, N, VL, LDVL, VR, LDVR )
END IF
*
ELSE IF( WANTVR ) THEN
*
* Want right eigenvectors
* Copy Householder vectors to VR
*
SIDE = 'R'
CALL CLACPY( 'L', N, N, A, LDA, VR, LDVR )
*
* Generate unitary matrix in VR
* (CWorkspace: need 2*N-1, prefer N+(N-1)*NB)
* (RWorkspace: none)
*
CALL CUNGHR( N, ILO, IHI, VR, LDVR, WORK( ITAU ), WORK( IWRK ),
$ LWORK-IWRK+1, IERR )
*
* Perform QR iteration, accumulating Schur vectors in VR
* (CWorkspace: need 1, prefer HSWORK (see comments) )
* (RWorkspace: none)
*
IWRK = ITAU
CALL CHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, W, VR, LDVR,
$ WORK( IWRK ), LWORK-IWRK+1, INFO )
*
ELSE
*
* Compute eigenvalues only
* If condition numbers desired, compute Schur form
*
IF( WNTSNN ) THEN
JOB = 'E'
ELSE
JOB = 'S'
END IF
*
* (CWorkspace: need 1, prefer HSWORK (see comments) )
* (RWorkspace: none)
*
IWRK = ITAU
CALL CHSEQR( JOB, 'N', N, ILO, IHI, A, LDA, W, VR, LDVR,
$ WORK( IWRK ), LWORK-IWRK+1, INFO )
END IF
*
* If INFO > 0 from CHSEQR, then quit
*
IF( INFO.GT.0 )
$ GO TO 50
*
IF( WANTVL .OR. WANTVR ) THEN
*
* Compute left and/or right eigenvectors
* (CWorkspace: need 2*N)
* (RWorkspace: need N)
*
CALL CTREVC( SIDE, 'B', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,
$ N, NOUT, WORK( IWRK ), RWORK, IERR )
END IF
*
* Compute condition numbers if desired
* (CWorkspace: need N*N+2*N unless SENSE = 'E')
* (RWorkspace: need 2*N unless SENSE = 'E')
*
IF( .NOT.WNTSNN ) THEN
CALL CTRSNA( SENSE, 'A', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,
$ RCONDE, RCONDV, N, NOUT, WORK( IWRK ), N, RWORK,
$ ICOND )
END IF
*
IF( WANTVL ) THEN
*
* Undo balancing of left eigenvectors
*
CALL CGEBAK( BALANC, 'L', N, ILO, IHI, SCALE, N, VL, LDVL,
$ IERR )
*
* Normalize left eigenvectors and make largest component real
*
DO 20 I = 1, N
SCL = ONE / SCNRM2( N, VL( 1, I ), 1 )
CALL CSSCAL( N, SCL, VL( 1, I ), 1 )
DO 10 K = 1, N
RWORK( K ) = REAL( VL( K, I ) )**2 +
$ AIMAG( VL( K, I ) )**2
10 CONTINUE
K = ISAMAX( N, RWORK, 1 )
TMP = CONJG( VL( K, I ) ) / SQRT( RWORK( K ) )
CALL CSCAL( N, TMP, VL( 1, I ), 1 )
VL( K, I ) = CMPLX( REAL( VL( K, I ) ), ZERO )
20 CONTINUE
END IF
*
IF( WANTVR ) THEN
*
* Undo balancing of right eigenvectors
*
CALL CGEBAK( BALANC, 'R', N, ILO, IHI, SCALE, N, VR, LDVR,
$ IERR )
*
* Normalize right eigenvectors and make largest component real
*
DO 40 I = 1, N
SCL = ONE / SCNRM2( N, VR( 1, I ), 1 )
CALL CSSCAL( N, SCL, VR( 1, I ), 1 )
DO 30 K = 1, N
RWORK( K ) = REAL( VR( K, I ) )**2 +
$ AIMAG( VR( K, I ) )**2
30 CONTINUE
K = ISAMAX( N, RWORK, 1 )
TMP = CONJG( VR( K, I ) ) / SQRT( RWORK( K ) )
CALL CSCAL( N, TMP, VR( 1, I ), 1 )
VR( K, I ) = CMPLX( REAL( VR( K, I ) ), ZERO )
40 CONTINUE
END IF
*
* Undo scaling if necessary
*
50 CONTINUE
IF( SCALEA ) THEN
CALL CLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, W( INFO+1 ),
$ MAX( N-INFO, 1 ), IERR )
IF( INFO.EQ.0 ) THEN
IF( ( WNTSNV .OR. WNTSNB ) .AND. ICOND.EQ.0 )
$ CALL SLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, RCONDV, N,
$ IERR )
ELSE
CALL CLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, W, N, IERR )
END IF
END IF
*
WORK( 1 ) = MAXWRK
RETURN
*
* End of CGEEVX
*
END
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?