Skip to content

Commit 54c9c28

Browse files
committed
0.1.0 SparseArray
1 parent 081e744 commit 54c9c28

File tree

16 files changed

+917
-0
lines changed

16 files changed

+917
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
compile:
2+
# Choosing to run compilation tests on 2 different Arduino platforms
3+
platforms:
4+
- uno
5+
# - due
6+
# - zero
7+
# - leonardo
8+
- m4
9+
- esp32
10+
- esp8266
11+
# - mega2560
12+
libraries:
13+
- "SHT85"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
name: Arduino-lint
3+
4+
on: [push, pull_request]
5+
jobs:
6+
lint:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v2
10+
- uses: arduino/arduino-lint-action@v1
11+
with:
12+
library-manager: update
13+
compliance: strict
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
name: Arduino CI
3+
4+
on: [push, pull_request]
5+
6+
jobs:
7+
runTest:
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- uses: actions/checkout@v2
12+
- uses: ruby/setup-ruby@v1
13+
with:
14+
ruby-version: 2.6
15+
- run: |
16+
gem install arduino_ci
17+
arduino_ci.rb
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: JSON check
2+
3+
on:
4+
push:
5+
paths:
6+
- '**.json'
7+
pull_request:
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v2
14+
- name: json-syntax-check
15+
uses: limitusus/json-syntax-check@v1
16+
with:
17+
pattern: "\\.json$"
18+

libraries/SparseArray/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022-2022 Rob Tillaart
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

