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 #ifndef RTC_BASE_NUMERICS_SAMPLES_STATS_COUNTER_H_
12 #define RTC_BASE_NUMERICS_SAMPLES_STATS_COUNTER_H_
13 
14 #include <vector>
15 
16 #include "api/array_view.h"
17 #include "api/units/timestamp.h"
18 #include "rtc_base/checks.h"
19 #include "rtc_base/numerics/running_statistics.h"
20 
21 namespace webrtc {
22 
23 // This class extends RunningStatistics by providing GetPercentile() method,
24 // while slightly adapting the interface.
25 class SamplesStatsCounter {
26  public:
27   struct StatsSample {
28     double value;
29     Timestamp time;
30   };
31 
32   SamplesStatsCounter();
33   ~SamplesStatsCounter();
34   SamplesStatsCounter(const SamplesStatsCounter&);
35   SamplesStatsCounter& operator=(const SamplesStatsCounter&);
36   SamplesStatsCounter(SamplesStatsCounter&&);
37   SamplesStatsCounter& operator=(SamplesStatsCounter&&);
38 
39   // Adds sample to the stats in amortized O(1) time.
40   void AddSample(double value);
41   void AddSample(StatsSample sample);
42 
43   // Adds samples from another counter.
44   void AddSamples(const SamplesStatsCounter& other);
45 
46   // Returns if there are any values in O(1) time.
IsEmpty()47   bool IsEmpty() const { return samples_.empty(); }
48 
49   // Returns min in O(1) time. This function may not be called if there are no
50   // samples.
GetMin()51   double GetMin() const {
52     RTC_DCHECK(!IsEmpty());
53     return *stats_.GetMin();
54   }
55   // Returns max in O(1) time. This function may not be called if there are no
56   // samples.
GetMax()57   double GetMax() const {
58     RTC_DCHECK(!IsEmpty());
59     return *stats_.GetMax();
60   }
61   // Returns average in O(1) time. This function may not be called if there are
62   // no samples.
GetAverage()63   double GetAverage() const {
64     RTC_DCHECK(!IsEmpty());
65     return *stats_.GetMean();
66   }
67   // Returns variance in O(1) time. This function may not be called if there are
68   // no samples.
GetVariance()69   double GetVariance() const {
70     RTC_DCHECK(!IsEmpty());
71     return *stats_.GetVariance();
72   }
73   // Returns standard deviation in O(1) time. This function may not be called if
74   // there are no samples.
GetStandardDeviation()75   double GetStandardDeviation() const {
76     RTC_DCHECK(!IsEmpty());
77     return *stats_.GetStandardDeviation();
78   }
79   // Returns percentile in O(nlogn) on first call and in O(1) after, if no
80   // additions were done. This function may not be called if there are no
81   // samples.
82   //
83   // |percentile| has to be in [0; 1]. 0 percentile is the min in the array and
84   // 1 percentile is the max in the array.
85   double GetPercentile(double percentile);
86   // Returns array view with all samples added into counter. There are no
87   // guarantees of order, so samples can be in different order comparing to in
88   // which they were added into counter. Also return value will be invalidate
89   // after call to any non const method.
GetTimedSamples()90   rtc::ArrayView<const StatsSample> GetTimedSamples() const { return samples_; }
GetSamples()91   std::vector<double> GetSamples() const {
92     std::vector<double> out;
93     out.reserve(samples_.size());
94     for (const auto& sample : samples_) {
95       out.push_back(sample.value);
96     }
97     return out;
98   }
99 
100  private:
101   RunningStatistics<double> stats_;
102   std::vector<StatsSample> samples_;
103   bool sorted_ = false;
104 };
105 
106 // Multiply all sample values on |value| and return new SamplesStatsCounter
107 // with resulted samples. Doesn't change origin SamplesStatsCounter.
108 SamplesStatsCounter operator*(const SamplesStatsCounter& counter, double value);
109 inline SamplesStatsCounter operator*(double value,
110                                      const SamplesStatsCounter& counter) {
111   return counter * value;
112 }
113 // Divide all sample values on |value| and return new SamplesStatsCounter with
114 // resulted samples. Doesn't change origin SamplesStatsCounter.
115 SamplesStatsCounter operator/(const SamplesStatsCounter& counter, double value);
116 
117 }  // namespace webrtc
118 
119 #endif  // RTC_BASE_NUMERICS_SAMPLES_STATS_COUNTER_H_
120