diff options
Diffstat (limited to 'chromium/third_party/libjingle/source/talk/base/rollingaccumulator.h')
-rw-r--r-- | chromium/third_party/libjingle/source/talk/base/rollingaccumulator.h | 82 |
1 files changed, 67 insertions, 15 deletions
diff --git a/chromium/third_party/libjingle/source/talk/base/rollingaccumulator.h b/chromium/third_party/libjingle/source/talk/base/rollingaccumulator.h index cdad0251f3f..dfda8fec072 100644 --- a/chromium/third_party/libjingle/source/talk/base/rollingaccumulator.h +++ b/chromium/third_party/libjingle/source/talk/base/rollingaccumulator.h @@ -42,11 +42,8 @@ template<typename T> class RollingAccumulator { public: explicit RollingAccumulator(size_t max_count) - : count_(0), - next_index_(0), - sum_(0.0), - sum_2_(0.0), - samples_(max_count) { + : samples_(max_count) { + Reset(); } ~RollingAccumulator() { } @@ -59,12 +56,29 @@ class RollingAccumulator { return count_; } + void Reset() { + count_ = 0U; + next_index_ = 0U; + sum_ = 0.0; + sum_2_ = 0.0; + 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_]; sum_ -= sample_to_remove; sum_2_ -= sample_to_remove * sample_to_remove; + if (sample_to_remove >= max_) { + max_stale_ = true; + } + if (sample_to_remove <= min_) { + min_stale_ = true; + } } else { // Increase count of samples. ++count_; @@ -73,6 +87,14 @@ class RollingAccumulator { samples_[next_index_] = sample; sum_ += sample; sum_2_ += sample * sample; + if (count_ == 1 || sample >= max_) { + max_ = sample; + max_stale_ = false; + } + if (count_ == 1 || sample <= min_) { + min_ = sample; + min_stale_ = false; + } // Update next_index_. next_index_ = (next_index_ + 1) % max_count(); } @@ -81,17 +103,43 @@ class RollingAccumulator { return static_cast<T>(sum_); } - T ComputeMean() const { + double ComputeMean() const { if (count_ == 0) { - return static_cast<T>(0); + return 0.0; + } + return sum_ / count_; + } + + T ComputeMax() const { + if (max_stale_) { + ASSERT(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_ = _max(max_, samples_[(next_index_ + i) % max_count()]); + } + max_stale_ = false; + } + return max_; + } + + T ComputeMin() const { + if (min_stale_) { + ASSERT(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_ = _min(min_, samples_[(next_index_ + i) % max_count()]); + } + min_stale_ = false; } - return static_cast<T>(sum_ / count_); + 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. - T ComputeWeightedMean(double learning_rate) const { + double ComputeWeightedMean(double learning_rate) const { if (count_ < 1 || learning_rate <= 0.0 || learning_rate >= 1.0) { return ComputeMean(); } @@ -106,27 +154,31 @@ class RollingAccumulator { size_t index = (next_index_ + max_size - i - 1) % max_size; weighted_mean += current_weight * samples_[index]; } - return static_cast<T>(weighted_mean / weight_sum); + return weighted_mean / weight_sum; } // Compute estimated variance. Estimation is more accurate // as the number of samples grows. - T ComputeVariance() const { + double ComputeVariance() const { if (count_ == 0) { - return static_cast<T>(0); + return 0.0; } // Var = E[x^2] - (E[x])^2 double count_inv = 1.0 / count_; double mean_2 = sum_2_ * count_inv; double mean = sum_ * count_inv; - return static_cast<T>(mean_2 - (mean * mean)); + return mean_2 - (mean * mean); } private: size_t count_; size_t next_index_; - double sum_; // Sum(x) - double sum_2_; // Sum(x*x) + double sum_; // Sum(x) - double to avoid overflow + double sum_2_; // Sum(x*x) - double to avoid overflow + mutable T max_; + mutable bool max_stale_; + mutable T min_; + mutable bool min_stale_; std::vector<T> samples_; DISALLOW_COPY_AND_ASSIGN(RollingAccumulator); |