mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
143 lines
2.9 KiB
C++
143 lines
2.9 KiB
C++
//
|
|
// FILE: Histogram.cpp
|
|
// AUTHOR: Rob Tillaart
|
|
// VERSION: 0.1.6
|
|
// PURPOSE: Histogram library for Arduino
|
|
// DATE: 2012-11-10
|
|
//
|
|
// Released to the public domain
|
|
//
|
|
// HISTORY:
|
|
// 0.1.0 - 2012-11-10 initial version
|
|
// 0.1.1 - 2012-11-10 added PMF() and CDF()
|
|
// 0.1.2 - 2012-12-23 changed float to double; some comments
|
|
// 0.1.3 - 2013-09-29 testing a lot & refactoring
|
|
// 0.1.4 - 2015-03-06 stricter interface
|
|
// 0.1.5 - 2017-07-16 refactor, support for > 256 buckets; prevent alloc errors
|
|
// 0.1.6 - 2017-07-27 revert double to float (issue #33)
|
|
//
|
|
// Released to the public domain
|
|
//
|
|
|
|
#include "histogram.h"
|
|
|
|
Histogram::Histogram(const int16_t len, float *bounds)
|
|
{
|
|
_bounds = bounds;
|
|
_len = len + 1;
|
|
_data = (int32_t *) malloc((_len) * sizeof(int32_t));
|
|
if (_data) clear();
|
|
else _len = 0;
|
|
_cnt = 0;
|
|
}
|
|
|
|
Histogram::~Histogram()
|
|
{
|
|
if (_data) free(_data);
|
|
}
|
|
|
|
// resets all counters
|
|
void Histogram::clear()
|
|
{
|
|
for (int16_t i = 0; i < _len; i++) _data[i] = 0;
|
|
_cnt = 0;
|
|
}
|
|
|
|
// adds a new value to the histogram - increasing
|
|
void Histogram::add(const float f)
|
|
{
|
|
if (_len > 0)
|
|
{
|
|
_data[find(f)]++;
|
|
_cnt++;
|
|
}
|
|
}
|
|
|
|
// adds a new value to the histogram - decreasing
|
|
void Histogram::sub(const float f)
|
|
{
|
|
if (_len > 0)
|
|
{
|
|
_data[find(f)]--;
|
|
_cnt++;
|
|
}
|
|
}
|
|
|
|
// returns the count of a bucket
|
|
int32_t Histogram::bucket(const int16_t idx)
|
|
{
|
|
if (idx > _len) return 0;
|
|
return _data[idx];
|
|
}
|
|
|
|
// returns the relative frequency of a bucket
|
|
float Histogram::frequency(const int16_t idx)
|
|
{
|
|
if (_cnt == 0 || _len == 0) return NAN;
|
|
|
|
if (idx > _len) return 0; // diff with PMF
|
|
return (1.0 * _data[idx]) / _cnt;
|
|
}
|
|
|
|
// EXPERIMENTAL
|
|
// returns the probability of the bucket of a value
|
|
float Histogram::PMF(const float val)
|
|
{
|
|
if (_cnt == 0 || _len == 0) return NAN;
|
|
|
|
int16_t idx = find(val);
|
|
return (1.0 * _data[idx]) / _cnt;
|
|
}
|
|
|
|
// EXPERIMENTAL
|
|
// returns the cummulative probability of
|
|
// values <= value
|
|
float Histogram::CDF(const float val)
|
|
{
|
|
if (_cnt == 0 || _len == 0) return NAN;
|
|
|
|
int16_t idx = find(val);
|
|
int32_t sum = 0;
|
|
for (int16_t i = 0; i <= idx; i++)
|
|
{
|
|
sum += _data[i];
|
|
}
|
|
return (1.0 * sum) / _cnt;
|
|
}
|
|
|
|
// EXPERIMENTAL
|
|
// returns the value of the original array for
|
|
// which the CDF is at least prob.
|
|
float Histogram::VAL(const float prob)
|
|
{
|
|
if (_cnt == 0 || _len == 0) return NAN;
|
|
float p = prob;
|
|
if (p < 0.0) p = 0.0;
|
|
if (p > 1.0) p = 1.0;
|
|
|
|
float probability = p * _cnt;
|
|
int32_t sum = 0;
|
|
for (int16_t i = 0; i < _len; i++)
|
|
{
|
|
sum += _data[i];
|
|
if (sum >= probability && (i <(_len-1)) ) return _bounds[i];
|
|
}
|
|
return INFINITY;
|
|
}
|
|
|
|
// returns the bucket number for value val
|
|
int16_t Histogram::find(const float val)
|
|
{
|
|
if (_len <= 0) return -1;
|
|
|
|
for (int16_t i = 0; i < (_len-1); i++)
|
|
{
|
|
if (_bounds[i] >= val) return i;
|
|
}
|
|
return _len-1; // len?
|
|
// int16_t i = 0;
|
|
// while ((i < (_len-1)) && (_bounds[i] < val)) i++;
|
|
// return i;
|
|
}
|
|
|
|
// END OF FILE
|