From 2c5af4f6dce2cf34ad49bb9a6303561d4f3eea58 Mon Sep 17 00:00:00 2001 From: Artem Titov Date: Wed, 3 Jul 2019 10:40:16 +0200 Subject: [PATCH] Add * and / operator into SamplesStatsCounter. Add * and / operator into SamplesStatsCounter to simplify convertion between samples units. Bug: webrtc:10138 Change-Id: I985b60bc63c071ceaf0fddcdbcd3e6476353c0fe Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/142171 Commit-Queue: Artem Titov Reviewed-by: Karl Wiberg Cr-Commit-Position: refs/heads/master@{#28456} --- rtc_base/numerics/samples_stats_counter.cc | 18 +++++ rtc_base/numerics/samples_stats_counter.h | 11 +++ .../samples_stats_counter_unittest.cc | 81 +++++++++++++++++-- 3 files changed, 104 insertions(+), 6 deletions(-) diff --git a/rtc_base/numerics/samples_stats_counter.cc b/rtc_base/numerics/samples_stats_counter.cc index 655f4c1fe6..0d18c9f16b 100644 --- a/rtc_base/numerics/samples_stats_counter.cc +++ b/rtc_base/numerics/samples_stats_counter.cc @@ -66,4 +66,22 @@ double SamplesStatsCounter::GetPercentile(double percentile) { return low + fract_part * (high - low); } +SamplesStatsCounter operator*(const SamplesStatsCounter& counter, + double value) { + SamplesStatsCounter out; + for (auto& sample : counter.GetSamples()) { + out.AddSample(sample * value); + } + return out; +} + +SamplesStatsCounter operator/(const SamplesStatsCounter& counter, + double value) { + SamplesStatsCounter out; + for (auto& sample : counter.GetSamples()) { + out.AddSample(sample / value); + } + return out; +} + } // namespace webrtc diff --git a/rtc_base/numerics/samples_stats_counter.h b/rtc_base/numerics/samples_stats_counter.h index 43c58c7c32..6f79ceeb23 100644 --- a/rtc_base/numerics/samples_stats_counter.h +++ b/rtc_base/numerics/samples_stats_counter.h @@ -88,6 +88,17 @@ class SamplesStatsCounter { bool sorted_ = false; }; +// Multiply all sample values on |value| and return new SamplesStatsCounter +// with resulted samples. Doesn't change origin SamplesStatsCounter. +SamplesStatsCounter operator*(const SamplesStatsCounter& counter, double value); +inline SamplesStatsCounter operator*(double value, + const SamplesStatsCounter& counter) { + return counter * value; +} +// Divide all sample values on |value| and return new SamplesStatsCounter with +// resulted samples. Doesn't change origin SamplesStatsCounter. +SamplesStatsCounter operator/(const SamplesStatsCounter& counter, double value); + } // namespace webrtc #endif // RTC_BASE_NUMERICS_SAMPLES_STATS_COUNTER_H_ diff --git a/rtc_base/numerics/samples_stats_counter_unittest.cc b/rtc_base/numerics/samples_stats_counter_unittest.cc index 590bf8c785..7760b42718 100644 --- a/rtc_base/numerics/samples_stats_counter_unittest.cc +++ b/rtc_base/numerics/samples_stats_counter_unittest.cc @@ -54,7 +54,7 @@ constexpr int SIZE_FOR_MERGE = 10; } // namespace -TEST(SamplesStatsCounter, FullSimpleTest) { +TEST(SamplesStatsCounterTest, FullSimpleTest) { SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(100); EXPECT_TRUE(!stats.IsEmpty()); @@ -68,7 +68,7 @@ TEST(SamplesStatsCounter, FullSimpleTest) { } } -TEST(SamplesStatsCounter, VarianceAndDeviation) { +TEST(SamplesStatsCounterTest, VarianceAndDeviation) { SamplesStatsCounter stats; stats.AddSample(2); stats.AddSample(2); @@ -80,13 +80,13 @@ TEST(SamplesStatsCounter, VarianceAndDeviation) { EXPECT_DOUBLE_EQ(stats.GetStandardDeviation(), sqrt(4.5)); } -TEST(SamplesStatsCounter, FractionPercentile) { +TEST(SamplesStatsCounterTest, FractionPercentile) { SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(5); EXPECT_DOUBLE_EQ(stats.GetPercentile(0.5), 3); } -TEST(SamplesStatsCounter, TestBorderValues) { +TEST(SamplesStatsCounterTest, TestBorderValues) { SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(5); EXPECT_GE(stats.GetPercentile(0.01), 1); @@ -94,7 +94,7 @@ TEST(SamplesStatsCounter, TestBorderValues) { EXPECT_DOUBLE_EQ(stats.GetPercentile(1.0), 5); } -TEST(SamplesStatsCounter, VarianceFromUniformDistribution) { +TEST(SamplesStatsCounterTest, VarianceFromUniformDistribution) { // Check variance converge to 1/12 for [0;1) uniform distribution. // Acts as a sanity check for NumericStabilityForVariance test. SamplesStatsCounter stats = CreateStatsFromUniformDistribution(1e6, 0, 1); @@ -102,7 +102,7 @@ TEST(SamplesStatsCounter, VarianceFromUniformDistribution) { EXPECT_NEAR(stats.GetVariance(), 1. / 12, 1e-3); } -TEST(SamplesStatsCounter, NumericStabilityForVariance) { +TEST(SamplesStatsCounterTest, NumericStabilityForVariance) { // Same test as VarianceFromUniformDistribution, // except the range is shifted to [1e9;1e9+1). // Variance should also converge to 1/12. @@ -144,6 +144,75 @@ TEST_P(SamplesStatsCounterTest, AddSamples) { EXPECT_DOUBLE_EQ(stats0.GetPercentile(0.9), 8.1); } +TEST(SamplesStatsCounterTest, MultiplyRight) { + SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(10); + + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5); + + SamplesStatsCounter multiplied_stats = stats * 10; + EXPECT_TRUE(!multiplied_stats.IsEmpty()); + EXPECT_DOUBLE_EQ(multiplied_stats.GetMin(), 10.0); + EXPECT_DOUBLE_EQ(multiplied_stats.GetMax(), 100.0); + EXPECT_DOUBLE_EQ(multiplied_stats.GetAverage(), 55.0); + EXPECT_EQ(multiplied_stats.GetSamples().size(), stats.GetSamples().size()); + + // Check that origin stats were not modified. + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5); +} + +TEST(SamplesStatsCounterTest, MultiplyLeft) { + SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(10); + + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5); + + SamplesStatsCounter multiplied_stats = 10 * stats; + EXPECT_TRUE(!multiplied_stats.IsEmpty()); + EXPECT_DOUBLE_EQ(multiplied_stats.GetMin(), 10.0); + EXPECT_DOUBLE_EQ(multiplied_stats.GetMax(), 100.0); + EXPECT_DOUBLE_EQ(multiplied_stats.GetAverage(), 55.0); + EXPECT_EQ(multiplied_stats.GetSamples().size(), stats.GetSamples().size()); + + // Check that origin stats were not modified. + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5); +} + +TEST(SamplesStatsCounterTest, Divide) { + SamplesStatsCounter stats; + for (int i = 1; i <= 10; i++) { + stats.AddSample(i * 10); + } + + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 100.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 55.0); + + SamplesStatsCounter divided_stats = stats / 10; + EXPECT_TRUE(!divided_stats.IsEmpty()); + EXPECT_DOUBLE_EQ(divided_stats.GetMin(), 1.0); + EXPECT_DOUBLE_EQ(divided_stats.GetMax(), 10.0); + EXPECT_DOUBLE_EQ(divided_stats.GetAverage(), 5.5); + EXPECT_EQ(divided_stats.GetSamples().size(), stats.GetSamples().size()); + + // Check that origin stats were not modified. + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 100.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 55.0); +} + INSTANTIATE_TEST_SUITE_P(SamplesStatsCounterTests, SamplesStatsCounterTest, ::testing::Range(0, SIZE_FOR_MERGE + 1));