README.md

blas
=====

This project is a NIF based wrapper of the Basic Linear Algebra Subprograms, which provides algorithms fine-tuned for a large variety of hardware.

This implementation uses [openblas](https://github.com/xianyi/OpenBLAS). Other cblas implementations can be used, but will need modifictations of c_src/Makefile linking options and c_src/eblas.h include options.

API
----
The following sites provide a clear BLAS API:
- [netlib's](https://netlib.org/blas/) concise reference.
- [intel's](https://www.intel.com/content/www/us/en/content-details/671183/developer-reference-for-intel-math-kernel-library-intel-mkl-11-3-c.html?wapkw=BLAS%20mlk) complete reference.
- [IBM's](https://www.ibm.com/docs/en) reference, with clear examples.

Usage
-----
```erlang
blas:run(Tuple);        % Execute on dirty scheduler
blas:run(Tuple, dirty); % Execute on dirty scheduler.
blas:run(Tuple, clean); % Execute on usual scheduler.
```
Tuple contains, in sequence, a BLAS function name (represented as an atom), followed by its arguments in Erlang representation.

Examples
-----

[caxpy](https://www.ibm.com/docs/en/essl/6.1?topic=vss-saxpy-daxpy-caxpy-zaxpy-multiply-vector-by-scalar-add-vector-store-in-vector): single Complex numbers, Alpha*x Plus Y:

```erlang
Alpha = blas:ltb(c, [1,0]),
X     = blas:ltb(c, [1,2,  2,3,  3,1]),
Y     = blas:new(c, [1,1,  0,0,  1,2]),
ok    = blas:run({caxpy, 3, Alpha, X, 1, Y, 1}),

io:format("Result: ~p~n", [blas:to_list(c, Y)]).
```

[stpmv](https://www.ibm.com/docs/en/essl/6.1?topic=mvs-strmv-dtrmv-ctrmv-ztrmv-stpmv-dtpmv-ctpmv-ztpmv-matrix-vector-product-triangular-matrix-its-transpose-its-conjugate-transpose): Single real numbers, Triangular Packed Matrix, Matrix*Vector operation.

```erlang
N  = 3,
A  = blas:new(s, [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]),
X  = blas:new(s, [-0.25,-0.125,0.5]),
ok = blas:run(
    {stpmv, blasRowMajor, blasUpper, blasNoTrans, blasNonUnit, N, A, X, 1},
    clean
),
[1.0,2.0,3.0] = blas:to_list(s, X).
```

Datatype conversion tables
-----

```
    enums       cblas[value]           blas[value]

    numbers
                (const)int             int
                void*                  c_binary
                const float            double; binary; c_binary
                const double           double; binary; c_binary
                const void*            binary; c_binary

```

For example, taking stpmv's cblas signature:

```c
void cblas_stpmv(OPENBLAS_CONST enum CBLAS_ORDER order, OPENBLAS_CONST enum CBLAS_UPLO Uplo, OPENBLAS_CONST enum CBLAS_TRANSPOSE TransA, OPENBLAS_CONST enum CBLAS_DIAG Diag,
                 OPENBLAS_CONST blasint N, OPENBLAS_CONST float *Ap, float *X, OPENBLAS_CONST blasint incX);
```
The arguments can be represented as such:
```erlang
% enums
Order  = blasRowMajor  || blasColMajor
Uplo   = blasUpper     || blasLower
Transa = blasNoTrans   || blasTrans
Diag   = blasNonUnit   || blasUnit

% int
N      = 3 
incX   = 1

% const float*
A      = blas:new(s, [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]); % c_binary, a mutable binary
A_2    = blas:ltb(s, [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]); % binary

% float*
X      = blas:new(s, [-0.25,-0.125,0.5]);             % c_binary
```

Creating c_binaries
-----
Since BLAS functions operate in place, c_binaries representing mutable arrays are needed. They can be created as such: 
```erlang
C_binary = blas:new(Binary).
% Binary is an erlang binary.
C_binary = blas:new(Type, List).
% List is a list of numbers.
% Type is used to encode the binary, and is one of: 
% s -> single precision
% d -> double precision
% c -> single complex numbers: List is of even size
% Z -> double complex numbers: List is of even size
```

Reading c_binaries
-----
The content of c_binaries can be retrieved as either a list of elements, or a constant binary.
Retrieving a list is done as such:
```erlang
C_binary = blas:to_list(Type, C_binary).
% Binary is a c_binary created using blas:new.
% Type is used to decode the binary, and is one of: 
% s -> single precision
% d -> double precision
% c -> single complex numbers (equivalent to s)
% Z -> double complex numbers (equivqlent to d)
```
Retrieving a binary is done as such:
```erlang
Binary = blas:to_bin(C_binary).
% Binary is a c_binary created using blas:new.
```