blob: 47d9eafa9ef37cf2e8074d169ec1bee85907a901 [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
60void SampleCounter::Reset() {
61 *this = {};
62}
63
64SampleCounterWithVariance::SampleCounterWithVariance() = default;
65SampleCounterWithVariance::~SampleCounterWithVariance() = default;
66
67absl::optional<int64_t> SampleCounterWithVariance::Variance(
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020068 int64_t min_required_samples) const {
69 RTC_DCHECK_GT(min_required_samples, 0);
70 if (num_samples_ < min_required_samples)
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020071 return absl::nullopt;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020072 // E[(x-mean)^2] = E[x^2] - mean^2
73 int64_t mean = sum_ / num_samples_;
74 return sum_squared_ / num_samples_ - mean * mean;
75}
76
Ilya Nikolaevskiy8c688452018-09-11 13:46:22 +020077void SampleCounterWithVariance::Add(int sample) {
78 SampleCounter::Add(sample);
79 // Prevent overflow in squaring.
80 RTC_DCHECK_GT(sample, std::numeric_limits<int32_t>::min());
81 RTC_DCHECK_LE(int64_t{sample} * sample,
82 std::numeric_limits<int64_t>::max() - sum_squared_);
83 sum_squared_ += int64_t{sample} * sample;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020084}
85
Ilya Nikolaevskiy8c688452018-09-11 13:46:22 +020086void SampleCounterWithVariance::Add(const SampleCounterWithVariance& other) {
87 SampleCounter::Add(other);
88 RTC_DCHECK_LE(other.sum_squared_,
89 std::numeric_limits<int64_t>::max() - sum_squared_);
90 sum_squared_ += other.sum_squared_;
91}
92
93void SampleCounterWithVariance::Reset() {
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020094 *this = {};
95}
96
97} // namespace rtc