+ version 0.1.06

+ dynamic internal buffers
+ replace sorted buffer with "indirection buffer"
+ bubble sort + flag (faster)
This commit is contained in:
Rob Tillaart 2013-10-19 15:55:43 +02:00
parent 28b1b43b2a
commit ff52d49117
3 changed files with 21 additions and 71 deletions

View File

@ -11,7 +11,7 @@
// 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
// 0.1.05 - 2013-10-18 fixed bug in sort; removes default constructor; dynamic memory
// 0.1.06 - 2013-10-19 faster sort? more dyn test.
// 0.1.06 - 2013-10-19 faster sort, dynamic arrays, replaced sorted float array with indirection array
//
// Released to the public domain
//
@ -21,10 +21,10 @@
RunningMedian::RunningMedian(uint8_t size)
{
_size = constrain(size, MEDIAN_MIN_SIZE, MEDIAN_MAX_SIZE);
#ifdef RUNNING_MEDIAN_USE_MALLOC
_ar = (float *) malloc(_size * sizeof(float));
_p = (uint8_t *) malloc(size * sizeof(uint8_t));
_p = (uint8_t *) malloc(_size * sizeof(uint8_t));
#endif
clear();
@ -45,15 +45,16 @@ void RunningMedian::clear()
_idx = 0;
_sorted = false;
// for (uint8_t i=0; i< _size; i++) _p[i] = i;
for (uint8_t i=0; i< _size; i++) _p[i] = i;
}
// adds a new value to the data-set
// or overwrites the oldest if full.
void RunningMedian::add(float value)
{
_ar[_idx++] = value;
_idx++;
if (_idx >= _size) _idx = 0; // wrap around
_ar[_idx] = value;
if (_cnt < _size) _cnt++;
_sorted = false;
}
@ -64,7 +65,6 @@ float RunningMedian::getMedian()
{
if (_sorted == false) sort();
return _ar[_p[_cnt/2]];
// return _as[_cnt/2];
}
return NAN;
}
@ -74,9 +74,8 @@ float RunningMedian::getHighest()
{
if (_cnt > 0)
{
if (_sorted == false) sort();
if (_sorted == false) sort(); // assumes other fields are also retrieved otherwise inefficient
return _ar[_p[_cnt-1]];
// return _as[_cnt-1];
}
return NAN;
}
@ -87,7 +86,6 @@ float RunningMedian::getLowest()
{
if (_sorted == false) sort();
return _ar[_p[0]];
// return _as[0];
}
return NAN;
}
@ -110,9 +108,11 @@ float RunningMedian::getAverage(uint8_t nMedians)
if (_cnt < nMedians) nMedians = _cnt; // when filling the array for first time
uint8_t start = ((_cnt - nMedians)/2);
uint8_t stop = start + nMedians;
if (_sorted == false) sort();
float sum = 0;
for (uint8_t i = start; i < stop; i++) sum += _ar[_p[i]]; // _as[i];
for (uint8_t i = start; i < stop; i++) sum += _ar[_p[i]];
return sum / nMedians;
}
return NAN;
@ -125,15 +125,7 @@ uint8_t RunningMedian::getCount() { return _cnt; };
void RunningMedian::sort()
{
// Serial.print("befor:\t");
// for (uint8_t i=0; i< _cnt; i++)
// {
// Serial.print(_ar[_p[i]]);
// Serial.print('\t');
// }
// Serial.println();
// sort all
// bubble sort with flag
for (uint8_t i=0; i< _cnt-1; i++)
{
bool flag = true;
@ -149,53 +141,8 @@ void RunningMedian::sort()
}
if (flag) break;
}
// for (uint8_t i=0; i< _cnt-1; i++)
// {
// uint8_t m = i;
// for (uint8_t j=i+1; j< _cnt; j++)
// {
// if (_ar[_p[j]] < _ar[_p[m]]) m = j;
// }
// if ( m != i )
// {
// uint8_t t = _p[i];
// _p[i] = _p[m];
// _p[m] = t;
// }
// }
// Serial.print("after:\t");
// for (uint8_t i=0; i< _cnt; i++)
// {
// Serial.print(_ar[_p[i]]);
// Serial.print('\t');
// }
// Serial.println();
_sorted = true;
}
// 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];
// _as[m] = _as[i];
// _as[i] = t;
// }
// }
// _sorted = true;
// }
// END OF FILE

View File

@ -32,8 +32,9 @@
// should at least be 5 to be practical
// odd size results in a 'real' middle element.
// even size takes the lower of the two middle elements (TODO)
#define MEDIAN_MIN_SIZE 1
#define MEDIAN_MAX_SIZE 19 // can be adjusted if needed
#define MEDIAN_MAX_SIZE 19 // adjust if needed
class RunningMedian
@ -64,11 +65,9 @@ protected:
#ifdef RUNNING_MEDIAN_USE_MALLOC
float * _ar;
// float * _as;
uint8_t * _p;
#else
float _ar[MEDIAN_MAX_SIZE];
// float _as[MEDIAN_MAX_SIZE];
uint8_t _p[MEDIAN_MAX_SIZE];
#endif
void sort();

View File

@ -11,7 +11,7 @@
#include "RunningMedian.h"
RunningMedian samples = RunningMedian(15);
RunningMedian samples = RunningMedian(7);
long count = 0;
@ -29,9 +29,9 @@ void loop()
void test1()
{
if (count % 20 == 0) Serial.println(F("\nmsec \tAnR \tSize \tCnt \tLow \tAvg \tAvg(3) \tMed \tHigh"));
if (count % 20 == 0) Serial.println(F("\nmsec \tAnR \tSize \tCnt \tLow \tAvg \tAvg(7) \tAvg(3) \tMed \tHigh"));
count++;
long x = analogRead(A0);
samples.add(x);
@ -39,6 +39,7 @@ void test1()
float l = samples.getLowest();
float m = samples.getMedian();
float a = samples.getAverage();
float a7 = samples.getAverage(7);
float a3 = samples.getAverage(3);
float h = samples.getHighest();
int s = samples.getSize();
@ -56,6 +57,8 @@ void test1()
Serial.print('\t');
Serial.print(a, 2);
Serial.print('\t');
Serial.print(a7, 2);
Serial.print('\t');
Serial.print(a3, 2);
Serial.print('\t');
Serial.print(m);
@ -64,3 +67,4 @@ void test1()
delay(100);
}