您的位置:首页 > 运维架构 > Linux

C语言调用 LAPACK (window+linux)详细步骤

2016-11-15 11:05 393 查看
搞这个clapack 花了很长时间,成功之后决定写个博客整理一下:

【写在前面】:LAPACK全称是 Linear Algebra PACKage, LAPACK, BLAS 本身是Fortran写的。函数以XYYZZZ形式命名,首字母代表数据类型,

- d: 双精度double

- c: 单精度复数 complex

- s: 单精度实数singble real

1. 下载 clapack

windows: 载VS配置的,根据需要生成debug,release,win32,x64的lib:

http://www.netlib.org/clapack/CLAPACK-3.1.1-VisualStudio.zip

linux: http://www.netlib.org/clapack/clapack-3.1.1.1.tgz

*

2. 解压,生成需要的静态库

windows: (我用的是VS2013)

注意VS的项目配置,调用的时候,项目的配置要和生成clapack lib的一样。(我一开始生成lib的时候用MTd(multi-thread-debug), 调用是时候用MDd(multi-thread-debug-dll),调用不成功 -_-

比如,我用32bit debug MTd



build 3个项目 blas clapck libf2c (Testing 的不用管)



生成的lib可以放到不用的文件夹 (debug的lib的命名结尾加d,我这里用的都是MT或者MTd)

├── 32_debug

│ ├── BLASd.lib

│ ├── clapackd.lib

│ └── libf2cd.lib

├── 32_release

│ ├── BLAS.lib

│ ├── clapack.lib

│ └── libf2c.lib

├── 64_debug

│ ├── BLASd.lib

│ ├── clapackd.lib

│ └── libf2cd.lib

└── 64_release

├── BLAS.lib

├── clapack.lib

└── libf2c.lib

也可以重命名为 blas_win64_MTd.lib, blas_win32_MT.lib, 方便自己后续调用

linux: 解压,看readme.install,我执行的命令为:

tar xzvf clapack-3.1.1.1.tgz
cd CLAPACK-3.1.1.1
mv make.inc.example make.inc
make f2clib
make blaslib
make


生产的4个库为:(不要重命名!!! 我就是重名为liblapack.a 折腾了好久,最后回到最初的名字)

F2CLIBS/libf2c.a

blas_LINUX.a

lapack_LINUX.a

tmglib_LINUX.a

3. 调用clapack进行计算

window: 把头文件加入(f2c.h, clapack.h),加入静态库路径和静态库名称





下面是一个svd分解的例子(test1.c)

#include "stdio.h"
#include "f2c.h"
#include "clapack.h"

#define SIZE 4

int main()
{
char JOBU;
char JOBVT;

int i;

integer M = SIZE;
integer N = SIZE;

integer LDA = M;
integer LDU = M;
integer LDVT = N;
integer LWORK;
integer INFO;

integer mn = min(M, N);
integer MN = max(M, N);

double a[SIZE*SIZE] = { 16.0, 5.0, 9.0, 4.0, 2.0, 11.0, 7.0, 14.0, 3.0, 10.0, 6.0, 15.0, 13.0, 8.0, 12.0, 1.0 };
double s[SIZE];
double wk[201];
double uu[SIZE*SIZE];
double vt[SIZE*SIZE];

JOBU = 'A';
JOBVT = 'A';
LWORK = 201;

/* Subroutine int dgesvd_(char *jobu, char *jobvt, integ
bf42
er *m, integer *n,
doublereal *a, integer *lda, doublereal *s, doublereal *u, integer *
ldu, doublereal *vt, integer *ldvt, doublereal *work, integer *lwork,
integer *info)
*/

dgesvd_(&JOBU, &JOBVT, &M, &N, a, &LDA, s, uu,
&LDU, vt, &LDVT, wk, &LWORK, &INFO);

if (INFO > 0) {
printf("The algorithm computing SVD failed to converge\n");
exit(1);
}

for (i = 0; i< SIZE; i++) {
printf("\n s[ %d ] = %f", i, s[i]);
}
getchar();
return 0;
}


输出结果为:

s[ 0 ] = 34.000000

s[ 1 ] = 17.888544

s[ 2 ] = 4.472136

s[ 3 ] = 0.000000

再来一个例子,给一个向量乘上一个常量(test2.c)

#include <stdio.h>

#include "f2c.h"
#include "blaswrap.h"

// scale a vector.
void main()
{
int i, j, n, one;
double coefficient;
double x[] = { 1, 1, 1 };

coefficient = 5;
one = 1;
n = 3;

dscal_(&n, &coefficient, x, &one);

for (i = 0; i <n; ++i)
printf("%f\n", x[i]);
getchar();
}


输出结果为:

5.000000

5.000000

5.000000

linux:

注意除了调用clapack的库,还有调用数学库(-lm),不然会出现找不到 pow, sqrt 之类的函数

在同一个路径下 放入

头文件: clapack.h, libf2c.h

源文件: test1.c

静态库: libf2c.a, blas_LINUX.a, lapack_LINUX.a

gcc test1.c -L./ lapack_LINUX.a blas_LINUX.a libf2c.a -lm -o test
./test1


输出结果为

s[ 0 ] = 34.000000

s[ 1 ] = 17.888544

s[ 2 ] = 4.472136

s[ 3 ] = 0.000000

另外我也尝试了用cmake, 自己写CMakeLists.txt

# 头文件放在include文件夹
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)

# 生成的可执行文件放在bin文件夹
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

# 生成的可执行文件用的源文件source.c
ADD_EXECUTABLE(test source.c)

# 设置静态库的路径(绝对路径)
SET(lib_dir $ENV{HOME}/test/lib)

# 加入依赖库(注意要加入数学库 m )
TARGET_LINK_LIBRARIES(test  ${lib_dir}/lapack_LINUX.a ${lib_dir}/blas_LINUX.a ${lib_dir}/libf2c.a m)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: