Micro Linear Algebra Package
Pronounced: mu la pack
A small linear algebra package to compute various matrix/vector operations. The library is optimized to work on microcontrollers and embedded environments, but can be used anywhere C can be compiled.
All μLAPack functions are "safe" in that the matrix/vector operations are checked for initialization and mathematic dimensional legality before an operation takes place. The library contains various operations and manipulations that can be configured to your needs. The library can be configured to run safely in even the most constrained environments where memory allocation is a concern.
μLAPack contains functionality to assist in your matrix math needs for feedback control, statistical analysis, data processing, filtering, estimation, basic algebraic computation, and machine learning.
ulapack_initialize
ulapack_print
ulapack_destroy
ulapack_edit_entry
ulapack_get_entry
ulapack_is_vector
ulapack_copy
ulapack_array_col_copy
ulapack_array_row_copy
ulapack_size
ulapack_is_equal
ulapack_sum
ulapack_add
ulapack_subtract
ulapack_trace
ulapack_product
ulapack_dot
ulapack_norm
ulapack_det
ulapack_scale
ulapack_diag
ulapack_eye
ulapack_set
ulapack_transpose
ulapack_inverse
ulapack_pinverse
ulapack_lu
ulapack_vandermonde
ulapack_least_squares
ulapack_polyfit
ulapack_svd
ulapack_pca
Compile time options can be set in either the file ulapack_options.h
or in a build/make system. The user of μLAPack can make the following considerations while using the library.
The user of this library has the option of only using static memory allocation. This option is most suitable in embedded environments that can not dynamically allocate memory because of safety concerns with calls to alloc and because of time critical requirements. The macro ULAPACK_USE_STATIC_ALLOC
must be #define
d at compile time in order to use the static memory allocation feature. The static allocation technique relies on using overhead memory in the static matrix memory allocation. Due to this technique, the maximum possible row and column dimensions of any matrix object must be explicitly defined at compile time via the macros: ULAPACK_MAX_MATRIX_N_ROWS
and ULAPACK_MAX_MATRIX_N_COLS
. Any matrix initialized after compile time can not exceed the dimensions defined by the macros, and an error will be returned upon initialization if this is attempted.
Define ULAPACK_USE_DYNAMIC_ALLOC
to specify using dynamic memory allocation for all objects.
The user of this library has the option of setting the matrix/vector element data type to a desired type via the ULAPACK_MATRIX_ENTRY_TYPE
#define
. It is recommended that a primitive floating point type is used. ULAPACK_MATRIX_ENTRY_TYPE
is set to double
by default, and is typedef
ed to MatrixEntry_t
in the source code.
MINIMUM_THRESHOLD_TOLERANCE
defines the threshold floating point limit for a 0.
All new matrix/vector objects made can be initialized to zeros if ULAPACK_INITIALIZE_MEMORY
is defined at compile time.
Define ULAPACK_INVERSE_VIA_LU
to use LU decomposition for matrix inversions.
If dynamic memory allocation is used, the memory allocator and freer can be configured via the macros ULAPACK_ALLOC
and ULAPACK_FREE
.
μLAPack was developed using test-driven practices. The unit tests and Makefile
for building and running the unit tests are in the test/
directory. To test static memory allocation run make ulapack_test_static
. To unit test the dynamically allocated methods, run make ulapack_test_dynamic
. To run both tests, use make
. valgrind ./ulapack_test_dynamic
returns no memory leaks while using dynamic memory allocation.
The following error codes can be returned from the library functions. See the in-file documentation for the function to check its return codes of type MatrixError_t
.
ulapack_error
- general error codeulapack_oom
- out of memory error codeulapack_invalid_argument
- bad argument given to functionulapack_uninit_obj
- uninitialized object passed into functionulapack_success
- general success code#include "ulapack.h"
An example of setting up and using μLAPack with static memory allocation turned on.
File: ulapack_options.h
#define ULAPACK_USE_STATIC_ALLOC // switch on static allocation
#define ULAPACK_MAX_MATRIX_N_ROWS (10u) // set maximum matrix rows possible to 10
#define ULAPACK_MAX_MATRIX_N_COLS (10u) // set maximum matrix cols possible to 10
File: another_c_file.c
#include "ulapack.h"
...
Matrix_t A; // declare a matrix object with name A
ulapack_initialize_matrix(&A, 3u, 3u); // initialize the matrix with size 3X3
ulapack_eye(&A); // set the matrix A equal to the 3X3 identity matrix
ulapack_scale(&A, 3, &A); // scale the matrix A by 3
ulapack_print(&A, stdout);
Output:
[ 3 0 0 ]
[ 0 3 0 ]
[ 0 0 3 ]
An example of setting up and using μLAPack with static memory allocation turned on.
File: ulapack_options.h
#define ULAPACK_USE_DYNAMIC_ALLOC // switch on dynamic allocation
File: a_c_file.c
#include "ulapack.h"
...
Matrix_t *A; // declare a matrix object pointer with name A
ulapack_initialize_matrix(&A, 3u, 3u); // initialize the matrix with size 3X3
ulapack_eye(A); // set the matrix A equal to the 3X3 identity matrix
ulapack_scale(A, 3, A); // scale the matrix A by 3
ulapack_print(A, stdout);
Output:
[ 3 0 0 ]
[ 0 3 0 ]
[ 0 0 3 ]
Navigate to the examples/
directory for code samples using μLAPack.
An example of using μLAPack for Principle Component Analysis (PCA).
#include "ulapack.h"
int main(void) {
const double Adata[10][8] = {{0.4170, 0.4192, 0.8007, 0.0983, 0.9889, 0.0194, 0.1023, 0.9034},
{0.7203, 0.6852, 0.9683, 0.4211, 0.7482, 0.6788, 0.4141, 0.1375},
{0.0001, 0.2045, 0.3134, 0.9579, 0.2804, 0.2116, 0.6944, 0.1393},
{0.3023, 0.8781, 0.6923, 0.5332, 0.7893, 0.2655, 0.4142, 0.8074},
{0.1468, 0.0274, 0.8764, 0.6919, 0.1032, 0.4916, 0.0500, 0.3977},
{0.0923, 0.6705, 0.8946, 0.3155, 0.4479, 0.0534, 0.5359, 0.1654},
{0.1863, 0.4173, 0.0850, 0.6865, 0.9086, 0.5741, 0.6638, 0.9275},
{0.3456, 0.5587, 0.0391, 0.8346, 0.2936, 0.1467, 0.5149, 0.3478},
{0.3968, 0.1404, 0.1698, 0.0183, 0.2878, 0.5893, 0.9446, 0.7508},
{0.5388, 0.1981, 0.8781, 0.7501, 0.1300, 0.6998, 0.5866, 0.7260}};
Matrix_t A;
Matrix_t T;
ulapack_init(&A, 10, 8);
ulapack_init(&T, 10, 10);
/*
* Copy data points into vector objects.
*/
for (uint64_t row_itor = 0; row_itor < 10; row_itor++) {
for (uint64_t col_itor = 0; col_itor < 8; col_itor++) {
ulapack_edit_entry(&A,
row_itor, col_itor,
Adata[row_itor][col_itor]);
}
}
ulapack_pca(&A, &T);
}
An example using μLAPack for polynomial regression.
#include "ulapack.h"
int main(void) {
/*
* Fit 10 data points.
*/
const uint64_t data_points = 10;
/*
* Fit to the 2nd degree.
*/
const uint64_t fit_degree = 2;
const double xdata[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
/*
* x^2 + noise
*/
const double ydata[] = {0.679196, 3.215585,
8.635037, 16.117271,
25.174340, 35.784344,
48.847389, 64.033688,
81.458282, 101.281631};
/*
* Declare vector objects for data points.
*/
Matrix_t x;
Matrix_t y;
/*
* Declare vector object for coefficients.
*/
Matrix_t p;
/*
* Initialize vector objects.
*/
ulapack_init(&x, data_points, 1);
ulapack_init(&y, data_points, 1);
ulapack_init(&p, fit_degree + 1, 1);
/*
* Copy data points into vector objects.
*/
for (uint64_t row_itor = 0; row_itor < data_points; row_itor++) {
ulapack_edit_entry(&x,
row_itor, 0,
xdata[row_itor]);
ulapack_edit_entry(&y,
row_itor, 0,
ydata[row_itor]);
}
/*
* Run the regression.
*/
ulapack_polyfit(&x, &y, fit_degree, &p);
}
The libc math.h library is required for a square root operation in the ulapack_norm
and ulapack_svd
functions. To avoid the use of additional cmath library calls, the math.h
pow()
function was rewritten as a private function.
μLAPack and any derivative works of μLAPack (and embedded_lapack) are free to use for personal and/or educational use without profit and for development purposes in your project(s) to verify if μLAPack is right for you.
For commercial use (with redistribution rights): Fill out the licensing inquiry form, and I will promptly reply with a response and proposed license agreement.
Refer to the LICENSE document for licensing details.
μLAPack is a fork of my now deprecated embedded_lapack library. μLAPack includes definitions for both static and dynamic memory allocation, safer type definitions, more explicit and safer error code status, Doxygen, more functionality, and more compiler support when compared to embedded_lapack.
ulapack_find
:
operator in MATLAB) - ulapack_copy_submatrix
ulapack_cross
ulapack_skew
μKalman
with:
Have a suggestion for a new feature/function? File an issue in this repository with your requests.