blob: 16a8e250988d79ea839856ed8e67b489cdd32246 [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "rtc_base/numerics/sample_counter.h"
12
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020013#include <limits>
14
15#include "rtc_base/checks.h"
16#include "rtc_base/numerics/safe_conversions.h"
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020017
18namespace rtc {
19
20SampleCounter::SampleCounter() = default;
21SampleCounter::~SampleCounter() = default;
22
23void SampleCounter::Add(int sample) {
24 if (sum_ > 0) {
25 RTC_DCHECK_LE(sample, std::numeric_limits<int64_t>::max() - sum_);
26 } else {
27 RTC_DCHECK_GE(sample, std::numeric_limits<int64_t>::min() - sum_);
28 }
29 sum_ += sample;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020030 ++num_samples_;
31 if (!max_ || sample > *max_) {
32 max_ = sample;
33 }
34}
35
36void SampleCounter::Add(const SampleCounter& other) {
37 if (sum_ > 0) {
38 RTC_DCHECK_LE(other.sum_, std::numeric_limits<int64_t>::max() - sum_);
39 } else {
40 RTC_DCHECK_GE(other.sum_, std::numeric_limits<int64_t>::min() - sum_);
41 }
42 sum_ += other.sum_;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020043 RTC_DCHECK_LE(other.num_samples_,
44 std::numeric_limits<int64_t>::max() - num_samples_);
45 num_samples_ += other.num_samples_;
46 if (other.max_ && (!max_ || *max_ < *other.max_))
47 max_ = other.max_;
48}
49
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020050absl::optional<int> SampleCounter::Avg(int64_t min_required_samples) const {
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020051 RTC_DCHECK_GT(min_required_samples, 0);
52 if (num_samples_ < min_required_samples)
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020053 return absl::nullopt;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020054 return rtc::dchecked_cast<int>(sum_ / num_samples_);
55}
56
Ilya Nikolaevskiy8c688452018-09-11 13:46:22 +020057absl::optional<int> SampleCounter::Max() const {
58 return max_;
59}
60
Sergey Silkin02371062019-01-31 16:45:42 +010061absl::optional<int64_t> SampleCounter::Sum(int64_t min_required_samples) const {
62 RTC_DCHECK_GT(min_required_samples, 0);
63 if (num_samples_ < min_required_samples)
64 return absl::nullopt;
65 return sum_;
66}
67
Sergey Silkinbea18ca2018-10-02 16:22:46 +020068int64_t SampleCounter::NumSamples() const {
69 return num_samples_;
70}
71
Ilya Nikolaevskiy8c688452018-09-11 13:46:22 +020072void SampleCounter::Reset() {
73 *this = {};
74}
75
76SampleCounterWithVariance::SampleCounterWithVariance() = default;
77SampleCounterWithVariance::~SampleCounterWithVariance() = default;
78
79absl::optional<int64_t> SampleCounterWithVariance::Variance(
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020080 int64_t min_required_samples) const {
81 RTC_DCHECK_GT(min_required_samples, 0);
82 if (num_samples_ < min_required_samples)
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020083 return absl::nullopt;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020084 // E[(x-mean)^2] = E[x^2] - mean^2
85 int64_t mean = sum_ / num_samples_;
86 return sum_squared_ / num_samples_ - mean * mean;
87}
88
Ilya Nikolaevskiy8c688452018-09-11 13:46:22 +020089void SampleCounterWithVariance::Add(int sample) {
90 SampleCounter::Add(sample);
91 // Prevent overflow in squaring.
92 RTC_DCHECK_GT(sample, std::numeric_limits<int32_t>::min());
93 RTC_DCHECK_LE(int64_t{sample} * sample,
94 std::numeric_limits<int64_t>::max() - sum_squared_);
95 sum_squared_ += int64_t{sample} * sample;
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +020096}
97
Ilya Nikolaevskiy8c688452018-09-11 13:46:22 +020098void SampleCounterWithVariance::Add(const SampleCounterWithVariance& other) {
99 SampleCounter::Add(other);
100 RTC_DCHECK_LE(other.sum_squared_,
101 std::numeric_limits<int64_t>::max() - sum_squared_);
102 sum_squared_ += other.sum_squared_;
103}
104
105void SampleCounterWithVariance::Reset() {
Ilya Nikolaevskiy0beed5d2018-05-22 10:54:30 +0200106 *this = {};
107}
108
109} // namespace rtc