假设我想使用 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 接口(interface),但是函数 dgesv_()
又如何呢?
显然我可以正常使用它,不需要 LAPACKE,也不需要在 Fortran 中编译任何东西,那么这有什么不同呢?
谢谢。
更新
奇怪的是,函数 dgemm_()
(矩阵乘法)没有任何 LAPACK_dgemm()
等价函数。
这是怎么回事?
最佳答案
请注意
LAPACKE_dgesv()
具有一个附加标志,可以是LAPACK_COL_MAJOR
(通常的 Fortran 命令)或LAPACK_ROW_MAJOR
(通常是c命令)。如果是LAPACK_COL_MAJOR
,它只是调用LAPACK_dgesv()
直接地。如果是LAPACK_ROW_MAJOR
,LAPACKE_dgesv()
将在调用LAPACK_dgesv()
之前转置矩阵。它不是dgesv_()
的新实现。看看lapack-3.5.0/lapacke/src/dgesv_work.c在此文件中,对错误处理进行了一些小的额外更改。LAPACK_dgesv()
在 header lapacke.h 中定义如LAPACK_GLOBAL(dgesv,DGESV)
。宏LAPACK_GLOBAL
在 lapacke_mangling.h 中定义:它只是包装dgesv_
如果使用其他约定,则关心命名约定。
所以,基本上,函数 LAPACK_dgesv()
只需要 lapacke 的 header 。与dgesv_
相比,可以避免一些与库中命名约定相关的问题。但是LAPACK_dgesv()
与 dgesv_()
完全相同。函数LAPACKE_dgesv()
扩大了LAPACK_dgesv()
的范围处理通常的c矩阵。但它仍然调用 dgesv_
最后。
函数 dgemm()
是 BLAS 库的一部分。封装的c版本cblas_dgemm()
可以在 CBLAS 中找到。再次,一个额外的标志 CBLAS_ORDER
为必填项,可能值为 CblasRowMajor
和CblasColMajor
.
关于c - xxxxx_()、LAPACK_xxxxx() 和 LAPACKE_xxxxx() 函数之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31170413/