tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pcg_engine_test.cc (25153B)


      1 // Copyright 2018 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/pcg_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/random/internal/explicit_seed_seq.h"
     25 #include "absl/time/clock.h"
     26 
     27 #define UPDATE_GOLDEN 0
     28 
     29 namespace {
     30 
     31 using absl::random_internal::ExplicitSeedSeq;
     32 using absl::random_internal::pcg32_2018_engine;
     33 using absl::random_internal::pcg64_2018_engine;
     34 
     35 template <typename EngineType>
     36 class PCGEngineTest : public ::testing::Test {};
     37 
     38 using EngineTypes = ::testing::Types<pcg64_2018_engine, pcg32_2018_engine>;
     39 
     40 TYPED_TEST_SUITE(PCGEngineTest, EngineTypes);
     41 
     42 TYPED_TEST(PCGEngineTest, VerifyReseedChangesAllValues) {
     43  using engine_type = TypeParam;
     44  using result_type = typename engine_type::result_type;
     45 
     46  const size_t kNumOutputs = 16;
     47  engine_type engine;
     48 
     49  // MSVC emits error 2719 without the use of std::ref below.
     50  //  * formal parameter with __declspec(align('#')) won't be aligned
     51 
     52  {
     53    std::seed_seq seq1{1, 2, 3, 4, 5, 6, 7};
     54    engine.seed(seq1);
     55  }
     56  result_type a[kNumOutputs];
     57  std::generate(std::begin(a), std::end(a), std::ref(engine));
     58 
     59  {
     60    std::random_device rd;
     61    std::seed_seq seq2{rd(), rd(), rd()};
     62    engine.seed(seq2);
     63  }
     64  result_type b[kNumOutputs];
     65  std::generate(std::begin(b), std::end(b), std::ref(engine));
     66 
     67  // Verify that two uncorrelated values have ~50% of there bits in common. Use
     68  // a 10% margin-of-error to reduce flakiness.
     69  size_t changed_bits = 0;
     70  size_t unchanged_bits = 0;
     71  size_t total_set = 0;
     72  size_t total_bits = 0;
     73  size_t equal_count = 0;
     74  for (size_t i = 0; i < kNumOutputs; ++i) {
     75    equal_count += (a[i] == b[i]) ? 1 : 0;
     76    std::bitset<sizeof(result_type) * 8> bitset(a[i] ^ b[i]);
     77    changed_bits += bitset.count();
     78    unchanged_bits += bitset.size() - bitset.count();
     79 
     80    std::bitset<sizeof(result_type) * 8> a_set(a[i]);
     81    std::bitset<sizeof(result_type) * 8> b_set(b[i]);
     82    total_set += a_set.count() + b_set.count();
     83    total_bits += 2 * 8 * sizeof(result_type);
     84  }
     85  // On average, half the bits are changed between two calls.
     86  EXPECT_LE(changed_bits, 0.60 * (changed_bits + unchanged_bits));
     87  EXPECT_GE(changed_bits, 0.40 * (changed_bits + unchanged_bits));
     88 
     89  // verify using a quick normal-approximation to the binomial.
     90  EXPECT_NEAR(total_set, total_bits * 0.5, 4 * std::sqrt(total_bits))
     91      << "@" << total_set / static_cast<double>(total_bits);
     92 
     93  // Also, A[i] == B[i] with probability (1/range) * N.
     94  // Give this a pretty wide latitude, though.
     95  const double kExpected = kNumOutputs / (1.0 * sizeof(result_type) * 8);
     96  EXPECT_LE(equal_count, 1.0 + kExpected);
     97 }
     98 
     99 // Number of values that needs to be consumed to clean two sizes of buffer
    100 // and trigger third refresh. (slightly overestimates the actual state size).
    101 constexpr size_t kTwoBufferValues = 16;
    102 
    103 TYPED_TEST(PCGEngineTest, VerifyDiscard) {
    104  using engine_type = TypeParam;
    105 
    106  for (size_t num_used = 0; num_used < kTwoBufferValues; ++num_used) {
    107    engine_type engine_used;
    108    for (size_t i = 0; i < num_used; ++i) {
    109      engine_used();
    110    }
    111 
    112    for (size_t num_discard = 0; num_discard < kTwoBufferValues;
    113         ++num_discard) {
    114      engine_type engine1 = engine_used;
    115      engine_type engine2 = engine_used;
    116      for (size_t i = 0; i < num_discard; ++i) {
    117        engine1();
    118      }
    119      engine2.discard(num_discard);
    120      for (size_t i = 0; i < kTwoBufferValues; ++i) {
    121        const auto r1 = engine1();
    122        const auto r2 = engine2();
    123        ASSERT_EQ(r1, r2) << "used=" << num_used << " discard=" << num_discard;
    124      }
    125    }
    126  }
    127 }
    128 
    129 TYPED_TEST(PCGEngineTest, StreamOperatorsResult) {
    130  using engine_type = TypeParam;
    131 
    132  std::wostringstream os;
    133  std::wistringstream is;
    134  engine_type engine;
    135 
    136  EXPECT_EQ(&(os << engine), &os);
    137  EXPECT_EQ(&(is >> engine), &is);
    138 }
    139 
    140 TYPED_TEST(PCGEngineTest, StreamSerialization) {
    141  using engine_type = TypeParam;
    142 
    143  for (size_t discard = 0; discard < kTwoBufferValues; ++discard) {
    144    ExplicitSeedSeq seed_sequence{12, 34, 56};
    145    engine_type engine(seed_sequence);
    146    engine.discard(discard);
    147 
    148    std::stringstream stream;
    149    stream << engine;
    150 
    151    engine_type new_engine;
    152    stream >> new_engine;
    153    for (size_t i = 0; i < 64; ++i) {
    154      EXPECT_EQ(engine(), new_engine()) << " " << i;
    155    }
    156  }
    157 }
    158 
    159 constexpr size_t kNumGoldenOutputs = 127;
    160 
    161 // This test is checking if randen_engine is meets interface requirements
    162 // defined in [rand.req.urbg].
    163 TYPED_TEST(PCGEngineTest, RandomNumberEngineInterface) {
    164  using engine_type = TypeParam;
    165 
    166  using E = engine_type;
    167  using T = typename E::result_type;
    168 
    169  static_assert(std::is_copy_constructible<E>::value,
    170                "engine_type must be copy constructible");
    171 
    172  static_assert(absl::is_copy_assignable<E>::value,
    173                "engine_type must be copy assignable");
    174 
    175  static_assert(std::is_move_constructible<E>::value,
    176                "engine_type must be move constructible");
    177 
    178  static_assert(absl::is_move_assignable<E>::value,
    179                "engine_type must be move assignable");
    180 
    181  static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,
    182                "return type of operator() must be result_type");
    183 
    184  // Names after definition of [rand.req.urbg] in C++ standard.
    185  // e us a value of E
    186  // v is a lvalue of E
    187  // x, y are possibly const values of E
    188  // s is a value of T
    189  // q is a value satisfying requirements of seed_sequence
    190  // z is a value of type unsigned long long
    191  // os is a some specialization of basic_ostream
    192  // is is a some specialization of basic_istream
    193 
    194  E e, v;
    195  const E x, y;
    196  T s = 1;
    197  std::seed_seq q{1, 2, 3};
    198  unsigned long long z = 1;  // NOLINT(runtime/int)
    199  std::wostringstream os;
    200  std::wistringstream is;
    201 
    202  E{};
    203  E{x};
    204  E{s};
    205  E{q};
    206 
    207  e.seed();
    208 
    209  // MSVC emits error 2718 when using EXPECT_EQ(e, x)
    210  //  * actual parameter with __declspec(align('#')) won't be aligned
    211  EXPECT_TRUE(e == x);
    212 
    213  e.seed(q);
    214  {
    215    E tmp(q);
    216    EXPECT_TRUE(e == tmp);
    217  }
    218 
    219  e();
    220  {
    221    E tmp(q);
    222    EXPECT_TRUE(e != tmp);
    223  }
    224 
    225  e.discard(z);
    226 
    227  static_assert(std::is_same<decltype(x == y), bool>::value,
    228                "return type of operator== must be bool");
    229 
    230  static_assert(std::is_same<decltype(x != y), bool>::value,
    231                "return type of operator== must be bool");
    232 }
    233 
    234 TYPED_TEST(PCGEngineTest, RandenEngineSFINAETest) {
    235  using engine_type = TypeParam;
    236  using result_type = typename engine_type::result_type;
    237 
    238  {
    239    engine_type engine(result_type(1));
    240    engine.seed(result_type(1));
    241  }
    242 
    243  {
    244    result_type n = 1;
    245    engine_type engine(n);
    246    engine.seed(n);
    247  }
    248 
    249  {
    250    engine_type engine(1);
    251    engine.seed(1);
    252  }
    253 
    254  {
    255    int n = 1;
    256    engine_type engine(n);
    257    engine.seed(n);
    258  }
    259 
    260  {
    261    std::seed_seq seed_seq;
    262    engine_type engine(seed_seq);
    263    engine.seed(seed_seq);
    264  }
    265 
    266  {
    267    engine_type engine{std::seed_seq()};
    268    engine.seed(std::seed_seq());
    269  }
    270 }
    271 
    272 // ------------------------------------------------------------------
    273 // Stability tests for pcg64_2018_engine
    274 // ------------------------------------------------------------------
    275 TEST(PCG642018EngineTest, VerifyGolden) {
    276  constexpr uint64_t kGolden[kNumGoldenOutputs] = {
    277      0x01070196e695f8f1, 0x703ec840c59f4493, 0xe54954914b3a44fa,
    278      0x96130ff204b9285e, 0x7d9fdef535ceb21a, 0x666feed42e1219a0,
    279      0x981f685721c8326f, 0xad80710d6eab4dda, 0xe202c480b037a029,
    280      0x5d3390eaedd907e2, 0x0756befb39c6b8aa, 0x1fb44ba6634d62a3,
    281      0x8d20423662426642, 0x34ea910167a39fb4, 0x93010b43a80d0ab6,
    282      0x663db08a98fc568a, 0x720b0a1335956fae, 0x2c35483e31e1d3ba,
    283      0x429f39776337409d, 0xb46d99e638687344, 0x105370b96aedcaee,
    284      0x3999e92f811cff71, 0xd230f8bcb591cfc9, 0x0dce3db2ba7bdea5,
    285      0xcf2f52c91eec99af, 0x2bc7c24a8b998a39, 0xbd8af1b0d599a19c,
    286      0x56bc45abc66059f5, 0x170a46dc170f7f1e, 0xc25daf5277b85fad,
    287      0xe629c2e0c948eadb, 0x1720a796915542ed, 0x22fb0caa4f909951,
    288      0x7e0c0f4175acd83d, 0xd9fcab37ff2a860c, 0xab2280fb2054bad1,
    289      0x58e8a06f37fa9e99, 0xc3a52a30b06528c7, 0x0175f773a13fc1bd,
    290      0x731cfc584b00e840, 0x404cc7b2648069cb, 0x5bc29153b0b7f783,
    291      0x771310a38cc999d1, 0x766a572f0a71a916, 0x90f450fb4fc48348,
    292      0xf080ea3e1c7b1a0d, 0x15471a4507d66a44, 0x7d58e55a78f3df69,
    293      0x0130a094576ac99c, 0x46669cb2d04b1d87, 0x17ab5bed20191840,
    294      0x95b177d260adff3e, 0x025fb624b6ee4c07, 0xb35de4330154a95f,
    295      0xe8510fff67e24c79, 0x132c3cbcd76ed2d3, 0x35e7cc145a093904,
    296      0x9f5b5b5f81583b79, 0x3ee749a533966233, 0x4af85886cdeda8cd,
    297      0x0ca5380ecb3ef3aa, 0x4f674eb7661d3192, 0x88a29aad00cd7733,
    298      0x70b627ca045ffac6, 0x5912b43ea887623d, 0x95dc9fc6f62cf221,
    299      0x926081a12a5c905b, 0x9c57d4cd7dfce651, 0x85ab2cbf23e3bb5d,
    300      0xc5cd669f63023152, 0x3067be0fad5d898e, 0x12b56f444cb53d05,
    301      0xbc2e5a640c3434fc, 0x9280bff0e4613fe1, 0x98819094c528743e,
    302      0x999d1c98d829df33, 0x9ff82a012dc89242, 0xf99183ed39c8be94,
    303      0xf0f59161cd421c55, 0x3c705730c2f6c48d, 0x66ad85c6e9278a61,
    304      0x2a3428e4a428d5d0, 0x79207d68fd04940d, 0xea7f2b402edc8430,
    305      0xa06b419ac857f63b, 0xcb1dd0e6fbc47e1c, 0x4f55229200ada6a4,
    306      0x9647b5e6359c927f, 0x30bf8f9197c7efe5, 0xa79519529cc384d0,
    307      0xbb22c4f339ad6497, 0xd7b9782f59d14175, 0x0dff12fff2ec0118,
    308      0xa331ad8305343a7c, 0x48dad7e3f17e0862, 0x324c6fb3fd3c9665,
    309      0xf0e4350e7933dfc4, 0x7ccda2f30b8b03b6, 0xa0afc6179005de40,
    310      0xee65da6d063b3a30, 0xb9506f42f2bfe87a, 0xc9a2e26b0ef5baa0,
    311      0x39fa9d4f495011d6, 0xbecc21a45d023948, 0x6bf484c6593f737f,
    312      0x8065e0070cadc3b7, 0x9ef617ed8d419799, 0xac692cf8c233dd15,
    313      0xd2ed87583c4ebb98, 0xad95ba1bebfedc62, 0x9b60b160a8264e43,
    314      0x0bc8c45f71fcf25b, 0x4a78035cdf1c9931, 0x4602dc106667e029,
    315      0xb335a3c250498ac8, 0x0256ebc4df20cab8, 0x0c61efd153f0c8d9,
    316      0xe5d0150a4f806f88, 0x99d6521d351e7d87, 0x8d4888c9f80f4325,
    317      0x106c5735c1ba868d, 0x73414881b880a878, 0x808a9a58a3064751,
    318      0x339a29f3746de3d5, 0x5410d7fa4f873896, 0xd84623c81d7b8a03,
    319      0x1f7c7e7a7f47f462,
    320  };
    321 
    322  pcg64_2018_engine engine(0);
    323 #if UPDATE_GOLDEN
    324  (void)kGolden;  // Silence warning.
    325  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
    326    printf("0x%016lx, ", engine());
    327    if (i % 3 == 2) {
    328      printf("\n");
    329    }
    330  }
    331  printf("\n\n\n");
    332 #else
    333  for (const auto& elem : kGolden) {
    334    EXPECT_EQ(elem, engine());
    335  }
    336  engine.seed();
    337  for (const auto& elem : kGolden) {
    338    EXPECT_EQ(elem, engine());
    339  }
    340 #endif
    341 }
    342 
    343 TEST(PCG642018EngineTest, VerifyGoldenSeeded) {
    344  constexpr uint64_t kGolden[kNumGoldenOutputs] = {
    345      0xb03988f1e39691ee, 0xbd2a1eb5ac31e97a, 0x8f00d6d433634d02,
    346      0x1823c28d483d5776, 0x000c3ee3e1aeb74a, 0xfa82ef27a4f3df9c,
    347      0xc6f382308654e454, 0x414afb1a238996c2, 0x4703a4bc252eb411,
    348      0x99d64f62c8f7f654, 0xbb07ebe11a34fa44, 0x79eb06a363c06131,
    349      0xf66ad3756f1c6b21, 0x130c01d5e869f457, 0x5ca2b9963aecbc81,
    350      0xfef7bebc1de27e6c, 0x1d174faa5ed2cdbf, 0xd75b7a773f2bb889,
    351      0xc35c872327a170a5, 0x46da6d88646a42fe, 0x4622985e0442dae2,
    352      0xbe3cbd67297f1f9b, 0xe7c37b4a4798bfd1, 0x173d5dfad15a25c3,
    353      0x0eb6849ba2961522, 0xb0ff7246e6700d73, 0x88cb9c42d3afa577,
    354      0xb609731dbd94d917, 0xd3941cda04b40081, 0x28d140f7409bea3a,
    355      0x3c96699a920a124a, 0xdb28be521958b2fd, 0x0a3f44db3d4c5124,
    356      0x7ac8e60ba13b70d2, 0x75f03a41ded5195a, 0xaed10ac7c4e4825d,
    357      0xb92a3b18aadb7adc, 0xda45e0081f2bca46, 0x74d39ab3753143fc,
    358      0xb686038018fac9ca, 0x4cc309fe99542dbb, 0xf3e1a4fcb311097c,
    359      0x58763d6fa698d69d, 0xd11c365dbecd8d60, 0x2c15d55725b1dee7,
    360      0x89805f254d85658c, 0x2374c44dfc62158b, 0x9a8350fa7995328d,
    361      0x198f838970cf91da, 0x96aff569562c0e53, 0xd76c8c52b7ec6e3f,
    362      0x23a01cd9ae4baa81, 0x3adb366b6d02a893, 0xb3313e2a4c5b333f,
    363      0x04c11230b96a5425, 0x1f7f7af04787d571, 0xaddb019365275ec7,
    364      0x5c960468ccb09f42, 0x8438db698c69a44a, 0x492be1e46111637e,
    365      0x9c6c01e18100c610, 0xbfe48e75b7d0aceb, 0xb5e0b89ec1ce6a00,
    366      0x9d280ecbc2fe8997, 0x290d9e991ba5fcab, 0xeec5bec7d9d2a4f0,
    367      0x726e81488f19150e, 0x1a6df7955a7e462c, 0x37a12d174ba46bb5,
    368      0x3cdcdffd96b1b5c5, 0x2c5d5ac10661a26e, 0xa742ed18f22e50c4,
    369      0x00e0ed88ff0d8a35, 0x3d3c1718cb1efc0b, 0x1d70c51ffbccbf11,
    370      0xfbbb895132a4092f, 0x619d27f2fb095f24, 0x69af68200985e5c4,
    371      0xbee4885f57373f8d, 0x10b7a6bfe0587e40, 0xa885e6cf2f7e5f0a,
    372      0x59f879464f767550, 0x24e805d69056990d, 0x860970b911095891,
    373      0xca3189954f84170d, 0x6652a5edd4590134, 0x5e1008cef76174bf,
    374      0xcbd417881f2bcfe5, 0xfd49fc9d706ecd17, 0xeebf540221ebd066,
    375      0x46af7679464504cb, 0xd4028486946956f1, 0xd4f41864b86c2103,
    376      0x7af090e751583372, 0x98cdaa09278cb642, 0xffd42b921215602f,
    377      0x1d05bec8466b1740, 0xf036fa78a0132044, 0x787880589d1ecc78,
    378      0x5644552cfef33230, 0x0a97e275fe06884b, 0x96d1b13333d470b5,
    379      0xc8b3cdad52d3b034, 0x091357b9db7376fd, 0xa5fe4232555edf8c,
    380      0x3371bc3b6ada76b5, 0x7deeb2300477c995, 0x6fc6d4244f2849c1,
    381      0x750e8cc797ca340a, 0x81728613cd79899f, 0x3467f4ee6f9aeb93,
    382      0x5ef0a905f58c640f, 0x432db85e5101c98a, 0x6488e96f46ac80c2,
    383      0x22fddb282625048c, 0x15b287a0bc2d4c5d, 0xa7e2343ef1f28bce,
    384      0xc87ee1aa89bed09e, 0x220610107812c5e9, 0xcbdab6fcd640f586,
    385      0x8d41047970928784, 0x1aa431509ec1ade0, 0xac3f0be53f518ddc,
    386      0x16f4428ad81d0cbb, 0x675b13c2736fc4bb, 0x6db073afdd87e32d,
    387      0x572f3ca2f1a078c6,
    388  };
    389 
    390  ExplicitSeedSeq seed_sequence{12, 34, 56};
    391  pcg64_2018_engine engine(seed_sequence);
    392 #if UPDATE_GOLDEN
    393  (void)kGolden;  // Silence warning.
    394  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
    395    printf("0x%016lx, ", engine());
    396    if (i % 3 == 2) {
    397      printf("\n");
    398    }
    399  }
    400  printf("\n\n\n");
    401 #else
    402  for (const auto& elem : kGolden) {
    403    EXPECT_EQ(elem, engine());
    404  }
    405  engine.seed(seed_sequence);
    406  for (const auto& elem : kGolden) {
    407    EXPECT_EQ(elem, engine());
    408  }
    409 #endif
    410 }
    411 
    412 TEST(PCG642018EngineTest, VerifyGoldenFromDeserializedEngine) {
    413  constexpr uint64_t kGolden[kNumGoldenOutputs] = {
    414      0xdd425b47b4113dea, 0x1b07176479d444b0, 0x6b391027586f2e42,
    415      0xa166f2b15f4a2143, 0xffb6dbd7a179ee97, 0xb2c00035365bf0b1,
    416      0x8fbb518b45855521, 0xfc789a55ddf87c3b, 0x429531f0f17ff355,
    417      0xbe708560d603d283, 0x5bff415175c5cb6b, 0xe813491f4ad45394,
    418      0xa853f4506d55880d, 0x7e538453e568172e, 0xe101f1e098ddd0ec,
    419      0x6ee31266ee4c766d, 0xa8786d92d66b39d7, 0xfee622a2acf5e5b0,
    420      0x5fe8e82c102fa7b3, 0x01f10be4cdb53c9d, 0xbe0545366f857022,
    421      0x12e74f010a339bca, 0xb10d85ca40d5ce34, 0xe80d6feba5054875,
    422      0x2b7c1ee6d567d4ee, 0x2a9cd043bfd03b66, 0x5cfc531bd239f3f1,
    423      0x1c4734e4647d70f5, 0x85a8f60f006b5760, 0x6a4239ce76dca387,
    424      0x8da0f86d7339335c, 0xf055b0468551374d, 0x486e8567e9bea9a0,
    425      0x4cb531b8405192dd, 0xf813b1ee3157110b, 0x214c2a664a875d8e,
    426      0x74531237b29b35f7, 0xa6f0267bb77a771e, 0x64b552bff54184a4,
    427      0xa2d6f7af2d75b6fc, 0x460a10018e03b5ab, 0x76fd1fdcb81d0800,
    428      0x76f5f81805070d9d, 0x1fb75cb1a70b289a, 0x9dfd25a022c4b27f,
    429      0x9a31a14a80528e9e, 0x910dc565ddc25820, 0xd6aef8e2b0936c10,
    430      0xe1773c507fe70225, 0xe027fd7aadd632bc, 0xc1fecb427089c8b8,
    431      0xb5c74c69fa9dbf26, 0x71bf9b0e4670227d, 0x25f48fad205dcfdd,
    432      0x905248ec4d689c56, 0x5c2b7631b0de5c9d, 0x9f2ee0f8f485036c,
    433      0xfd6ce4ebb90bf7ea, 0xd435d20046085574, 0x6b7eadcb0625f986,
    434      0x679d7d44b48be89e, 0x49683b8e1cdc49de, 0x4366cf76e9a2f4ca,
    435      0x54026ec1cdad7bed, 0xa9a04385207f28d3, 0xc8e66de4eba074b2,
    436      0x40b08c42de0f4cc0, 0x1d4c5e0e93c5bbc0, 0x19b80792e470ae2d,
    437      0x6fcaaeaa4c2a5bd9, 0xa92cb07c4238438e, 0x8bb5c918a007e298,
    438      0x7cd671e944874cf4, 0x88166470b1ba3cac, 0xd013d476eaeeade6,
    439      0xcee416947189b3c3, 0x5d7c16ab0dce6088, 0xd3578a5c32b13d27,
    440      0x3875db5adc9cc973, 0xfbdaba01c5b5dc56, 0xffc4fdd391b231c3,
    441      0x2334520ecb164fec, 0x361c115e7b6de1fa, 0xeee58106cc3563d7,
    442      0x8b7f35a8db25ebb8, 0xb29d00211e2cafa6, 0x22a39fe4614b646b,
    443      0x92ca6de8b998506d, 0x40922fe3d388d1db, 0x9da47f1e540f802a,
    444      0x811dceebf16a25db, 0xf6524ae22e0e53a9, 0x52d9e780a16eb99d,
    445      0x4f504286bb830207, 0xf6654d4786bd5cc3, 0x00bd98316003a7e1,
    446      0xefda054a6ab8f5f3, 0x46cfb0f4c1872827, 0xc22b316965c0f3b2,
    447      0xd1a28087c7e7562a, 0xaa4f6a094b7f5cff, 0xfe2bc853a041f7da,
    448      0xe9d531402a83c3ba, 0xe545d8663d3ce4dd, 0xfa2dcd7d91a13fa8,
    449      0xda1a080e52a127b8, 0x19c98f1f809c3d84, 0x2cef109af4678c88,
    450      0x53462accab3b9132, 0x176b13a80415394e, 0xea70047ef6bc178b,
    451      0x57bca80506d6dcdf, 0xd853ba09ff09f5c4, 0x75f4df3a7ddd4775,
    452      0x209c367ade62f4fe, 0xa9a0bbc74d5f4682, 0x5dfe34bada86c21a,
    453      0xc2c05bbcd38566d1, 0x6de8088e348c916a, 0x6a7001c6000c2196,
    454      0xd9fb51865fc4a367, 0x12f320e444ece8ff, 0x6d56f7f793d65035,
    455      0x138f31b7a865f8aa, 0x58fc68b4026b9adf, 0xcd48954b79fb6436,
    456      0x27dfce4a0232af87,
    457  };
    458 
    459 #if UPDATE_GOLDEN
    460  (void)kGolden;  // Silence warning.
    461  std::seed_seq seed_sequence{1, 2, 3};
    462  pcg64_2018_engine engine(seed_sequence);
    463  std::ostringstream stream;
    464  stream << engine;
    465  auto str = stream.str();
    466  printf("%s\n\n", str.c_str());
    467  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
    468    printf("0x%016lx, ", engine());
    469    if (i % 3 == 2) {
    470      printf("\n");
    471    }
    472  }
    473  printf("\n\n\n");
    474 #else
    475  pcg64_2018_engine engine;
    476  std::istringstream stream(
    477      "2549297995355413924 4865540595714422341 6364136223846793005 "
    478      "1442695040888963407 18088519957565336995 4845369368158826708");
    479  stream >> engine;
    480  for (const auto& elem : kGolden) {
    481    EXPECT_EQ(elem, engine());
    482  }
    483 #endif
    484 }
    485 
    486 // ------------------------------------------------------------------
    487 // Stability tests for pcg32_2018_engine
    488 // ------------------------------------------------------------------
    489 TEST(PCG322018EngineTest, VerifyGolden) {
    490  constexpr uint32_t kGolden[kNumGoldenOutputs] = {
    491      0x7a7ecbd9, 0x89fd6c06, 0xae646aa8, 0xcd3cf945, 0x6204b303, 0x198c8585,
    492      0x49fce611, 0xd1e9297a, 0x142d9440, 0xee75f56b, 0x473a9117, 0xe3a45903,
    493      0xbce807a1, 0xe54e5f4d, 0x497d6c51, 0x61829166, 0xa740474b, 0x031912a8,
    494      0x9de3defa, 0xd266dbf1, 0x0f38bebb, 0xec3c4f65, 0x07c5057d, 0xbbce03c8,
    495      0xfd2ac7a8, 0xffcf4773, 0x5b10affb, 0xede1c842, 0xe22b01b7, 0xda133c8c,
    496      0xaf89b0f4, 0x25d1b8bc, 0x9f625482, 0x7bfd6882, 0x2e2210c0, 0x2c8fb9a6,
    497      0x42cb3b83, 0x40ce0dab, 0x644a3510, 0x36230ef2, 0xe2cb6d43, 0x1012b343,
    498      0x746c6c9f, 0x36714cf8, 0xed1f5026, 0x8bbbf83e, 0xe98710f4, 0x8a2afa36,
    499      0x09035349, 0x6dc1a487, 0x682b634b, 0xc106794f, 0x7dd78beb, 0x628c262b,
    500      0x852fb232, 0xb153ac4c, 0x4f169d1b, 0xa69ab774, 0x4bd4b6f2, 0xdc351dd3,
    501      0x93ff3c8c, 0xa30819ab, 0xff07758c, 0x5ab13c62, 0xd16d7fb5, 0xc4950ffa,
    502      0xd309ae49, 0xb9677a87, 0x4464e317, 0x90dc44f1, 0xc694c1d4, 0x1d5e1168,
    503      0xadf37a2d, 0xda38990d, 0x1ec4bd33, 0x36ca25ce, 0xfa0dc76a, 0x968a9d43,
    504      0x6950ac39, 0xdd3276bc, 0x06d5a71e, 0x1f6f282d, 0x5c626c62, 0xdde3fc31,
    505      0x152194ce, 0xc35ed14c, 0xb1f7224e, 0x47f76bb8, 0xb34fdd08, 0x7011395e,
    506      0x162d2a49, 0x0d1bf09f, 0x9428a952, 0x03c5c344, 0xd3525616, 0x7816fff3,
    507      0x6bceb8a8, 0x8345a081, 0x366420fd, 0x182abeda, 0x70f82745, 0xaf15ded8,
    508      0xc7f52ca2, 0xa98db9c5, 0x919d99ba, 0x9c376c1c, 0xed8d34c2, 0x716ae9f5,
    509      0xef062fa5, 0xee3b6c56, 0x52325658, 0x61afa9c3, 0xfdaf02f0, 0x961cf3ab,
    510      0x9f291565, 0x4fbf3045, 0x0590c899, 0xde901385, 0x45005ffb, 0x509db162,
    511      0x262fa941, 0x4c421653, 0x4b17c21e, 0xea0d1530, 0xde803845, 0x61bfd515,
    512      0x438523ef,
    513  };
    514 
    515  pcg32_2018_engine engine(0);
    516 #if UPDATE_GOLDEN
    517  (void)kGolden;  // Silence warning.
    518  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
    519    printf("0x%08x, ", engine());
    520    if (i % 6 == 5) {
    521      printf("\n");
    522    }
    523  }
    524  printf("\n\n\n");
    525 #else
    526  for (const auto& elem : kGolden) {
    527    EXPECT_EQ(elem, engine());
    528  }
    529  engine.seed();
    530  for (const auto& elem : kGolden) {
    531    EXPECT_EQ(elem, engine());
    532  }
    533 #endif
    534 }
    535 
    536 TEST(PCG322018EngineTest, VerifyGoldenSeeded) {
    537  constexpr uint32_t kGolden[kNumGoldenOutputs] = {
    538      0x60b5a64c, 0x978502f9, 0x80a75f60, 0x241f1158, 0xa4cd1dbb, 0xe7284017,
    539      0x3b678da5, 0x5223ec99, 0xe4bdd5d9, 0x72190e6d, 0xe6e702c9, 0xff80c768,
    540      0xcf126ed3, 0x1fbd20ab, 0x60980489, 0xbc72bf89, 0x407ac6c0, 0x00bf3c51,
    541      0xf9087897, 0x172e4eb6, 0xe9e4f443, 0x1a6098bf, 0xbf44f8c2, 0xdd84a0e5,
    542      0xd9a52364, 0xc0e2e786, 0x061ae2ba, 0x9facb8e3, 0x6109432d, 0xd4e0a013,
    543      0xbd8eb9a6, 0x7e86c3b6, 0x629c0e68, 0x05337430, 0xb495b9f4, 0x11ccd65d,
    544      0xb578db25, 0x66f1246d, 0x6ef20a7f, 0x5e429812, 0x11772130, 0xb944b5c2,
    545      0x01624128, 0xa2385ab7, 0xd3e10d35, 0xbe570ec3, 0xc951656f, 0xbe8944a0,
    546      0x7be41062, 0x5709f919, 0xd745feda, 0x9870b9ae, 0xb44b8168, 0x19e7683b,
    547      0xded8017f, 0xc6e4d544, 0x91ae4225, 0xd6745fba, 0xb992f284, 0x65b12b33,
    548      0xa9d5fdb4, 0xf105ce1a, 0x35ca1a6e, 0x2ff70dd0, 0xd8335e49, 0xfb71ddf2,
    549      0xcaeabb89, 0x5c6f5f84, 0x9a811a7d, 0xbcecbbd1, 0x0f661ba0, 0x9ad93b9d,
    550      0xedd23e0b, 0x42062f48, 0xd38dd7e4, 0x6cd63c9c, 0x640b98ae, 0x4bff5653,
    551      0x12626371, 0x13266017, 0xe7a698d8, 0x39c74667, 0xe8fdf2e3, 0x52803bf8,
    552      0x2af6895b, 0x91335b7b, 0x699e4961, 0x00a40fff, 0x253ff2b6, 0x4a6cf672,
    553      0x9584e85f, 0xf2a5000c, 0x4d58aba8, 0xb8513e6a, 0x767fad65, 0x8e326f9e,
    554      0x182f15a1, 0x163dab52, 0xdf99c780, 0x047282a1, 0xee4f90dd, 0xd50394ae,
    555      0x6c9fd5f0, 0xb06a9194, 0x387e3840, 0x04a9487b, 0xf678a4c2, 0xd0a78810,
    556      0xd502c97e, 0xd6a9b12a, 0x4accc5dc, 0x416ed53e, 0x50411536, 0xeeb89c24,
    557      0x813a7902, 0x034ebca6, 0xffa52e7c, 0x7ecd3d0e, 0xfa37a0d2, 0xb1fbe2c1,
    558      0xb7efc6d1, 0xefa4ccee, 0xf6f80424, 0x2283f3d9, 0x68732284, 0x94f3b5c8,
    559      0xbbdeceb9,
    560  };
    561 
    562  ExplicitSeedSeq seed_sequence{12, 34, 56};
    563  pcg32_2018_engine engine(seed_sequence);
    564 #if UPDATE_GOLDEN
    565  (void)kGolden;  // Silence warning.
    566  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
    567    printf("0x%08x, ", engine());
    568    if (i % 6 == 5) {
    569      printf("\n");
    570    }
    571  }
    572  printf("\n\n\n");
    573 #else
    574  for (const auto& elem : kGolden) {
    575    EXPECT_EQ(elem, engine());
    576  }
    577  engine.seed(seed_sequence);
    578  for (const auto& elem : kGolden) {
    579    EXPECT_EQ(elem, engine());
    580  }
    581 #endif
    582 }
    583 
    584 TEST(PCG322018EngineTest, VerifyGoldenFromDeserializedEngine) {
    585  constexpr uint64_t kGolden[kNumGoldenOutputs] = {
    586      0x780f7042, 0xba137215, 0x43ab6f22, 0x0cb55f46, 0x44b2627d, 0x835597af,
    587      0xea973ea1, 0x0d2abd35, 0x4fdd601c, 0xac4342fe, 0x7db7e93c, 0xe56ebcaf,
    588      0x3596470a, 0x7770a9ad, 0x9b893320, 0x57db3415, 0xb432de54, 0xa02baf71,
    589      0xa256aadb, 0x88921fc7, 0xa35fa6b3, 0xde3eca46, 0x605739a7, 0xa890b82b,
    590      0xe457b7ad, 0x335fb903, 0xeb06790c, 0xb3c54bf6, 0x6141e442, 0xa599a482,
    591      0xb78987cc, 0xc61dfe9d, 0x0f1d6ace, 0x17460594, 0x8f6a5061, 0x083dc354,
    592      0xe9c337fb, 0xcfd105f7, 0x926764b6, 0x638d24dc, 0xeaac650a, 0x67d2cb9c,
    593      0xd807733c, 0x205fc52e, 0xf5399e2e, 0x6c46ddcc, 0xb603e875, 0xce113a25,
    594      0x3c8d4813, 0xfb584db8, 0xf6d255ff, 0xea80954f, 0x42e8be85, 0xb2feee72,
    595      0x62bd8d16, 0x1be4a142, 0x97dca1a4, 0xdd6e7333, 0xb2caa20e, 0xa12b1588,
    596      0xeb3a5a1a, 0x6fa5ba89, 0x077ea931, 0x8ddb1713, 0x0dd03079, 0x2c2ba965,
    597      0xa77fac17, 0xc8325742, 0x8bb893bf, 0xc2315741, 0xeaceee92, 0x81dd2ee2,
    598      0xe5214216, 0x1b9b8fb2, 0x01646d03, 0x24facc25, 0xd8c0e0bb, 0xa33fe106,
    599      0xf34fe976, 0xb3b4b44e, 0x65618fed, 0x032c6192, 0xa9dd72ce, 0xf391887b,
    600      0xf41c6a6e, 0x05c4bd6d, 0x37fa260e, 0x46b05659, 0xb5f6348a, 0x62d26d89,
    601      0x39f6452d, 0xb17b30a2, 0xbdd82743, 0x38ecae3b, 0xfe90f0a2, 0xcb2d226d,
    602      0xcf8a0b1c, 0x0eed3d4d, 0xa1f69cfc, 0xd7ac3ba5, 0xce9d9a6b, 0x121deb4c,
    603      0x4a0d03f3, 0xc1821ed1, 0x59c249ac, 0xc0abb474, 0x28149985, 0xfd9a82ba,
    604      0x5960c3b2, 0xeff00cba, 0x6073aa17, 0x25dc0919, 0x9976626e, 0xdd2ccc33,
    605      0x39ecb6ec, 0xc6e15d13, 0xfac94cfd, 0x28cfd34f, 0xf2d2c32d, 0x51c23d08,
    606      0x4fdb2f48, 0x97baa807, 0xf2c1004c, 0xc4ae8136, 0x71f31c94, 0x8c92d601,
    607      0x36caf5cd,
    608  };
    609 
    610 #if UPDATE_GOLDEN
    611  (void)kGolden;  // Silence warning.
    612  std::seed_seq seed_sequence{1, 2, 3};
    613  pcg32_2018_engine engine(seed_sequence);
    614  std::ostringstream stream;
    615  stream << engine;
    616  auto str = stream.str();
    617  printf("%s\n\n", str.c_str());
    618  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
    619    printf("0x%08x, ", engine());
    620    if (i % 6 == 5) {
    621      printf("\n");
    622    }
    623  }
    624  printf("\n\n\n");
    625 
    626  EXPECT_FALSE(true);
    627 #else
    628  pcg32_2018_engine engine;
    629  std::istringstream stream(
    630      "6364136223846793005 1442695040888963407 6537028157270659894");
    631  stream >> engine;
    632  for (const auto& elem : kGolden) {
    633    EXPECT_EQ(elem, engine());
    634  }
    635 #endif
    636 }
    637 
    638 }  // namespace