├── .gitignore ├── LICENSE.md ├── README.md ├── examples └── AverageExample │ └── AverageExample.ino ├── keywords.txt ├── library.json ├── library.properties ├── src └── Average.h └── uecide.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Majenko Technologies 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | * Neither the name of Majenko Technologies nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Average 2 | ======= 3 | 4 | Templated class for calculating averages and statistics of data sets. 5 | -------------------------------------------------------------------------------- /examples/AverageExample/AverageExample.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Reserve space for 10 entries in the average bucket. 4 | // Change the type between < and > to change the entire way the library works. 5 | Average ave(10); 6 | 7 | void setup() { 8 | Serial.begin(9600); 9 | } 10 | 11 | void loop() { 12 | int minat = 0; 13 | int maxat = 0; 14 | 15 | // Add a new random value to the bucket 16 | ave.push(rand()); 17 | 18 | // Display the current data set 19 | for (int i = 0; i < 10; i++) { 20 | Serial.print(ave.get(i)); 21 | Serial.print(" "); 22 | } 23 | Serial.println(); 24 | 25 | // And show some interesting results. 26 | Serial.print("Mean: "); Serial.println(ave.mean()); 27 | Serial.print("Mode: "); Serial.println(ave.mode()); 28 | Serial.print("Max: "); Serial.println(ave.maximum(&maxat)); 29 | Serial.print(" at: "); Serial.println(maxat); 30 | Serial.print("Min: "); Serial.println(ave.minimum(&minat)); 31 | Serial.print(" at: "); Serial.println(minat); 32 | Serial.print("StdDev: "); Serial.println(ave.stddev()); 33 | delay(1000); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | Average KEYWORD1 2 | rolling KEYWORD2 3 | push KEYWORD2 4 | mean KEYWORD2 5 | mode KEYWORD2 6 | minimum KEYWORD2 7 | maximum KEYWORD2 8 | stddev KEYWORD2 9 | get KEYWORD2 10 | leastSquares KEYWORD2 11 | getCount KEYWORD2 12 | predict KEYWORD2 13 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Average", 3 | "keywords": "math, maths, average", 4 | "description": "Average and statictical class", 5 | "repository": 6 | { 7 | "type": "git", 8 | "url": "https://github.com/MajenkoLibraries/Average" 9 | }, 10 | "version": "1.0.17", 11 | "frameworks": "arduino", 12 | "platforms": "*" 13 | } 14 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Average 2 | version=1.2.4 3 | author=Matt Jenkins 4 | maintainer=Matt Jenkins 5 | sentence=Averaging storage array 6 | paragraph=Average\n=======\n\nTemplated class for calculating averages and statistics of data sets.\n 7 | url=https://github.com/MajenkoLibraries/Average 8 | category=Data Processing 9 | architectures=* 10 | includes=Average.h 11 | -------------------------------------------------------------------------------- /src/Average.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) , Majenko Technologies 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of Majenko Technologies nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | 32 | #ifndef _AVERAGE_H 33 | #define _AVERAGE_H 34 | 35 | #if (ARDUINO >= 100) 36 | # include 37 | #else 38 | # include 39 | #endif 40 | 41 | #include 42 | 43 | inline static float sqr(float x) { 44 | return x*x; 45 | } 46 | 47 | template class Average { 48 | private: 49 | // Private functions and variables here. They can only be accessed 50 | // by functions within the class. 51 | T *_store; 52 | T _sum; // _sum variable for faster mean calculation 53 | uint32_t _position; // _position variable for circular buffer 54 | uint32_t _count; 55 | uint32_t _size; 56 | 57 | public: 58 | // Public functions and variables. These can be accessed from 59 | // outside the class. 60 | Average(uint32_t size); 61 | ~Average(); 62 | float rolling(T entry); 63 | void push(T entry); 64 | float mean(); 65 | T mode(); 66 | T minimum(); 67 | T minimum(int *); 68 | T maximum(); 69 | T maximum(int *); 70 | float stddev(); 71 | T get(uint32_t); 72 | void leastSquares(float &m, float &b, float &r); 73 | int getCount(); 74 | T predict(int x); 75 | T sum(); 76 | void clear(); 77 | Average &operator=(Average &a); 78 | 79 | }; 80 | 81 | template int Average::getCount() { 82 | return _count; 83 | } 84 | 85 | template Average::Average(uint32_t size) { 86 | _size = size; 87 | _count = 0; 88 | _store = (T *)malloc(sizeof(T) * size); 89 | _position = 0; // track position for circular storage 90 | _sum = 0; // track sum for fast mean calculation 91 | for (uint32_t i = 0; i < size; i++) { 92 | _store[i] = 0; 93 | } 94 | } 95 | 96 | template Average::~Average() { 97 | free(_store); 98 | } 99 | 100 | template void Average::push(T entry) { 101 | if (_count < _size) { // adding new values to array 102 | _count++; // count number of values in array 103 | } else { // overwriting old values 104 | _sum = _sum -_store[_position]; // remove old value from _sum 105 | } 106 | _store[_position] = entry; // store new value in array 107 | _sum += entry; // add the new value to _sum 108 | _position += 1; // increment the position counter 109 | if (_position >= _size) _position = 0; // loop the position counter 110 | } 111 | 112 | 113 | template float Average::rolling(T entry) { 114 | push(entry); 115 | return mean(); 116 | } 117 | 118 | template float Average::mean() { 119 | if (_count == 0) { 120 | return 0; 121 | } 122 | return ((float)_sum / (float)_count); // mean calculation based on _sum 123 | } 124 | 125 | template T Average::mode() { 126 | uint32_t pos; 127 | uint32_t inner; 128 | T most; 129 | uint32_t mostcount; 130 | T current; 131 | uint32_t currentcount; 132 | 133 | if (_count == 0) { 134 | return 0; 135 | } 136 | 137 | most = get(0); 138 | mostcount = 1; 139 | for(pos = 0; pos < _count; pos++) { 140 | current = get(pos); 141 | currentcount = 1; 142 | for(inner = pos + 1; inner < _count; inner++) { 143 | if(get(inner) == current) { 144 | currentcount++; 145 | } 146 | } 147 | if(currentcount > mostcount) { 148 | most = current; 149 | mostcount = currentcount; 150 | } 151 | // If we have less array slices left than the current 152 | // maximum count, then there is no room left to find 153 | // a bigger count. We have finished early and we can 154 | // go home. 155 | if(_count - pos < mostcount) { 156 | break; 157 | } 158 | } 159 | return most; 160 | } 161 | 162 | template T Average::minimum() { 163 | return minimum(NULL); 164 | } 165 | 166 | template T Average::minimum(int *index) { 167 | T minval; 168 | 169 | if (index != NULL) { 170 | *index = 0; 171 | } 172 | 173 | if (_count == 0) { 174 | return 0; 175 | } 176 | 177 | minval = get(0); 178 | 179 | for(uint32_t i = 0; i < _count; i++) { 180 | if(get(i) < minval) { 181 | minval = get(i); 182 | if (index != NULL) { 183 | *index = i; 184 | } 185 | } 186 | } 187 | return minval; 188 | } 189 | 190 | template T Average::maximum() { 191 | return maximum(NULL); 192 | } 193 | 194 | template T Average::maximum(int *index) { 195 | T maxval; 196 | 197 | if (index != NULL) { 198 | *index = 0; 199 | } 200 | 201 | if (_count == 0) { 202 | return 0; 203 | } 204 | 205 | maxval = get(0); 206 | 207 | for(uint32_t i = 0; i < _count; i++) { 208 | if(get(i) > maxval) { 209 | maxval = get(i); 210 | if (index != NULL) { 211 | *index = i; 212 | } 213 | } 214 | } 215 | return maxval; 216 | } 217 | 218 | template float Average::stddev() { 219 | float square; 220 | float sum; 221 | float mu; 222 | float theta; 223 | 224 | if (_count == 0) { 225 | return 0; 226 | } 227 | 228 | mu = mean(); 229 | 230 | sum = 0; 231 | for(uint32_t i = 0; i < _count; i++) { 232 | theta = mu - (float)get(i); 233 | square = theta * theta; 234 | sum += square; 235 | } 236 | return sqrt(sum/(float)_count); 237 | } 238 | 239 | template T Average::get(uint32_t index) { 240 | if (index >= _count) { 241 | return -1; 242 | } 243 | 244 | int32_t start = _position - _count; 245 | if (start < 0) start += _size; 246 | uint32_t cindex = start + index; 247 | if (cindex >= _size) cindex -= _size; 248 | return _store[cindex]; 249 | } 250 | 251 | template void Average::leastSquares(float &m, float &c, float &r) { 252 | float sumx = 0.0; /* sum of x */ 253 | float sumx2 = 0.0; /* sum of x**2 */ 254 | float sumxy = 0.0; /* sum of x * y */ 255 | float sumy = 0.0; /* sum of y */ 256 | float sumy2 = 0.0; /* sum of y**2 */ 257 | 258 | for (uint32_t i=0;i<_count;i++) { 259 | sumx += i; 260 | sumx2 += sqr(i); 261 | sumxy += i * get(i); 262 | sumy += get(i); 263 | sumy2 += sqr(get(i)); 264 | } 265 | 266 | float denom = (_count * sumx2 - sqr(sumx)); 267 | if (denom == 0) { 268 | // singular matrix. can't solve the problem. 269 | m = 0; 270 | c = 0; 271 | r = 0; 272 | return; 273 | } 274 | 275 | m = 0 - (_count * sumxy - sumx * sumy) / denom; 276 | c = (sumy * sumx2 - sumx * sumxy) / denom; 277 | r = (sumxy - sumx * sumy / _count) / sqrt((sumx2 - sqr(sumx)/_count) * (sumy2 - sqr(sumy)/_count)); 278 | } 279 | 280 | template T Average::predict(int x) { 281 | float m, c, r; 282 | leastSquares(m, c, r); // y = mx + c; 283 | 284 | T y = m * x + c; 285 | return y; 286 | } 287 | 288 | // Return the sum of all the array items 289 | template T Average::sum() { 290 | return _sum; 291 | } 292 | 293 | template void Average::clear() { 294 | _count = 0; 295 | _sum = 0; 296 | _position = 0; 297 | } 298 | 299 | template Average &Average::operator=(Average &a) { 300 | clear(); 301 | for (int i = 0; i < _size; i++) { 302 | push(a.get(i)); 303 | } 304 | return *this; 305 | } 306 | 307 | #endif 308 | -------------------------------------------------------------------------------- /uecide.json: -------------------------------------------------------------------------------- 1 | {"name":"Average","provides":"Average.h","license":"LICENSE.md","readme":"README.md","description":"Averaging storage array","category":"Math","subcategory":"Algorithms","maintainer":"Matt Jenkins ","version":"1.2.4","family":"all","core":"all","install":{"examples":"\/","keywords.txt":"\/","library.properties":"\/","src":"\/"}} --------------------------------------------------------------------------------