• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
13 #include <cmath>
14 
15 #include "absl/algorithm/container.h"
16 #include "rtc_base/time_utils.h"
17 
18 namespace webrtc {
19 
20 SamplesStatsCounter::SamplesStatsCounter() = default;
21 SamplesStatsCounter::~SamplesStatsCounter() = default;
22 SamplesStatsCounter::SamplesStatsCounter(const SamplesStatsCounter&) = default;
23 SamplesStatsCounter& SamplesStatsCounter::operator=(
24     const SamplesStatsCounter&) = default;
25 SamplesStatsCounter::SamplesStatsCounter(SamplesStatsCounter&&) = default;
26 SamplesStatsCounter& SamplesStatsCounter::operator=(SamplesStatsCounter&&) =
27     default;
28 
AddSample(double value)29 void SamplesStatsCounter::AddSample(double value) {
30   AddSample(StatsSample{value, Timestamp::Micros(rtc::TimeMicros())});
31 }
32 
AddSample(StatsSample sample)33 void SamplesStatsCounter::AddSample(StatsSample sample) {
34   stats_.AddSample(sample.value);
35   samples_.push_back(sample);
36   sorted_ = false;
37 }
38 
AddSamples(const SamplesStatsCounter & other)39 void SamplesStatsCounter::AddSamples(const SamplesStatsCounter& other) {
40   stats_.MergeStatistics(other.stats_);
41   samples_.insert(samples_.end(), other.samples_.begin(), other.samples_.end());
42   sorted_ = false;
43 }
44 
GetPercentile(double percentile)45 double SamplesStatsCounter::GetPercentile(double percentile) {
46   RTC_DCHECK(!IsEmpty());
47   RTC_CHECK_GE(percentile, 0);
48   RTC_CHECK_LE(percentile, 1);
49   if (!sorted_) {
50     absl::c_sort(samples_, [](const StatsSample& a, const StatsSample& b) {
51       return a.value < b.value;
52     });
53     sorted_ = true;
54   }
55   const double raw_rank = percentile * (samples_.size() - 1);
56   double int_part;
57   double fract_part = std::modf(raw_rank, &int_part);
58   size_t rank = static_cast<size_t>(int_part);
59   if (fract_part >= 1.0) {
60     // It can happen due to floating point calculation error.
61     rank++;
62     fract_part -= 1.0;
63   }
64 
65   RTC_DCHECK_GE(rank, 0);
66   RTC_DCHECK_LT(rank, samples_.size());
67   RTC_DCHECK_GE(fract_part, 0);
68   RTC_DCHECK_LT(fract_part, 1);
69   RTC_DCHECK(rank + fract_part == raw_rank);
70 
71   const double low = samples_[rank].value;
72   const double high = samples_[std::min(rank + 1, samples_.size() - 1)].value;
73   return low + fract_part * (high - low);
74 }
75 
operator *(const SamplesStatsCounter & counter,double value)76 SamplesStatsCounter operator*(const SamplesStatsCounter& counter,
77                               double value) {
78   SamplesStatsCounter out;
79   for (const auto& sample : counter.GetTimedSamples()) {
80     out.AddSample(
81         SamplesStatsCounter::StatsSample{sample.value * value, sample.time});
82   }
83   return out;
84 }
85 
operator /(const SamplesStatsCounter & counter,double value)86 SamplesStatsCounter operator/(const SamplesStatsCounter& counter,
87                               double value) {
88   SamplesStatsCounter out;
89   for (const auto& sample : counter.GetTimedSamples()) {
90     out.AddSample(
91         SamplesStatsCounter::StatsSample{sample.value / value, sample.time});
92   }
93   return out;
94 }
95 
96 }  // namespace webrtc
97