#include #include #include #include #include // ////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////// float Stats::stddev() const { return sqrt(var()); } float Stats::normalize(float value) const { return ( value - mean() ) / (stddev() + FLT_MIN); } SimpleStats::SimpleStats(float startMean, float startVar) { reset(startMean, startVar); } void SimpleStats::reset(float startMean, float startVar) { _mean = startMean; _mean2 = startVar + sq(_mean); _nSamples = 0; // _min = FLT_MAX; // _max = -FLT_MAX; } float SimpleStats::update(float value) { if (_nSamples == ULONG_MAX) _nSamples = (ULONG_MAX / 4) * 3; // simple trick that makes sure we don't overflow // Add one to number of samples _nSamples++; // Update mean and mean2 float prop = (float)(_nSamples-1) / (float)_nSamples; _mean = _mean * prop + value / _nSamples; _mean2 = _mean2 * prop + sq(value) / _nSamples; // Update min and max // _min = min(_min, value); // _max = max(_max, value); return normalize(value); } float SimpleStats::var() const { float v = (_mean2 - sq(_mean)); return max(v, (float)0); // make sure the result is >= 0 } // ////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////// MovingAverage::MovingAverage(float alphaOrN) : _value(0.5f) { setAlphaOrN(alphaOrN); reset(); } MovingAverage::MovingAverage(float alphaOrN, float startValue) : _value(startValue) { setAlphaOrN(alphaOrN); } void MovingAverage::setAlphaOrN(float alphaOrN) { alphaOrN = max(alphaOrN, 0); // make sure factor >= 0 _alpha = (alphaOrN > 1 ? 2 / (alphaOrN + 1) : alphaOrN); } void MovingAverage::reset() { _setStarted(false); } void MovingAverage::reset(float startValue) { _value = startValue; _setStarted(true); } float MovingAverage::update(float v) { if (!isStarted()) { _value = v; _setStarted(true); // start return _value; } else return (_value -= _alpha * (_value - v)); } bool MovingAverage::isStarted() const { return _alpha >= 0; } void MovingAverage::_setStarted(bool start) { _alpha = (start ? +1 : -1) * abs(_alpha); } MovingStats::MovingStats(float alphaOrN) : avg(alphaOrN) { } MovingStats::MovingStats(float alphaOrN, float startMean, float startVar) : avg(alphaOrN, startMean), _var(startVar) { reset(startMean, startVar); } void MovingStats::reset() { avg.reset(); _var = 0; } void MovingStats::reset(float startMean, float startVar) { avg.reset(startMean); _var = startVar; } float MovingStats::update(float value) { avg.update(value); if (!isStarted()) _var = 0; else { float diff = value - avg.get(); _var -= avg.alpha() * (_var - sq(diff)); } return normalize(value); } bool MovingStats::isStarted() const { return avg.isStarted(); } // ////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////// AdaptiveNormalizer::AdaptiveNormalizer(float smoothFactor) : MovingStats(smoothFactor), _value(0.5f), _mean(0.5f), _stddev(0.25f) {} AdaptiveNormalizer::AdaptiveNormalizer(float mean, float stddev, float smoothFactor) : MovingStats(smoothFactor), _value(mean), _mean(mean), _stddev(abs(stddev)) {} float AdaptiveNormalizer::put(float value) { return (_value = MovingStats::update(value) * _stddev + _mean); } Normalizer::Normalizer() : SimpleStats(), _value(0.5f), _mean(0.5f), _stddev(0.25f) {} Normalizer::Normalizer(float mean, float stddev) : SimpleStats(), _value(mean), _mean(mean), _stddev(abs(stddev)) {} float Normalizer::put(float value) { return (_value = SimpleStats::update(value) * _stddev + _mean); } MinMaxScaler::MinMaxScaler() : _value(0.5f), _minValue(FLT_MAX), _maxValue(FLT_MIN) {} float MinMaxScaler::put(float value) { _minValue = min(value, _minValue); _maxValue = max(value, _maxValue); _value = (_minValue == _maxValue ? 0.5f : map(value, _minValue, _maxValue, 0.0f, 1.0f)); return _value; }