How can we call the BLAS and LAPACK libraries from a C code without being tied to an implementation? For BLAS, there is CBLAS, a native C interface. For LAPACK, the native C interface is LAPACKE, not CLAPACK. If you don't have LAPACKE, use
BLAS and LAPACK
In fact, since libraries are often distributed in binary form (think Linux distro packages for example), BLAS and LAPACK could be written in any language as long as that a Fortran code calling a BLAS or LAPACK subroutine with the syntax used on Netlib can compile and link with the library and the resulting executable produces the same result the Netlib code.
Well, I have not touched Fortran for years bus as long as I remember
Fortran binary interface (ABI) is not standardized. An object file
produced by a compiler may not be usable by another compiler (cf
ifort). But let's just suppose here that we are
only working with one compiler with a well defined ABI. So, if we know
the binary calling convention for a Fortran function, the the Fortran
API also defines an ABI.
On the C side, the C ABI is standardized: from a source-level function definition, we know how the binary-level call will happen. Moreover, there is a C type matching every Fortran scalar type used in BLAS and LAPACK. As a result, the Fortran source API for BLAS/LAPACK plus assumptions about the Fortran compiler result in a C source API for BLAS/LAPACK.
For example, we can access the BLAS
dgemm and LAPACK
SUBROUTINE dgemm(TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC) DOUBLE PRECISION alpha,beta INTEGER k,lda,ldb,ldc,m,n CHARACTER transa,transb DOUBLE PRECISION a(lda,*),b(ldb,*),c(ldc,*) SUBROUTINE dgesv(N, NRHS, A, LDA, IPIV, B, LDB, INFO) INTEGER info, lda, ldb, n, nrhs INTEGER ipiv(*) DOUBLE PRECISION a(lda, *), b(ldb, *)
... as the external C functions
extern dgemm_(char * transa, char * transb, int * m, int * n, int * k, double * alpha, double * A, int * lda, double * B, int * ldb, double * beta, double *, int * ldc); extern dgesv_(int * n, int * nrhs, double * A, int * lda, int * ipiv, double * B, int * ldb, int * info);
... and this stands for any BLAS/LAPACK subroutine.
Note that since this Fortran API to C ABI is compiler-dependent, no
BLAS library provides a
lapack.h header with all these
declarations. You have to do it yourself, and trust the compilers for long term
validity. Or you may prefer a truly portable, standard interface.
This interface exists for BLAS, it's called
CBLAS. Following on the
example, we now have this new C API/ABI:
void cblas_dgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const double alpha, const double *A, const int lda, const double *B, const int ldb, const double beta, double *C, const int ldc)
CBLAS is in fact just a very thin layer (no performance penalty) over BLAS, with these benefits:
- standard and simple, implemented by every BLAS library;
- scalars passed by value, arrays by pointers;
constto protect read-only parameters;
enumand macros instead of characters with "magic values";
Orderparameter to use row-major or column-major arrays without juggling with transpositions.
If you use BLAS from a C code, there is no reason to use the Fortran
interface directly. Just
#include <cblas.h> (provided with every
BLAS library) and link with your preferred BLAS.
There also is something on Netlib called CLAPACK, but it is not a standard C interface to the Fortran LAPACK. CLAPACK is a translation of the Fortran LAPACK code into C.
Still on the
dgesv example, now in CLAPACK it is defined as ...
int dgesv_(integer *n, integer *nrhs, doublereal *a, integer *lda, integer *ipiv, doublereal *b, integer *ldb, integer *info);
doublereal typedef'd as
somewhere else. Based on 100% C code, this interface is
compiler-independent. But that's all you can get: it is not
implemented by other vendors and does not provide any of the other
benefits of a native C interface like CBLAS does.
Finally, CLAPACK is mentioned as "no longer maintained" on Netlib, so let's just avoid this trap.
There is also something called
ATLAS, with functions like ...
int clapack_dgesv(const enum CBLAS_ORDER Order, const int N, const int NRHS, void *A, const int lda, int *ipiv, void *B, const int ldb);
This something else, a C interface provided by ATLAS for some of the LAPACK routines in ATLAS, entirely different from Netlib CLAPACK. And ATLAS doesn't provide every LAPACK subroutine. So it's time to conclude on the absence of anything standard and portable called CLAPACK. As written by Clint Whaley (author of ATLAS), "there has been no official standardization of a C interface to LAPACK ... your best bet is to call the Fortran77 interface".
Well that was sadly true until ...
Here it is. LAPACKE is relatively recent (proposed in 2008, accepted in 2010) but it's the closest we have to a native C source-level interface to the original Fortran API. LAPACKE is to LAPACK what CBLAS is to BLAS, with this interface:
lapack_int LAPACKE_dgesv(int matrix_order, lapack_int n, lapack_int nrhs, double * a, lapack_int lda, lapack_int * ipiv, double * b, lapack_int ldb);
This one is standardized, as mentioned on Netlib: "Standard C language
APIs for LAPACK". Moreover, as LAPACKE is a thin layer over
LAPACK, which itself calls BLAS to perform the real expensive
computations, I think that it is possible to use the
library from Netlib with any LAPACK and BLAS back-end. Everything you
need to the good linking options, in the correct order. Finally,
LAPACKE is also included in the MKL package.
The BLAS case is clear: we must use the CBLAS interface, available with every BLAS library. For LAPACK, we should use LAPACKE if we have it. If not, we could either use the LAPACKE layer from Netlib, and possibly the LAPACK layer too, over our preferred BLAS library, or directly link to the Fortran interface if we know the compiler ABI.
For reference, here is the list of Fortran and C interfaces available (ignoring unmaintained CLAPACK) in major BLAS/LAPACK implementations, with the package, shared library and C header names in Debian 8.0 Jessie:
- BLAS (
- CBLAS (
- LAPACK (
- BLAS (
- CBLAS (
- LAPACK (
<C> is the compiler ABI (
gf for GFortran and
intel for IFort)
<P> is the 64-bit model,