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

搞这个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
    C语言调用 LAPACK (window+linux)详细步骤_第1张图片

build 3个项目 blas clapck libf2c (Testing 的不用管)
C语言调用 LAPACK (window+linux)详细步骤_第2张图片

生成的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),加入静态库路径和静态库名称

C语言调用 LAPACK (window+linux)详细步骤_第3张图片

C语言调用 LAPACK (window+linux)详细步骤_第4张图片

下面是一个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, integer *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 

#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 "%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) 

你可能感兴趣的:(编程)