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 ,它将完美运行。最愉快的部分是我只需要更改一个字母。

您使用了错误的程序。 cgeevzgeev 之间的参数类型相同但种类不同。对于 zgeev,数组 RWORK 的类型和种类为 double precision,数组 AVLVRWWORKcomplex*16。对于cgeev,types和kinds分别是realcomplex

您将实数隐式键入为 real*8,这是不可移植的双精度形式。同样,您的复杂变量被键入为 complex*16。您的变量与 zgeev 的参数列表匹配,这就是它对您有效而 cgeev 无效的原因。要使用 cgeev,请将您的隐式类型更改为 realcomplex,您会发现 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