Update 2022 Nov 6
I know this is useful code in an article that is useful but needs updating. So here it is updated.
- Godbolt single header is much improved: https://godbolt.org/z/sWbKxnqo7
- Please study that short header for usage too.
The rest is probably updated too.
The Introduction
27 Feb 2019
The other day I have developed a handy little template to hold and provide, a plain 2d array on the stack (aka the “matrix”).
It is also fully “compile time capable” with the full static internal presentation.
It is very handy to gently enforce company-wide C++ policies and to give some useful functionality in return. I am calling this approach “almost a pod”.
All of the dbj::stack_matrix
is in this one header file.
(Tests have been in this another, single header file. But not anymore. The full Godbolt ready sample is above)
Probably the main reason for having matrices in some apps is matrix multiplication. With this API it is rather “silly simple”, one could say:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/* taken from https://github.com/dbj-systems/dbjplusplus/blob/master/test/dbj_static_matrix_test.h */ /* make 3 matrices */ using A = stack_matrix<int, 3, 3, DBJ_UID >; using B = stack_matrix<int, A::cols(),3,DBJ_UID >; using R = stack_matrix<int, A::rows(), B::cols(), DBJ_UID >; /* fill them with a callback */ A::for_each(filler); B::for_each(filler); /* multiply them*/ stack_matrix_multiply<A, B, R>(); /* R contains the result */ |
After multiplication, the A, B, and R relationship is: A[n][m] x B[m][p] = R[n][p]
. Columns of A must be the same as rows of B, and R matrix size must be A rows x B cols.
Nice, simple, functional, and easy. Since this is a stack solution, the maximum matrix size matter here a lot and is approx 64KB.
This API is more than enough for 99% of real-life use cases. No huge and complex matrix libraries are required.
In case you need matrix addition, difference and such I am sure you will find it very easy to add them by observing how is multiplication implemented, there.
This is, after all, an open source. Just please respect the copyright.
In case you just want to use ‘dbj::static_matrix’ as matrix storage, you are most welcome. You will be also more than capable to do so. By looking into the two headers, whose GitHub links are provided.
Example. I personally use its storage in a C++ standard way
1 2 3 4 5 6 7 8 9 10 |
// unique int[5][7] on the stack using A = stack_matrix<int, 5, 7, DBJ_UID >; // // make the standard C++ reference wrapper std::reference_wrapper<int[A::rows()][A::cols()]> ref_a = std::ref(A::data()); // // or make a native reference to the matrix inside // int(&)[5][7] A::matrix_ref_type mr_a = ref_a; |
That way I can reach the storage inside and use it elsewhere, to change it or to read it.
If I am using some external API written in a proper standard C++
1 2 3 4 5 6 7 8 9 10 11 |
// // external API // template< typename T, size_t N, size_t M, size_t P > void multiply( T(&a)[N][M], T(&b)[M][P], T(&c)[N][P] ); |
I can use this in a “super silly” way:
1 2 |
// use the 3rd party API and dbj static_matrix storage multiply(A::data(), B::data(), R::data()); |
Really, a celebration of modern C++. But you have a question.