xxxxx_(),LAPACK_xxxxx()和LAPACKE_xxxxx()函数之间的区别

时间:2015-07-01 19:50:15

标签: c lapack lapacke

假设我想用LAPACK来解决C(GCC)中的线性方程组。 我将问题设置如下:

/* Want to solve Ax=b */
int n = ...;      // size
double *A = ...;  // nxn matrix
double *b = ...;  // length-n vector
int m = 1;        // number of columns in b (needs to be in a variable)
double *pivot;    // records pivoting
int info;         // return value

现在看来我可以使用三种功能中的一种来解决这个问题。 第一个是:

dgesv_( &n, &m, A, &n, pivot, b, &n, &info );

我很惊讶地发现这不需要任何#include,这看起来很奇怪。

第二个函数具有几乎相同的签名,除了前缀LAPACK_,我认为它不会引起歧义,并且可能不太容易出错:

#include <lapack/lapacke.h>
LAPACK_dgesv( &n, &m, A, &n, pivot, b, &n, &info );

请注意,这需要我加入lapacke.h

第三个函数通过返回info而不是将所有参数作为指针来改变签名:

#include <lapack/lapacke.h>
info = LAPACKE_dgesv( LAPACK_COL_MAJOR, n, m, A, n, pivot, b, n);

同样,此功能需要lapacke.h。它还需要链接到-llapacke的额外库。 这三个函数都需要-llapack

我正试图找出这些功能之间的差异。 我做了一些窥探,我在lapacke.h和相关的头文件中找到了以下宏:

#define LAPACK_GLOBAL(name,NAME) name##_
#define LAPACK_dgesv LAPACK_GLOBAL(dgesv,DGESV)

因此LAPACK_dgesv()dgesv_()似乎是完全相同的函数的不同名称。 但是,看起来LAPACKE_dgesv()是可能有不同实现的其他东西,特别是考虑到它需要一个额外的库。

所以我的问题是:这两个函数之间有什么区别? 文档说LAPACKE是LAPACK的C接口,但那么函数dgesv_()呢? 显然,我可以正常使用它而不需要LAPACKE并且不需要在Fortran中编译任何东西,那么它有什么不同呢?

感谢。

更新

奇怪的是,函数dgemm_()(矩阵乘法)没有任何LAPACK_dgemm()等价物。 发生了什么事?

1 个答案:

答案 0 :(得分:2)

  • 请注意,LAPACKE_dgesv()有一个额外的标记,可以是LAPACK_COL_MAJOR(通常的fortran顺序)或LAPACK_ROW_MAJOR(通常的c顺序)。如果是LAPACK_COL_MAJOR,则只需直接调用LAPACK_dgesv()。如果是LAPACK_ROW_MAJORLAPACKE_dgesv()会在调用LAPACK_dgesv()之前转置矩阵。它不是dgesv_()的新实现。查看lapack-3.5.0/lapacke/src/dgesv_work.c在此文件中,有关于错误处理的一些小的其他更改。

  • LAPACK_dgesv()在标题lapacke.h中定义为LAPACK_GLOBAL(dgesv,DGESV)。宏LAPACK_GLOBAL在lapacke_mangling.h中定义:如果使用其他约定,它只包装dgesv_并关注命名约定。

所以,基本上,函数LAPACK_dgesv()只需要lapacke的头文件。与dgesv_相比,可以避免与库中的命名约定相关的一些问题。但LAPACK_dgesv()dgesv_()完全相同。函数LAPACKE_dgesv()扩大了LAPACK_dgesv()的范围以处理通常的c矩阵。但它最后仍然调用dgesv_

函数dgemm()是BLAS库的一部分。可以在CBLAS中找到包装的c版cblas_dgemm()。同样,还需要一个附加标志CBLAS_ORDER,其值可能为CblasRowMajorCblasColMajor