libraries/SparseArray/README.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
2+
[![Arduino CI](https://github.com/RobTillaart/SparseArray/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
3+
[![Arduino-lint](https://github.com/RobTillaart/SparseArray/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/SparseArray/actions/workflows/arduino-lint.yml)
4+
[![JSON check](https://github.com/RobTillaart/SparseArray/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/SparseArray/actions/workflows/jsoncheck.yml)
5+
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/SparseArray/blob/master/LICENSE)
6+
[![GitHub release](https://img.shields.io/github/release/RobTillaart/SparseArray.svg?maxAge=3600)](https://github.com/RobTillaart/SparseArray/releases)
7+
8+
9+
# SparseArray
10+
11+
Arduino library for sparse arrays of floats.
12+
13+
14+
TODO REDO DOCUMENTATION.
15+
16+
17+
## Description
18+
19+
SparseArray is an **experimental** library to implement a one
20+
dimensional sparse array of floats (a.k.a. vector) on an Arduino.
21+
A sparse array is a mn array with mostly zeros and a low percentage
22+
non-zero values.
23+
The purpose of this library is efficient storage in memory.
24+
25+
The maximum array that can be represented is 65535 elements
26+
with a theoretical maximum of 65535 non-zero elements.
27+
(although that does not make sense due to overhead)
28+
In practice the library limits this to 1000 non-zero elements.
29+
Note: 255 elements would still fit in an UNO's 2K memory.
30+
31+
Relates to:
32+
- https://github.com/RobTillaart/SparseMatrix
33+
- https://github.com/RobTillaart/distanceTable
34+
35+
Note: this library is derived from SparseMatrix.
36+
37+
38+
#### Implementation
39+
40+
The implementation is based on 2 arrays holding ``` x, value```
41+
where value is float, and x is an uint16_t.
42+
That are 6 bytes per element.
43+
The number of elements that the sparse array object can hold are
44+
given as parameter to the constructor.
45+
If the space cannot be allocated the size is set to zero.
46+
47+
In the future other data types should be possible.
48+
49+
50+
#### Performance
51+
52+
The elements are not kept sorted or indexed so optimizations might be
53+
possible but are not investigated yet.
54+
There is however a test sketch to monitor the performance of
55+
the most important functions.
56+
57+
Accessing elements internally is done with a linear search,
58+
which becomes (much) slower if the number of elements is increasing.
59+
This means that although in theory there can be 65535 elements,
60+
in practice a few 100 can already become annoyingly slow.
61+
To keep performance a bit the library has a limit build in.
62+
Check the .h file for **SPARSEARRAY_MAX_SIZE 1000**
63+
64+
65+
## Interface
66+
67+
```cpp
68+
#include "SparseArray.h"
69+
```
70+
71+
### Constructor + meta
72+
73+
- **SparseArray(uint16_t size)** constructor.
74+
Parameter is the maximum number of elements in the sparse array.
75+
Note this number is limited to **SPARSEARRAY_MAX_SIZE 1000**.
76+
If the space requested cannot be allocated size will be set to 0.
77+
- **uint16_t size()** maximum number of elements.
78+
If this is zero, a problem occurred with allocation happened.
79+
- **uint16_t count()** current number of elements in the array.
80+
Should be between 0 and size.
81+
- **float sum()** sum of all elements ( != 0 ) in the array.
82+
- **void clear()** resets the array to all zero's again.
83+
84+
85+
### Access
86+
87+
- **bool set(uint16_t x, float value)** gives an element in the array a value.
88+
If the value is set to zero, it is removed from the internal store.
89+
Returns false if the internal store is full, true otherwise.
90+
- **float get(uint16_t x)** returns a value from the array.
91+
- **bool add(uint16_t x, float value)** adds value to an element in the array.
92+
If needed a new internal element is created.
93+
If the sum is zero, the element is removed from the internal store.
94+
Returns false if the internal store is full, true otherwise.
95+
- **void boundingSegment(uint16_t &minX, uint16_t &maxX)**
96+
Returns the bounding box in which all values != 0 are located.
97+
This can be useful for printing or processing the non zero elements.
98+
99+
100+
## Future
101+
102+
- documentation
103+
- test
104+
- keep in sync with SparseMatrix where possible
105+
- merge into one class hierarchy?
106+
- dump should be in the class?
107+
- or as static function...
108+
- stream as param dump(Stream str, ...
109+
110+
#### ideas
111+
112+
- array { uint32_t, float }; for logging millis/micros + measurement
113+
delta coding of time stamp? if it fit in 16 bit?
114+
=> sounds like a class on its own.
115+
116+
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
//
2+
// FILE: SparseArray.cpp
3+
// AUTHOR: Rob Tillaart
4+
// VERSION: 0.1.0
5+
// DATE: 2022-07-17
6+
// PURPOSE: Arduino library for sparse arrays of floats
7+
// URL: https://github.com/RobTillaart/SparseArray
8+
//
9+
// HISTORY:
10+
// 0.1.0 2022-07-17 initial version
11+
// derives from SparseMatrix
12+
13+
14+
15+
#include "SparseArray.h"
16+
17+
18+
SparseArray::SparseArray(uint16_t sz)
19+
{
20+
_count = 0;
21+
_size = sz;
22+
if ( _size > SPARSEARRAY_MAX_SIZE)
23+
{
24+
_size = SPARSEARRAY_MAX_SIZE;
25+
}
26+
_x = (uint16_t *) malloc(sz * sizeof(uint16_t));
27+
_value = (float *) malloc(sz * sizeof(float));
28+
// catch malloc error
29+
if (_x && _value) return;
30+
// if malloc error set size to zero.
31+
_size = 0;
32+
}
33+
34+
35+
SparseArray::~SparseArray()
36+
{
37+
if (_x) free(_x);
38+
if (_value) free(_value);
39+
}
40+
41+
42+
uint16_t SparseArray::size()
43+
{
44+
return _size;
45+
}
46+
47+
48+
uint16_t SparseArray::count()
49+
{
50+
return _count;
51+
}
52+
53+
54+
void SparseArray::clear()
55+
{
56+
_count = 0;
57+
}
58+
59+
60+
float SparseArray::sum()
61+
{
62+
float _sum = 0;
63+
for (uint16_t i = 0; i < _count; i++)
64+
{
65+
_sum += _value[i];
66+
}
67+
return _sum;
68+
}
69+
70+
71+
bool SparseArray::set(uint16_t x, float value)
72+
{
73+
int32_t pos = findPos(x);
74+
// existing element
75+
if (pos > -1)
76+
{
77+
_value[pos] = value;
78+
if (_value[pos] == 0.0) removeElement(pos);
79+
return true;
80+
}
81+
82+
// does not exist => new element ?
83+
return newElement(x, value);
84+
}
85+
86+
87+
bool SparseArray::add(uint16_t x, float value)
88+
{
89+
int32_t pos = findPos(x);
90+
// existing element
91+
if (pos > -1)
92+
{
93+
_value[pos] += value;
94+
if (_value[pos] == 0.0) removeElement(pos);
95+
return true;
96+
}
97+
98+
// does not exist => new element ?
99+
return newElement(x, value);
100+
}
101+
102+
103+
float SparseArray::get(uint16_t x)
104+
{
105+
int32_t pos = findPos(x);
106+
if (pos > -1)
107+
{
108+
return _value[pos];
109+
}
110+
return 0;
111+
}
112+
113+
114+
void SparseArray::boundingSegment(uint16_t &minX, uint16_t &maxX)
115+
{
116+
uint16_t _minx = 65535, _maxx = 0;
117+
for (uint16_t i = 0; i < _count; i++)
118+
{
119+
if (_x[i] < _minx) _minx = _x[i];
120+
if (_x[i] > _maxx) _maxx = _x[i];
121+
}
122+
minX = _minx;
123+
maxX = _maxx;
124+
}
125+
126+
127+
//////////////////////////////////////////////////////
128+
//
129+
// PRIVATE
130+
//
131+
int32_t SparseArray::findPos(uint16_t x)
132+
{
133+
// linear search - not optimized.
134+
for (uint16_t i = 0; i < _count; i++)
135+
{
136+
if (_x[i] == x)
137+
{
138+
return (int32_t)i;
139+
}
140+
}
141+
return -1;
142+
}
143+
144+
145+
void SparseArray::removeElement(uint16_t pos)
146+
{
147+
_count--;
148+
// move last element
149+
// efficiency (keep sorted) is no requirement.
150+
if (pos == _count) return;
151+
_x[pos] = _x[_count];
152+
_value[pos] = _value[_count];
153+
}
154+
155+
156+
bool SparseArray::newElement(uint16_t x, float value)
157+
{
158+
if (value == 0.0) return true;
159+
if (_count >= _size) return false;
160+
_x[_count] = x;
161+
_value[_count] = value;
162+
_count++;
163+
return true;
164+
}
165+
166+
167+
// -- END OF FILE --
168+

0 commit comments

Comments
 (0)