SpectMorph
smpcg32rng.hh
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2 // Author: 2014, Tim Janik, see http://testbit.org/keccak
3 
4 #ifndef SPECTMORPH_PCG32_RNG_HH
5 #define SPECTMORPH_PCG32_RNG_HH
6 
7 #include <glib.h>
8 #include <stdint.h>
9 
10 namespace SpectMorph
11 {
12 
24 class Pcg32Rng {
25  uint64_t increment_; // must be odd, allows for 2^63 distinct random sequences
26  uint64_t accu_; // can contain all 2^64 possible values
27  static constexpr const uint64_t A = 6364136223846793005ULL; // from C. E. Hayness, see TAOCP by D. E. Knuth, 3.3.4, table 1, line 26.
28  static inline constexpr uint32_t
29  ror32 (const uint32_t bits, const uint32_t offset)
30  {
31  // bitwise rotate-right pattern recognized by gcc & clang iff 32==sizeof (bits)
32  return (bits >> offset) | (bits << (32 - offset));
33  }
34  static inline constexpr uint32_t
35  pcg_xsh_rr (const uint64_t input)
36  {
37  // Section 6.3.1. 32-bit Output, 64-bit State: PCG-XSH-RR
38  // http://www.pcg-random.org/pdf/toms-oneill-pcg-family-v1.02.pdf
39  return ror32 ((input ^ (input >> 18)) >> 27, input >> 59);
40  }
41 public:
43  template<class SeedSeq>
44  explicit Pcg32Rng (SeedSeq &seed_sequence) : increment_ (0), accu_ (0) { seed (seed_sequence); }
46  explicit Pcg32Rng (uint64_t offset, uint64_t sequence) :
47  increment_ (0), accu_ (0)
48  {
49  seed (offset, sequence);
50  }
52  explicit Pcg32Rng () :
53  increment_ (0), accu_ (0)
54  {
55  auto_seed();
56  }
57 
59  void auto_seed ()
60  {
61  //AutoSeeder seeder;
62  //seed (seeder);
63  seed (g_random_int(), g_random_int());
64  }
66  void seed (uint64_t offset, uint64_t sequence)
67  {
68  accu_ = sequence;
69  increment_ = (sequence << 1) | 1; // force increment_ to be odd
70  accu_ += offset;
71  accu_ = A * accu_ + increment_;
72  }
74  template<class SeedSeq> void
75  seed (SeedSeq &seed_sequence)
76  {
77  uint64_t seeds[2];
78  seed_sequence.generate (&seeds[0], &seeds[2]);
79  seed (seeds[0], seeds[1]);
80  }
82  uint32_t
83  random ()
84  {
85  const uint64_t lcgout = accu_; // using the *last* state as ouput helps with CPU pipelining
86  accu_ = A * accu_ + increment_;
87  return pcg_xsh_rr (lcgout); // PCG XOR-shift + random rotation
88  }
89 };
90 
91 }
92 
93 #endif
uint32_t random()
Generate uniformly distributed 32 bit pseudo random number.
Definition: smpcg32rng.hh:83
void seed(uint64_t offset, uint64_t sequence)
Seed by seeking to position offset within stream sequence.
Definition: smpcg32rng.hh:66
Definition: smpcg32rng.hh:24
Pcg32Rng(SeedSeq &seed_sequence)
Initialize and seed from seed_sequence.
Definition: smpcg32rng.hh:44
void seed(SeedSeq &seed_sequence)
Seed the generator state from a seed_sequence.
Definition: smpcg32rng.hh:75
Definition: smalignedarray.cc:7
void auto_seed()
Seed the generator from a system specific nondeterministic random source.
Definition: smpcg32rng.hh:59
Pcg32Rng(uint64_t offset, uint64_t sequence)
Initialize and seed by seeking to position offset within stream sequence.
Definition: smpcg32rng.hh:46
Pcg32Rng()
Initialize and seed the generator from a system specific nondeterministic random source.
Definition: smpcg32rng.hh:52