2 * Copyright 2014 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();
68 local_ = localInstance.get();
75 class LocalInstancePRNG;
76 static LocalInstancePRNG* initLocal();
77 static folly::ThreadLocalPtr<ThreadLocalPRNG::LocalInstancePRNG>
80 static result_type getImpl(LocalInstancePRNG* local);
81 LocalInstancePRNG* local_;
89 using ValidRNG = typename std::enable_if<
90 std::is_unsigned<typename std::result_of<RNG&()>::type>::value,
94 // Default generator type.
95 #if FOLLY_USE_SIMD_PRNG
96 typedef __gnu_cxx::sfmt19937 DefaultGenerator;
98 typedef std::mt19937 DefaultGenerator;
102 * Get secure random bytes. (On Linux and OSX, this means /dev/urandom).
104 static void secureRandom(void* data, size_t len);
107 * Shortcut to get a secure random value of integral type.
110 static typename std::enable_if<
111 std::is_integral<T>::value && !std::is_same<T,bool>::value,
115 secureRandom(&val, sizeof(val));
120 * (Re-)Seed an existing RNG with a good seed.
122 * Note that you should usually use ThreadLocalPRNG unless you need
123 * reproducibility (such as during a test), in which case you'd want
124 * to create a RNG with a good seed in production, and seed it yourself
127 template <class RNG = DefaultGenerator>
128 static void seed(ValidRNG<RNG>& rng);
131 * Create a new RNG, seeded with a good seed.
133 * Note that you should usually use ThreadLocalPRNG unless you need
134 * reproducibility (such as during a test), in which case you'd want
135 * to create a RNG with a good seed in production, and seed it yourself
138 template <class RNG = DefaultGenerator>
139 static ValidRNG<RNG> create();
142 * Returns a random uint32_t
144 template<class RNG = ThreadLocalPRNG>
145 static uint32_t rand32(ValidRNG<RNG> rng = RNG()) {
146 uint32_t r = rng.operator()();
151 * Returns a random uint32_t in [0, max). If max == 0, returns 0.
153 template<class RNG = ThreadLocalPRNG>
154 static uint32_t rand32(uint32_t max, ValidRNG<RNG> rng = RNG()) {
159 return std::uniform_int_distribution<uint32_t>(0, max - 1)(rng);
163 * Returns a random uint32_t in [min, max). If min == max, returns 0.
165 template<class RNG = ThreadLocalPRNG>
166 static uint32_t rand32(uint32_t min,
168 ValidRNG<RNG> rng = RNG()) {
173 return std::uniform_int_distribution<uint32_t>(min, max - 1)(rng);
177 * Returns a random uint64_t
179 template<class RNG = ThreadLocalPRNG>
180 static uint64_t rand64(ValidRNG<RNG> rng = RNG()) {
181 return ((uint64_t) rng() << 32) | rng();
185 * Returns a random uint64_t in [0, max). If max == 0, returns 0.
187 template<class RNG = ThreadLocalPRNG>
188 static uint64_t rand64(uint64_t max, ValidRNG<RNG> rng = RNG()) {
193 return std::uniform_int_distribution<uint64_t>(0, max - 1)(rng);
197 * Returns a random uint64_t in [min, max). If min == max, returns 0.
199 template<class RNG = ThreadLocalPRNG>
200 static uint64_t rand64(uint64_t min,
202 ValidRNG<RNG> rng = RNG()) {
207 return std::uniform_int_distribution<uint64_t>(min, max - 1)(rng);
211 * Returns true 1/n of the time. If n == 0, always returns false
213 template<class RNG = ThreadLocalPRNG>
214 static bool oneIn(uint32_t n, ValidRNG<RNG> rng = RNG()) {
219 return rand32(n, rng) == 0;
223 * Returns a double in [0, 1)
225 template<class RNG = ThreadLocalPRNG>
226 static double randDouble01(ValidRNG<RNG> rng = RNG()) {
227 return std::generate_canonical<double, std::numeric_limits<double>::digits>
232 * Returns a double in [min, max), if min == max, returns 0.
234 template<class RNG = ThreadLocalPRNG>
235 static double randDouble(double min, double max, ValidRNG<RNG> rng = RNG()) {
236 if (std::fabs(max - min) < std::numeric_limits<double>::epsilon()) {
239 return std::uniform_real_distribution<double>(min, max)(rng);
245 * Return a good seed for a random number generator.
246 * Note that this is a legacy function, as it returns a 32-bit value, which
247 * is too small to be useful as a "real" RNG seed. Use the functions in class
250 inline uint32_t randomNumberSeed() {
251 return Random::rand32();
256 #include <folly/Random-inl.h>