https://github.com/meh/ela
Embedded Linear Algebra
https://github.com/meh/ela
column-vector cpp cpp11 embedded expression-template linear-algebra matrix row-vector vector
Last synced: 3 months ago
JSON representation
Embedded Linear Algebra
- Host: GitHub
- URL: https://github.com/meh/ela
- Owner: meh
- License: mit
- Created: 2017-11-26T00:57:05.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2018-02-06T22:36:39.000Z (about 8 years ago)
- Last Synced: 2025-02-12T22:22:07.980Z (about 1 year ago)
- Topics: column-vector, cpp, cpp11, embedded, expression-template, linear-algebra, matrix, row-vector, vector
- Language: C++
- Size: 96.7 KB
- Stars: 4
- Watchers: 5
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Embedded Linear Algebra [](https://opensource.org/licenses/MIT) [](https://travis-ci.org/1aim/ela)
=======================
Minimal header only linear algebra library with expression templates and low
footprint designed to run on embedded devices.
Matrix
======
A `matrix` is generic over the scalar type, the number of rows and the number
of columns, dynamically sized matrices are not supported.
The internal buffer is always allocated on the stack as a contiguous
row-major array and by default is set to `0`.
Vector
======
There are three classes of vectors, two concrete and one as a view.
Column Vector
-------------
A `column_vector` is just a type alias for `matrix`
but in addition to expression access it implements direct access through the
`[]` operator.
Row Vector
----------
A `row_vector` is just a type alias for `matrix` but
in addition to expression access it implements direct access through the `[]`
operator.
Vector
------
A `vector` is a column or row vector view into an expression (or matrix if
mutable access is required).
### Example
```cpp
ela::matrix a{{1, 0, 3}, {4, 0, 6}, {7, 0, 9}};
// Assign a column of a matrix.
a.column(1) = {2, 5, 8};
// Scale a row of the matrix and save it as a column vector.
ela::column_vector b = ~(a.row(1) * 2);
```
Bound checking
--------------
Bound checks are used at any runtime indexing operation through a call to
`ELA_ASSUME`.
Unless `ELA_ASSUME` is defined before `ela/ela.hpp` is included its definition
will become an `assert` call when `NDEBUG` is not defined and a compiler
unreachable hint when `NDEBUG` is defined.
In your custom expression implementations you're advised to call `ELA_ASSUME`
yourself to make sure the compiler knows what's going on.
Expression
==========
All matrix operations are implemented as expression templates so no
intermediary objects are created unless explictly assigned to a `matrix`.
If all your matrix values are known at compile time compilers are able to
completely constant unfold the results most of the time.
What is an `expression`?
------------------------
An `expression` is any type that implements the `ela::expression::traits` and
provides the appropriate indexing operator.
### Example
We'll implement a generic RGB type as if it were a column vector.
```cpp
/* Inheriting from `ela::expression::base` is not required but it automatically
* implements all generic expression operators for free, it doesn't add any
* data.
*/
template
struct RGB: public ela::expression::base>
{
public:
using ela::expression::base>::operator =;
public:
Type r = 0;
Type g = 0;
Type b = 0;
/* Create an empty color.
*/
RGB () noexcept
{ }
RGB (Type r, Type g, Type b) noexcept
: r(r), g(g), b(b)
{ }
template
RGB (Input const& expr, typename std::enable_if<
3 == ela::expression::traits::rows &&
1 == ela::expression::traits::columns &&
std::is_same::type>::value>::type* = 0) noexcept
{
ela::expression::base>::operator=(expr);
}
RGB (std::initializer_list> elements) noexcept
{
ela::expression::base>::operator=(elements);
}
RGB (std::initializer_list elements) noexcept
{
ela::expression::base>::operator=(elements);
}
/* This is the expression access operator.
*/
inline
Type const&
operator () (size_t row, size_t column) const noexcept
{
ELA_ASSUME(row < 3 && column == 0);
if (row == 0) {
return r;
}
else if (row == 1) {
return g;
}
else {
return b;
}
}
/* This is the expression access operator.
*/
inline
Type&
operator () (size_t row, size_t column) noexcept
{
ELA_ASSUME(row < 3 && column == 0);
if (row == 0) {
return r;
}
else if (row == 1) {
return g;
}
else {
return b;
}
}
};
namespace ela { namespace expression {
/* This defines the experssion traits for `RGB`.
*/
template
struct traits>
{
/* This is always the scalar type.
*/
typedef Type type;
/* This is the number of rows the expression will produce.
*/
static constexpr size_t rows = 3;
/* This is the number of columns the expression will produce.
*/
static constexpr size_t columns = 1;
/* This says the expression can return references.
*/
static constexpr bool concrete = true;
};
} }
```
This code will make `RGB` behave as an expression, you can look into `tests/`
for more examples of expressions and other stuff.