123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- /*
- * Copyright 2011 The WebRTC Project Authors. All rights reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
- #ifndef RTC_BASE_ROLLING_ACCUMULATOR_H_
- #define RTC_BASE_ROLLING_ACCUMULATOR_H_
- #include <stddef.h>
- #include <algorithm>
- #include <vector>
- #include "rtc_base/checks.h"
- #include "rtc_base/constructor_magic.h"
- #include "rtc_base/numerics/running_statistics.h"
- namespace rtc {
- // RollingAccumulator stores and reports statistics
- // over N most recent samples.
- //
- // T is assumed to be an int, long, double or float.
- template <typename T>
- class RollingAccumulator {
- public:
- explicit RollingAccumulator(size_t max_count) : samples_(max_count) {
- RTC_DCHECK(max_count > 0);
- Reset();
- }
- ~RollingAccumulator() {}
- size_t max_count() const { return samples_.size(); }
- size_t count() const { return static_cast<size_t>(stats_.Size()); }
- void Reset() {
- stats_ = webrtc::webrtc_impl::RunningStatistics<T>();
- next_index_ = 0U;
- max_ = T();
- max_stale_ = false;
- min_ = T();
- min_stale_ = false;
- }
- void AddSample(T sample) {
- if (count() == max_count()) {
- // Remove oldest sample.
- T sample_to_remove = samples_[next_index_];
- stats_.RemoveSample(sample_to_remove);
- if (sample_to_remove >= max_) {
- max_stale_ = true;
- }
- if (sample_to_remove <= min_) {
- min_stale_ = true;
- }
- }
- // Add new sample.
- samples_[next_index_] = sample;
- if (count() == 0 || sample >= max_) {
- max_ = sample;
- max_stale_ = false;
- }
- if (count() == 0 || sample <= min_) {
- min_ = sample;
- min_stale_ = false;
- }
- stats_.AddSample(sample);
- // Update next_index_.
- next_index_ = (next_index_ + 1) % max_count();
- }
- double ComputeMean() const { return stats_.GetMean().value_or(0); }
- T ComputeMax() const {
- if (max_stale_) {
- RTC_DCHECK(count() > 0)
- << "It shouldn't be possible for max_stale_ && count() == 0";
- max_ = samples_[next_index_];
- for (size_t i = 1u; i < count(); i++) {
- max_ = std::max(max_, samples_[(next_index_ + i) % max_count()]);
- }
- max_stale_ = false;
- }
- return max_;
- }
- T ComputeMin() const {
- if (min_stale_) {
- RTC_DCHECK(count() > 0)
- << "It shouldn't be possible for min_stale_ && count() == 0";
- min_ = samples_[next_index_];
- for (size_t i = 1u; i < count(); i++) {
- min_ = std::min(min_, samples_[(next_index_ + i) % max_count()]);
- }
- min_stale_ = false;
- }
- return min_;
- }
- // O(n) time complexity.
- // Weights nth sample with weight (learning_rate)^n. Learning_rate should be
- // between (0.0, 1.0], otherwise the non-weighted mean is returned.
- double ComputeWeightedMean(double learning_rate) const {
- if (count() < 1 || learning_rate <= 0.0 || learning_rate >= 1.0) {
- return ComputeMean();
- }
- double weighted_mean = 0.0;
- double current_weight = 1.0;
- double weight_sum = 0.0;
- const size_t max_size = max_count();
- for (size_t i = 0; i < count(); ++i) {
- current_weight *= learning_rate;
- weight_sum += current_weight;
- // Add max_size to prevent underflow.
- size_t index = (next_index_ + max_size - i - 1) % max_size;
- weighted_mean += current_weight * samples_[index];
- }
- return weighted_mean / weight_sum;
- }
- // Compute estimated variance. Estimation is more accurate
- // as the number of samples grows.
- double ComputeVariance() const { return stats_.GetVariance().value_or(0); }
- private:
- webrtc::webrtc_impl::RunningStatistics<T> stats_;
- size_t next_index_;
- mutable T max_;
- mutable bool max_stale_;
- mutable T min_;
- mutable bool min_stale_;
- std::vector<T> samples_;
- RTC_DISALLOW_COPY_AND_ASSIGN(RollingAccumulator);
- };
- } // namespace rtc
- #endif // RTC_BASE_ROLLING_ACCUMULATOR_H_
|