2 * Copyright 2017 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #define FOLLY_RANDOM_H_
20 #include <type_traits>
23 #include <folly/Portability.h>
25 #if FOLLY_HAVE_EXTRANDOM_SFMT19937
32 * A PRNG with one instance per thread. This PRNG uses a mersenne twister random
33 * number generator and is seeded from /dev/urandom. It should not be used for
34 * anything which requires security, only for statistical randomness.
36 * An instance of this class represents the current threads PRNG. This means
37 * copying an instance of this class across threads will result in corruption
39 * Most users will use the Random class which implicitly creates this class.
40 * However, if you are worried about performance, you can memoize the TLS
41 * lookups that get the per thread state by manually using this class:
43 * ThreadLocalPRNG rng;
45 * Random::rand32(rng);
48 class ThreadLocalPRNG {
50 typedef uint32_t result_type;
52 uint32_t operator()() {
53 // Using a static method allows the compiler to avoid allocating stack space
55 return getImpl(local_);
58 static constexpr result_type min() {
59 return std::numeric_limits<result_type>::min();
61 static constexpr result_type max() {
62 return std::numeric_limits<result_type>::max();
68 class LocalInstancePRNG;
71 static result_type getImpl(LocalInstancePRNG* local);
72 LocalInstancePRNG* local_;
80 using ValidRNG = typename std::enable_if<
81 std::is_unsigned<typename std::result_of<RNG&()>::type>::value,
85 // Default generator type.
86 #if FOLLY_HAVE_EXTRANDOM_SFMT19937
87 typedef __gnu_cxx::sfmt19937 DefaultGenerator;
89 typedef std::mt19937 DefaultGenerator;
93 * Get secure random bytes. (On Linux and OSX, this means /dev/urandom).
95 static void secureRandom(void* data, size_t len);
98 * Shortcut to get a secure random value of integral type.
101 static typename std::enable_if<
102 std::is_integral<T>::value && !std::is_same<T,bool>::value,
106 secureRandom(&val, sizeof(val));
111 * (Re-)Seed an existing RNG with a good seed.
113 * Note that you should usually use ThreadLocalPRNG unless you need
114 * reproducibility (such as during a test), in which case you'd want
115 * to create a RNG with a good seed in production, and seed it yourself
118 template <class RNG = DefaultGenerator, class /* EnableIf */ = ValidRNG<RNG>>
119 static void seed(RNG& rng);
122 * Create a new RNG, seeded with a good seed.
124 * Note that you should usually use ThreadLocalPRNG unless you need
125 * reproducibility (such as during a test), in which case you'd want
126 * to create a RNG with a good seed in production, and seed it yourself
129 template <class RNG = DefaultGenerator, class /* EnableIf */ = ValidRNG<RNG>>
133 * Returns a random uint32_t
135 static uint32_t rand32() {
136 return rand32(ThreadLocalPRNG());
140 * Returns a random uint32_t given a specific RNG
142 template <class RNG, class /* EnableIf */ = ValidRNG<RNG>>
143 static uint32_t rand32(RNG&& rng) {
148 * Returns a random uint32_t in [0, max). If max == 0, returns 0.
150 static uint32_t rand32(uint32_t max) {
151 return rand32(0, max, ThreadLocalPRNG());
155 * Returns a random uint32_t in [0, max) given a specific RNG.
156 * If max == 0, returns 0.
158 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
159 static uint32_t rand32(uint32_t max, RNG&& rng) {
160 return rand32(0, max, rng);
164 * Returns a random uint32_t in [min, max). If min == max, returns 0.
166 static uint32_t rand32(uint32_t min, uint32_t max) {
167 return rand32(min, max, ThreadLocalPRNG());
171 * Returns a random uint32_t in [min, max) given a specific RNG.
172 * If min == max, returns 0.
174 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
175 static uint32_t rand32(uint32_t min, uint32_t max, RNG&& rng) {
179 return std::uniform_int_distribution<uint32_t>(min, max - 1)(rng);
183 * Returns a random uint64_t
185 static uint64_t rand64() {
186 return rand64(ThreadLocalPRNG());
190 * Returns a random uint64_t
192 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
193 static uint64_t rand64(RNG&& rng) {
194 return ((uint64_t)rng() << 32) | rng();
198 * Returns a random uint64_t in [0, max). If max == 0, returns 0.
200 static uint64_t rand64(uint64_t max) {
201 return rand64(0, max, ThreadLocalPRNG());
205 * Returns a random uint64_t in [0, max). If max == 0, returns 0.
207 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
208 static uint64_t rand64(uint64_t max, RNG&& rng) {
209 return rand64(0, max, rng);
213 * Returns a random uint64_t in [min, max). If min == max, returns 0.
215 static uint64_t rand64(uint64_t min, uint64_t max) {
216 return rand64(min, max, ThreadLocalPRNG());
220 * Returns a random uint64_t in [min, max). If min == max, returns 0.
222 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
223 static uint64_t rand64(uint64_t min, uint64_t max, RNG&& rng) {
227 return std::uniform_int_distribution<uint64_t>(min, max - 1)(rng);
231 * Returns true 1/n of the time. If n == 0, always returns false
233 static bool oneIn(uint32_t n) {
234 return oneIn(n, ThreadLocalPRNG());
238 * Returns true 1/n of the time. If n == 0, always returns false
240 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
241 static bool oneIn(uint32_t n, RNG&& rng) {
245 return rand32(0, n, rng) == 0;
249 * Returns a double in [0, 1)
251 static double randDouble01() {
252 return randDouble01(ThreadLocalPRNG());
256 * Returns a double in [0, 1)
258 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
259 static double randDouble01(RNG&& rng) {
260 return std::generate_canonical<double, std::numeric_limits<double>::digits>(
265 * Returns a double in [min, max), if min == max, returns 0.
267 static double randDouble(double min, double max) {
268 return randDouble(min, max, ThreadLocalPRNG());
272 * Returns a double in [min, max), if min == max, returns 0.
274 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
275 static double randDouble(double min, double max, RNG&& rng) {
276 if (std::fabs(max - min) < std::numeric_limits<double>::epsilon()) {
279 return std::uniform_real_distribution<double>(min, max)(rng);
285 * Return a good seed for a random number generator.
286 * Note that this is a legacy function, as it returns a 32-bit value, which
287 * is too small to be useful as a "real" RNG seed. Use the functions in class
290 inline uint32_t randomNumberSeed() {
291 return Random::rand32();
296 #include <folly/Random-inl.h>