-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRunningMedian.cpp
136 lines (122 loc) · 2.82 KB
/
RunningMedian.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//
// FILE: RunningMedian.cpp
// AUTHOR: Rob dot Tillaart at gmail dot com
// VERSION: 0.1.04.waspmote
// PURPOSE: RunningMedian library for Arduino
//
// HISTORY:
// 0.1.00 - 2011-02-16 initial version
// 0.1.01 - 2011-02-22 added remarks from CodingBadly
// 0.1.02 - 2012-03-15 added
// 0.1.03 - 2013-09-30 added _sorted flag, minor refactor
// 0.1.04 - 2013-10-17 added getAverage(uint8_t) - kudo's to Sembazuru
// 2017-10-20 minor changes in .h file to support Libelium Waspmote
//
// Released to the public domain
//
#include "RunningMedian.h"
RunningMedian::RunningMedian(uint8_t size)
{
_size = constrain(size, MEDIAN_MIN_SIZE, MEDIAN_MAX_SIZE);
// array's could be allocated by malloc here,
// but using fixed size is easier.
clear();
}
RunningMedian::RunningMedian()
{
_size = MEDIAN_DEF_SIZE;
clear();
}
// resets all counters
void RunningMedian::clear()
{
_cnt = 0;
_idx = 0;
_sorted = false;
}
// adds a new value to the data-set
// or overwrites the oldest if full.
void RunningMedian::add(float value)
{
_ar[_idx++] = value;
if (_idx >= _size) _idx = 0; // wrap around
if (_cnt < _size) _cnt++;
_sorted = false;
}
float RunningMedian::getMedian()
{
if (_cnt > 0)
{
if (_sorted == false) sort();
return _as[_cnt/2];
}
return NAN;
}
#ifdef RUNNING_MEDIAN_ALL
float RunningMedian::getHighest()
{
if (_cnt > 0)
{
if (_sorted == false) sort();
return _as[_cnt-1];
}
return NAN;
}
float RunningMedian::getLowest()
{
if (_cnt > 0)
{
if (_sorted == false) sort();
return _as[0];
}
return NAN;
}
float RunningMedian::getAverage()
{
if (_cnt > 0)
{
float sum = 0;
for (uint8_t i=0; i< _cnt; i++) sum += _ar[i];
return sum / _cnt;
}
return NAN;
}
float RunningMedian::getAverage(uint8_t nMedians)
{
if ((_cnt > 0) && (nMedians > 0))
{
if (_cnt < nMedians) nMedians = _cnt; // when filling the array for first time
uint8_t start = ((_cnt - nMedians)/2);
uint8_t stop = start + nMedians;
sort();
float sum = 0;
for (uint8_t i = start; i < stop; i++) sum += _as[i];
return sum / nMedians;
}
return NAN;
}
uint8_t RunningMedian::getSize() { return _size; };
uint8_t RunningMedian::getCount() { return _cnt; };
#endif
void RunningMedian::sort()
{
// copy
for (uint8_t i=0; i< _cnt; i++) _as[i] = _ar[i];
// sort all
for (uint8_t i=0; i< _cnt-1; i++)
{
uint8_t m = i;
for (uint8_t j=i+1; j< _cnt; j++)
{
if (_as[j] < _as[m]) m = j;
}
if (m != i)
{
float t = _as[m]; // PATCH from 0.1.05 (was long)
_as[m] = _as[i];
_as[i] = t;
}
}
_sorted = true;
}
// END OF FILE