blob: 0d18c9f16b07b300162c075a7fe5278d5415d427 [file] [log] [blame]
Artem Titove4ed6ea2019-01-11 11:02:19 +01001/*
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 "rtc_base/numerics/samples_stats_counter.h"
12
Artem Titove4ed6ea2019-01-11 11:02:19 +010013#include <cmath>
14
Steve Anton2acd1632019-03-25 13:48:30 -070015#include "absl/algorithm/container.h"
16
Artem Titove4ed6ea2019-01-11 11:02:19 +010017namespace webrtc {
18
19SamplesStatsCounter::SamplesStatsCounter() = default;
20SamplesStatsCounter::~SamplesStatsCounter() = default;
Artem Titove6f6a0c2019-02-07 12:14:35 +010021SamplesStatsCounter::SamplesStatsCounter(const SamplesStatsCounter&) = default;
22SamplesStatsCounter& SamplesStatsCounter::operator=(
23 const SamplesStatsCounter&) = default;
Artem Titove4ed6ea2019-01-11 11:02:19 +010024SamplesStatsCounter::SamplesStatsCounter(SamplesStatsCounter&&) = default;
Artem Titove6f6a0c2019-02-07 12:14:35 +010025SamplesStatsCounter& SamplesStatsCounter::operator=(SamplesStatsCounter&&) =
26 default;
Artem Titove4ed6ea2019-01-11 11:02:19 +010027
28void SamplesStatsCounter::AddSample(double value) {
Yves Gerey890f62b2019-04-10 17:18:48 +020029 stats_.AddSample(value);
Artem Titove4ed6ea2019-01-11 11:02:19 +010030 samples_.push_back(value);
31 sorted_ = false;
Artem Titove4ed6ea2019-01-11 11:02:19 +010032}
33
Sebastian Janssond93a0042019-04-09 15:38:07 +020034void SamplesStatsCounter::AddSamples(const SamplesStatsCounter& other) {
Yves Gerey890f62b2019-04-10 17:18:48 +020035 stats_.MergeStatistics(other.stats_);
36 samples_.insert(samples_.end(), other.samples_.begin(), other.samples_.end());
Sebastian Janssond93a0042019-04-09 15:38:07 +020037 sorted_ = false;
Sebastian Janssond93a0042019-04-09 15:38:07 +020038}
39
Artem Titove4ed6ea2019-01-11 11:02:19 +010040double SamplesStatsCounter::GetPercentile(double percentile) {
41 RTC_DCHECK(!IsEmpty());
42 RTC_CHECK_GE(percentile, 0);
43 RTC_CHECK_LE(percentile, 1);
44 if (!sorted_) {
Steve Anton2acd1632019-03-25 13:48:30 -070045 absl::c_sort(samples_);
Artem Titove4ed6ea2019-01-11 11:02:19 +010046 sorted_ = true;
47 }
48 const double raw_rank = percentile * (samples_.size() - 1);
49 double int_part;
50 double fract_part = std::modf(raw_rank, &int_part);
51 size_t rank = static_cast<size_t>(int_part);
52 if (fract_part >= 1.0) {
53 // It can happen due to floating point calculation error.
54 rank++;
55 fract_part -= 1.0;
56 }
57
58 RTC_DCHECK_GE(rank, 0);
59 RTC_DCHECK_LT(rank, samples_.size());
60 RTC_DCHECK_GE(fract_part, 0);
61 RTC_DCHECK_LT(fract_part, 1);
62 RTC_DCHECK(rank + fract_part == raw_rank);
63
64 const double low = samples_[rank];
65 const double high = samples_[std::min(rank + 1, samples_.size() - 1)];
66 return low + fract_part * (high - low);
67}
68
Artem Titov2c5af4f2019-07-03 10:40:16 +020069SamplesStatsCounter operator*(const SamplesStatsCounter& counter,
70 double value) {
71 SamplesStatsCounter out;
72 for (auto& sample : counter.GetSamples()) {
73 out.AddSample(sample * value);
74 }
75 return out;
76}
77
78SamplesStatsCounter operator/(const SamplesStatsCounter& counter,
79 double value) {
80 SamplesStatsCounter out;
81 for (auto& sample : counter.GetSamples()) {
82 out.AddSample(sample / value);
83 }
84 return out;
85}
86
Artem Titove4ed6ea2019-01-11 11:02:19 +010087} // namespace webrtc