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 |