鲲鹏社区首页
中文
注册
开发者
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

?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

字符型

  • ‘N’:左特征向量不计算。
  • ‘V’:左特征向量计算。

输入

jobvr

字符型

  • ‘N’:右特征向量不计算。
  • ‘V’:右特征向量计算。

输入

n

整数型

矩阵A的维度,大于或等于0。

输入

a

  • 在sgeev中为单精度浮点型数组。
  • 在dgeev中为双精度浮点型数组。
  • 在cgeev中为单精度复数型数组。
  • 在zgeev中为双精度复数型数组。

N*N的矩阵

输入,输出

lda

整数型

矩阵A的主维,大于或等于max(1, N)。

输入

w

  • 在cgeev中为单精度复数型数组。
  • 在zgeev中为双精度复数型数组。

包含了所有的特征值,长度为n。

输出

wr

  • 在sgeev中为单精度浮点型数组。
  • 在dgeev中为双精度浮点型数组。

特征值的实部,大小为n

输出

wi

  • 在sgeev中为单精度浮点型数组。
  • 在dgeev中为双精度浮点型数组。

特征值的虚部,大小为n

输出

vl

  • 在sgeev中为单精度浮点型数组。
  • 在dgeev中为双精度浮点型数组。
  • 在cgeev中为单精度复数型数组。
  • 在zgeev中为双精度复数型数组。

大小:ldvl*n

若jobvl='v':存放左特征向量;若jobvl='n':不使用。

输出

ldvl

整数型

vl的leading dimension, ldvl>=1

输入

vr

  • 在sgeev中为单精度浮点型数组。
  • 在dgeev中为双精度浮点型数组。
  • 在cgeev中为单精度复数型数组。
  • 在zgeev中为双精度复数型数组。

大小:ldvr*n

若jobvr='v':存放右特征向量;若jobvr='n':不使用。

输出

ldvr

整数型

vr的leading dimension, ldvr>=1

输入

work

  • 在sgeev中为单精度浮点型数组。
  • 在dgeev中为双精度浮点型数组。
  • 在cgeev中为单精度复数型数组。
  • 在zgeev中为双精度复数型数组。

大小:max(1, lwork)

临时工作空间;info=0时,work(1)返回最优的lwork大小。

输出

lwork

整数型

work数组的长度。

lwork=-1时查询最优work大小,结果保存在work[0]中。且lwork ≥ max(1, 2*n-1)。

输入

rwork(复数特有)

  • 在cgeev中为单精度实数。
  • 在zgeev中为双精度实数。

临时存储空间,大小为2*n。

输出

info

整数型

状态值:

  • 等于0:表示成功。
  • 小于0:第-info个参数值不合法。
  • 大于0:算法出错。

输出

依赖

#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)