| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include <math.h> | 11 #include <math.h> |
| 12 | 12 |
| 13 #include <limits> | 13 #include <limits> |
| 14 #include <vector> | 14 #include <vector> |
| 15 | 15 |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 #include "webrtc/base/mathutils.h" // unsigned difference |
| 17 #include "webrtc/base/random.h" | 18 #include "webrtc/base/random.h" |
| 18 | 19 |
| 19 namespace webrtc { | 20 namespace webrtc { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 // Computes the positive remainder of x/n. | 23 // Computes the positive remainder of x/n. |
| 23 template <typename T> | 24 template <typename T> |
| 24 T fdiv_remainder(T x, T n) { | 25 T fdiv_remainder(T x, T n) { |
| 25 RTC_CHECK_GE(n, static_cast<T>(0)); | 26 RTC_CHECK_GE(n, static_cast<T>(0)); |
| 26 T remainder = x % n; | 27 T remainder = x % n; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 void BucketTestSignedInterval(unsigned int bucket_count, | 112 void BucketTestSignedInterval(unsigned int bucket_count, |
| 112 unsigned int samples, | 113 unsigned int samples, |
| 113 int32_t low, | 114 int32_t low, |
| 114 int32_t high, | 115 int32_t high, |
| 115 int sigma_level, | 116 int sigma_level, |
| 116 Random* prng) { | 117 Random* prng) { |
| 117 std::vector<unsigned int> buckets(bucket_count, 0); | 118 std::vector<unsigned int> buckets(bucket_count, 0); |
| 118 | 119 |
| 119 ASSERT_GE(high, low); | 120 ASSERT_GE(high, low); |
| 120 ASSERT_GE(bucket_count, 2u); | 121 ASSERT_GE(bucket_count, 2u); |
| 121 uint32_t interval = static_cast<uint32_t>(high - low + 1); | 122 uint32_t interval = unsigned_difference<int32_t>(high, low) + 1; |
| 122 uint32_t numbers_per_bucket; | 123 uint32_t numbers_per_bucket; |
| 123 if (interval == 0) { | 124 if (interval == 0) { |
| 124 // The computation high - low + 1 should be 2^32 but overflowed | 125 // The computation high - low + 1 should be 2^32 but overflowed |
| 125 // Hence, bucket_count must be a power of 2 | 126 // Hence, bucket_count must be a power of 2 |
| 126 ASSERT_EQ(bucket_count & (bucket_count - 1), 0u); | 127 ASSERT_EQ(bucket_count & (bucket_count - 1), 0u); |
| 127 numbers_per_bucket = (0x80000000u / bucket_count) * 2; | 128 numbers_per_bucket = (0x80000000u / bucket_count) * 2; |
| 128 } else { | 129 } else { |
| 129 ASSERT_EQ(interval % bucket_count, 0u); | 130 ASSERT_EQ(interval % bucket_count, 0u); |
| 130 numbers_per_bucket = interval / bucket_count; | 131 numbers_per_bucket = interval / bucket_count; |
| 131 } | 132 } |
| 132 | 133 |
| 133 for (unsigned int i = 0; i < samples; i++) { | 134 for (unsigned int i = 0; i < samples; i++) { |
| 134 int32_t sample = prng->Rand(low, high); | 135 int32_t sample = prng->Rand(low, high); |
| 135 EXPECT_LE(low, sample); | 136 EXPECT_LE(low, sample); |
| 136 EXPECT_GE(high, sample); | 137 EXPECT_GE(high, sample); |
| 137 buckets[static_cast<uint32_t>(sample - low) / numbers_per_bucket]++; | 138 buckets[unsigned_difference<int32_t>(sample, low) / numbers_per_bucket]++; |
| 138 } | 139 } |
| 139 | 140 |
| 140 for (unsigned int i = 0; i < bucket_count; i++) { | 141 for (unsigned int i = 0; i < bucket_count; i++) { |
| 141 // Expect the result to be within 3 standard deviations of the mean, | 142 // Expect the result to be within 3 standard deviations of the mean, |
| 142 // or more generally, within sigma_level standard deviations of the mean. | 143 // or more generally, within sigma_level standard deviations of the mean. |
| 143 double mean = static_cast<double>(samples) / bucket_count; | 144 double mean = static_cast<double>(samples) / bucket_count; |
| 144 EXPECT_NEAR(buckets[i], mean, sigma_level * sqrt(mean)); | 145 EXPECT_NEAR(buckets[i], mean, sigma_level * sqrt(mean)); |
| 145 } | 146 } |
| 146 } | 147 } |
| 147 | 148 |
| 148 // The range of the random numbers is divided into bucket_count intervals | 149 // The range of the random numbers is divided into bucket_count intervals |
| 149 // of consecutive numbers. Check that approximately equally many numbers | 150 // of consecutive numbers. Check that approximately equally many numbers |
| 150 // from each inteval are generated. | 151 // from each inteval are generated. |
| 151 void BucketTestUnsignedInterval(unsigned int bucket_count, | 152 void BucketTestUnsignedInterval(unsigned int bucket_count, |
| 152 unsigned int samples, | 153 unsigned int samples, |
| 153 uint32_t low, | 154 uint32_t low, |
| 154 uint32_t high, | 155 uint32_t high, |
| 155 int sigma_level, | 156 int sigma_level, |
| 156 Random* prng) { | 157 Random* prng) { |
| 157 std::vector<unsigned int> buckets(bucket_count, 0); | 158 std::vector<unsigned int> buckets(bucket_count, 0); |
| 158 | 159 |
| 159 ASSERT_GE(high, low); | 160 ASSERT_GE(high, low); |
| 160 ASSERT_GE(bucket_count, 2u); | 161 ASSERT_GE(bucket_count, 2u); |
| 161 uint32_t interval = static_cast<uint32_t>(high - low + 1); | 162 uint32_t interval = high - low + 1; |
| 162 uint32_t numbers_per_bucket; | 163 uint32_t numbers_per_bucket; |
| 163 if (interval == 0) { | 164 if (interval == 0) { |
| 164 // The computation high - low + 1 should be 2^32 but overflowed | 165 // The computation high - low + 1 should be 2^32 but overflowed |
| 165 // Hence, bucket_count must be a power of 2 | 166 // Hence, bucket_count must be a power of 2 |
| 166 ASSERT_EQ(bucket_count & (bucket_count - 1), 0u); | 167 ASSERT_EQ(bucket_count & (bucket_count - 1), 0u); |
| 167 numbers_per_bucket = (0x80000000u / bucket_count) * 2; | 168 numbers_per_bucket = (0x80000000u / bucket_count) * 2; |
| 168 } else { | 169 } else { |
| 169 ASSERT_EQ(interval % bucket_count, 0u); | 170 ASSERT_EQ(interval % bucket_count, 0u); |
| 170 numbers_per_bucket = interval / bucket_count; | 171 numbers_per_bucket = interval / bucket_count; |
| 171 } | 172 } |
| 172 | 173 |
| 173 for (unsigned int i = 0; i < samples; i++) { | 174 for (unsigned int i = 0; i < samples; i++) { |
| 174 uint32_t sample = prng->Rand(low, high); | 175 uint32_t sample = prng->Rand(low, high); |
| 175 EXPECT_LE(low, sample); | 176 EXPECT_LE(low, sample); |
| 176 EXPECT_GE(high, sample); | 177 EXPECT_GE(high, sample); |
| 177 buckets[static_cast<uint32_t>(sample - low) / numbers_per_bucket]++; | 178 buckets[(sample - low) / numbers_per_bucket]++; |
| 178 } | 179 } |
| 179 | 180 |
| 180 for (unsigned int i = 0; i < bucket_count; i++) { | 181 for (unsigned int i = 0; i < bucket_count; i++) { |
| 181 // Expect the result to be within 3 standard deviations of the mean, | 182 // Expect the result to be within 3 standard deviations of the mean, |
| 182 // or more generally, within sigma_level standard deviations of the mean. | 183 // or more generally, within sigma_level standard deviations of the mean. |
| 183 double mean = static_cast<double>(samples) / bucket_count; | 184 double mean = static_cast<double>(samples) / bucket_count; |
| 184 EXPECT_NEAR(buckets[i], mean, sigma_level * sqrt(mean)); | 185 EXPECT_NEAR(buckets[i], mean, sigma_level * sqrt(mean)); |
| 185 } | 186 } |
| 186 } | 187 } |
| 187 | 188 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 double f_mid = kScale * exp((n - kMean) * (n - kMean) / kDiv); | 300 double f_mid = kScale * exp((n - kMean) * (n - kMean) / kDiv); |
| 300 double f_right = kScale * exp((n - kMean + 0.5) * (n - kMean + 0.5) / kDiv); | 301 double f_right = kScale * exp((n - kMean + 0.5) * (n - kMean + 0.5) / kDiv); |
| 301 double normal_dist = (f_left + 4 * f_mid + f_right) / 6; | 302 double normal_dist = (f_left + 4 * f_mid + f_right) / 6; |
| 302 // Expect the number of samples to be within 3 standard deviations | 303 // Expect the number of samples to be within 3 standard deviations |
| 303 // (rounded up) of the expected number of samples in the bucket. | 304 // (rounded up) of the expected number of samples in the bucket. |
| 304 EXPECT_NEAR(buckets[n], kN * normal_dist, 3 * sqrt(kN * normal_dist) + 1); | 305 EXPECT_NEAR(buckets[n], kN * normal_dist, 3 * sqrt(kN * normal_dist) + 1); |
| 305 } | 306 } |
| 306 } | 307 } |
| 307 | 308 |
| 308 } // namespace webrtc | 309 } // namespace webrtc |
| OLD | NEW |