Currently, there are:
however, these are C interfaces.
Obviously, you can use them in a C++ code, but you do not get all the benefits you would get if these interfaces were designed for C++. So my question is: are such interfaces exist in native C++?
Recently these two interfaces, from University of Tennessee, has been released:
There are some immediate benefits of using these native C++ implementations.
Let's consider a basic generic programming example:
Imagine that you want to scale a vector: v = alpha*v
thanks to the cblas_?scal functions.
With cblas, if you wanted something "generic" in the sense that it has the same interface for all supported scalar types (float
, double
, complex<float>
, complex<double>
,...), all the C functions had to be wrapped:
void scal(cblas_int n,float alpha, float *x, cblas_int inc) {
...
cblas_sscal(n,alpha,x,inc); <- s for float
}
void scal(cblas_int n,double alpha, double *x, cblas_int inc) {
...
cblas_dscal(n,alpha,x,inc); <- d for double
}
// do the same for complex<float>, complex<double> ...
The reason is that in C, two functions are differents if they have different names: cblas_sscal
, cblas_dscal
...
In C++ you can have the same name scal and this is the compiler job to dispatch to the right function according to its arguments, here float
, double
...
The situation now. With the mentioned https://bitbucket.org/icl/blaspp C++ native interface this boilerplate code has already been written once for all. For instance if you look scal.hh header file you have:
void scal(int64_t n, float alpha, float *x, int64_t incx ) { ... }
void scal(int64_t n, double alpha, double *x, int64_t incx ) { ... }
void scal(int64_t n, std:complex<float> alpha, std:complex<float> *x, int64_t incx ) { ... }
void scal(int64_t n, std:complex<double> alpha, std:complex<double> *x, int64_t incx ) { ... }
and even a generic implementation:
template<typename T>
void scal(int64_t n, T alpha, T *x, int64_t incx ) { ... }
Hence with this C++ interface, it is easy to define a generic interface for your favorit vector/matrix type. As example, with std::vector<T>
, you only have to write (independently of the actual T type):
template<typename T>
void scal(T alpha, std::vector<T>& v) {
scal(v.size(),alpha,v.data(),1);
}
No more boilerplate code!
This is the idea, however note that:
.
template< typename TA, typename TX >
void trmm(
blas::Layout layout,
blas::Side side,
blas::Uplo uplo,
blas::Op trans,
blas::Diag diag,
int64_t m,
int64_t n,
typename blas::traits2<TA, TX>::scalar_t alpha,
TA const *A, int64_t lda,
TX *B, int64_t ldb )
{
throw std::exception(); // not yet implemented
}