Understanding LAPACK calls in C++ with a simple example

a 夏天 提交于 2019-11-27 21:19:43

You need to factor the matrix (by calling dgetrf) before you can solve the system using dgetrs. Alternatively, you can use the dgesv routine, which does both steps for you.

By the way, you don't need to declare the interfaces yourself, they are in the Accelerate headers:

// LAPACK test code

#include <iostream>
#include <vector>
#include <Accelerate/Accelerate.h>

using namespace std;

int main()
{
    char trans = 'N';
    int dim = 2;    
    int nrhs = 1;
    int LDA = dim;
    int LDB = dim;
    int info;

    vector<double> a, b;

    a.push_back(1);
    a.push_back(1);
    a.push_back(1);
    a.push_back(-1);

    b.push_back(2);
    b.push_back(0);

    int ipiv[3];

    dgetrf_(&dim, &dim, &*a.begin(), &LDA, ipiv, &info);
    dgetrs_(&trans, &dim, &nrhs, & *a.begin(), &LDA, ipiv, & *b.begin(), &LDB, &info);


    std::cout << "solution is:";    
    std::cout << "[" << b[0] << ", " << b[1] << ", " << "]" << std::endl;
    std::cout << "Info = " << info << std::endl; 

    return(0);
}

For those who don't want bother with the Accelerate Framework, I provide the code of Stephen Canon (thanks to him, of course) with nothing but pure library linking

// LAPACK test code
//compile with: g++ main.cpp -llapack -lblas -o testprog

#include <iostream>
#include <vector>

using namespace std;

extern "C" void dgetrf_(int* dim1, int* dim2, double* a, int* lda, int* ipiv, int* info);
extern "C" void dgetrs_(char *TRANS, int *N, int *NRHS, double *A, int *LDA, int *IPIV, double *B, int *LDB, int *INFO );

int main()
{
    char trans = 'N';
    int dim = 2;
    int nrhs = 1;
    int LDA = dim;
    int LDB = dim;
    int info;

    vector<double> a, b;

    a.push_back(1);
    a.push_back(1);
    a.push_back(1);
    a.push_back(-1);

    b.push_back(2);
    b.push_back(0);

    int ipiv[3];

    dgetrf_(&dim, &dim, &*a.begin(), &LDA, ipiv, &info);
    dgetrs_(&trans, &dim, &nrhs, & *a.begin(), &LDA, ipiv, & *b.begin(), &LDB, &info);


    std::cout << "solution is:";
    std::cout << "[" << b[0] << ", " << b[1] << ", " << "]" << std::endl;
    std::cout << "Info = " << info << std::endl;

    return(0);
}

And about the manual, there's a full PDF version available at Intel's website. Here's a sample of their HTML documentation.

http://software.intel.com/sites/products/documentation/hpc/mkl/mklman/GUID-A02DB70F-9704-42A4-9071-D409D783D911.htm

If you want to use LAPACK from C++ you might want to have a look a FLENS. It defines low- and high-level interfaces to LAPACK but also re-implements some LAPACK functions.

With the low-level FLENS-LAPACK interface you can use your own matrix/vector types (if they have a LAPACK conform memory layout). Your call of dgetrf would look like that:

info = lapack::getrf(NoTrans, dim, nrhs, a.begin(), LDA, ipiv);

and for dgetrs

lapack::getrs(NoTrans, dim, nrhs, a.begin(), LDA, ipiv, b.begin(), LDB);

So the low-level FLENS-LAPACK functions are overloaded with respect to the element types. Consequently LAPACK function sgetrs, dgetrs, cgetrs, zgetrs are in the low-level interface of FLENS-LAPACK lapack::getrs. You also pass parameters by value/reference and not as pointer (e.g. LDA instead of &LDA).

If you use the FLENS matrix-types you can code it as

info = lapack::trf(NoTrans, A, ipiv);
if (info==0) {
    lapack::trs(NoTrans, A, ipiv, b);
}

Or you just use the LAPACK driver function dgesv

lapack::sv(NoTrans, A, ipiv, b);

Here a list of FLENS-LAPACK driver functions.

Disclaimer: Yes, FLENS is my baby! That means I coded about 95% of it and every line of code was worth it.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!