2 * Copyright 2016 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 = Random::threadLocalPRNG()
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();
69 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 ThreadLocalPRNG prng;
141 * Returns a random uint32_t given a specific RNG
143 template <class RNG, class /* EnableIf */ = ValidRNG<RNG>>
144 static uint32_t rand32(RNG rng) {
145 uint32_t r = rng.operator()();
150 * Returns a random uint32_t in [0, max). If max == 0, returns 0.
152 static uint32_t rand32(uint32_t max) {
153 ThreadLocalPRNG prng;
154 return rand32(max, prng);
158 * Returns a random uint32_t in [0, max) given a specific RNG.
159 * If max == 0, returns 0.
161 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
162 static uint32_t rand32(uint32_t max, RNG rng = RNG()) {
167 return std::uniform_int_distribution<uint32_t>(0, max - 1)(rng);
171 * Returns a random uint32_t in [min, max). If min == max, returns 0.
173 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
174 static uint32_t rand32(uint32_t min, uint32_t max, RNG rng = RNG()) {
179 return std::uniform_int_distribution<uint32_t>(min, max - 1)(rng);
183 * Returns a random uint64_t
185 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
186 static uint64_t rand64(RNG rng = RNG()) {
187 return ((uint64_t) rng() << 32) | rng();
191 * Returns a random uint64_t in [0, max). If max == 0, returns 0.
193 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
194 static uint64_t rand64(uint64_t max, RNG rng = RNG()) {
199 return std::uniform_int_distribution<uint64_t>(0, max - 1)(rng);
203 * Returns a random uint64_t in [min, max). If min == max, returns 0.
205 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
206 static uint64_t rand64(uint64_t min, uint64_t max, RNG rng = RNG()) {
211 return std::uniform_int_distribution<uint64_t>(min, max - 1)(rng);
215 * Returns true 1/n of the time. If n == 0, always returns false
217 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
218 static bool oneIn(uint32_t n, ValidRNG<RNG> rng = RNG()) {
223 return rand32(n, rng) == 0;
227 * Returns a double in [0, 1)
229 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
230 static double randDouble01(RNG rng = RNG()) {
231 return std::generate_canonical<double, std::numeric_limits<double>::digits>
236 * Returns a double in [min, max), if min == max, returns 0.
238 template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
239 static double randDouble(double min, double max, RNG rng = RNG()) {
240 if (std::fabs(max - min) < std::numeric_limits<double>::epsilon()) {
243 return std::uniform_real_distribution<double>(min, max)(rng);
249 * Return a good seed for a random number generator.
250 * Note that this is a legacy function, as it returns a 32-bit value, which
251 * is too small to be useful as a "real" RNG seed. Use the functions in class
254 inline uint32_t randomNumberSeed() {
255 return Random::rand32();
260 #include <folly/Random-inl.h>