【问题标题】:On entry to DGEEV parameter number 9 had an illegal value在进入 DGEEV 参数号 9 时具有非法值
【发布时间】:2025-12-10 03:20:07
【问题描述】:

我第一次尝试使用 C 中的 LAPACK 对矩阵进行对角化,但我被卡住了。

我一直在尝试将这个示例 http://rcabreral.blogspot.co.uk/2010/05/eigenvalues-clapack.htmlzgeev 修改为 dgeev。我看过DGEEV 输入参数,http://www.netlib.org/lapack/explore-html/d9/d28/dgeev_8f.html 但似乎我不太了解。

因此,下面的代码产生:

**** 在进入 DGEEV 参数编号 9 时具有非法值**

编辑:错误发生在dgeev 的调用中,跨越第 48 行到(包括)第 53 行。

编辑:请注意,参数与此处的规范不同 http://www.netlib.org/lapack/explore-html/d9/d28/dgeev_8f.html 因为它们已被翻译成指针。在 C 中使用这些 Fortran 例程时,这是必要的,如下所述: http://www.physics.orst.edu/~rubin/nacphy/lapack/cprogp.html

#include <stdio.h>
#include <math.h>    
#include <complex.h>
#include <stdlib.h>
//.........................................................................

void dgeTranspose( double *Transposed, double *M ,int n) {    
  int i,j;
  for(i=0;i<n;i++)
    for(j=0;j<n;j++)
      Transposed[i+n*j] = M[i*n+j];
}
//.........................................................................
//  MatrixComplexEigensystem: computes the eigenvectors and eigenValues of input matrix A
//  The eigenvectors are stored in columns
//.........................................................................
void MatrixComplexEigensystem( double *eigenvectorsVR, double *eigenvaluesW, double *A, int N){
  int i;
  double *AT = (double *) malloc( N*N*sizeof(double ) );

  dgeTranspose( AT, A , N);

  char JOBVL ='N';   // Compute Right eigenvectors
  char JOBVR ='V';   // Do not compute Left eigenvectors
  double VL[1];

  int LDVL = 1;
  int LDVR = N;
  int LWORK = 4*N; 

  double *WORK =  (double *)malloc( LWORK*sizeof(double));
  double *RWORK = (double *)malloc( 2*N*sizeof(double));
  int INFO;

  dgeev_( &JOBVL, &JOBVR, &N, AT ,  &N , eigenvaluesW ,   
       VL, &LDVL,
       eigenvectorsVR, &LDVR, 
       WORK, 
       &LWORK, RWORK, &INFO );

  dgeTranspose( AT, eigenvectorsVR , N);

  for(i=0;i<N*N;i++) eigenvectorsVR[i]=AT[i];

  free(WORK);
  free(RWORK);
  free(AT);
}

int main(){
  int i,j;
  const int N = 3;
  double A[] = { 1.+I , 2. ,  3 , 4. , 5.+I , 6. , 7., 8., 9. + I};
  double eigenVectors[N*N];
  double eigenValues[N];

  MatrixComplexEigensystem( eigenVectors, eigenValues, A, N);

  printf("\nEigenvectors\n");
  for(i=0;i<N;i++){
    for(j=0;j<N;j++) printf("%e", eigenVectors[i*N + j]);
    printf("\n");
  }
  printf("\nEigenvalues \n");
  for(i=0;i<N;i++) printf("%e",  eigenValues[i] );
  printf("\n------------------------------------------------------------\n"); 

  return 0;
}

【问题讨论】:

  • 代码中的哪一行产生了这条消息?
  • @WeatherVane 没说。它只是说 ludi@ludi-M17xR4:~/Desktop/tests$ gcc -o mamapack mamapack.c -L/usr/local/lib -llapack -lblas && ./mamapack ** 在进入 DGEEV 参数号 9 时有非法价值 ludi@ludi-M17xR4:~/Desktop/tests$
  • 如果你使用调试器,或者插入策略性自我调试printf 指令,你可以通过分而治之的方法发现这一点,这在思想上类似于二分查找。
  • @WeatherVane 谢谢!它发生在第 48 行到第 53 行的 degeev 调用中。我在第 47 行和第 54 行放置了一个“战略 printf ping”...
  • 参数#9(从1开始)是eigenvectorsVR,它来自函数参数double *eigenvectorsVR。由于我们对dgeev_ 一无所知,因此您要么传递了非法指针,要么传递了应该传递其值的指针,或者传递了指向未初始化数组的指针,或者因为这是一个二维数组,也许dgeev_ 期待一个** 指针。调用它的函数MatrixComplexEigensystem 本身传递了两个未初始化的数组,一个初始化的数组和一个大小。是这样吗?

标签: c lapack eigenvalue eigenvector


【解决方案1】:

您不能直接从zgeev 移植到dgeevzgeev 得到一个复数矩阵并计算复数特征值。而dgeev 得到一个实矩阵并计算复杂的特征值。为了保持一致,LAPACK 使用WRWI,分别用于每个特征值的实部和虚部。

所以注意dgeev的定义是

void dgeev_(char* JOBVL, char* JOBVR, int* N, double* A, int* LDA, double* WR, double* WI, double* VL, int* LDVL, double* VR, int* LDVR, double* WORK, int* LWORK, int* INFO);

我对您的示例的建议是删除:

#include <complex.h>

从双精度矩阵中删除I

double A[] = { 1. , 2. ,  3 , 4. , 5. , 6. , 7., 8., 9.};

然后将特征值向量的大小加倍:

double eigenValues[2*N];

并使用WRWI 调用dgeev

double *eigenvaluesWR = eigenvaluesW;
double *eigenvaluesWI = eigenvaluesW+N;
dgeev_(&JOBVL, &JOBVR, &N, AT, &N, 
    eigenvaluesWR, eigenvaluesWI, 
    VL, &LDVL, 
    eigenvectorsVR, &LDVR,
    WORK, &LWORK, &INFO);

【讨论】:

  • 你知道原作者为什么要转置矩阵吗?
  • @user1816316 这是CFortran 之间二维矩阵交换的常见问题。 C 用户以 RowMajor 格式存储矩阵。 dgeev_ 调用使用 ColumnMajor 格式存储的 Fortran 子例程。因此,转置矩阵会将其从 RowMajor 转换为 ColumnMajor。
最近更新 更多