diff --git a/libraries/SparseMatrix/README.md b/libraries/SparseMatrix/README.md index f004d3d6..6edc7b48 100644 --- a/libraries/SparseMatrix/README.md +++ b/libraries/SparseMatrix/README.md @@ -88,6 +88,9 @@ Returns false if the internal store is full, true otherwise. 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. +- **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. ## Future @@ -101,14 +104,19 @@ Returns false if the internal store is full, true otherwise. - investigate performance optimizations - sort - linked list, tree, hashing? -- can **set()** and **add()** be merged? #### Functions - walk through the elements? - - first() -> next(); optional last() -> prev(). - + - 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); + - returns false if there is no element anymore + - if count = 0 or current == -1 or end of list. + #### won't diff --git a/libraries/SparseMatrix/SparseMatrix.cpp b/libraries/SparseMatrix/SparseMatrix.cpp index 17179252..0231eb53 100644 --- a/libraries/SparseMatrix/SparseMatrix.cpp +++ b/libraries/SparseMatrix/SparseMatrix.cpp @@ -1,7 +1,7 @@ // // FILE: SparseMatrix.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.2 +// VERSION: 0.1.3 // DATE: 2022-07-12 // PURPOSE: Arduino library for sparse matrices // URL: https://github.com/RobTillaart/SparseMatrix @@ -14,6 +14,9 @@ // 0.1.2 2022-07-14 increase size to uint16_t // add SPARSEMATRIX_MAX_SIZE // improve documentation +// 0.1.3 2022-07-16 add boundingBox(...) +// fix #4 set() add() + #include "SparseMatrix.h" @@ -80,33 +83,13 @@ bool SparseMatrix::set(uint8_t x, uint8_t y, float value) // existing element if (pos > -1) { - if (value != 0.0) - { - _value[pos] = value; - } - else - { - _count--; - // move last element - // efficiency is not a requirement yet. - if (_count > 0) - { - _x[pos] = _x[_count]; - _y[pos] = _y[_count]; - _value[pos] = _value[_count]; - } - } + _value[pos] = value; + if (_value[pos] == 0.0) removeElement(pos); return true; } // does not exist => new element ? - if (value == 0) return true; - if (_count >= _size) return false; - _x[_count] = x; - _y[_count] = y; - _value[_count] = value; - _count++; - return true; + return newElement(x, y, value); } @@ -117,29 +100,12 @@ bool SparseMatrix::add(uint8_t x, uint8_t y, float value) if (pos > -1) { _value[pos] += value; - if (_value[pos] == 0.0) - { - _count--; - // move last element - // efficiency is not a requirement yet. - if (_count > 0) - { - _x[pos] = _x[_count]; - _y[pos] = _y[_count]; - _value[pos] = _value[_count]; - } - } + if (_value[pos] == 0.0) removeElement(pos); return true; } // does not exist => new element ? - if (value == 0) return true; - if (_count >= _size) return false; - _x[_count] = x; - _y[_count] = y; - _value[_count] = value; - _count++; - return true; + return newElement(x, y, value); } @@ -154,6 +120,24 @@ float SparseMatrix::get(uint8_t x, uint8_t y) } +void SparseMatrix::boundingBox(uint8_t &minX, uint8_t &maxX, uint8_t &minY, uint8_t &maxY) +{ + uint8_t _minx = 255, _maxx = 0, + _miny = 255, _maxy = 0; + for (uint16_t i = 0; i < _count; i++) + { + if (_x[i] < _minx) _minx = _x[i]; + if (_x[i] > _maxx) _maxx = _x[i]; + if (_y[i] < _miny) _miny = _y[i]; + if (_y[i] > _maxy) _maxy = _y[i]; + } + minX = _minx; + maxX = _maxx; + minY = _miny; + maxY = _maxy; +} + + ////////////////////////////////////////////////////// // // PRIVATE @@ -172,6 +156,29 @@ int32_t SparseMatrix::findPos(uint8_t x, uint8_t y) } +void SparseMatrix::removeElement(uint16_t pos) +{ + _count--; + // move last element + // efficiency (keep sorted) is no requirement. + if (pos == _count) return; + _x[pos] = _x[_count]; + _y[pos] = _y[_count]; + _value[pos] = _value[_count]; +} + + +bool SparseMatrix::newElement(uint8_t x, uint8_t y, float value) +{ + if (value == 0.0) return true; + if (_count >= _size) return false; + _x[_count] = x; + _y[_count] = y; + _value[_count] = value; + _count++; + return true; +} + // -- END OF FILE -- diff --git a/libraries/SparseMatrix/SparseMatrix.h b/libraries/SparseMatrix/SparseMatrix.h index b2e61b87..33277b38 100644 --- a/libraries/SparseMatrix/SparseMatrix.h +++ b/libraries/SparseMatrix/SparseMatrix.h @@ -2,7 +2,7 @@ // // FILE: SparseMatrix.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.2 +// VERSION: 0.1.3 // DATE: 2022-07-12 // PURPOSE: Arduino library for sparse matrices // URL: https://github.com/RobTillaart/SparseMatrix @@ -11,7 +11,7 @@ #include "Arduino.h" -#define SPARSEMATRIX_LIB_VERSION (F("0.1.2")) +#define SPARSEMATRIX_LIB_VERSION (F("0.1.3")) #ifndef SPARSEMATRIX_MAX_SIZE #define SPARSEMATRIX_MAX_SIZE 1000 @@ -38,6 +38,10 @@ public: float get(uint8_t x, uint8_t y); + // returns four sides between all values != 0 are located. + void boundingBox(uint8_t &minX, uint8_t &maxX, uint8_t &minY, uint8_t &maxY); + + private: uint16_t _size = 0; uint16_t _count = 0; @@ -49,6 +53,12 @@ private: // returns index of x, y if in set // otherwise -1 int32_t findPos(uint8_t x, uint8_t y); + + // removes element at pos (from findPos) + // pre: count > 0 + void removeElement(uint16_t pos); + // creates a new element if value != 0 and if there is room + bool newElement(uint8_t x, uint8_t y, float value); }; diff --git a/libraries/SparseMatrix/examples/sparse_matrix_boundingBox/sparse_matrix_boundingBox.ino b/libraries/SparseMatrix/examples/sparse_matrix_boundingBox/sparse_matrix_boundingBox.ino new file mode 100644 index 00000000..baa3c5d3 --- /dev/null +++ b/libraries/SparseMatrix/examples/sparse_matrix_boundingBox/sparse_matrix_boundingBox.ino @@ -0,0 +1,79 @@ +// +// FILE: sparse_matrix_boundingBox.ino +// AUTHOR: Rob Tillaart +// PURPOSE: demo +// URL: https://github.com/RobTillaart/SparseMatrix + + +#include "SparseMatrix.h" + + +SparseMatrix sm(10); + + +void setup() +{ + Serial.begin(115200); + Serial.println(); + Serial.println(__FILE__); + Serial.println(); + + // 10 x 10 matrix - 6 random elements in the middle + for (int i = 0; i < 6; i++) + { + uint8_t x = random(5) + 3; + uint8_t y = random(5) + 3; + sm.set(x, y, random(37)); + } + dump(10, 10); + + uint8_t minX, maxX, minY, maxY; + sm.boundingBox(minX, maxX, minY, maxY); + + Serial.println("\tBounding Box"); + Serial.print("\t"); + Serial.print(minX); + Serial.print("\t"); + Serial.print(maxX); + Serial.print("\t"); + Serial.print(minY); + Serial.print("\t"); + Serial.print(maxY); + Serial.println(); +} + + +void loop() +{ +} + + +void dump(uint8_t sx, uint8_t sy) +{ + 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)); + Serial.print('\t'); + } + Serial.println(); + } + Serial.println(); +} + + +// -- END OF FILE -- diff --git a/libraries/SparseMatrix/examples/sparse_matrix_performance/performance_0.1.3.txt b/libraries/SparseMatrix/examples/sparse_matrix_performance/performance_0.1.3.txt new file mode 100644 index 00000000..7842e02e --- /dev/null +++ b/libraries/SparseMatrix/examples/sparse_matrix_performance/performance_0.1.3.txt @@ -0,0 +1,15 @@ +sparse_matrix_performance.ino + +0.1.3 +20 +0 + +set 20x : 428 +redo 20x : 380 +full 20x : 528 +add 20x : 452 +get 20x : 244 +9.00 +sum 20x : 164 +clr 20x : 4 + diff --git a/libraries/SparseMatrix/library.json b/libraries/SparseMatrix/library.json index 4b503d4a..a05ee48c 100644 --- a/libraries/SparseMatrix/library.json +++ b/libraries/SparseMatrix/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/SparseMatrix.git" }, - "version": "0.1.2", + "version": "0.1.3", "license": "MIT", "frameworks": "arduino", "platforms": "*", diff --git a/libraries/SparseMatrix/library.properties b/libraries/SparseMatrix/library.properties index 4096cf64..98813e69 100644 --- a/libraries/SparseMatrix/library.properties +++ b/libraries/SparseMatrix/library.properties @@ -1,5 +1,5 @@ name=SparseMatrix -version=0.1.2 +version=0.1.3 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library for sparse matrices. diff --git a/libraries/SparseMatrix/test/unit_test_001.cpp b/libraries/SparseMatrix/test/unit_test_001.cpp index b5e3f9de..900823fe 100644 --- a/libraries/SparseMatrix/test/unit_test_001.cpp +++ b/libraries/SparseMatrix/test/unit_test_001.cpp @@ -119,6 +119,26 @@ unittest(test_add) } +unittest(test_boundix_box) +{ + SparseMatrix sm(10); + // 10 x 10 matrix - 6 random elements in the middle + for (int i = 0; i < 6; i++) + { + uint8_t x = random(5) + 3; + uint8_t y = random(5) + 3; + sm.set(x, y, random(37)); + } + // random generator does not work + // assertEqual(6, sm.count()); + assertEqual(1, sm.count()); + + uint8_t minX, maxX, minY, maxY; + sm.boundingBox(minX, maxX, minY, maxY); + fprintf(stderr, "%d\t%d\t%d\t%d\n", minX, maxX, minY, maxY); +} + + unittest_main()