1*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors. 2*9356374aSAndroid Build Coastguard Worker // 3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*9356374aSAndroid Build Coastguard Worker // 7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*9356374aSAndroid Build Coastguard Worker // 9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*9356374aSAndroid Build Coastguard Worker // limitations under the License. 14*9356374aSAndroid Build Coastguard Worker 15*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_ 16*9356374aSAndroid Build Coastguard Worker #define ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_ 17*9356374aSAndroid Build Coastguard Worker 18*9356374aSAndroid Build Coastguard Worker #include <type_traits> 19*9356374aSAndroid Build Coastguard Worker 20*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h" 21*9356374aSAndroid Build Coastguard Worker #include "absl/meta/type_traits.h" 22*9356374aSAndroid Build Coastguard Worker #include "absl/numeric/bits.h" 23*9356374aSAndroid Build Coastguard Worker #include "absl/numeric/int128.h" 24*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/fastmath.h" 25*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/iostream_state_saver.h" 26*9356374aSAndroid Build Coastguard Worker 27*9356374aSAndroid Build Coastguard Worker namespace absl { 28*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN 29*9356374aSAndroid Build Coastguard Worker namespace random_internal { 30*9356374aSAndroid Build Coastguard Worker 31*9356374aSAndroid Build Coastguard Worker // pcg_engine is a simplified implementation of Melissa O'Neil's PCG engine in 32*9356374aSAndroid Build Coastguard Worker // C++. PCG combines a linear congruential generator (LCG) with output state 33*9356374aSAndroid Build Coastguard Worker // mixing functions to generate each random variate. pcg_engine supports only a 34*9356374aSAndroid Build Coastguard Worker // single sequence (oneseq), and does not support streams. 35*9356374aSAndroid Build Coastguard Worker // 36*9356374aSAndroid Build Coastguard Worker // pcg_engine is parameterized by two types: 37*9356374aSAndroid Build Coastguard Worker // Params, which provides the multiplier and increment values; 38*9356374aSAndroid Build Coastguard Worker // Mix, which mixes the state into the result. 39*9356374aSAndroid Build Coastguard Worker // 40*9356374aSAndroid Build Coastguard Worker template <typename Params, typename Mix> 41*9356374aSAndroid Build Coastguard Worker class pcg_engine { 42*9356374aSAndroid Build Coastguard Worker static_assert(std::is_same<typename Params::state_type, 43*9356374aSAndroid Build Coastguard Worker typename Mix::state_type>::value, 44*9356374aSAndroid Build Coastguard Worker "Class-template absl::pcg_engine must be parameterized by " 45*9356374aSAndroid Build Coastguard Worker "Params and Mix with identical state_type"); 46*9356374aSAndroid Build Coastguard Worker 47*9356374aSAndroid Build Coastguard Worker static_assert(std::is_unsigned<typename Mix::result_type>::value, 48*9356374aSAndroid Build Coastguard Worker "Class-template absl::pcg_engine must be parameterized by " 49*9356374aSAndroid Build Coastguard Worker "an unsigned Mix::result_type"); 50*9356374aSAndroid Build Coastguard Worker 51*9356374aSAndroid Build Coastguard Worker using params_type = Params; 52*9356374aSAndroid Build Coastguard Worker using mix_type = Mix; 53*9356374aSAndroid Build Coastguard Worker using state_type = typename Mix::state_type; 54*9356374aSAndroid Build Coastguard Worker 55*9356374aSAndroid Build Coastguard Worker public: 56*9356374aSAndroid Build Coastguard Worker // C++11 URBG interface: 57*9356374aSAndroid Build Coastguard Worker using result_type = typename Mix::result_type; 58*9356374aSAndroid Build Coastguard Worker result_type(min)59*9356374aSAndroid Build Coastguard Worker static constexpr result_type(min)() { 60*9356374aSAndroid Build Coastguard Worker return (std::numeric_limits<result_type>::min)(); 61*9356374aSAndroid Build Coastguard Worker } 62*9356374aSAndroid Build Coastguard Worker result_type(max)63*9356374aSAndroid Build Coastguard Worker static constexpr result_type(max)() { 64*9356374aSAndroid Build Coastguard Worker return (std::numeric_limits<result_type>::max)(); 65*9356374aSAndroid Build Coastguard Worker } 66*9356374aSAndroid Build Coastguard Worker 67*9356374aSAndroid Build Coastguard Worker explicit pcg_engine(uint64_t seed_value = 0) { seed(seed_value); } 68*9356374aSAndroid Build Coastguard Worker 69*9356374aSAndroid Build Coastguard Worker template <class SeedSequence, 70*9356374aSAndroid Build Coastguard Worker typename = typename absl::enable_if_t< 71*9356374aSAndroid Build Coastguard Worker !std::is_same<SeedSequence, pcg_engine>::value>> pcg_engine(SeedSequence && seq)72*9356374aSAndroid Build Coastguard Worker explicit pcg_engine(SeedSequence&& seq) { 73*9356374aSAndroid Build Coastguard Worker seed(seq); 74*9356374aSAndroid Build Coastguard Worker } 75*9356374aSAndroid Build Coastguard Worker 76*9356374aSAndroid Build Coastguard Worker pcg_engine(const pcg_engine&) = default; 77*9356374aSAndroid Build Coastguard Worker pcg_engine& operator=(const pcg_engine&) = default; 78*9356374aSAndroid Build Coastguard Worker pcg_engine(pcg_engine&&) = default; 79*9356374aSAndroid Build Coastguard Worker pcg_engine& operator=(pcg_engine&&) = default; 80*9356374aSAndroid Build Coastguard Worker operator()81*9356374aSAndroid Build Coastguard Worker result_type operator()() { 82*9356374aSAndroid Build Coastguard Worker // Advance the LCG state, always using the new value to generate the output. 83*9356374aSAndroid Build Coastguard Worker state_ = lcg(state_); 84*9356374aSAndroid Build Coastguard Worker return Mix{}(state_); 85*9356374aSAndroid Build Coastguard Worker } 86*9356374aSAndroid Build Coastguard Worker 87*9356374aSAndroid Build Coastguard Worker void seed(uint64_t seed_value = 0) { 88*9356374aSAndroid Build Coastguard Worker state_type tmp = seed_value; 89*9356374aSAndroid Build Coastguard Worker state_ = lcg(tmp + Params::increment()); 90*9356374aSAndroid Build Coastguard Worker } 91*9356374aSAndroid Build Coastguard Worker 92*9356374aSAndroid Build Coastguard Worker template <class SeedSequence> 93*9356374aSAndroid Build Coastguard Worker typename absl::enable_if_t< 94*9356374aSAndroid Build Coastguard Worker !std::is_convertible<SeedSequence, uint64_t>::value, void> seed(SeedSequence && seq)95*9356374aSAndroid Build Coastguard Worker seed(SeedSequence&& seq) { 96*9356374aSAndroid Build Coastguard Worker reseed(seq); 97*9356374aSAndroid Build Coastguard Worker } 98*9356374aSAndroid Build Coastguard Worker discard(uint64_t count)99*9356374aSAndroid Build Coastguard Worker void discard(uint64_t count) { state_ = advance(state_, count); } 100*9356374aSAndroid Build Coastguard Worker 101*9356374aSAndroid Build Coastguard Worker bool operator==(const pcg_engine& other) const { 102*9356374aSAndroid Build Coastguard Worker return state_ == other.state_; 103*9356374aSAndroid Build Coastguard Worker } 104*9356374aSAndroid Build Coastguard Worker 105*9356374aSAndroid Build Coastguard Worker bool operator!=(const pcg_engine& other) const { return !(*this == other); } 106*9356374aSAndroid Build Coastguard Worker 107*9356374aSAndroid Build Coastguard Worker template <class CharT, class Traits> 108*9356374aSAndroid Build Coastguard Worker friend typename absl::enable_if_t<(sizeof(state_type) == 16), 109*9356374aSAndroid Build Coastguard Worker std::basic_ostream<CharT, Traits>&> 110*9356374aSAndroid Build Coastguard Worker operator<<( 111*9356374aSAndroid Build Coastguard Worker std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) 112*9356374aSAndroid Build Coastguard Worker const pcg_engine& engine) { 113*9356374aSAndroid Build Coastguard Worker auto saver = random_internal::make_ostream_state_saver(os); 114*9356374aSAndroid Build Coastguard Worker random_internal::stream_u128_helper<state_type> helper; 115*9356374aSAndroid Build Coastguard Worker helper.write(pcg_engine::params_type::multiplier(), os); 116*9356374aSAndroid Build Coastguard Worker os << os.fill(); 117*9356374aSAndroid Build Coastguard Worker helper.write(pcg_engine::params_type::increment(), os); 118*9356374aSAndroid Build Coastguard Worker os << os.fill(); 119*9356374aSAndroid Build Coastguard Worker helper.write(engine.state_, os); 120*9356374aSAndroid Build Coastguard Worker return os; 121*9356374aSAndroid Build Coastguard Worker } 122*9356374aSAndroid Build Coastguard Worker 123*9356374aSAndroid Build Coastguard Worker template <class CharT, class Traits> 124*9356374aSAndroid Build Coastguard Worker friend typename absl::enable_if_t<(sizeof(state_type) <= 8), 125*9356374aSAndroid Build Coastguard Worker std::basic_ostream<CharT, Traits>&> 126*9356374aSAndroid Build Coastguard Worker operator<<( 127*9356374aSAndroid Build Coastguard Worker std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) 128*9356374aSAndroid Build Coastguard Worker const pcg_engine& engine) { 129*9356374aSAndroid Build Coastguard Worker auto saver = random_internal::make_ostream_state_saver(os); 130*9356374aSAndroid Build Coastguard Worker os << pcg_engine::params_type::multiplier() << os.fill(); 131*9356374aSAndroid Build Coastguard Worker os << pcg_engine::params_type::increment() << os.fill(); 132*9356374aSAndroid Build Coastguard Worker os << engine.state_; 133*9356374aSAndroid Build Coastguard Worker return os; 134*9356374aSAndroid Build Coastguard Worker } 135*9356374aSAndroid Build Coastguard Worker 136*9356374aSAndroid Build Coastguard Worker template <class CharT, class Traits> 137*9356374aSAndroid Build Coastguard Worker friend typename absl::enable_if_t<(sizeof(state_type) == 16), 138*9356374aSAndroid Build Coastguard Worker std::basic_istream<CharT, Traits>&> 139*9356374aSAndroid Build Coastguard Worker operator>>( 140*9356374aSAndroid Build Coastguard Worker std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) 141*9356374aSAndroid Build Coastguard Worker pcg_engine& engine) { // NOLINT(runtime/references) 142*9356374aSAndroid Build Coastguard Worker random_internal::stream_u128_helper<state_type> helper; 143*9356374aSAndroid Build Coastguard Worker auto mult = helper.read(is); 144*9356374aSAndroid Build Coastguard Worker auto inc = helper.read(is); 145*9356374aSAndroid Build Coastguard Worker auto tmp = helper.read(is); 146*9356374aSAndroid Build Coastguard Worker if (mult != pcg_engine::params_type::multiplier() || 147*9356374aSAndroid Build Coastguard Worker inc != pcg_engine::params_type::increment()) { 148*9356374aSAndroid Build Coastguard Worker // signal failure by setting the failbit. 149*9356374aSAndroid Build Coastguard Worker is.setstate(is.rdstate() | std::ios_base::failbit); 150*9356374aSAndroid Build Coastguard Worker } 151*9356374aSAndroid Build Coastguard Worker if (!is.fail()) { 152*9356374aSAndroid Build Coastguard Worker engine.state_ = tmp; 153*9356374aSAndroid Build Coastguard Worker } 154*9356374aSAndroid Build Coastguard Worker return is; 155*9356374aSAndroid Build Coastguard Worker } 156*9356374aSAndroid Build Coastguard Worker 157*9356374aSAndroid Build Coastguard Worker template <class CharT, class Traits> 158*9356374aSAndroid Build Coastguard Worker friend typename absl::enable_if_t<(sizeof(state_type) <= 8), 159*9356374aSAndroid Build Coastguard Worker std::basic_istream<CharT, Traits>&> 160*9356374aSAndroid Build Coastguard Worker operator>>( 161*9356374aSAndroid Build Coastguard Worker std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) 162*9356374aSAndroid Build Coastguard Worker pcg_engine& engine) { // NOLINT(runtime/references) 163*9356374aSAndroid Build Coastguard Worker state_type mult{}, inc{}, tmp{}; 164*9356374aSAndroid Build Coastguard Worker is >> mult >> inc >> tmp; 165*9356374aSAndroid Build Coastguard Worker if (mult != pcg_engine::params_type::multiplier() || 166*9356374aSAndroid Build Coastguard Worker inc != pcg_engine::params_type::increment()) { 167*9356374aSAndroid Build Coastguard Worker // signal failure by setting the failbit. 168*9356374aSAndroid Build Coastguard Worker is.setstate(is.rdstate() | std::ios_base::failbit); 169*9356374aSAndroid Build Coastguard Worker } 170*9356374aSAndroid Build Coastguard Worker if (!is.fail()) { 171*9356374aSAndroid Build Coastguard Worker engine.state_ = tmp; 172*9356374aSAndroid Build Coastguard Worker } 173*9356374aSAndroid Build Coastguard Worker return is; 174*9356374aSAndroid Build Coastguard Worker } 175*9356374aSAndroid Build Coastguard Worker 176*9356374aSAndroid Build Coastguard Worker private: 177*9356374aSAndroid Build Coastguard Worker state_type state_; 178*9356374aSAndroid Build Coastguard Worker 179*9356374aSAndroid Build Coastguard Worker // Returns the linear-congruential generator next state. lcg(state_type s)180*9356374aSAndroid Build Coastguard Worker static inline constexpr state_type lcg(state_type s) { 181*9356374aSAndroid Build Coastguard Worker return s * Params::multiplier() + Params::increment(); 182*9356374aSAndroid Build Coastguard Worker } 183*9356374aSAndroid Build Coastguard Worker 184*9356374aSAndroid Build Coastguard Worker // Returns the linear-congruential arbitrary seek state. advance(state_type s,uint64_t n)185*9356374aSAndroid Build Coastguard Worker inline state_type advance(state_type s, uint64_t n) const { 186*9356374aSAndroid Build Coastguard Worker state_type mult = Params::multiplier(); 187*9356374aSAndroid Build Coastguard Worker state_type inc = Params::increment(); 188*9356374aSAndroid Build Coastguard Worker state_type m = 1; 189*9356374aSAndroid Build Coastguard Worker state_type i = 0; 190*9356374aSAndroid Build Coastguard Worker while (n > 0) { 191*9356374aSAndroid Build Coastguard Worker if (n & 1) { 192*9356374aSAndroid Build Coastguard Worker m *= mult; 193*9356374aSAndroid Build Coastguard Worker i = i * mult + inc; 194*9356374aSAndroid Build Coastguard Worker } 195*9356374aSAndroid Build Coastguard Worker inc = (mult + 1) * inc; 196*9356374aSAndroid Build Coastguard Worker mult *= mult; 197*9356374aSAndroid Build Coastguard Worker n >>= 1; 198*9356374aSAndroid Build Coastguard Worker } 199*9356374aSAndroid Build Coastguard Worker return m * s + i; 200*9356374aSAndroid Build Coastguard Worker } 201*9356374aSAndroid Build Coastguard Worker 202*9356374aSAndroid Build Coastguard Worker template <class SeedSequence> reseed(SeedSequence & seq)203*9356374aSAndroid Build Coastguard Worker void reseed(SeedSequence& seq) { 204*9356374aSAndroid Build Coastguard Worker using sequence_result_type = typename SeedSequence::result_type; 205*9356374aSAndroid Build Coastguard Worker constexpr size_t kBufferSize = 206*9356374aSAndroid Build Coastguard Worker sizeof(state_type) / sizeof(sequence_result_type); 207*9356374aSAndroid Build Coastguard Worker sequence_result_type buffer[kBufferSize]; 208*9356374aSAndroid Build Coastguard Worker seq.generate(std::begin(buffer), std::end(buffer)); 209*9356374aSAndroid Build Coastguard Worker // Convert the seed output to a single state value. 210*9356374aSAndroid Build Coastguard Worker state_type tmp = buffer[0]; 211*9356374aSAndroid Build Coastguard Worker for (size_t i = 1; i < kBufferSize; i++) { 212*9356374aSAndroid Build Coastguard Worker tmp <<= (sizeof(sequence_result_type) * 8); 213*9356374aSAndroid Build Coastguard Worker tmp |= buffer[i]; 214*9356374aSAndroid Build Coastguard Worker } 215*9356374aSAndroid Build Coastguard Worker state_ = lcg(tmp + params_type::increment()); 216*9356374aSAndroid Build Coastguard Worker } 217*9356374aSAndroid Build Coastguard Worker }; 218*9356374aSAndroid Build Coastguard Worker 219*9356374aSAndroid Build Coastguard Worker // Parameterized implementation of the PCG 128-bit oneseq state. 220*9356374aSAndroid Build Coastguard Worker // This provides state_type, multiplier, and increment for pcg_engine. 221*9356374aSAndroid Build Coastguard Worker template <uint64_t kMultA, uint64_t kMultB, uint64_t kIncA, uint64_t kIncB> 222*9356374aSAndroid Build Coastguard Worker class pcg128_params { 223*9356374aSAndroid Build Coastguard Worker public: 224*9356374aSAndroid Build Coastguard Worker using state_type = absl::uint128; multiplier()225*9356374aSAndroid Build Coastguard Worker static inline constexpr state_type multiplier() { 226*9356374aSAndroid Build Coastguard Worker return absl::MakeUint128(kMultA, kMultB); 227*9356374aSAndroid Build Coastguard Worker } increment()228*9356374aSAndroid Build Coastguard Worker static inline constexpr state_type increment() { 229*9356374aSAndroid Build Coastguard Worker return absl::MakeUint128(kIncA, kIncB); 230*9356374aSAndroid Build Coastguard Worker } 231*9356374aSAndroid Build Coastguard Worker }; 232*9356374aSAndroid Build Coastguard Worker 233*9356374aSAndroid Build Coastguard Worker // Implementation of the PCG xsl_rr_128_64 128-bit mixing function, which 234*9356374aSAndroid Build Coastguard Worker // accepts an input of state_type and mixes it into an output of result_type. 235*9356374aSAndroid Build Coastguard Worker struct pcg_xsl_rr_128_64 { 236*9356374aSAndroid Build Coastguard Worker using state_type = absl::uint128; 237*9356374aSAndroid Build Coastguard Worker using result_type = uint64_t; 238*9356374aSAndroid Build Coastguard Worker operatorpcg_xsl_rr_128_64239*9356374aSAndroid Build Coastguard Worker inline uint64_t operator()(state_type state) { 240*9356374aSAndroid Build Coastguard Worker // This is equivalent to the xsl_rr_128_64 mixing function. 241*9356374aSAndroid Build Coastguard Worker uint64_t rotate = static_cast<uint64_t>(state >> 122u); 242*9356374aSAndroid Build Coastguard Worker state ^= state >> 64; 243*9356374aSAndroid Build Coastguard Worker uint64_t s = static_cast<uint64_t>(state); 244*9356374aSAndroid Build Coastguard Worker return rotr(s, static_cast<int>(rotate)); 245*9356374aSAndroid Build Coastguard Worker } 246*9356374aSAndroid Build Coastguard Worker }; 247*9356374aSAndroid Build Coastguard Worker 248*9356374aSAndroid Build Coastguard Worker // Parameterized implementation of the PCG 64-bit oneseq state. 249*9356374aSAndroid Build Coastguard Worker // This provides state_type, multiplier, and increment for pcg_engine. 250*9356374aSAndroid Build Coastguard Worker template <uint64_t kMult, uint64_t kInc> 251*9356374aSAndroid Build Coastguard Worker class pcg64_params { 252*9356374aSAndroid Build Coastguard Worker public: 253*9356374aSAndroid Build Coastguard Worker using state_type = uint64_t; multiplier()254*9356374aSAndroid Build Coastguard Worker static inline constexpr state_type multiplier() { return kMult; } increment()255*9356374aSAndroid Build Coastguard Worker static inline constexpr state_type increment() { return kInc; } 256*9356374aSAndroid Build Coastguard Worker }; 257*9356374aSAndroid Build Coastguard Worker 258*9356374aSAndroid Build Coastguard Worker // Implementation of the PCG xsh_rr_64_32 64-bit mixing function, which accepts 259*9356374aSAndroid Build Coastguard Worker // an input of state_type and mixes it into an output of result_type. 260*9356374aSAndroid Build Coastguard Worker struct pcg_xsh_rr_64_32 { 261*9356374aSAndroid Build Coastguard Worker using state_type = uint64_t; 262*9356374aSAndroid Build Coastguard Worker using result_type = uint32_t; operatorpcg_xsh_rr_64_32263*9356374aSAndroid Build Coastguard Worker inline uint32_t operator()(uint64_t state) { 264*9356374aSAndroid Build Coastguard Worker return rotr(static_cast<uint32_t>(((state >> 18) ^ state) >> 27), 265*9356374aSAndroid Build Coastguard Worker state >> 59); 266*9356374aSAndroid Build Coastguard Worker } 267*9356374aSAndroid Build Coastguard Worker }; 268*9356374aSAndroid Build Coastguard Worker 269*9356374aSAndroid Build Coastguard Worker // Stable pcg_engine implementations: 270*9356374aSAndroid Build Coastguard Worker // This is a 64-bit generator using 128-bits of state. 271*9356374aSAndroid Build Coastguard Worker // The output sequence is equivalent to Melissa O'Neil's pcg64_oneseq. 272*9356374aSAndroid Build Coastguard Worker using pcg64_2018_engine = pcg_engine< 273*9356374aSAndroid Build Coastguard Worker random_internal::pcg128_params<0x2360ed051fc65da4ull, 0x4385df649fccf645ull, 274*9356374aSAndroid Build Coastguard Worker 0x5851f42d4c957f2d, 0x14057b7ef767814f>, 275*9356374aSAndroid Build Coastguard Worker random_internal::pcg_xsl_rr_128_64>; 276*9356374aSAndroid Build Coastguard Worker 277*9356374aSAndroid Build Coastguard Worker // This is a 32-bit generator using 64-bits of state. 278*9356374aSAndroid Build Coastguard Worker // This is equivalent to Melissa O'Neil's pcg32_oneseq. 279*9356374aSAndroid Build Coastguard Worker using pcg32_2018_engine = pcg_engine< 280*9356374aSAndroid Build Coastguard Worker random_internal::pcg64_params<0x5851f42d4c957f2dull, 0x14057b7ef767814full>, 281*9356374aSAndroid Build Coastguard Worker random_internal::pcg_xsh_rr_64_32>; 282*9356374aSAndroid Build Coastguard Worker 283*9356374aSAndroid Build Coastguard Worker } // namespace random_internal 284*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END 285*9356374aSAndroid Build Coastguard Worker } // namespace absl 286*9356374aSAndroid Build Coastguard Worker 287*9356374aSAndroid Build Coastguard Worker #endif // ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_ 288