/* * Copyright (c) 2018 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. */ #include "rtc_base/numerics/sample_counter.h" #include #include "rtc_base/checks.h" #include "rtc_base/numerics/safe_conversions.h" namespace rtc { SampleCounter::SampleCounter() = default; SampleCounter::~SampleCounter() = default; void SampleCounter::Add(int sample) { if (sum_ > 0) { RTC_DCHECK_LE(sample, std::numeric_limits::max() - sum_); } else { RTC_DCHECK_GE(sample, std::numeric_limits::min() - sum_); } sum_ += sample; ++num_samples_; if (!max_ || sample > *max_) { max_ = sample; } if (!min_ || sample < *min_) { min_ = sample; } } void SampleCounter::Add(const SampleCounter& other) { if (sum_ > 0) { RTC_DCHECK_LE(other.sum_, std::numeric_limits::max() - sum_); } else { RTC_DCHECK_GE(other.sum_, std::numeric_limits::min() - sum_); } sum_ += other.sum_; RTC_DCHECK_LE(other.num_samples_, std::numeric_limits::max() - num_samples_); num_samples_ += other.num_samples_; if (other.max_ && (!max_ || *max_ < *other.max_)) max_ = other.max_; if (other.min_ && (!min_ || *min_ > *other.min_)) min_ = other.min_; } absl::optional SampleCounter::Avg(int64_t min_required_samples) const { RTC_DCHECK_GT(min_required_samples, 0); if (num_samples_ < min_required_samples) return absl::nullopt; return rtc::dchecked_cast(sum_ / num_samples_); } absl::optional SampleCounter::Max() const { return max_; } absl::optional SampleCounter::Min() const { return min_; } absl::optional SampleCounter::Sum(int64_t min_required_samples) const { RTC_DCHECK_GT(min_required_samples, 0); if (num_samples_ < min_required_samples) return absl::nullopt; return sum_; } int64_t SampleCounter::NumSamples() const { return num_samples_; } void SampleCounter::Reset() { *this = {}; } SampleCounterWithVariance::SampleCounterWithVariance() = default; SampleCounterWithVariance::~SampleCounterWithVariance() = default; absl::optional SampleCounterWithVariance::Variance( int64_t min_required_samples) const { RTC_DCHECK_GT(min_required_samples, 0); if (num_samples_ < min_required_samples) return absl::nullopt; // E[(x-mean)^2] = E[x^2] - mean^2 int64_t mean = sum_ / num_samples_; return sum_squared_ / num_samples_ - mean * mean; } void SampleCounterWithVariance::Add(int sample) { SampleCounter::Add(sample); // Prevent overflow in squaring. RTC_DCHECK_GT(sample, std::numeric_limits::min()); RTC_DCHECK_LE(int64_t{sample} * sample, std::numeric_limits::max() - sum_squared_); sum_squared_ += int64_t{sample} * sample; } void SampleCounterWithVariance::Add(const SampleCounterWithVariance& other) { SampleCounter::Add(other); RTC_DCHECK_LE(other.sum_squared_, std::numeric_limits::max() - sum_squared_); sum_squared_ += other.sum_squared_; } void SampleCounterWithVariance::Reset() { *this = {}; } } // namespace rtc