@leaveye
2022-03-22T06:10:10.000000Z
字数 1718
阅读 318
代码
样本
速度
class SpeedEstimator {
constexpr static const float epsilon = 1E-24;
constexpr static const float duration_default_multiplier = 50;
using timeValue = uint64_t;
public:
SpeedEstimator() : SpeedEstimator(0) {}
explicit SpeedEstimator(timeValue now, timeValue interval = 20, timeValue mean_duration = 0) {
init(now, interval, mean_duration);
}
void init(timeValue now, timeValue interval, timeValue mean_duration) {
_ts_state = now, _interval = interval;
_n = 0, _d = epsilon;
if (mean_duration != 0) _decay = 1 - interval / (float) mean_duration;
else _decay = 1 - 1 / duration_default_multiplier;
_duration = interval / (1 - _decay);
}
void reset(timeValue now) {
init(now, _interval, _duration);
}
timeValue duration() const {
return (timeValue) std::lround(_duration);
}
float avg() const {
assert(_d >= epsilon || _d <= -epsilon);
return 1000 * _n / _d;
}
void update(timeValue now, size_t size) {
update(now, (float) size);
}
void update(timeValue now, float state) {
auto period = (float) (now - _ts_state);
if (period < _interval) {
_state = state;
} else if (period < _duration + _interval * 4) {
auto stage = state / period * _interval;
while (period >= _interval) {
_d *= _decay, _d += _interval;
_n *= _decay, _n += stage;
state -= stage, period -= _interval;
}
_ts_state = now - period;
_state = state;
} else {
state *= _duration / period;
_d = _duration;
_n = state * (_duration / period);
_ts_state = now;
_state = 0;
}
}
void update(size_t size) {
update((float) size);
}
void update(float state) {
update(_ts_state + _interval, state);
}
void acc(timeValue now, ssize_t count) {
acc(now, (float) count);
}
void acc(timeValue now, float diff) {
update(now, _state + diff);
}
void acc(size_t count) {
acc((float) count);
}
void acc(float diff) {
_state += diff;
}
void accNext(size_t count) {
accNext((float) count);
}
void accNext(float diff) {
update(_state + diff);
}
protected:
float _n = 0, _d = 1E-24;
float _state = 0;
float _decay{};
timeValue _ts_state{}, _interval{};
float _duration{};
};