假设我想用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()
等价物。
发生了什么事?
答案 0 :(得分:2)
请注意,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()
在标题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
,其值可能为CblasRowMajor
和CblasColMajor
。