?geev
计算一般矩阵的部分特征值与特征向量。
接口定义
C Interface:
void sgeev_( const char *jobvl, const char *jobvr, const int *n, float *a, const int *lda, float *wr, float *wi, float *vl, const int *ldvl, float *vr, const int *ldvr, float *work, int *lwork, int *info);
void dgeev_(const char *jobvl, const char *jobvr, const int *n, double *a, const int *lda, double *wr, double *wi, double *vl, const int *ldvl, double *vr, const int *ldvr, double *work, int *lwork, int *info);
void cgeev_( const char *jobvl, const char *jobvr, const int *n, float _Complex *a, const int *lda, float _Complex *w, float _Complex *vl, const int *ldvl, float _Complex *vr, const int *ldvr, float _Complex *work, int *lwork, float *rwork, int *info);
void zgeev_( const char *jobvl, const char *jobvr, const int *n, double _Complex *a, const int *lda, double _Complex *w, double _Complex *vl, const int *ldvl, double _Complex *vr, const int *ldvr, double _Complex *work, int *lwork, double *rwork, int *info);
Fortran Interface:
SGEEV(jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, info);
DGEEV(jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, info);
CGEEV(jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr, work, lwork, rwork, info);
ZGEEV(jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr, work, lwork, rwork, info);
参数
参数 |
类型 |
说明 |
输入/输出 |
|---|---|---|---|
jobvl |
字符型 |
|
输入 |
jobvr |
字符型 |
|
输入 |
n |
整数型 |
矩阵A的维度,大于或等于0。 |
输入 |
a |
|
N*N的矩阵 |
输入,输出 |
lda |
整数型 |
矩阵A的主维,大于或等于max(1, N)。 |
输入 |
w |
|
包含了所有的特征值,长度为n。 |
输出 |
wr |
|
特征值的实部,大小为n |
输出 |
wi |
|
特征值的虚部,大小为n |
输出 |
vl |
|
大小:ldvl*n 若jobvl='v':存放左特征向量;若jobvl='n':不使用。 |
输出 |
ldvl |
整数型 |
vl的leading dimension, ldvl>=1 |
输入 |
vr |
|
大小:ldvr*n 若jobvr='v':存放右特征向量;若jobvr='n':不使用。 |
输出 |
ldvr |
整数型 |
vr的leading dimension, ldvr>=1 |
输入 |
work |
|
大小:max(1, lwork) 临时工作空间;info=0时,work(1)返回最优的lwork大小。 |
输出 |
lwork |
整数型 |
work数组的长度。 lwork=-1时查询最优work大小,结果保存在work[0]中。且lwork ≥ max(1, 2*n-1)。 |
输入 |
rwork(复数特有) |
|
临时存储空间,大小为2*n。 |
输出 |
info |
整数型 |
状态值:
|
输出 |
依赖
#include "klapack.h"
示例
C Interface:
#include <stdio.h>
#include <stdlib.h>
#include "lapack.h"
int main() {
int i, j;
int n = 3; // 矩阵维度
int lda = n;
int ldvl = n;
int ldvr = n;
int lwork;
int info;
// 定义矩阵A (3x3)
float a[9] = {
1.0, 2.0, 3.0,
4.0, 5.0, 6.0,
7.0, 8.0, 9.0
};
// 输出原始矩阵
printf("Original matrix A:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%8.4f ", a[i*n + j]);
}
printf("\n");
}
printf("\n");
// 分配内存用于存储特征值和特征向量
float *wr = (float*)malloc(n * sizeof(float)); // 实部
float *wi = (float*)malloc(n * sizeof(float)); // 虚部
float *vl = (float*)malloc(n * n * sizeof(float)); // 左特征向量
float *vr = (float*)malloc(n * n * sizeof(float)); // 右特征向量
// 查询最优工作空间大小
lwork = -1;
float query_work;
sgeev_("V", "V", &n, a, &lda, wr, wi, vl, &ldvl, vr, &ldvr, &query_work, &lwork, &info,1,1);
// 分配工作空间
lwork = (int)query_work;
float *work = (float*)malloc(lwork * sizeof(float));
// 计算特征值和特征向量
sgeev_("V", "V", &n, a, &lda, wr, wi, vl, &ldvl, vr, &ldvr, work, &lwork, &info,1,1);
// 检查是否成功
if (info != 0) {
printf("SGEEV failed with error code %d\n", info);
return 1;
}
// 输出特征值
printf("Eigenvalues:\n");
for (i = 0; i < n; i++) {
if (wi[i] == 0.0) {
printf("%8.4f\n", wr[i]);
} else {
printf("%8.4f + %8.4fi\n", wr[i], wi[i]);
printf("%8.4f - %8.4fi\n", wr[i], -wi[i]);
i++; // 跳过共轭对
}
}
printf("\n");
// 输出右特征向量
printf("Right eigenvectors:\n");
for (i = 0; i < n; i++) {
if (wi[i] == 0.0) {
printf("Eigenvector for eigenvalue %8.4f:\n", wr[i]);
for (j = 0; j < n; j++) {
printf("%8.4f ", vr[j*n + i]);
}
printf("\n");
} else {
printf("Eigenvector pair for eigenvalue %8.4f + %8.4fi:\n", wr[i], wi[i]);
for (j = 0; j < n; j++) {
printf("%8.4f + %8.4fi ", vr[j*n + i], vr[j*n + i+1]);
}
printf("\n");
for (j = 0; j < n; j++) {
printf("%8.4f - %8.4fi ", vr[j*n + i], -vr[j*n + i+1]);
}
printf("\n");
i++; // 跳过共轭对
}
}
// 释放内存
free(wr);
free(wi);
free(vl);
free(vr);
free(work);
return 0;
}
Fortran Interface:
! 定义常量与变量
integer, parameter :: n = 3 ! 矩阵维度
character(1) :: jobvl = 'N' ! 不计算左特征向量
character(1) :: jobvr = 'V' ! 计算右特征向量
integer :: lda = n, ldvl = n, ldvr = n
integer :: lwork, info, i, j,k
double precision :: a(n, n) ! 输入矩阵(列优先)
double precision :: wr(n), wi(n) ! 特征值实部和虚部
double precision :: vr(n, n), vl(n, n) ! 特征向量(列存储)
double precision, allocatable :: work(:) ! 工作空间数组
! 初始化测试矩阵(按列优先存储)
! 矩阵示例:
! [ 1.0 4.0 7.0 ]
! [ 2.0 5.0 8.0 ]
! [ 3.0 6.0 9.0 ]
a = reshape([1.0d0, 2.0d0, 3.0d0, &
4.0d0, 5.0d0, 6.0d0, &
7.0d0, 8.0d0, 9.0d0], [n, n])
! === 步骤1:查询最优工作空间大小 ===
lwork = -1
allocate(work(1)) ! 临时分配最小空间
call dgeev(jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, info)
! 检查查询是否成功
if (info /= 0) then
print *, "工作空间查询失败,错误码:", info
stop
end if
! 根据查询结果分配工作空间
lwork = int(work(1))
deallocate(work)
allocate(work(lwork))
! === 步骤2:实际计算特征值与特征向量 ===
call dgeev(jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, info)
! 检查计算是否成功
if (info /= 0) then
print *, "特征值计算失败,错误码:", info
stop
end if
k = 1
! === 输出结果 ===
print *, "=== 特征值 ==="
do i = 1, n
if (wi(k) == 0.0d0) then
! 实数特征值
write(*, '(A, I1, A, F12.6)') "λ", k, " = ", wr(k)
else
! 复数共轭对(显示一对)
write(*, '(A, I1, A, F12.6, A, F12.6, A)') "λ", k, " = ", wr(k), " ± ", wi(k), "i"
k = k + 1 ! 跳过下一个共轭虚部
end if
k = k + 1
end do
print *, ""
print *, "=== 右特征向量(按列存储)==="
do j = 1, n
write(*, '(A, I1, A)', advance='no') "向量 ", j, ": "
do i = 1, n
write(*, '(F12.6, 2X)', advance='no') vr(i, j)
end do
print *, ""
end do
! 释放内存
deallocate(work)