cgeev 的特征值不正确
Incorrect eigenvalues with cgeev
我编写了以下代码,使用 cgeev 在 Fortran 中获取矩阵的特征值和行列式:
SUBROUTINE CDETS(CS,CW,CDET,N)
IMPLICIT REAL*8 (A,B,D-H,O-Z)
IMPLICIT COMPLEX*16 (C)
DIMENSION CW(*),CS(N,*)
ALLOCATABLE :: CWK(:), WK(:), CWL(:,:),CWR(:,:)
ALLOCATE (WK(2*N),CWK(10*N),CWL(N,N),CWR(N,N))
CALL CGEEV('N','N',N,CS,N,CW,CWL,N,CWR,N,CWK,10*N,
& WK,INFO)
DEALLOCATE (WK,CWK,CWL,CWR)
CDET = 1.D0
DO i=1,N
CDET = CDET*CW(i)
ENDDO
END SUBROUTINE
还有这个简单的程序来检查它:
PROGRAM TESTDET
IMPLICIT REAL*8 (A,B,D-H,O-Z)
IMPLICIT COMPLEX*16 (C)
DIMENSION :: CS(2,2), CW(2)
CS(1,1)=(1.D0,1.D0)
CS(1,2)=1.D0
CS(2,1)=0.D0
CS(2,2)=1.D0
CALL CDETS(CS,CW,CDET,2)
PRINT *, CW(1)
PRINT *, CW(2)
END
我得到了以下令人困惑的结果:
( 0.0000000000000000 , 1.0000000000000000 )
( 1.2828908559913808E-319, 7.6130689002776223E-317)
这是怎么回事?
我找到了解决此问题的方法,但 cgeev 似乎已损坏。如果您将 cgeev 替换为另一个 lapack 例程 zgeev ,它将完美运行。最愉快的部分是我只需要更改一个字母。
您使用了错误的程序。 cgeev
和 zgeev
之间的参数类型相同但种类不同。对于 zgeev
,数组 RWORK
的类型和种类为 double precision
,数组 A
、VL
、VR
、W
,WORK
为 complex*16
。对于cgeev
,types和kinds分别是real
和complex
。
您将实数隐式键入为 real*8
,这是不可移植的双精度形式。同样,您的复杂变量被键入为 complex*16
。您的变量与 zgeev
的参数列表匹配,这就是它对您有效而 cgeev
无效的原因。要使用 cgeev
,请将您的隐式类型更改为 real
和 complex
,您会发现 cgeev
现在有效,而 zgeev
无效。
来自 BLAS 命名约定:
Every routine in the BLAS library comes in four flavors, each prefixed by the letters S, D, C, and Z, respectively. Each letter indicates the format of input data:
- S stands for single-precision (32-bit IEEE floating point numbers),
- D stands for double-precision (64-bit IEEE floating point numbers),
- C stands for complex numbers (represented by pairs of 32-bit IEEE floating point numbers),
- Z stands for double complex numbers (represented by pairs of 64-bit IEEE floating point numbers)
对于双精度复杂变量,您需要使用函数的 Z
变体而不是 C
。
我编写了以下代码,使用 cgeev 在 Fortran 中获取矩阵的特征值和行列式:
SUBROUTINE CDETS(CS,CW,CDET,N)
IMPLICIT REAL*8 (A,B,D-H,O-Z)
IMPLICIT COMPLEX*16 (C)
DIMENSION CW(*),CS(N,*)
ALLOCATABLE :: CWK(:), WK(:), CWL(:,:),CWR(:,:)
ALLOCATE (WK(2*N),CWK(10*N),CWL(N,N),CWR(N,N))
CALL CGEEV('N','N',N,CS,N,CW,CWL,N,CWR,N,CWK,10*N,
& WK,INFO)
DEALLOCATE (WK,CWK,CWL,CWR)
CDET = 1.D0
DO i=1,N
CDET = CDET*CW(i)
ENDDO
END SUBROUTINE
还有这个简单的程序来检查它:
PROGRAM TESTDET
IMPLICIT REAL*8 (A,B,D-H,O-Z)
IMPLICIT COMPLEX*16 (C)
DIMENSION :: CS(2,2), CW(2)
CS(1,1)=(1.D0,1.D0)
CS(1,2)=1.D0
CS(2,1)=0.D0
CS(2,2)=1.D0
CALL CDETS(CS,CW,CDET,2)
PRINT *, CW(1)
PRINT *, CW(2)
END
我得到了以下令人困惑的结果:
( 0.0000000000000000 , 1.0000000000000000 )
( 1.2828908559913808E-319, 7.6130689002776223E-317)
这是怎么回事?
我找到了解决此问题的方法,但 cgeev 似乎已损坏。如果您将 cgeev 替换为另一个 lapack 例程 zgeev ,它将完美运行。最愉快的部分是我只需要更改一个字母。
您使用了错误的程序。 cgeev
和 zgeev
之间的参数类型相同但种类不同。对于 zgeev
,数组 RWORK
的类型和种类为 double precision
,数组 A
、VL
、VR
、W
,WORK
为 complex*16
。对于cgeev
,types和kinds分别是real
和complex
。
您将实数隐式键入为 real*8
,这是不可移植的双精度形式。同样,您的复杂变量被键入为 complex*16
。您的变量与 zgeev
的参数列表匹配,这就是它对您有效而 cgeev
无效的原因。要使用 cgeev
,请将您的隐式类型更改为 real
和 complex
,您会发现 cgeev
现在有效,而 zgeev
无效。
来自 BLAS 命名约定:
Every routine in the BLAS library comes in four flavors, each prefixed by the letters S, D, C, and Z, respectively. Each letter indicates the format of input data:
- S stands for single-precision (32-bit IEEE floating point numbers),
- D stands for double-precision (64-bit IEEE floating point numbers),
- C stands for complex numbers (represented by pairs of 32-bit IEEE floating point numbers),
- Z stands for double complex numbers (represented by pairs of 64-bit IEEE floating point numbers)
对于双精度复杂变量,您需要使用函数的 Z
变体而不是 C
。