mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-09-20 00:55:58 -04:00
0.1.2 SparseMatrix
This commit is contained in:
parent
84b8c6b223
commit
7aefcd0252
@ -8,4 +8,6 @@ compile:
|
||||
- m4
|
||||
- esp32
|
||||
- esp8266
|
||||
# - mega2560
|
||||
# - mega2560
|
||||
libraries:
|
||||
- "SHT85"
|
@ -13,44 +13,78 @@ Arduino library for sparse matrices.
|
||||
|
||||
## Description
|
||||
|
||||
SparseMatrix is an **experimental** library to implement sparse matrices on an Arduino.
|
||||
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.
|
||||
|
||||
The maximum matrix that can be represented is 255 x 255
|
||||
with a maximum of 255 non-zero elements.
|
||||
This would just fit in an UNO's 2K memory.
|
||||
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.
|
||||
|
||||
The library does not hold the dimensions of the matrix (at least in 0.1.0)
|
||||
Note: the library does not do matrix math operations.
|
||||
|
||||
The purpose of the library is efficient storage in memory.
|
||||
It does not do math operations except sum().
|
||||
Note: the library does not hold the dimensions of the matrix
|
||||
and cannot check these.
|
||||
|
||||
Relates to https://github.com/RobTillaart/distanceTable
|
||||
Relates somewhat to https://github.com/RobTillaart/distanceTable
|
||||
|
||||
|
||||
#### Implementation
|
||||
|
||||
The implementation is based on 3 arrays holding ``` x, y, value``` where value is float.
|
||||
In the future other datatypes should be possible.
|
||||
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.
|
||||
|
||||
|
||||
#### Performance
|
||||
|
||||
The elements are not kept sorted or indexed so optimizations are possible
|
||||
but not investigated yet.
|
||||
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**
|
||||
|
||||
|
||||
## Interface
|
||||
|
||||
- **SparseMatrix(uint8_t size)** constructor.
|
||||
```cpp
|
||||
#include "SparseMatrix.h"
|
||||
```
|
||||
|
||||
### Constructor + meta
|
||||
|
||||
- **SparseMatrix(uint16_t size)** constructor.
|
||||
Parameter is the maximum number of elements in the sparse matrix.
|
||||
- **uint8_t size()** maximum number of elements.
|
||||
- **uint8_t count()** current number of elements in the matrix.
|
||||
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.
|
||||
- **float sum()** sum of all elements ( > 0 ) in the matrix.
|
||||
- **void clear()** resets the matrix to all zero's again.
|
||||
|
||||
|
||||
### Access
|
||||
|
||||
- **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.
|
||||
- **bool add(uint8_t x, uint8_t y, float value)** adds a value to an element in the matrix.
|
||||
- **bool add(uint8_t x, uint8_t y, float value)** adds value to an element in the matrix.
|
||||
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.
|
||||
@ -64,32 +98,33 @@ Returns false if the internal store is full, true otherwise.
|
||||
- 1, 2, 3 (RGB), 4 byte integer or 8 byte doubles
|
||||
- struct, complex number
|
||||
- etc
|
||||
- add examples
|
||||
- 2D histogram e.g. temperature vs humidity
|
||||
- N queens game.
|
||||
- investigate optimizations.
|
||||
- should **set()** and **add()** return the number of free places?
|
||||
- no hard code and more informative than just a bool.
|
||||
- investigate performance optimizations
|
||||
- sort
|
||||
- linked list, tree, hashing?
|
||||
- can **set()** and **add()** be merged?
|
||||
- add link in distanceTable repo
|
||||
- uint16_t size for larger platforms.
|
||||
- max matrix still 255 x 255 but more elements <> 0.
|
||||
|
||||
|
||||
#### new functions
|
||||
#### Functions
|
||||
|
||||
- walk through the elements?
|
||||
- first -> next; last -> prev.
|
||||
|
||||
- first() -> next(); optional last() -> prev().
|
||||
|
||||
|
||||
#### won't
|
||||
|
||||
- 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.
|
||||
- math
|
||||
- determinant?
|
||||
- M x M
|
||||
- diagonal?
|
||||
- add examples
|
||||
- N queens game.
|
||||
- battleship game
|
||||
- minesweeper game
|
||||
- nice exercise
|
||||
|
||||
|
@ -1,24 +1,32 @@
|
||||
//
|
||||
// FILE: SparseMatrix.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// VERSION: 0.1.2
|
||||
// DATE: 2022-07-12
|
||||
// PURPOSE: Arduino library for sparse matrices
|
||||
// URL: https://github.com/RobTillaart/SparseMatrix
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1.0 2022-07-12 initial version
|
||||
// 0.1.1 2022-07-13 add clear();
|
||||
// add add(x, y, value);
|
||||
// fix set(x, y, 0);
|
||||
// 0.1.2 2022-07-14 increase size to uint16_t
|
||||
// add SPARSEMATRIX_MAX_SIZE
|
||||
// improve documentation
|
||||
|
||||
|
||||
#include "SparseMatrix.h"
|
||||
|
||||
|
||||
SparseMatrix::SparseMatrix(uint8_t sz)
|
||||
SparseMatrix::SparseMatrix(uint16_t sz)
|
||||
{
|
||||
_count = 0;
|
||||
_size = sz;
|
||||
if ( _size > SPARSEMATRIX_MAX_SIZE)
|
||||
{
|
||||
_size = SPARSEMATRIX_MAX_SIZE;
|
||||
}
|
||||
_x = (uint8_t *) malloc(sz);
|
||||
_y = (uint8_t *) malloc(sz);
|
||||
_value = (float *) malloc(sz * sizeof(float));
|
||||
@ -37,13 +45,13 @@ SparseMatrix::~SparseMatrix()
|
||||
}
|
||||
|
||||
|
||||
uint8_t SparseMatrix::size()
|
||||
uint16_t SparseMatrix::size()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
|
||||
uint8_t SparseMatrix::count()
|
||||
uint16_t SparseMatrix::count()
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
@ -58,7 +66,7 @@ void SparseMatrix::clear()
|
||||
float SparseMatrix::sum()
|
||||
{
|
||||
float _sum = 0;
|
||||
for (int i = 0; i < _count; i++)
|
||||
for (uint16_t i = 0; i < _count; i++)
|
||||
{
|
||||
_sum += _value[i];
|
||||
}
|
||||
@ -68,7 +76,7 @@ float SparseMatrix::sum()
|
||||
|
||||
bool SparseMatrix::set(uint8_t x, uint8_t y, float value)
|
||||
{
|
||||
int pos = findPos(x, y);
|
||||
int32_t pos = findPos(x, y);
|
||||
// existing element
|
||||
if (pos > -1)
|
||||
{
|
||||
@ -104,7 +112,7 @@ bool SparseMatrix::set(uint8_t x, uint8_t y, float value)
|
||||
|
||||
bool SparseMatrix::add(uint8_t x, uint8_t y, float value)
|
||||
{
|
||||
int pos = findPos(x, y);
|
||||
int32_t pos = findPos(x, y);
|
||||
// existing element
|
||||
if (pos > -1)
|
||||
{
|
||||
@ -137,7 +145,7 @@ bool SparseMatrix::add(uint8_t x, uint8_t y, float value)
|
||||
|
||||
float SparseMatrix::get(uint8_t x, uint8_t y)
|
||||
{
|
||||
int pos = findPos(x, y);
|
||||
int32_t pos = findPos(x, y);
|
||||
if (pos > -1)
|
||||
{
|
||||
return _value[pos];
|
||||
@ -146,13 +154,18 @@ float SparseMatrix::get(uint8_t x, uint8_t y)
|
||||
}
|
||||
|
||||
|
||||
int SparseMatrix::findPos(uint8_t x, uint8_t y)
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// PRIVATE
|
||||
//
|
||||
int32_t SparseMatrix::findPos(uint8_t x, uint8_t y)
|
||||
{
|
||||
for (int i = 0; i < _count; i++)
|
||||
// linear search - not optimized.
|
||||
for (uint16_t i = 0; i < _count; i++)
|
||||
{
|
||||
if ((_x[i] == x) && (_y[i] == y))
|
||||
{
|
||||
return i;
|
||||
return (int32_t)i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@ -161,3 +174,4 @@ int SparseMatrix::findPos(uint8_t x, uint8_t y)
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -2,25 +2,30 @@
|
||||
//
|
||||
// FILE: SparseMatrix.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// VERSION: 0.1.2
|
||||
// DATE: 2022-07-12
|
||||
// PURPOSE: Arduino library for sparse matrices
|
||||
// URL: https://github.com/RobTillaart/SparseMatrix
|
||||
//
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#define SPARSEMATRIX_LIB_VERSION (F("0.1.1"))
|
||||
#define SPARSEMATRIX_LIB_VERSION (F("0.1.2"))
|
||||
|
||||
#ifndef SPARSEMATRIX_MAX_SIZE
|
||||
#define SPARSEMATRIX_MAX_SIZE 1000
|
||||
#endif
|
||||
|
||||
|
||||
class SparseMatrix
|
||||
{
|
||||
public:
|
||||
SparseMatrix(uint8_t sz);
|
||||
SparseMatrix(uint16_t sz);
|
||||
~SparseMatrix();
|
||||
|
||||
uint8_t size();
|
||||
uint8_t count();
|
||||
uint16_t size();
|
||||
uint16_t count();
|
||||
float sum();
|
||||
void clear();
|
||||
|
||||
@ -34,16 +39,16 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
int _size = 0;
|
||||
int _count = 0;
|
||||
uint16_t _size = 0;
|
||||
uint16_t _count = 0;
|
||||
|
||||
uint8_t *_x = NULL;
|
||||
uint8_t *_y = NULL;
|
||||
float *_value = NULL;
|
||||
|
||||
// returns index of x,y if in set
|
||||
// returns index of x, y if in set
|
||||
// otherwise -1
|
||||
int findPos(uint8_t x, uint8_t y);
|
||||
int32_t findPos(uint8_t x, uint8_t y);
|
||||
};
|
||||
|
||||
|
||||
|
@ -0,0 +1,92 @@
|
||||
//
|
||||
// FILE: sparse_matrix_2D_histogram.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo 2D
|
||||
// URL: https://github.com/RobTillaart/SparseMatrix
|
||||
//
|
||||
// TOPVIEW SHT85 (check datasheet)
|
||||
// +-------+
|
||||
// +-----\ | SDA 4 -----
|
||||
// | +-+ ----+ GND 3 -----
|
||||
// | +-+ ----+ +5V 2 -----
|
||||
// +-----/ | SCL 1 -----
|
||||
// +-------+
|
||||
|
||||
|
||||
#include "SparseMatrix.h"
|
||||
#include "SHT85.h"
|
||||
|
||||
#define SHT85_ADDRESS 0x44
|
||||
|
||||
SHT85 sht;
|
||||
|
||||
SparseMatrix sm(40);
|
||||
uint32_t lastTime = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
|
||||
Serial.print("SHT_LIB_VERSION: \t");
|
||||
Serial.println(SHT_LIB_VERSION);
|
||||
Serial.print("SPARSEMATRIX_LIB_VERSION: \t");
|
||||
Serial.println(SPARSEMATRIX_LIB_VERSION);
|
||||
|
||||
sm.clear();
|
||||
|
||||
Wire.begin();
|
||||
sht.begin(SHT85_ADDRESS);
|
||||
Wire.setClock(100000);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (millis() - lastTime > 10000)
|
||||
{
|
||||
lastTime = millis();
|
||||
dump(20, 10, 0);
|
||||
}
|
||||
sht.read();
|
||||
uint8_t x = round(sht.getHumidity()) - 45; // adjust if needed
|
||||
uint8_t y = round(sht.getTemperature()) - 20; // adjust if needed
|
||||
// Serial.print(x);
|
||||
// Serial.print(" ");
|
||||
// Serial.print(y);
|
||||
// Serial.print("\n");
|
||||
sm.add(x, y, 1);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
void dump(uint8_t sx, uint8_t sy, uint8_t dm)
|
||||
{
|
||||
Serial.println();
|
||||
Serial.print("DUMP\t");
|
||||
|
||||
Serial.print(sm.size());
|
||||
Serial.print("\t");
|
||||
Serial.print(sm.count());
|
||||
Serial.print("\t");
|
||||
|
||||
Serial.print(sx);
|
||||
Serial.print("x");
|
||||
Serial.print(sy);
|
||||
Serial.print("\t");
|
||||
Serial.println(sm.sum());
|
||||
for (int y = 0; y < sy; y++)
|
||||
{
|
||||
for (int x = 0; x < sx; x++)
|
||||
{
|
||||
Serial.print(sm.get(x, y), dm);
|
||||
Serial.print('\t');
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
@ -2,6 +2,7 @@
|
||||
// FILE: sparse_matrix_demo.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/SparseMatrix
|
||||
|
||||
|
||||
#include "SparseMatrix.h"
|
||||
|
@ -2,6 +2,7 @@
|
||||
// FILE: sparse_matrix_max.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo max size matrix.
|
||||
// URL: https://github.com/RobTillaart/SparseMatrix
|
||||
|
||||
|
||||
#include "SparseMatrix.h"
|
||||
|
@ -0,0 +1,15 @@
|
||||
sparse_matrix_performance.ino
|
||||
|
||||
0.1.2
|
||||
20
|
||||
0
|
||||
|
||||
set 20x : 428
|
||||
redo 20x : 380
|
||||
full 20x : 532
|
||||
add 20x : 452
|
||||
get 20x : 244
|
||||
9.00
|
||||
sum 20x : 160
|
||||
clr 20x : 4
|
||||
|
@ -2,7 +2,7 @@
|
||||
// FILE: sparse_matrix_performance.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: performance measurement functions
|
||||
|
||||
// URL: https://github.com/RobTillaart/SparseMatrix
|
||||
|
||||
#include "SparseMatrix.h"
|
||||
|
||||
@ -19,6 +19,8 @@ void setup()
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
|
||||
Serial.println();
|
||||
Serial.println(SPARSEMATRIX_LIB_VERSION);
|
||||
Serial.println(sm.size());
|
||||
Serial.println(sm.count());
|
||||
Serial.println();
|
||||
|
@ -16,5 +16,5 @@ add KEYWORD2
|
||||
|
||||
# Constants (LITERAL1)
|
||||
SPARSEMATRIX_LIB_VERSION LITERAL1
|
||||
|
||||
SPARSEMATRIX_MAX_SIZE LITERAL1
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/SparseMatrix.git"
|
||||
},
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=SparseMatrix
|
||||
version=0.1.1
|
||||
version=0.1.2
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for sparse matrices.
|
||||
|
@ -38,11 +38,20 @@ unittest_teardown()
|
||||
}
|
||||
|
||||
|
||||
unittest(test_constants)
|
||||
{
|
||||
assertEqual(1000, SPARSEMATRIX_MAX_SIZE);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_constructor)
|
||||
{
|
||||
SparseMatrix sm(10);
|
||||
assertEqual(10, sm.size());
|
||||
assertEqual(0, sm.count());
|
||||
|
||||
SparseMatrix sm2(1100);
|
||||
assertEqual(1000, sm2.size());
|
||||
}
|
||||
|
||||
|
||||
@ -57,7 +66,7 @@ unittest(test_set)
|
||||
assertTrue(sm.set(3, 4, 5));
|
||||
assertFalse(sm.set(5, 4, 5)); // don't fit any more...
|
||||
|
||||
// do not set new element to zero
|
||||
// do not set new element to zero
|
||||
sm.clear();
|
||||
assertEqual(0, sm.count());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user