| /* |
| * Copyright 2015 Facebook, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef FOLLY_RANDOM_H_ |
| #error This file may only be included from folly/Random.h |
| #endif |
| |
| namespace folly { |
| |
| namespace detail { |
| |
| // Return the state size needed by RNG, expressed as a number of uint32_t |
| // integers. Specialized for all templates specified in the C++11 standard. |
| // For some (mersenne_twister_engine), this is exported as a state_size static |
| // data member; for others, the standard shows formulas. |
| |
| template <class RNG> struct StateSize { |
| // A sane default. |
| static constexpr size_t value = 512; |
| }; |
| |
| template <class RNG> |
| constexpr size_t StateSize<RNG>::value; |
| |
| template <class UIntType, UIntType a, UIntType c, UIntType m> |
| struct StateSize<std::linear_congruential_engine<UIntType, a, c, m>> { |
| // From the standard [rand.eng.lcong], this is ceil(log2(m) / 32) + 3, |
| // which is the same as ceil(ceil(log2(m) / 32) + 3, and |
| // ceil(log2(m)) <= std::numeric_limits<UIntType>::digits |
| static constexpr size_t value = |
| (std::numeric_limits<UIntType>::digits + 31) / 32 + 3; |
| }; |
| |
| template <class UIntType, UIntType a, UIntType c, UIntType m> |
| constexpr size_t |
| StateSize<std::linear_congruential_engine<UIntType, a, c, m>>::value; |
| |
| template <class UIntType, size_t w, size_t n, size_t m, size_t r, |
| UIntType a, size_t u, UIntType d, size_t s, |
| UIntType b, size_t t, |
| UIntType c, size_t l, UIntType f> |
| struct StateSize<std::mersenne_twister_engine<UIntType, w, n, m, r, |
| a, u, d, s, b, t, c, l, f>> { |
| static constexpr size_t value = |
| std::mersenne_twister_engine<UIntType, w, n, m, r, |
| a, u, d, s, b, t, c, l, f>::state_size; |
| }; |
| |
| template <class UIntType, size_t w, size_t n, size_t m, size_t r, |
| UIntType a, size_t u, UIntType d, size_t s, |
| UIntType b, size_t t, |
| UIntType c, size_t l, UIntType f> |
| constexpr size_t |
| StateSize<std::mersenne_twister_engine<UIntType, w, n, m, r, |
| a, u, d, s, b, t, c, l, f>>::value; |
| |
| #if FOLLY_USE_SIMD_PRNG |
| |
| template <class UIntType, size_t m, size_t pos1, size_t sl1, size_t sl2, |
| size_t sr1, size_t sr2, uint32_t msk1, uint32_t msk2, uint32_t msk3, |
| uint32_t msk4, uint32_t parity1, uint32_t parity2, uint32_t parity3, |
| uint32_t parity4> |
| struct StateSize<__gnu_cxx::simd_fast_mersenne_twister_engine< |
| UIntType, m, pos1, sl1, sl2, sr1, sr2, msk1, msk2, msk3, msk4, |
| parity1, parity2, parity3, parity4>> { |
| static constexpr size_t value = |
| __gnu_cxx::simd_fast_mersenne_twister_engine< |
| UIntType, m, pos1, sl1, sl2, sr1, sr2, |
| msk1, msk2, msk3, msk4, |
| parity1, parity2, parity3, parity4>::state_size; |
| }; |
| |
| template <class UIntType, size_t m, size_t pos1, size_t sl1, size_t sl2, |
| size_t sr1, size_t sr2, uint32_t msk1, uint32_t msk2, uint32_t msk3, |
| uint32_t msk4, uint32_t parity1, uint32_t parity2, uint32_t parity3, |
| uint32_t parity4> |
| constexpr size_t |
| StateSize<__gnu_cxx::simd_fast_mersenne_twister_engine< |
| UIntType, m, pos1, sl1, sl2, sr1, sr2, msk1, msk2, msk3, msk4, |
| parity1, parity2, parity3, parity4>>::value; |
| |
| #endif |
| |
| template <class UIntType, size_t w, size_t s, size_t r> |
| struct StateSize<std::subtract_with_carry_engine<UIntType, w, s, r>> { |
| // [rand.eng.sub]: r * ceil(w / 32) |
| static constexpr size_t value = r * ((w + 31) / 32); |
| }; |
| |
| template <class UIntType, size_t w, size_t s, size_t r> |
| constexpr size_t |
| StateSize<std::subtract_with_carry_engine<UIntType, w, s, r>>::value; |
| |
| template <class RNG> |
| struct SeedData { |
| SeedData() { |
| Random::secureRandom(seedData.data(), seedData.size() * sizeof(uint32_t)); |
| } |
| |
| static constexpr size_t stateSize = StateSize<RNG>::value; |
| std::array<uint32_t, stateSize> seedData; |
| }; |
| |
| } // namespace detail |
| |
| template <class RNG> |
| void Random::seed(ValidRNG<RNG>& rng) { |
| detail::SeedData<RNG> sd; |
| std::seed_seq s(std::begin(sd.seedData), std::end(sd.seedData)); |
| rng.seed(s); |
| } |
| |
| template <class RNG> |
| auto Random::create() -> ValidRNG<RNG> { |
| detail::SeedData<RNG> sd; |
| std::seed_seq s(std::begin(sd.seedData), std::end(sd.seedData)); |
| return RNG(s); |
| } |
| |
| } // namespaces |