Files
platform-external-webrtc/webrtc/base/rollingaccumulator.h
kwiberg 4485ffb58d #include "webrtc/base/constructormagic.h" where appropriate
Any file that uses the RTC_DISALLOW_* macros should #include
"webrtc/base/constructormagic.h", but a shocking number of them don't.
This causes trouble when we try to wean files off of #including
scoped_ptr.h, since a bunch of files get their constructormagic macros
only from there.

Rather than fixing these errors one by one as they turn up, this CL
simply ensures that every file in the WebRTC tree that uses the
RTC_DISALLOW_* macros #includes "webrtc/base/constructormagic.h".

BUG=webrtc:5520

Review URL: https://codereview.webrtc.org/1917043005

Cr-Commit-Position: refs/heads/master@{#12509}
2016-04-26 15:14:48 +00:00

175 lines
4.5 KiB
C++

/*
* 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 WEBRTC_BASE_ROLLINGACCUMULATOR_H_
#define WEBRTC_BASE_ROLLINGACCUMULATOR_H_
#include <algorithm>
#include <vector>
#include "webrtc/base/common.h"
#include "webrtc/base/constructormagic.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) {
Reset();
}
~RollingAccumulator() {
}
size_t max_count() const {
return samples_.size();
}
size_t count() const {
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_ -= static_cast<double>(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_;
}
// Add new sample.
samples_[next_index_] = sample;
sum_ += sample;
sum_2_ += static_cast<double>(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();
}
T ComputeSum() const {
return static_cast<T>(sum_);
}
double ComputeMean() const {
if (count_ == 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_ = std::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_ = 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 {
if (count_ == 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 mean_2 - (mean * mean);
}
private:
size_t count_;
size_t next_index_;
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_;
RTC_DISALLOW_COPY_AND_ASSIGN(RollingAccumulator);
};
} // namespace rtc
#endif // WEBRTC_BASE_ROLLINGACCUMULATOR_H_