Random-inl.h 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * Copyright 2014-present Facebook, Inc.
  3. *
  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
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  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.
  15. */
  16. #ifndef FOLLY_RANDOM_H_
  17. #error This file may only be included from folly/Random.h
  18. #endif
  19. namespace folly {
  20. namespace detail {
  21. // Return the state size needed by RNG, expressed as a number of uint32_t
  22. // integers. Specialized for all templates specified in the C++11 standard.
  23. // For some (mersenne_twister_engine), this is exported as a state_size static
  24. // data member; for others, the standard shows formulas.
  25. template <class RNG, typename = void>
  26. struct StateSize {
  27. // A sane default.
  28. using type = std::integral_constant<size_t, 512>;
  29. };
  30. template <class RNG>
  31. struct StateSize<RNG, void_t<decltype(RNG::state_size)>> {
  32. using type = std::integral_constant<size_t, RNG::state_size>;
  33. };
  34. template <class UIntType, UIntType a, UIntType c, UIntType m>
  35. struct StateSize<std::linear_congruential_engine<UIntType, a, c, m>> {
  36. // From the standard [rand.eng.lcong], this is ceil(log2(m) / 32) + 3,
  37. // which is the same as ceil(ceil(log2(m) / 32) + 3, and
  38. // ceil(log2(m)) <= std::numeric_limits<UIntType>::digits
  39. using type = std::integral_constant<
  40. size_t,
  41. (std::numeric_limits<UIntType>::digits + 31) / 32 + 3>;
  42. };
  43. template <class UIntType, size_t w, size_t s, size_t r>
  44. struct StateSize<std::subtract_with_carry_engine<UIntType, w, s, r>> {
  45. // [rand.eng.sub]: r * ceil(w / 32)
  46. using type = std::integral_constant<size_t, r*((w + 31) / 32)>;
  47. };
  48. template <typename RNG>
  49. using StateSizeT = _t<StateSize<RNG>>;
  50. template <class RNG>
  51. struct SeedData {
  52. SeedData() {
  53. Random::secureRandom(seedData.data(), seedData.size() * sizeof(uint32_t));
  54. }
  55. static constexpr size_t stateSize = StateSizeT<RNG>::value;
  56. std::array<uint32_t, stateSize> seedData;
  57. };
  58. } // namespace detail
  59. template <class RNG, class /* EnableIf */>
  60. void Random::seed(RNG& rng) {
  61. detail::SeedData<RNG> sd;
  62. std::seed_seq s(std::begin(sd.seedData), std::end(sd.seedData));
  63. rng.seed(s);
  64. }
  65. template <class RNG, class /* EnableIf */>
  66. auto Random::create() -> RNG {
  67. detail::SeedData<RNG> sd;
  68. std::seed_seq s(std::begin(sd.seedData), std::end(sd.seedData));
  69. return RNG(s);
  70. }
  71. } // namespace folly