blob: 7f76b743d251de98e45053f7d1275e66bfee04a9 [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;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020029 ++num_samples_;
30 if (!max_ || sample > *max_) {
31 max_ = sample;
32 }
33}
34
35void SampleCounter::Add(const SampleCounter& other) {
36 if (sum_ > 0) {
37 RTC_DCHECK_LE(other.sum_, std::numeric_limits<int64_t>::max() - sum_);
38 } else {
39 RTC_DCHECK_GE(other.sum_, std::numeric_limits<int64_t>::min() - sum_);
40 }
41 sum_ += other.sum_;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020042 RTC_DCHECK_LE(other.num_samples_,
43 std::numeric_limits<int64_t>::max() - num_samples_);
44 num_samples_ += other.num_samples_;
45 if (other.max_ && (!max_ || *max_ < *other.max_))
46 max_ = other.max_;
47}
48
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020049absl::optional<int> SampleCounter::Avg(int64_t min_required_samples) const {
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020050 RTC_DCHECK_GT(min_required_samples, 0);
51 if (num_samples_ < min_required_samples)
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020052 return absl::nullopt;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020053 return rtc::dchecked_cast<int>(sum_ / num_samples_);
54}
55
Ilya Nikolaevskiy8c688452018-09-11 13:46:22 +020056absl::optional<int> SampleCounter::Max() const {
57 return max_;
58}
59
Sergey Silkin02371062019-01-31 16:45:42 +010060absl::optional<int64_t> SampleCounter::Sum(int64_t min_required_samples) const {
61 RTC_DCHECK_GT(min_required_samples, 0);
62 if (num_samples_ < min_required_samples)
63 return absl::nullopt;
64 return sum_;
65}
66
Sergey Silkinbea18ca2018-10-02 16:22:46 +020067int64_t SampleCounter::NumSamples() const {
68 return num_samples_;
69}
70
Ilya Nikolaevskiy8c688452018-09-11 13:46:22 +020071void SampleCounter::Reset() {
72 *this = {};
73}
74
75SampleCounterWithVariance::SampleCounterWithVariance() = default;
76SampleCounterWithVariance::~SampleCounterWithVariance() = default;
77
78absl::optional<int64_t> SampleCounterWithVariance::Variance(
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020079 int64_t min_required_samples) const {
80 RTC_DCHECK_GT(min_required_samples, 0);
81 if (num_samples_ < min_required_samples)
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020082 return absl::nullopt;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020083 // E[(x-mean)^2] = E[x^2] - mean^2
84 int64_t mean = sum_ / num_samples_;
85 return sum_squared_ / num_samples_ - mean * mean;
86}
87
Ilya Nikolaevskiy8c688452018-09-11 13:46:22 +020088void SampleCounterWithVariance::Add(int sample) {
89 SampleCounter::Add(sample);
90 // Prevent overflow in squaring.
91 RTC_DCHECK_GT(sample, std::numeric_limits<int32_t>::min());
92 RTC_DCHECK_LE(int64_t{sample} * sample,
93 std::numeric_limits<int64_t>::max() - sum_squared_);
94 sum_squared_ += int64_t{sample} * sample;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020095}
96
Ilya Nikolaevskiy8c688452018-09-11 13:46:22 +020097void SampleCounterWithVariance::Add(const SampleCounterWithVariance& other) {
98 SampleCounter::Add(other);
99 RTC_DCHECK_LE(other.sum_squared_,
100 std::numeric_limits<int64_t>::max() - sum_squared_);
101 sum_squared_ += other.sum_squared_;
102}
103
104void SampleCounterWithVariance::Reset() {
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +0200105 *this = {};
106}
107
108} // namespace rtc