Templated class for calculating averages and statistics of data sets. Original code is here: https://github.com/MajenkoLibraries/Average

Committer:
smartsystemdesign
Date:
Tue Oct 18 21:10:34 2016 +0000
Revision:
1:eb5616b13885
Parent:
0:f44fc7f90e31
Added license

Who changed what in which revision?

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