1 /* 2 * Tiny self-contained version of the PCG Random Number Generation for C++ 3 * put together from pieces of the much larger C/C++ codebase. 4 * Wenzel Jakob, February 2015 5 * 6 * The PCG random number generator was developed by Melissa O'Neill <oneill@pcg-random.org> 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 * For additional information about the PCG random number generation scheme, 21 * including its license and other licensing options, visit 22 * 23 * http://www.pcg-random.org 24 */ 25 26 #ifndef __PCG32_H 27 #define __PCG32_H 1 28 29 #define PCG32_DEFAULT_STATE 0x853c49e6748fea9bULL 30 #define PCG32_DEFAULT_STREAM 0xda3e39cb94b95bdbULL 31 #define PCG32_MULT 0x5851f42d4c957f2dULL 32 33 #include <inttypes.h> 34 #include <cmath> 35 #include <cassert> 36 #include <algorithm> 37 38 /// PCG32 Pseudorandom number generator 39 struct pcg32 { 40 /// Initialize the pseudorandom number generator with default seed pcg32pcg3241 pcg32() : state(PCG32_DEFAULT_STATE), inc(PCG32_DEFAULT_STREAM) {} 42 43 /// Initialize the pseudorandom number generator with the \ref seed() function 44 pcg32(uint64_t initstate, uint64_t initseq = 1u) { seed(initstate, initseq); } 45 46 /** 47 * \brief Seed the pseudorandom number generator 48 * 49 * Specified in two parts: a state initializer and a sequence selection 50 * constant (a.k.a. stream id) 51 */ 52 void seed(uint64_t initstate, uint64_t initseq = 1) { 53 state = 0U; 54 inc = (initseq << 1u) | 1u; 55 nextUInt(); 56 state += initstate; 57 nextUInt(); 58 } 59 60 /// Generate a uniformly distributed unsigned 32-bit random number nextUIntpcg3261 uint32_t nextUInt() { 62 uint64_t oldstate = state; 63 state = oldstate * PCG32_MULT + inc; 64 uint32_t xorshifted = (uint32_t) (((oldstate >> 18u) ^ oldstate) >> 27u); 65 uint32_t rot = (uint32_t) (oldstate >> 59u); 66 return (xorshifted >> rot) | (xorshifted << ((~rot + 1u) & 31)); 67 } 68 69 /// Generate a uniformly distributed number, r, where 0 <= r < bound nextUIntpcg3270 uint32_t nextUInt(uint32_t bound) { 71 // To avoid bias, we need to make the range of the RNG a multiple of 72 // bound, which we do by dropping output less than a threshold. 73 // A naive scheme to calculate the threshold would be to do 74 // 75 // uint32_t threshold = 0x100000000ull % bound; 76 // 77 // but 64-bit div/mod is slower than 32-bit div/mod (especially on 78 // 32-bit platforms). In essence, we do 79 // 80 // uint32_t threshold = (0x100000000ull-bound) % bound; 81 // 82 // because this version will calculate the same modulus, but the LHS 83 // value is less than 2^32. 84 85 uint32_t threshold = (~bound+1u) % bound; 86 87 // Uniformity guarantees that this loop will terminate. In practice, it 88 // should usually terminate quickly; on average (assuming all bounds are 89 // equally likely), 82.25% of the time, we can expect it to require just 90 // one iteration. In the worst case, someone passes a bound of 2^31 + 1 91 // (i.e., 2147483649), which invalidates almost 50% of the range. In 92 // practice, bounds are typically small and only a tiny amount of the range 93 // is eliminated. 94 for (;;) { 95 uint32_t r = nextUInt(); 96 if (r >= threshold) 97 return r % bound; 98 } 99 } 100 101 /// Generate a single precision floating point value on the interval [0, 1) nextFloatpcg32102 float nextFloat() { 103 /* Trick from MTGP: generate an uniformly distributed 104 single precision number in [1,2) and subtract 1. */ 105 union { 106 uint32_t u; 107 float f; 108 } x; 109 x.u = (nextUInt() >> 9) | 0x3f800000UL; 110 return x.f - 1.0f; 111 } 112 113 /** 114 * \brief Generate a double precision floating point value on the interval [0, 1) 115 * 116 * \remark Since the underlying random number generator produces 32 bit output, 117 * only the first 32 mantissa bits will be filled (however, the resolution is still 118 * finer than in \ref nextFloat(), which only uses 23 mantissa bits) 119 */ nextDoublepcg32120 double nextDouble() { 121 /* Trick from MTGP: generate an uniformly distributed 122 double precision number in [1,2) and subtract 1. */ 123 union { 124 uint64_t u; 125 double d; 126 } x; 127 x.u = ((uint64_t) nextUInt() << 20) | 0x3ff0000000000000ULL; 128 return x.d - 1.0; 129 } 130 131 /** 132 * \brief Multi-step advance function (jump-ahead, jump-back) 133 * 134 * The method used here is based on Brown, "Random Number Generation 135 * with Arbitrary Stride", Transactions of the American Nuclear 136 * Society (Nov. 1994). The algorithm is very similar to fast 137 * exponentiation. 138 */ advancepcg32139 void advance(int64_t delta_) { 140 uint64_t 141 cur_mult = PCG32_MULT, 142 cur_plus = inc, 143 acc_mult = 1u, 144 acc_plus = 0u; 145 146 /* Even though delta is an unsigned integer, we can pass a signed 147 integer to go backwards, it just goes "the long way round". */ 148 uint64_t delta = (uint64_t) delta_; 149 150 while (delta > 0) { 151 if (delta & 1) { 152 acc_mult *= cur_mult; 153 acc_plus = acc_plus * cur_mult + cur_plus; 154 } 155 cur_plus = (cur_mult + 1) * cur_plus; 156 cur_mult *= cur_mult; 157 delta /= 2; 158 } 159 state = acc_mult * state + acc_plus; 160 } 161 162 /** 163 * \brief Draw uniformly distributed permutation and permute the 164 * given STL container 165 * 166 * From: Knuth, TAoCP Vol. 2 (3rd 3d), Section 3.4.2 167 */ shufflepcg32168 template <typename Iterator> void shuffle(Iterator begin, Iterator end) { 169 for (Iterator it = end - 1; it > begin; --it) 170 std::iter_swap(it, begin + nextUInt((uint32_t) (it - begin + 1))); 171 } 172 173 /// Compute the distance between two PCG32 pseudorandom number generators 174 int64_t operator-(const pcg32 &other) const { 175 assert(inc == other.inc); 176 177 uint64_t 178 cur_mult = PCG32_MULT, 179 cur_plus = inc, 180 cur_state = other.state, 181 the_bit = 1u, 182 distance = 0u; 183 184 while (state != cur_state) { 185 if ((state & the_bit) != (cur_state & the_bit)) { 186 cur_state = cur_state * cur_mult + cur_plus; 187 distance |= the_bit; 188 } 189 assert((state & the_bit) == (cur_state & the_bit)); 190 the_bit <<= 1; 191 cur_plus = (cur_mult + 1ULL) * cur_plus; 192 cur_mult *= cur_mult; 193 } 194 195 return (int64_t) distance; 196 } 197 198 /// Equality operator 199 bool operator==(const pcg32 &other) const { return state == other.state && inc == other.inc; } 200 201 /// Inequality operator 202 bool operator!=(const pcg32 &other) const { return state != other.state || inc != other.inc; } 203 204 uint64_t state; // RNG state. All values are possible. 205 uint64_t inc; // Controls which RNG sequence (stream) is selected. Must *always* be odd. 206 }; 207 208 #endif // __PCG32_H 209