sgeevx.f
来自「famous linear algebra library (LAPACK) p」· F 代码 · 共 556 行 · 第 1/2 页
F
556 行
ELSE
MAXWRK = N + N*ILAENV( 1, 'SGEHRD', ' ', N, 1, N, 0 )
*
IF( WANTVL ) THEN
CALL SHSEQR( 'S', 'V', N, 1, N, A, LDA, WR, WI, VL, LDVL,
$ WORK, -1, INFO )
ELSE IF( WANTVR ) THEN
CALL SHSEQR( 'S', 'V', N, 1, N, A, LDA, WR, WI, VR, LDVR,
$ WORK, -1, INFO )
ELSE
IF( WNTSNN ) THEN
CALL SHSEQR( 'E', 'N', N, 1, N, A, LDA, WR, WI, VR,
$ LDVR, WORK, -1, INFO )
ELSE
CALL SHSEQR( 'S', 'N', N, 1, N, A, LDA, WR, WI, 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 )
$ MINWRK = MAX( MINWRK, N*N+6*N )
MAXWRK = MAX( MAXWRK, HSWORK )
IF( .NOT.WNTSNN )
$ MAXWRK = MAX( MAXWRK, N*N + 6*N )
ELSE
MINWRK = 3*N
IF( ( .NOT.WNTSNN ) .AND. ( .NOT.WNTSNE ) )
$ MINWRK = MAX( MINWRK, N*N + 6*N )
MAXWRK = MAX( MAXWRK, HSWORK )
MAXWRK = MAX( MAXWRK, N + ( N - 1 )*ILAENV( 1, 'SORGHR',
$ ' ', N, 1, N, -1 ) )
IF( ( .NOT.WNTSNN ) .AND. ( .NOT.WNTSNE ) )
$ MAXWRK = MAX( MAXWRK, N*N + 6*N )
MAXWRK = MAX( MAXWRK, 3*N )
END IF
MAXWRK = MAX( MAXWRK, MINWRK )
END IF
WORK( 1 ) = MAXWRK
*
IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
INFO = -21
END IF
END IF
*
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'SGEEVX', -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 = SLANGE( '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 SLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )
*
* Balance the matrix and compute ABNRM
*
CALL SGEBAL( BALANC, N, A, LDA, ILO, IHI, SCALE, IERR )
ABNRM = SLANGE( '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
* (Workspace: need 2*N, prefer N+N*NB)
*
ITAU = 1
IWRK = ITAU + N
CALL SGEHRD( 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 SLACPY( 'L', N, N, A, LDA, VL, LDVL )
*
* Generate orthogonal matrix in VL
* (Workspace: need 2*N-1, prefer N+(N-1)*NB)
*
CALL SORGHR( N, ILO, IHI, VL, LDVL, WORK( ITAU ), WORK( IWRK ),
$ LWORK-IWRK+1, IERR )
*
* Perform QR iteration, accumulating Schur vectors in VL
* (Workspace: need 1, prefer HSWORK (see comments) )
*
IWRK = ITAU
CALL SHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, VL, LDVL,
$ WORK( IWRK ), LWORK-IWRK+1, INFO )
*
IF( WANTVR ) THEN
*
* Want left and right eigenvectors
* Copy Schur vectors to VR
*
SIDE = 'B'
CALL SLACPY( 'F', N, N, VL, LDVL, VR, LDVR )
END IF
*
ELSE IF( WANTVR ) THEN
*
* Want right eigenvectors
* Copy Householder vectors to VR
*
SIDE = 'R'
CALL SLACPY( 'L', N, N, A, LDA, VR, LDVR )
*
* Generate orthogonal matrix in VR
* (Workspace: need 2*N-1, prefer N+(N-1)*NB)
*
CALL SORGHR( N, ILO, IHI, VR, LDVR, WORK( ITAU ), WORK( IWRK ),
$ LWORK-IWRK+1, IERR )
*
* Perform QR iteration, accumulating Schur vectors in VR
* (Workspace: need 1, prefer HSWORK (see comments) )
*
IWRK = ITAU
CALL SHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, 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
*
* (Workspace: need 1, prefer HSWORK (see comments) )
*
IWRK = ITAU
CALL SHSEQR( JOB, 'N', N, ILO, IHI, A, LDA, WR, WI, VR, LDVR,
$ WORK( IWRK ), LWORK-IWRK+1, INFO )
END IF
*
* If INFO > 0 from SHSEQR, then quit
*
IF( INFO.GT.0 )
$ GO TO 50
*
IF( WANTVL .OR. WANTVR ) THEN
*
* Compute left and/or right eigenvectors
* (Workspace: need 3*N)
*
CALL STREVC( SIDE, 'B', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,
$ N, NOUT, WORK( IWRK ), IERR )
END IF
*
* Compute condition numbers if desired
* (Workspace: need N*N+6*N unless SENSE = 'E')
*
IF( .NOT.WNTSNN ) THEN
CALL STRSNA( SENSE, 'A', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,
$ RCONDE, RCONDV, N, NOUT, WORK( IWRK ), N, IWORK,
$ ICOND )
END IF
*
IF( WANTVL ) THEN
*
* Undo balancing of left eigenvectors
*
CALL SGEBAK( BALANC, 'L', N, ILO, IHI, SCALE, N, VL, LDVL,
$ IERR )
*
* Normalize left eigenvectors and make largest component real
*
DO 20 I = 1, N
IF( WI( I ).EQ.ZERO ) THEN
SCL = ONE / SNRM2( N, VL( 1, I ), 1 )
CALL SSCAL( N, SCL, VL( 1, I ), 1 )
ELSE IF( WI( I ).GT.ZERO ) THEN
SCL = ONE / SLAPY2( SNRM2( N, VL( 1, I ), 1 ),
$ SNRM2( N, VL( 1, I+1 ), 1 ) )
CALL SSCAL( N, SCL, VL( 1, I ), 1 )
CALL SSCAL( N, SCL, VL( 1, I+1 ), 1 )
DO 10 K = 1, N
WORK( K ) = VL( K, I )**2 + VL( K, I+1 )**2
10 CONTINUE
K = ISAMAX( N, WORK, 1 )
CALL SLARTG( VL( K, I ), VL( K, I+1 ), CS, SN, R )
CALL SROT( N, VL( 1, I ), 1, VL( 1, I+1 ), 1, CS, SN )
VL( K, I+1 ) = ZERO
END IF
20 CONTINUE
END IF
*
IF( WANTVR ) THEN
*
* Undo balancing of right eigenvectors
*
CALL SGEBAK( BALANC, 'R', N, ILO, IHI, SCALE, N, VR, LDVR,
$ IERR )
*
* Normalize right eigenvectors and make largest component real
*
DO 40 I = 1, N
IF( WI( I ).EQ.ZERO ) THEN
SCL = ONE / SNRM2( N, VR( 1, I ), 1 )
CALL SSCAL( N, SCL, VR( 1, I ), 1 )
ELSE IF( WI( I ).GT.ZERO ) THEN
SCL = ONE / SLAPY2( SNRM2( N, VR( 1, I ), 1 ),
$ SNRM2( N, VR( 1, I+1 ), 1 ) )
CALL SSCAL( N, SCL, VR( 1, I ), 1 )
CALL SSCAL( N, SCL, VR( 1, I+1 ), 1 )
DO 30 K = 1, N
WORK( K ) = VR( K, I )**2 + VR( K, I+1 )**2
30 CONTINUE
K = ISAMAX( N, WORK, 1 )
CALL SLARTG( VR( K, I ), VR( K, I+1 ), CS, SN, R )
CALL SROT( N, VR( 1, I ), 1, VR( 1, I+1 ), 1, CS, SN )
VR( K, I+1 ) = ZERO
END IF
40 CONTINUE
END IF
*
* Undo scaling if necessary
*
50 CONTINUE
IF( SCALEA ) THEN
CALL SLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WR( INFO+1 ),
$ MAX( N-INFO, 1 ), IERR )
CALL SLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WI( 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 SLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WR, N,
$ IERR )
CALL SLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WI, N,
$ IERR )
END IF
END IF
*
WORK( 1 ) = MAXWRK
RETURN
*
* End of SGEEVX
*
END
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?