Embedded developers have it harder than most. Often we don't have library options most other developers do. For example, the library might depend on file I/O, or it might require easy access to a large heap, or it even might require floating point arithmetic that our part is no good at implementing in software.
Overtime we learn to adapt and overcome. We develop a set of libraries which performs most of the functionality we need. We find good articles in different embedded magazines that have code we can rip off. And we even sometimes suck it up, and buy better parts or operating systems to make development easier.
Over the recent months, I've been re-tweaking a simple set of C matrix functions I've used before. The library is specifically designed for embedded developers. What I mean by that is I tried to follow a number of goals:
- The library should be optimized for readability/portability.
- Don't try to be all things to all people, provide the basic functionality people will require for one and two dimensional matrices.
- Don't require a heap.
The following is my MTRX library:
mtrx.h
mtrx.c
The library provides the basic matrix functionality like:
- Scalar addition, subtraction, and multiplication
- Multiplication
- Inversion
- In-place and out of place transposition
I haven't extended it to include eigenvalues and vectors. Additionally, I haven't added different matrix decompositions that others might need. Again, the library is a barebones matrix implementation that most embedded developers can use with a little tweaking.
Here's an example of using the library:
#include "mtrx.h" #include <stdlib.h> #include <time.h> #define N (100) int main() { unsigned i,j; srand(time(0)); for(i = 0; i < 1000; ++i) { MTRX_t m1, m2, m3; MTRX_Element_t f[N * N]; for(j = 0; j < N * N; ++j) f[j] = ((float)(rand())) / ((float)RAND_MAX); MTRX_Create(&m1, N, N, f); // will use the stack's f[] for storage MTRX_Create(&m2, N, N, 0); // uses the heap MTRX_Create(&m3, N, N, 0); // uses the heap MTRX_Copy(&m2, &m1); if (MTRX_Invert(&m2, 0)) // will use heap for temp storage MTRX_Multiply(&m3, &m1, &m2); MTRX_Destroy(&m1); MTRX_Destroy(&m2); MTRX_Destroy(&m3); } return 0; }
The library is pretty smart about using the allocations. In other words, if you create matrices, and give them enough size, they should never be allocated on the heap; however, if built right, the library will yank space from the heap when needed. To turn off heap allocation, build with MTRX_NO_MALLOC_.
Additionally, the return values from most functions are bool's. This means two things, most functions can fail (generally if the matrices aren't big enough), and you need C9X to build it. Also, a few minor notes:
- Don't use the inplace transpose function if you can help it. It's quite expensive.
- The inversion routine requires a temporary buffer. Read the header file for size requirements. (If no buffer is passed, and the library is compiled with heap support, one is allocated.)
As usual this library is MIT licensed, but I'd appreciate it if people would drop me a line if they use it.
Post a Comment