blob: c8e7685bddad474394e6ce69dc1dde6b257def46 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001// Copyright 2017 The Abseil Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "absl/random/internal/randen_engine.h"
16
17#include <algorithm>
18#include <bitset>
19#include <random>
20#include <sstream>
21
22#include "gmock/gmock.h"
23#include "gtest/gtest.h"
24#include "absl/base/internal/raw_logging.h"
25#include "absl/random/internal/explicit_seed_seq.h"
26#include "absl/strings/str_cat.h"
27#include "absl/time/clock.h"
28
29#define UPDATE_GOLDEN 0
30
31using randen_u64 = absl::random_internal::randen_engine<uint64_t>;
32using randen_u32 = absl::random_internal::randen_engine<uint32_t>;
33using absl::random_internal::ExplicitSeedSeq;
34
35namespace {
36
37template <typename UIntType>
38class RandenEngineTypedTest : public ::testing::Test {};
39
40using UIntTypes = ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t>;
41
42TYPED_TEST_SUITE(RandenEngineTypedTest, UIntTypes);
43
44TYPED_TEST(RandenEngineTypedTest, VerifyReseedChangesAllValues) {
45 using randen = typename absl::random_internal::randen_engine<TypeParam>;
46 using result_type = typename randen::result_type;
47
48 const size_t kNumOutputs = (sizeof(randen) * 2 / sizeof(TypeParam)) + 1;
49 randen engine;
50
51 // MSVC emits error 2719 without the use of std::ref below.
52 // * formal parameter with __declspec(align('#')) won't be aligned
53
54 {
55 std::seed_seq seq1{1, 2, 3, 4, 5, 6, 7};
56 engine.seed(seq1);
57 }
58 result_type a[kNumOutputs];
59 std::generate(std::begin(a), std::end(a), std::ref(engine));
60
61 {
62 std::random_device rd;
63 std::seed_seq seq2{rd(), rd(), rd()};
64 engine.seed(seq2);
65 }
66 result_type b[kNumOutputs];
67 std::generate(std::begin(b), std::end(b), std::ref(engine));
68
69 // Test that generated sequence changed as sequence of bits, i.e. if about
70 // half of the bites were flipped between two non-correlated values.
71 size_t changed_bits = 0;
72 size_t unchanged_bits = 0;
73 size_t total_set = 0;
74 size_t total_bits = 0;
75 size_t equal_count = 0;
76 for (size_t i = 0; i < kNumOutputs; ++i) {
77 equal_count += (a[i] == b[i]) ? 1 : 0;
78 std::bitset<sizeof(result_type) * 8> bitset(a[i] ^ b[i]);
79 changed_bits += bitset.count();
80 unchanged_bits += bitset.size() - bitset.count();
81
82 std::bitset<sizeof(result_type) * 8> a_set(a[i]);
83 std::bitset<sizeof(result_type) * 8> b_set(b[i]);
84 total_set += a_set.count() + b_set.count();
85 total_bits += 2 * 8 * sizeof(result_type);
86 }
87 // On average, half the bits are changed between two calls.
88 EXPECT_LE(changed_bits, 0.60 * (changed_bits + unchanged_bits));
89 EXPECT_GE(changed_bits, 0.40 * (changed_bits + unchanged_bits));
90
91 // Verify using a quick normal-approximation to the binomial.
92 EXPECT_NEAR(total_set, total_bits * 0.5, 4 * std::sqrt(total_bits))
93 << "@" << total_set / static_cast<double>(total_bits);
94
95 // Also, A[i] == B[i] with probability (1/range) * N.
96 // Give this a pretty wide latitude, though.
97 const double kExpected = kNumOutputs / (1.0 * sizeof(result_type) * 8);
98 EXPECT_LE(equal_count, 1.0 + kExpected);
99}
100
101// Number of values that needs to be consumed to clean two sizes of buffer
102// and trigger third refresh. (slightly overestimates the actual state size).
103constexpr size_t kTwoBufferValues = sizeof(randen_u64) / sizeof(uint16_t) + 1;
104
105TYPED_TEST(RandenEngineTypedTest, VerifyDiscard) {
106 using randen = typename absl::random_internal::randen_engine<TypeParam>;
107
108 for (size_t num_used = 0; num_used < kTwoBufferValues; ++num_used) {
109 randen engine_used;
110 for (size_t i = 0; i < num_used; ++i) {
111 engine_used();
112 }
113
114 for (size_t num_discard = 0; num_discard < kTwoBufferValues;
115 ++num_discard) {
116 randen engine1 = engine_used;
117 randen engine2 = engine_used;
118 for (size_t i = 0; i < num_discard; ++i) {
119 engine1();
120 }
121 engine2.discard(num_discard);
122 for (size_t i = 0; i < kTwoBufferValues; ++i) {
123 const auto r1 = engine1();
124 const auto r2 = engine2();
125 ASSERT_EQ(r1, r2) << "used=" << num_used << " discard=" << num_discard;
126 }
127 }
128 }
129}
130
131TYPED_TEST(RandenEngineTypedTest, StreamOperatorsResult) {
132 using randen = typename absl::random_internal::randen_engine<TypeParam>;
133 std::wostringstream os;
134 std::wistringstream is;
135 randen engine;
136
137 EXPECT_EQ(&(os << engine), &os);
138 EXPECT_EQ(&(is >> engine), &is);
139}
140
141TYPED_TEST(RandenEngineTypedTest, StreamSerialization) {
142 using randen = typename absl::random_internal::randen_engine<TypeParam>;
143
144 for (size_t discard = 0; discard < kTwoBufferValues; ++discard) {
145 ExplicitSeedSeq seed_sequence{12, 34, 56};
146 randen engine(seed_sequence);
147 engine.discard(discard);
148
149 std::stringstream stream;
150 stream << engine;
151
152 randen new_engine;
153 stream >> new_engine;
154 for (size_t i = 0; i < 64; ++i) {
155 EXPECT_EQ(engine(), new_engine()) << " " << i;
156 }
157 }
158}
159
160constexpr size_t kNumGoldenOutputs = 127;
161
162// This test is checking if randen_engine is meets interface requirements
163// defined in [rand.req.urbg].
164TYPED_TEST(RandenEngineTypedTest, RandomNumberEngineInterface) {
165 using randen = typename absl::random_internal::randen_engine<TypeParam>;
166
167 using E = randen;
168 using T = typename E::result_type;
169
170 static_assert(std::is_copy_constructible<E>::value,
171 "randen_engine must be copy constructible");
172
173 static_assert(absl::is_copy_assignable<E>::value,
174 "randen_engine must be copy assignable");
175
176 static_assert(std::is_move_constructible<E>::value,
177 "randen_engine must be move constructible");
178
179 static_assert(absl::is_move_assignable<E>::value,
180 "randen_engine must be move assignable");
181
182 static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,
183 "return type of operator() must be result_type");
184
185 // Names after definition of [rand.req.urbg] in C++ standard.
186 // e us a value of E
187 // v is a lvalue of E
188 // x, y are possibly const values of E
189 // s is a value of T
190 // q is a value satisfying requirements of seed_sequence
191 // z is a value of type unsigned long long
192 // os is a some specialization of basic_ostream
193 // is is a some specialization of basic_istream
194
195 E e, v;
196 const E x, y;
197 T s = 1;
198 std::seed_seq q{1, 2, 3};
199 unsigned long long z = 1; // NOLINT(runtime/int)
200 std::wostringstream os;
201 std::wistringstream is;
202
203 E{};
204 E{x};
205 E{s};
206 E{q};
207
208 e.seed();
209
210 // MSVC emits error 2718 when using EXPECT_EQ(e, x)
211 // * actual parameter with __declspec(align('#')) won't be aligned
212 EXPECT_TRUE(e == x);
213
214 e.seed(q);
215 {
216 E tmp(q);
217 EXPECT_TRUE(e == tmp);
218 }
219
220 e();
221 {
222 E tmp(q);
223 EXPECT_TRUE(e != tmp);
224 }
225
226 e.discard(z);
227
228 static_assert(std::is_same<decltype(x == y), bool>::value,
229 "return type of operator== must be bool");
230
231 static_assert(std::is_same<decltype(x != y), bool>::value,
232 "return type of operator== must be bool");
233}
234
235TYPED_TEST(RandenEngineTypedTest, RandenEngineSFINAETest) {
236 using randen = typename absl::random_internal::randen_engine<TypeParam>;
237 using result_type = typename randen::result_type;
238
239 {
240 randen engine(result_type(1));
241 engine.seed(result_type(1));
242 }
243
244 {
245 result_type n = 1;
246 randen engine(n);
247 engine.seed(n);
248 }
249
250 {
251 randen engine(1);
252 engine.seed(1);
253 }
254
255 {
256 int n = 1;
257 randen engine(n);
258 engine.seed(n);
259 }
260
261 {
262 std::seed_seq seed_seq;
263 randen engine(seed_seq);
264 engine.seed(seed_seq);
265 }
266
267 {
268 randen engine{std::seed_seq()};
269 engine.seed(std::seed_seq());
270 }
271}
272
273TEST(RandenTest, VerifyGoldenRanden64Default) {
274 constexpr uint64_t kGolden[kNumGoldenOutputs] = {
275 0xc3c14f134e433977, 0xdda9f47cd90410ee, 0x887bf3087fd8ca10,
276 0xf0b780f545c72912, 0x15dbb1d37696599f, 0x30ec63baff3c6d59,
277 0xb29f73606f7f20a6, 0x02808a316f49a54c, 0x3b8feaf9d5c8e50e,
278 0x9cbf605e3fd9de8a, 0xc970ae1a78183bbb, 0xd8b2ffd356301ed5,
279 0xf4b327fe0fc73c37, 0xcdfd8d76eb8f9a19, 0xc3a506eb91420c9d,
280 0xd5af05dd3eff9556, 0x48db1bb78f83c4a1, 0x7023920e0d6bfe8c,
281 0x58d3575834956d42, 0xed1ef4c26b87b840, 0x8eef32a23e0b2df3,
282 0x497cabf3431154fc, 0x4e24370570029a8b, 0xd88b5749f090e5ea,
283 0xc651a582a970692f, 0x78fcec2cbb6342f5, 0x463cb745612f55db,
284 0x352ee4ad1816afe3, 0x026ff374c101da7e, 0x811ef0821c3de851,
285 0x6f7e616704c4fa59, 0xa0660379992d58fc, 0x04b0a374a3b795c7,
286 0x915f3445685da798, 0x26802a8ac76571ce, 0x4663352533ce1882,
287 0xb9fdefb4a24dc738, 0x5588ba3a4d6e6c51, 0xa2101a42d35f1956,
288 0x607195a5e200f5fd, 0x7e100308f3290764, 0xe1e5e03c759c0709,
289 0x082572cc5da6606f, 0xcbcf585399e432f1, 0xe8a2be4f8335d8f1,
290 0x0904469acbfee8f2, 0xf08bd31b6daecd51, 0x08e8a1f1a69da69a,
291 0x6542a20aad57bff5, 0x2e9705bb053d6b46, 0xda2fc9db0713c391,
292 0x78e3a810213b6ffb, 0xdc16a59cdd85f8a6, 0xc0932718cd55781f,
293 0xb9bfb29c2b20bfe5, 0xb97289c1be0f2f9c, 0xc0a2a0e403a892d4,
294 0x5524bb834771435b, 0x8265da3d39d1a750, 0xff4af3ab8d1b78c5,
295 0xf0ec5f424bcad77f, 0x66e455f627495189, 0xc82d3120b57e3270,
296 0x3424e47dc22596e3, 0xbc0c95129ccedcdd, 0xc191c595afc4dcbf,
297 0x120392bd2bb70939, 0x7f90650ea6cd6ab4, 0x7287491832695ad3,
298 0xa7c8fac5a7917eb0, 0xd088cb9418be0361, 0x7c1bf9839c7c1ce5,
299 0xe2e991fa58e1e79e, 0x78565cdefd28c4ad, 0x7351b9fef98bafad,
300 0x2a9eac28b08c96bf, 0x6c4f179696cb2225, 0x13a685861bab87e0,
301 0x64c6de5aa0501971, 0x30537425cac70991, 0x01590d9dc6c532b7,
302 0x7e05e3aa8ec720dc, 0x74a07d9c54e3e63f, 0x738184388f3bc1d2,
303 0x26ffdc5067be3acb, 0x6bcdf185561f255f, 0xa0eaf2e1cf99b1c6,
304 0x171df81934f68604, 0x7ea5a21665683e5a, 0x5d1cb02075ba1cea,
305 0x957f38cbd2123fdf, 0xba6364eff80de02f, 0x606e0a0e41d452ee,
306 0x892d8317de82f7a2, 0xe707b1db50f7b43e, 0x4eb28826766fcf5b,
307 0x5a362d56e80a0951, 0x6ee217df16527d78, 0xf6737962ba6b23dd,
308 0x443e63857d4076ca, 0x790d9a5f048adfeb, 0xd796b052151ee94d,
309 0x033ed95c12b04a03, 0x8b833ff84893da5d, 0x3d6724b1bb15eab9,
310 0x9877c4225061ca76, 0xd68d6810adf74fb3, 0x42e5352fe30ce989,
311 0x265b565a7431fde7, 0x3cdbf7e358df4b8b, 0x2922a47f6d3e8779,
312 0x52d2242f65b37f88, 0x5d836d6e2958d6b5, 0x29d40f00566d5e26,
313 0x288db0e1124b14a0, 0x6c056608b7d9c1b6, 0x0b9471bdb8f19d32,
314 0x8fb946504faa6c9d, 0x8943a9464540251c, 0xfd1fe27d144a09e0,
315 0xea6ac458da141bda, 0x8048f217633fce36, 0xfeda1384ade74d31,
316 0x4334b8b02ff7612f, 0xdbc8441f5227e216, 0x096d119a3605c85b,
317 0x2b72b31c21b7d7d0};
318
319 randen_u64 engine;
320#if UPDATE_GOLDEN
321 (void)kGolden; // Silence warning.
322 for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
323 printf("0x%016lx, ", engine());
324 if (i % 3 == 2) {
325 printf("\n");
326 }
327 }
328 printf("\n\n\n");
329#else
330 for (const auto& elem : kGolden) {
331 EXPECT_EQ(elem, engine());
332 }
333 engine.seed();
334 for (const auto& elem : kGolden) {
335 EXPECT_EQ(elem, engine());
336 }
337#endif
338}
339
340TEST(RandenTest, VerifyGoldenRanden64Seeded) {
341 constexpr uint64_t kGolden[kNumGoldenOutputs] = {
342 0x83a9e58f94d3dcd5, 0x70bbdff3d97949fb, 0x0438481f7471c1b4,
343 0x34fdc58ee5fb5930, 0xceee4f2d2a937d17, 0xb5a26a68e432aea9,
344 0x8b64774a3fb51740, 0xd89ac1fc74249c74, 0x03910d1d23fc3fdf,
345 0xd38f630878aa897f, 0x0ee8f0f5615f7e44, 0x98f5a53df8279d52,
346 0xb403f52c25938d0e, 0x240072996ea6e838, 0xd3a791246190fa61,
347 0xaaedd3df7a7b4f80, 0xc6eacabe05deaf6e, 0xb7967dd8790edf4d,
348 0x9a0a8e67e049d279, 0x0494f606aebc23e7, 0x598dcd687bc3e0ee,
349 0x010ac81802d452a1, 0x6407c87160aa2842, 0x5a56e276486f93a0,
350 0xc887a399d46a8f02, 0x9e1e6100fe93b740, 0x12d02e330f8901f6,
351 0xc39ca52b47e790b7, 0xb0b0a2fa11e82e61, 0x1542d841a303806a,
352 0x1fe659fd7d6e9d86, 0xb8c90d80746541ac, 0x239d56a5669ddc94,
353 0xd40db57c8123d13c, 0x3abc2414153a0db0, 0x9bad665630cb8d61,
354 0x0bd1fb90ee3f4bbc, 0x8f0b4d7e079b4e42, 0xfa0fb0e0ee59e793,
355 0x51080b283e071100, 0x2c4b9e715081cc15, 0xbe10ed49de4941df,
356 0xf8eaac9d4b1b0d37, 0x4bcce4b54605e139, 0xa64722b76765dda6,
357 0xb9377d738ca28ab5, 0x779fad81a8ccc1af, 0x65cb3ee61ffd3ba7,
358 0xd74e79087862836f, 0xd05b9c584c3f25bf, 0x2ba93a4693579827,
359 0xd81530aff05420ce, 0xec06cea215478621, 0x4b1798a6796d65ad,
360 0xf142f3fb3a6f6fa6, 0x002b7bf7e237b560, 0xf47f2605ef65b4f8,
361 0x9804ec5517effc18, 0xaed3d7f8b7d481cd, 0x5651c24c1ce338d1,
362 0x3e7a38208bf0a3c6, 0x6796a7b614534aed, 0x0d0f3b848358460f,
363 0x0fa5fe7600b19524, 0x2b0cf38253faaedc, 0x10df9188233a9fd6,
364 0x3a10033880138b59, 0x5fb0b0d23948e80f, 0x9e76f7b02fbf5350,
365 0x0816052304b1a985, 0x30c9880db41fd218, 0x14aa399b65e20f28,
366 0xe1454a8cace787b4, 0x325ac971b6c6f0f5, 0x716b1aa2784f3d36,
367 0x3d5ce14accfd144f, 0x6c0c97710f651792, 0xbc5b0f59fb333532,
368 0x2a90a7d2140470bc, 0x8da269f55c1e1c8d, 0xcfc37143895792ca,
369 0xbe21eab1f30b238f, 0x8c47229dee4d65fd, 0x5743614ed1ed7d54,
370 0x351372a99e9c476e, 0x2bd5ea15e5db085f, 0x6925fde46e0af4ca,
371 0xed3eda2bdc1f45bd, 0xdef68c68d460fa6e, 0xe42a0de76253e2b5,
372 0x4e5176dcbc29c305, 0xbfd85fba9f810f6e, 0x76a5a2a9beb815c6,
373 0x01edc4ddceaf414c, 0xa4e98904b4bb3b4b, 0x00bd63ac7d2f1ddd,
374 0xb8491fe6e998ddbb, 0xb386a3463dda6800, 0x0081887688871619,
375 0x33d394b3344e9a38, 0x815dba65a3a8baf9, 0x4232f6ec02c2fd1a,
376 0xb5cff603edd20834, 0x580189243f687663, 0xa8d5a2cbdc27fe99,
377 0x725d881693fa0131, 0xa2be2c13db2c7ac5, 0x7b6a9614b509fd78,
378 0xb6b136d71e717636, 0x660f1a71aff046ea, 0x0ba10ae346c8ec9e,
379 0xe66dde53e3145b41, 0x3b18288c88c26be6, 0x4d9d9d2ff02db933,
380 0x4167da8c70f46e8a, 0xf183beef8c6318b4, 0x4d889e1e71eeeef1,
381 0x7175c71ad6689b6b, 0xfb9e42beacd1b7dd, 0xc33d0e91b29b5e0d,
382 0xd39b83291ce47922, 0xc4d570fb8493d12e, 0x23d5a5724f424ae6,
383 0x5245f161876b6616, 0x38d77dbd21ab578d, 0x9c3423311f4ecbfe,
384 0x76fe31389bacd9d5,
385 };
386
387 ExplicitSeedSeq seed_sequence{12, 34, 56};
388 randen_u64 engine(seed_sequence);
389#if UPDATE_GOLDEN
390 (void)kGolden; // Silence warning.
391 for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
392 printf("0x%016lx, ", engine());
393 if (i % 3 == 2) {
394 printf("\n");
395 }
396 }
397 printf("\n\n\n");
398#else
399 for (const auto& elem : kGolden) {
400 EXPECT_EQ(elem, engine());
401 }
402 engine.seed(seed_sequence);
403 for (const auto& elem : kGolden) {
404 EXPECT_EQ(elem, engine());
405 }
406#endif
407}
408
409TEST(RandenTest, VerifyGoldenRanden32Default) {
410 constexpr uint64_t kGolden[2 * kNumGoldenOutputs] = {
411 0x4e433977, 0xc3c14f13, 0xd90410ee, 0xdda9f47c, 0x7fd8ca10, 0x887bf308,
412 0x45c72912, 0xf0b780f5, 0x7696599f, 0x15dbb1d3, 0xff3c6d59, 0x30ec63ba,
413 0x6f7f20a6, 0xb29f7360, 0x6f49a54c, 0x02808a31, 0xd5c8e50e, 0x3b8feaf9,
414 0x3fd9de8a, 0x9cbf605e, 0x78183bbb, 0xc970ae1a, 0x56301ed5, 0xd8b2ffd3,
415 0x0fc73c37, 0xf4b327fe, 0xeb8f9a19, 0xcdfd8d76, 0x91420c9d, 0xc3a506eb,
416 0x3eff9556, 0xd5af05dd, 0x8f83c4a1, 0x48db1bb7, 0x0d6bfe8c, 0x7023920e,
417 0x34956d42, 0x58d35758, 0x6b87b840, 0xed1ef4c2, 0x3e0b2df3, 0x8eef32a2,
418 0x431154fc, 0x497cabf3, 0x70029a8b, 0x4e243705, 0xf090e5ea, 0xd88b5749,
419 0xa970692f, 0xc651a582, 0xbb6342f5, 0x78fcec2c, 0x612f55db, 0x463cb745,
420 0x1816afe3, 0x352ee4ad, 0xc101da7e, 0x026ff374, 0x1c3de851, 0x811ef082,
421 0x04c4fa59, 0x6f7e6167, 0x992d58fc, 0xa0660379, 0xa3b795c7, 0x04b0a374,
422 0x685da798, 0x915f3445, 0xc76571ce, 0x26802a8a, 0x33ce1882, 0x46633525,
423 0xa24dc738, 0xb9fdefb4, 0x4d6e6c51, 0x5588ba3a, 0xd35f1956, 0xa2101a42,
424 0xe200f5fd, 0x607195a5, 0xf3290764, 0x7e100308, 0x759c0709, 0xe1e5e03c,
425 0x5da6606f, 0x082572cc, 0x99e432f1, 0xcbcf5853, 0x8335d8f1, 0xe8a2be4f,
426 0xcbfee8f2, 0x0904469a, 0x6daecd51, 0xf08bd31b, 0xa69da69a, 0x08e8a1f1,
427 0xad57bff5, 0x6542a20a, 0x053d6b46, 0x2e9705bb, 0x0713c391, 0xda2fc9db,
428 0x213b6ffb, 0x78e3a810, 0xdd85f8a6, 0xdc16a59c, 0xcd55781f, 0xc0932718,
429 0x2b20bfe5, 0xb9bfb29c, 0xbe0f2f9c, 0xb97289c1, 0x03a892d4, 0xc0a2a0e4,
430 0x4771435b, 0x5524bb83, 0x39d1a750, 0x8265da3d, 0x8d1b78c5, 0xff4af3ab,
431 0x4bcad77f, 0xf0ec5f42, 0x27495189, 0x66e455f6, 0xb57e3270, 0xc82d3120,
432 0xc22596e3, 0x3424e47d, 0x9ccedcdd, 0xbc0c9512, 0xafc4dcbf, 0xc191c595,
433 0x2bb70939, 0x120392bd, 0xa6cd6ab4, 0x7f90650e, 0x32695ad3, 0x72874918,
434 0xa7917eb0, 0xa7c8fac5, 0x18be0361, 0xd088cb94, 0x9c7c1ce5, 0x7c1bf983,
435 0x58e1e79e, 0xe2e991fa, 0xfd28c4ad, 0x78565cde, 0xf98bafad, 0x7351b9fe,
436 0xb08c96bf, 0x2a9eac28, 0x96cb2225, 0x6c4f1796, 0x1bab87e0, 0x13a68586,
437 0xa0501971, 0x64c6de5a, 0xcac70991, 0x30537425, 0xc6c532b7, 0x01590d9d,
438 0x8ec720dc, 0x7e05e3aa, 0x54e3e63f, 0x74a07d9c, 0x8f3bc1d2, 0x73818438,
439 0x67be3acb, 0x26ffdc50, 0x561f255f, 0x6bcdf185, 0xcf99b1c6, 0xa0eaf2e1,
440 0x34f68604, 0x171df819, 0x65683e5a, 0x7ea5a216, 0x75ba1cea, 0x5d1cb020,
441 0xd2123fdf, 0x957f38cb, 0xf80de02f, 0xba6364ef, 0x41d452ee, 0x606e0a0e,
442 0xde82f7a2, 0x892d8317, 0x50f7b43e, 0xe707b1db, 0x766fcf5b, 0x4eb28826,
443 0xe80a0951, 0x5a362d56, 0x16527d78, 0x6ee217df, 0xba6b23dd, 0xf6737962,
444 0x7d4076ca, 0x443e6385, 0x048adfeb, 0x790d9a5f, 0x151ee94d, 0xd796b052,
445 0x12b04a03, 0x033ed95c, 0x4893da5d, 0x8b833ff8, 0xbb15eab9, 0x3d6724b1,
446 0x5061ca76, 0x9877c422, 0xadf74fb3, 0xd68d6810, 0xe30ce989, 0x42e5352f,
447 0x7431fde7, 0x265b565a, 0x58df4b8b, 0x3cdbf7e3, 0x6d3e8779, 0x2922a47f,
448 0x65b37f88, 0x52d2242f, 0x2958d6b5, 0x5d836d6e, 0x566d5e26, 0x29d40f00,
449 0x124b14a0, 0x288db0e1, 0xb7d9c1b6, 0x6c056608, 0xb8f19d32, 0x0b9471bd,
450 0x4faa6c9d, 0x8fb94650, 0x4540251c, 0x8943a946, 0x144a09e0, 0xfd1fe27d,
451 0xda141bda, 0xea6ac458, 0x633fce36, 0x8048f217, 0xade74d31, 0xfeda1384,
452 0x2ff7612f, 0x4334b8b0, 0x5227e216, 0xdbc8441f, 0x3605c85b, 0x096d119a,
453 0x21b7d7d0, 0x2b72b31c};
454
455 randen_u32 engine;
456#if UPDATE_GOLDEN
457 (void)kGolden; // Silence warning.
458 for (size_t i = 0; i < 2 * kNumGoldenOutputs; ++i) {
459 printf("0x%08x, ", engine());
460 if (i % 6 == 5) {
461 printf("\n");
462 }
463 }
464 printf("\n\n\n");
465#else
466 for (const auto& elem : kGolden) {
467 EXPECT_EQ(elem, engine());
468 }
469 engine.seed();
470 for (const auto& elem : kGolden) {
471 EXPECT_EQ(elem, engine());
472 }
473#endif
474}
475
476TEST(RandenTest, VerifyGoldenRanden32Seeded) {
477 constexpr uint64_t kGolden[2 * kNumGoldenOutputs] = {
478 0x94d3dcd5, 0x83a9e58f, 0xd97949fb, 0x70bbdff3, 0x7471c1b4, 0x0438481f,
479 0xe5fb5930, 0x34fdc58e, 0x2a937d17, 0xceee4f2d, 0xe432aea9, 0xb5a26a68,
480 0x3fb51740, 0x8b64774a, 0x74249c74, 0xd89ac1fc, 0x23fc3fdf, 0x03910d1d,
481 0x78aa897f, 0xd38f6308, 0x615f7e44, 0x0ee8f0f5, 0xf8279d52, 0x98f5a53d,
482 0x25938d0e, 0xb403f52c, 0x6ea6e838, 0x24007299, 0x6190fa61, 0xd3a79124,
483 0x7a7b4f80, 0xaaedd3df, 0x05deaf6e, 0xc6eacabe, 0x790edf4d, 0xb7967dd8,
484 0xe049d279, 0x9a0a8e67, 0xaebc23e7, 0x0494f606, 0x7bc3e0ee, 0x598dcd68,
485 0x02d452a1, 0x010ac818, 0x60aa2842, 0x6407c871, 0x486f93a0, 0x5a56e276,
486 0xd46a8f02, 0xc887a399, 0xfe93b740, 0x9e1e6100, 0x0f8901f6, 0x12d02e33,
487 0x47e790b7, 0xc39ca52b, 0x11e82e61, 0xb0b0a2fa, 0xa303806a, 0x1542d841,
488 0x7d6e9d86, 0x1fe659fd, 0x746541ac, 0xb8c90d80, 0x669ddc94, 0x239d56a5,
489 0x8123d13c, 0xd40db57c, 0x153a0db0, 0x3abc2414, 0x30cb8d61, 0x9bad6656,
490 0xee3f4bbc, 0x0bd1fb90, 0x079b4e42, 0x8f0b4d7e, 0xee59e793, 0xfa0fb0e0,
491 0x3e071100, 0x51080b28, 0x5081cc15, 0x2c4b9e71, 0xde4941df, 0xbe10ed49,
492 0x4b1b0d37, 0xf8eaac9d, 0x4605e139, 0x4bcce4b5, 0x6765dda6, 0xa64722b7,
493 0x8ca28ab5, 0xb9377d73, 0xa8ccc1af, 0x779fad81, 0x1ffd3ba7, 0x65cb3ee6,
494 0x7862836f, 0xd74e7908, 0x4c3f25bf, 0xd05b9c58, 0x93579827, 0x2ba93a46,
495 0xf05420ce, 0xd81530af, 0x15478621, 0xec06cea2, 0x796d65ad, 0x4b1798a6,
496 0x3a6f6fa6, 0xf142f3fb, 0xe237b560, 0x002b7bf7, 0xef65b4f8, 0xf47f2605,
497 0x17effc18, 0x9804ec55, 0xb7d481cd, 0xaed3d7f8, 0x1ce338d1, 0x5651c24c,
498 0x8bf0a3c6, 0x3e7a3820, 0x14534aed, 0x6796a7b6, 0x8358460f, 0x0d0f3b84,
499 0x00b19524, 0x0fa5fe76, 0x53faaedc, 0x2b0cf382, 0x233a9fd6, 0x10df9188,
500 0x80138b59, 0x3a100338, 0x3948e80f, 0x5fb0b0d2, 0x2fbf5350, 0x9e76f7b0,
501 0x04b1a985, 0x08160523, 0xb41fd218, 0x30c9880d, 0x65e20f28, 0x14aa399b,
502 0xace787b4, 0xe1454a8c, 0xb6c6f0f5, 0x325ac971, 0x784f3d36, 0x716b1aa2,
503 0xccfd144f, 0x3d5ce14a, 0x0f651792, 0x6c0c9771, 0xfb333532, 0xbc5b0f59,
504 0x140470bc, 0x2a90a7d2, 0x5c1e1c8d, 0x8da269f5, 0x895792ca, 0xcfc37143,
505 0xf30b238f, 0xbe21eab1, 0xee4d65fd, 0x8c47229d, 0xd1ed7d54, 0x5743614e,
506 0x9e9c476e, 0x351372a9, 0xe5db085f, 0x2bd5ea15, 0x6e0af4ca, 0x6925fde4,
507 0xdc1f45bd, 0xed3eda2b, 0xd460fa6e, 0xdef68c68, 0x6253e2b5, 0xe42a0de7,
508 0xbc29c305, 0x4e5176dc, 0x9f810f6e, 0xbfd85fba, 0xbeb815c6, 0x76a5a2a9,
509 0xceaf414c, 0x01edc4dd, 0xb4bb3b4b, 0xa4e98904, 0x7d2f1ddd, 0x00bd63ac,
510 0xe998ddbb, 0xb8491fe6, 0x3dda6800, 0xb386a346, 0x88871619, 0x00818876,
511 0x344e9a38, 0x33d394b3, 0xa3a8baf9, 0x815dba65, 0x02c2fd1a, 0x4232f6ec,
512 0xedd20834, 0xb5cff603, 0x3f687663, 0x58018924, 0xdc27fe99, 0xa8d5a2cb,
513 0x93fa0131, 0x725d8816, 0xdb2c7ac5, 0xa2be2c13, 0xb509fd78, 0x7b6a9614,
514 0x1e717636, 0xb6b136d7, 0xaff046ea, 0x660f1a71, 0x46c8ec9e, 0x0ba10ae3,
515 0xe3145b41, 0xe66dde53, 0x88c26be6, 0x3b18288c, 0xf02db933, 0x4d9d9d2f,
516 0x70f46e8a, 0x4167da8c, 0x8c6318b4, 0xf183beef, 0x71eeeef1, 0x4d889e1e,
517 0xd6689b6b, 0x7175c71a, 0xacd1b7dd, 0xfb9e42be, 0xb29b5e0d, 0xc33d0e91,
518 0x1ce47922, 0xd39b8329, 0x8493d12e, 0xc4d570fb, 0x4f424ae6, 0x23d5a572,
519 0x876b6616, 0x5245f161, 0x21ab578d, 0x38d77dbd, 0x1f4ecbfe, 0x9c342331,
520 0x9bacd9d5, 0x76fe3138,
521 };
522
523 ExplicitSeedSeq seed_sequence{12, 34, 56};
524 randen_u32 engine(seed_sequence);
525#if UPDATE_GOLDEN
526 (void)kGolden; // Silence warning.
527 for (size_t i = 0; i < 2 * kNumGoldenOutputs; ++i) {
528 printf("0x%08x, ", engine());
529 if (i % 6 == 5) {
530 printf("\n");
531 }
532 }
533 printf("\n\n\n");
534#else
535 for (const auto& elem : kGolden) {
536 EXPECT_EQ(elem, engine());
537 }
538 engine.seed(seed_sequence);
539 for (const auto& elem : kGolden) {
540 EXPECT_EQ(elem, engine());
541 }
542#endif
543}
544
545TEST(RandenTest, VerifyGoldenFromDeserializedEngine) {
546 constexpr uint64_t kGolden[kNumGoldenOutputs] = {
547 0x067f9f9ab919657a, 0x0534605912988583, 0x8a303f72feaa673f,
548 0x77b7fd747909185c, 0xd9af90403c56d891, 0xd939c6cb204d14b5,
549 0x7fbe6b954a47b483, 0x8b31a47cc34c768d, 0x3a9e546da2701a9c,
550 0x5246539046253e71, 0x417191ffb2a848a1, 0x7b1c7bf5a5001d09,
551 0x9489b15d194f2361, 0xfcebdeea3bcd2461, 0xd643027c854cec97,
552 0x5885397f91e0d21c, 0x53173b0efae30d58, 0x1c9c71168449fac1,
553 0xe358202b711ed8aa, 0x94e3918ed1d8227c, 0x5bb4e251450144cf,
554 0xb5c7a519b489af3b, 0x6f8b560b1f7b3469, 0xfde11dd4a1c74eef,
555 0x33383d2f76457dcf, 0x3060c0ec6db9fce1, 0x18f451fcddeec766,
556 0xe73c5d6b9f26da2a, 0x8d4cc566671b32a4, 0xb8189b73776bc9ff,
557 0x497a70f9caf0bc23, 0x23afcc509791dcea, 0x18af70dc4b27d306,
558 0xd3853f955a0ce5b9, 0x441db6c01a0afb17, 0xd0136c3fb8e1f13f,
559 0x5e4fd6fc2f33783c, 0xe0d24548adb5da51, 0x0f4d8362a7d3485a,
560 0x9f572d68270fa563, 0x6351fbc823024393, 0xa66dbfc61810e9ab,
561 0x0ff17fc14b651af8, 0xd74c55dafb99e623, 0x36303bc1ad85c6c2,
562 0x4920cd6a2af7e897, 0x0b8848addc30fecd, 0x9e1562eda6488e93,
563 0x197553807d607828, 0xbef5eaeda5e21235, 0x18d91d2616aca527,
564 0xb7821937f5c873cd, 0x2cd4ae5650dbeefc, 0xb35a64376f75ffdf,
565 0x9226d414d647fe07, 0x663f3db455bbb35e, 0xa829eead6ae93247,
566 0x7fd69c204dd0d25f, 0xbe1411f891c9acb1, 0xd476f34a506d5f11,
567 0xf423d2831649c5ca, 0x1e503962951abd75, 0xeccc9e8b1e34b537,
568 0xb11a147294044854, 0xc4cf27f0abf4929d, 0xe9193abf6fa24c8c,
569 0xa94a259e3aba8808, 0x21dc414197deffa3, 0xa2ae211d1ff622ae,
570 0xfe3995c46be5a4f4, 0xe9984c284bf11128, 0xcb1ce9d2f0851a80,
571 0x42fee17971d87cd8, 0xac76a98d177adc88, 0xa0973b3dedc4af6f,
572 0xdf56d6bbcb1b8e86, 0xf1e6485f407b11c9, 0x2c63de4deccb15c0,
573 0x6fe69db32ed4fad7, 0xaa51a65f84bca1f1, 0x242f2ee81d608afc,
574 0x8eb88b2b69fc153b, 0x22c20098baf73fd1, 0x57759466f576488c,
575 0x075ca562cea1be9d, 0x9a74814d73d28891, 0x73d1555fc02f4d3d,
576 0xc17f8f210ee89337, 0x46cca7999eaeafd4, 0x5db8d6a327a0d8ac,
577 0xb79b4f93c738d7a1, 0x9994512f0036ded1, 0xd3883026f38747f4,
578 0xf31f7458078d097c, 0x736ce4d480680669, 0x7a496f4c7e1033e3,
579 0xecf85bf297fbc68c, 0x9e37e1d0f24f3c4e, 0x15b6e067ca0746fc,
580 0xdd4a39905c5db81c, 0xb5dfafa7bcfdf7da, 0xca6646fb6f92a276,
581 0x1c6b35f363ef0efd, 0x6a33d06037ad9f76, 0x45544241afd8f80f,
582 0x83f8d83f859c90c5, 0x22aea9c5365e8c19, 0xfac35b11f20b6a6a,
583 0xd1acf49d1a27dd2f, 0xf281cd09c4fed405, 0x076000a42cd38e4f,
584 0x6ace300565070445, 0x463a62781bddc4db, 0x1477126b46b569ac,
585 0x127f2bb15035fbb8, 0xdfa30946049c04a8, 0x89072a586ba8dd3e,
586 0x62c809582bb7e74d, 0x22c0c3641406c28b, 0x9b66e36c47ff004d,
587 0xb9cd2c7519653330, 0x18608d79cd7a598d, 0x92c0bd1323e53e32,
588 0x887ff00de8524aa5, 0xa074410b787abd10, 0x18ab41b8057a2063,
589 0x1560abf26bc5f987};
590
591#if UPDATE_GOLDEN
592 (void)kGolden; // Silence warning.
593 std::seed_seq seed_sequence{1, 2, 3, 4, 5};
594 randen_u64 engine(seed_sequence);
595 std::ostringstream stream;
596 stream << engine;
597 auto str = stream.str();
598 printf("%s\n\n", str.c_str());
599 for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
600 printf("0x%016lx, ", engine());
601 if (i % 3 == 2) {
602 printf("\n");
603 }
604 }
605 printf("\n\n\n");
606#else
607 randen_u64 engine;
608 std::istringstream stream(
609 "0 0 9824501439887287479 3242284395352394785 243836530774933777 "
610 "4047941804708365596 17165468127298385802 949276103645889255 "
611 "10659970394998657921 1657570836810929787 11697746266668051452 "
612 "9967209969299905230 14140390331161524430 7383014124183271684 "
613 "13146719127702337852 13983155220295807171 11121125587542359264 "
614 "195757810993252695 17138580243103178492 11326030747260920501 "
615 "8585097322474965590 18342582839328350995 15052982824209724634 "
616 "7321861343874683609 1806786911778767826 10100850842665572955 "
617 "9249328950653985078 13600624835326909759 11137960060943860251 "
618 "10208781341792329629 9282723971471525577 16373271619486811032 32");
619 stream >> engine;
620 for (const auto& elem : kGolden) {
621 EXPECT_EQ(elem, engine());
622 }
623#endif
624}
625
626TEST(RandenTest, IsFastOrSlow) {
627 // randen_engine typically costs ~5ns per value for the optimized code paths,
628 // and the ~1000ns per value for slow code paths. However when running under
629 // msan, asan, etc. it can take much longer.
630 //
631 // The estimated operation time is something like:
632 //
633 // linux, optimized ~5ns
634 // ppc, optimized ~7ns
635 // nacl (slow), ~1100ns
636 //
637 // `kCount` is chosen below so that, in debug builds and without hardware
638 // acceleration, the test (assuming ~1us per call) should finish in ~0.1s
639 static constexpr size_t kCount = 100000;
640 randen_u64 engine;
641 randen_u64::result_type sum = 0;
642 auto start = absl::GetCurrentTimeNanos();
643 for (int i = 0; i < kCount; i++) {
644 sum += engine();
645 }
646 auto duration = absl::GetCurrentTimeNanos() - start;
647
648 ABSL_INTERNAL_LOG(INFO, absl::StrCat(static_cast<double>(duration) /
649 static_cast<double>(kCount),
650 "ns"));
651
652 EXPECT_GT(sum, 0);
653 EXPECT_GE(duration, kCount); // Should be slower than 1ns per call.
654}
655
656} // namespace