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