blob: d9244c385adf415064e1b02679f4ed06edd9dae3 [file] [log] [blame]
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +02001/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <limits>
12
13#include "rtc_base/checks.h"
14#include "rtc_base/numerics/safe_conversions.h"
15#include "rtc_base/numerics/sample_counter.h"
16
17namespace rtc {
18
19SampleCounter::SampleCounter() = default;
20SampleCounter::~SampleCounter() = default;
21
22void SampleCounter::Add(int sample) {
23 if (sum_ > 0) {
24 RTC_DCHECK_LE(sample, std::numeric_limits<int64_t>::max() - sum_);
25 } else {
26 RTC_DCHECK_GE(sample, std::numeric_limits<int64_t>::min() - sum_);
27 }
28 sum_ += sample;
29 // Prevent overflow in squaring.
30 RTC_DCHECK_GT(sample, std::numeric_limits<int32_t>::min());
31 RTC_DCHECK_LE(int64_t{sample} * sample,
32 std::numeric_limits<int64_t>::max() - sum_squared_);
33 sum_squared_ += int64_t{sample} * sample;
34 ++num_samples_;
35 if (!max_ || sample > *max_) {
36 max_ = sample;
37 }
38}
39
40void SampleCounter::Add(const SampleCounter& other) {
41 if (sum_ > 0) {
42 RTC_DCHECK_LE(other.sum_, std::numeric_limits<int64_t>::max() - sum_);
43 } else {
44 RTC_DCHECK_GE(other.sum_, std::numeric_limits<int64_t>::min() - sum_);
45 }
46 sum_ += other.sum_;
47 RTC_DCHECK_LE(other.sum_squared_,
48 std::numeric_limits<int64_t>::max() - sum_squared_);
49 sum_squared_ += other.sum_squared_;
50 RTC_DCHECK_LE(other.num_samples_,
51 std::numeric_limits<int64_t>::max() - num_samples_);
52 num_samples_ += other.num_samples_;
53 if (other.max_ && (!max_ || *max_ < *other.max_))
54 max_ = other.max_;
55}
56
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020057absl::optional<int> SampleCounter::Avg(int64_t min_required_samples) const {
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020058 RTC_DCHECK_GT(min_required_samples, 0);
59 if (num_samples_ < min_required_samples)
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020060 return absl::nullopt;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020061 return rtc::dchecked_cast<int>(sum_ / num_samples_);
62}
63
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020064absl::optional<int64_t> SampleCounter::Variance(
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020065 int64_t min_required_samples) const {
66 RTC_DCHECK_GT(min_required_samples, 0);
67 if (num_samples_ < min_required_samples)
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020068 return absl::nullopt;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020069 // E[(x-mean)^2] = E[x^2] - mean^2
70 int64_t mean = sum_ / num_samples_;
71 return sum_squared_ / num_samples_ - mean * mean;
72}
73
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020074absl::optional<int> SampleCounter::Max() const {
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020075 return max_;
76}
77
78void SampleCounter::Reset() {
79 *this = {};
80}
81
82} // namespace rtc