2 * Copyright 2015 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.
17 #ifndef FOLLY_RANDOM_H_
18 #define FOLLY_RANDOM_H_
20 #include <type_traits>
23 #include <folly/ThreadLocal.h>
25 #if __GNUC_PREREQ(4, 8) && !defined(ANDROID)
27 #define FOLLY_USE_SIMD_PRNG 1
33 * A PRNG with one instance per thread. This PRNG uses a mersenne twister random
34 * number generator and is seeded from /dev/urandom. It should not be used for
35 * anything which requires security, only for statistical randomness.
37 * An instance of this class represents the current threads PRNG. This means
38 * copying an instance of this class across threads will result in corruption
40 * Most users will use the Random class which implicitly creates this class.
41 * However, if you are worried about performance, you can memoize the TLS
42 * lookups that get the per thread state by manually using this class:
44 * ThreadLocalPRNG rng = Random::threadLocalPRNG()
46 * Random::rand32(rng);
49 class ThreadLocalPRNG {
51 typedef uint32_t result_type;
53 uint32_t operator()() {
54 // Using a static method allows the compiler to avoid allocating stack space
56 return getImpl(local_);
59 static constexpr result_type min() {
60 return std::numeric_limits<result_type>::min();
62 static constexpr result_type max() {
63 return std::numeric_limits<result_type>::max();
70 class LocalInstancePRNG;
72 static result_type getImpl(LocalInstancePRNG* local);
73 LocalInstancePRNG* local_;
81 using ValidRNG = typename std::enable_if<
82 std::is_unsigned<typename std::result_of<RNG&()>::type>::value,
86 // Default generator type.
87 #if FOLLY_USE_SIMD_PRNG
88 typedef __gnu_cxx::sfmt19937 DefaultGenerator;
90 typedef std::mt19937 DefaultGenerator;
94 * Get secure random bytes. (On Linux and OSX, this means /dev/urandom).
96 static void secureRandom(void* data, size_t len);
99 * Shortcut to get a secure random value of integral type.
102 static typename std::enable_if<
103 std::is_integral<T>::value && !std::is_same<T,bool>::value,
107 secureRandom(&val, sizeof(val));
112 * (Re-)Seed an existing RNG with a good seed.
114 * Note that you should usually use ThreadLocalPRNG unless you need
115 * reproducibility (such as during a test), in which case you'd want
116 * to create a RNG with a good seed in production, and seed it yourself
119 template <class RNG = DefaultGenerator>
120 static void seed(ValidRNG<RNG>& rng);
123 * Create a new RNG, seeded with a good seed.
125 * Note that you should usually use ThreadLocalPRNG unless you need
126 * reproducibility (such as during a test), in which case you'd want
127 * to create a RNG with a good seed in production, and seed it yourself
130 template <class RNG = DefaultGenerator>
131 static ValidRNG<RNG> create();
134 * Returns a random uint32_t
136 template<class RNG = ThreadLocalPRNG>
137 static uint32_t rand32(ValidRNG<RNG> rng = RNG()) {
138 uint32_t r = rng.operator()();
143 * Returns a random uint32_t in [0, max). If max == 0, returns 0.
145 template<class RNG = ThreadLocalPRNG>
146 static uint32_t rand32(uint32_t max, ValidRNG<RNG> rng = RNG()) {
151 return std::uniform_int_distribution<uint32_t>(0, max - 1)(rng);
155 * Returns a random uint32_t in [min, max). If min == max, returns 0.
157 template<class RNG = ThreadLocalPRNG>
158 static uint32_t rand32(uint32_t min,
160 ValidRNG<RNG> rng = RNG()) {
165 return std::uniform_int_distribution<uint32_t>(min, max - 1)(rng);
169 * Returns a random uint64_t
171 template<class RNG = ThreadLocalPRNG>
172 static uint64_t rand64(ValidRNG<RNG> rng = RNG()) {
173 return ((uint64_t) rng() << 32) | rng();
177 * Returns a random uint64_t in [0, max). If max == 0, returns 0.
179 template<class RNG = ThreadLocalPRNG>
180 static uint64_t rand64(uint64_t max, ValidRNG<RNG> rng = RNG()) {
185 return std::uniform_int_distribution<uint64_t>(0, max - 1)(rng);
189 * Returns a random uint64_t in [min, max). If min == max, returns 0.
191 template<class RNG = ThreadLocalPRNG>
192 static uint64_t rand64(uint64_t min,
194 ValidRNG<RNG> rng = RNG()) {
199 return std::uniform_int_distribution<uint64_t>(min, max - 1)(rng);
203 * Returns true 1/n of the time. If n == 0, always returns false
205 template<class RNG = ThreadLocalPRNG>
206 static bool oneIn(uint32_t n, ValidRNG<RNG> rng = RNG()) {
211 return rand32(n, rng) == 0;
215 * Returns a double in [0, 1)
217 template<class RNG = ThreadLocalPRNG>
218 static double randDouble01(ValidRNG<RNG> rng = RNG()) {
219 return std::generate_canonical<double, std::numeric_limits<double>::digits>
224 * Returns a double in [min, max), if min == max, returns 0.
226 template<class RNG = ThreadLocalPRNG>
227 static double randDouble(double min, double max, ValidRNG<RNG> rng = RNG()) {
228 if (std::fabs(max - min) < std::numeric_limits<double>::epsilon()) {
231 return std::uniform_real_distribution<double>(min, max)(rng);
237 * Return a good seed for a random number generator.
238 * Note that this is a legacy function, as it returns a 32-bit value, which
239 * is too small to be useful as a "real" RNG seed. Use the functions in class
242 inline uint32_t randomNumberSeed() {
243 return Random::rand32();
248 #include <folly/Random-inl.h>