2022-07-12 14:20:20 -04:00
|
|
|
|
|
|
|
[![Arduino CI](https://github.com/RobTillaart/SparseMatrix/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
|
|
|
|
[![Arduino-lint](https://github.com/RobTillaart/SparseMatrix/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/SparseMatrix/actions/workflows/arduino-lint.yml)
|
|
|
|
[![JSON check](https://github.com/RobTillaart/SparseMatrix/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/SparseMatrix/actions/workflows/jsoncheck.yml)
|
|
|
|
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/SparseMatrix/blob/master/LICENSE)
|
|
|
|
[![GitHub release](https://img.shields.io/github/release/RobTillaart/SparseMatrix.svg?maxAge=3600)](https://github.com/RobTillaart/SparseMatrix/releases)
|
|
|
|
|
|
|
|
|
|
|
|
# SparseMatrix
|
|
|
|
|
|
|
|
Arduino library for sparse matrices.
|
|
|
|
|
|
|
|
|
|
|
|
## Description
|
|
|
|
|
2022-07-14 11:28:24 -04:00
|
|
|
SparseMatrix is an **experimental** library to implement
|
|
|
|
two dimensional sparse matrices (of floats) on an Arduino.
|
|
|
|
A sparse matrix is a matrix with mostly zeros and a low percentage non-zero values.
|
|
|
|
The purpose of this library is efficient storage in memory.
|
2022-07-12 14:20:20 -04:00
|
|
|
|
|
|
|
The maximum matrix that can be represented is 255 x 255
|
2022-07-14 11:28:24 -04:00
|
|
|
with a theoretical maximum of 65535 non-zero elements.
|
|
|
|
In practice the library limits this to 1000 non-zero elements.
|
|
|
|
Note: 255 elements would still fit in an UNO's 2K memory.
|
2022-07-12 14:20:20 -04:00
|
|
|
|
2022-07-14 11:28:24 -04:00
|
|
|
Note: the library does not do matrix math operations.
|
2022-07-12 14:20:20 -04:00
|
|
|
|
2022-07-14 11:28:24 -04:00
|
|
|
Note: the library does not hold the dimensions of the matrix
|
|
|
|
and cannot check these.
|
2022-07-12 14:20:20 -04:00
|
|
|
|
2022-11-25 08:22:25 -05:00
|
|
|
Relates to:
|
|
|
|
- https://github.com/RobTillaart/SparseArray
|
|
|
|
- https://github.com/RobTillaart/distanceTable
|
|
|
|
|
2022-07-12 14:20:20 -04:00
|
|
|
|
|
|
|
#### Implementation
|
|
|
|
|
2022-07-14 11:28:24 -04:00
|
|
|
The implementation is based on 3 arrays holding ``` x, y, value```
|
|
|
|
where value is float, and x and y are uint8_t.
|
|
|
|
That are 6 bytes per element.
|
|
|
|
The number of elements that the sparse matrix object can hold are
|
|
|
|
given as parameter to the constructor.
|
|
|
|
If the space cannot be allocated the size is set to zero.
|
|
|
|
|
|
|
|
In the future other data types should be possible.
|
|
|
|
|
2022-07-12 14:20:20 -04:00
|
|
|
|
2022-07-13 11:47:55 -04:00
|
|
|
#### Performance
|
|
|
|
|
2022-07-14 11:28:24 -04:00
|
|
|
The elements are not kept sorted or indexed so optimizations might be
|
|
|
|
possible but are not investigated yet.
|
|
|
|
There is however a test sketch to monitor the performance of
|
|
|
|
the most important functions.
|
|
|
|
|
|
|
|
Accessing elements internally is done with a linear search,
|
|
|
|
which becomes (much) slower if the number of elements is increasing.
|
|
|
|
This means that although in theory there can be 65535 elements,
|
|
|
|
in practice a few 100 can already become annoyingly slow.
|
|
|
|
To keep performance a bit the library has a limit build in.
|
|
|
|
Check the .h file for **SPARSEMATRIX_MAX_SIZE 1000**
|
2022-07-12 14:20:20 -04:00
|
|
|
|
|
|
|
|
|
|
|
## Interface
|
|
|
|
|
2022-07-14 11:28:24 -04:00
|
|
|
```cpp
|
|
|
|
#include "SparseMatrix.h"
|
|
|
|
```
|
|
|
|
|
|
|
|
### Constructor + meta
|
|
|
|
|
|
|
|
- **SparseMatrix(uint16_t size)** constructor.
|
2022-07-12 14:20:20 -04:00
|
|
|
Parameter is the maximum number of elements in the sparse matrix.
|
2022-07-14 11:28:24 -04:00
|
|
|
Note this number is limited to **SPARSEMATRIX_MAX_SIZE 1000**.
|
|
|
|
If the space requested cannot be allocated size will be set to 0.
|
|
|
|
- **uint16_t size()** maximum number of elements.
|
|
|
|
If this is zero, a problem occurred with allocation happened.
|
|
|
|
- **uint16_t count()** current number of elements in the matrix.
|
|
|
|
Should be between 0 and size.
|
2022-07-12 14:20:20 -04:00
|
|
|
- **float sum()** sum of all elements ( > 0 ) in the matrix.
|
2022-07-13 11:47:55 -04:00
|
|
|
- **void clear()** resets the matrix to all zero's again.
|
2022-07-14 11:28:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
### Access
|
|
|
|
|
2022-07-12 14:20:20 -04:00
|
|
|
- **bool set(uint8_t x, uint8_t y, float value)** gives an element in the matrix a value.
|
|
|
|
If the value is set to zero, it is removed from the internal store.
|
|
|
|
Returns false if the internal store is full, true otherwise.
|
|
|
|
- **float get(uint8_t x, uint8_t y)** returns the value in the matrix.
|
2022-07-14 11:28:24 -04:00
|
|
|
- **bool add(uint8_t x, uint8_t y, float value)** adds value to an element in the matrix.
|
2022-07-13 11:47:55 -04:00
|
|
|
If needed a new internal element is created.
|
|
|
|
If the sum is zero, the element is removed from the internal store.
|
|
|
|
Returns false if the internal store is full, true otherwise.
|
2022-07-16 07:42:58 -04:00
|
|
|
- **void boundingBox(uint8_t &minX, uint8_t &maxX, uint8_t &minY, uint8_t &maxY)**
|
|
|
|
Returns the bounding box in which all values != 0 are located.
|
|
|
|
This can be useful for printing or processing the non zero elements.
|
2022-07-12 14:20:20 -04:00
|
|
|
|
|
|
|
|
|
|
|
## Future
|
|
|
|
|
2022-11-25 08:22:25 -05:00
|
|
|
#### must
|
|
|
|
- update documentation
|
|
|
|
|
|
|
|
#### should
|
|
|
|
- do tests
|
|
|
|
|
|
|
|
#### could
|
2022-07-12 14:20:20 -04:00
|
|
|
- template version to store other data types
|
|
|
|
- 1, 2, 3 (RGB), 4 byte integer or 8 byte doubles
|
|
|
|
- struct, complex number
|
|
|
|
- etc
|
2022-07-14 11:28:24 -04:00
|
|
|
- investigate performance optimizations
|
|
|
|
- sort
|
|
|
|
- linked list, tree, hashing?
|
2022-11-25 08:22:25 -05:00
|
|
|
- SparseArray?
|
|
|
|
- derived class that only uses X and Value
|
|
|
|
- only need an extra get/set/add
|
|
|
|
- separate class memory efficient (base class?)
|
|
|
|
- class tree - Sparse1D <- Sparse2D <- Sparse3D ...
|
|
|
|
- dump should be in the class?
|
|
|
|
- or as static function...
|
|
|
|
- stream as parameter dump(Stream str,
|
2022-07-12 14:20:20 -04:00
|
|
|
|
|
|
|
|
2022-07-14 11:28:24 -04:00
|
|
|
#### Functions
|
2022-07-12 14:20:20 -04:00
|
|
|
|
2022-11-25 08:22:25 -05:00
|
|
|
- extend the add() math series.
|
|
|
|
- sub(uint8_t x, uint8_t y, float value);
|
|
|
|
- mul(uint8_t x, uint8_t y, float value);
|
|
|
|
- div(uint8_t x, uint8_t y, float value);
|
|
|
|
- sqrt(uint8_t x, uint8_t y, float value);
|
|
|
|
- pow(uint8_t x, uint8_t y, float value);
|
|
|
|
- exp(uint8_t x, uint8_t y, float value);
|
|
|
|
- log(uint8_t x, uint8_t y, float value);
|
|
|
|
- ln(uint8_t x, uint8_t y, float value);
|
|
|
|
- on request.
|
|
|
|
- do we need 'vector' operations
|
|
|
|
- add(value) which adds to all elements.
|
|
|
|
- walk through the elements.
|
2022-07-16 07:42:58 -04:00
|
|
|
- in storage order.
|
|
|
|
- bool first(uint8_t &x, uint8_t &y, float &value);
|
|
|
|
- bool next(uint8_t &x, uint8_t &y, float &value);
|
|
|
|
- bool prev(uint8_t &x, uint8_t &y, float &value);
|
|
|
|
- bool last(uint8_t &x, uint8_t &y, float &value);
|
2022-11-25 08:22:25 -05:00
|
|
|
- returns false if there is no element any more
|
2022-07-16 07:42:58 -04:00
|
|
|
- if count = 0 or current == -1 or end of list.
|
2022-11-25 08:22:25 -05:00
|
|
|
- mutating values can disrupt the iteration..
|
2022-07-16 07:42:58 -04:00
|
|
|
|
2022-07-12 14:20:20 -04:00
|
|
|
|
|
|
|
#### won't
|
|
|
|
|
2022-07-14 11:28:24 -04:00
|
|
|
- should **set()** and **add()** return the number of free places?
|
|
|
|
- more informative than just a bool.
|
|
|
|
- One looses the info that the operation was successful
|
|
|
|
- set a zero threshold ?
|
|
|
|
- if (abs(x) < TH) element is considered zero => remove
|
|
|
|
- not portable to template version (sum() is not either!)
|
|
|
|
- user can do this.
|
2022-07-12 14:20:20 -04:00
|
|
|
- math
|
|
|
|
- determinant?
|
|
|
|
- M x M
|
|
|
|
- diagonal?
|
|
|
|
- add examples
|
2022-07-14 11:28:24 -04:00
|
|
|
- N queens game.
|
2022-07-12 14:20:20 -04:00
|
|
|
- battleship game
|
|
|
|
- minesweeper game
|
|
|
|
|