假设我想使用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()
。怎么回事?
-
注意,
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在这个文件中,有一些关于错误处理的小的附加更改。 -
CCD_ 24在报头lapacke.h中被定义为CCD_。宏
LAPACK_GLOBAL
是在lapack_mangling.h中定义的:它只是包装dgesv_
,如果使用其他约定,则关心命名约定。
所以,基本上,函数LAPACK_dgesv()
只需要lapacke的头。与dgesv_
相比,可以避免库中与命名约定有关的一些问题。但CCD_ 30与CCD_。函数CCD_ 32扩大了CCD_。但最终还是调用了dgesv_
。
函数dgemm()
是BLAS库的一部分。在CBLAS中可以找到一个封装的c版本cblas_dgemm()
。同样,需要具有可能值CblasRowMajor
和CblasColMajor
的加法标志CBLAS_ORDER
。