File indexing completed on 2024-11-15 09:01:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef ABSL_RANDOM_INTERNAL_POOL_URBG_H_
0016 #define ABSL_RANDOM_INTERNAL_POOL_URBG_H_
0017
0018 #include <cinttypes>
0019 #include <limits>
0020
0021 #include "absl/random/internal/traits.h"
0022 #include "absl/types/span.h"
0023
0024 namespace absl {
0025 ABSL_NAMESPACE_BEGIN
0026 namespace random_internal {
0027
0028
0029
0030
0031
0032 template <typename T>
0033 class RandenPool {
0034 public:
0035 using result_type = T;
0036 static_assert(std::is_unsigned<result_type>::value,
0037 "RandenPool template argument must be a built-in unsigned "
0038 "integer type");
0039
0040 static constexpr result_type(min)() {
0041 return (std::numeric_limits<result_type>::min)();
0042 }
0043
0044 static constexpr result_type(max)() {
0045 return (std::numeric_limits<result_type>::max)();
0046 }
0047
0048 RandenPool() {}
0049
0050
0051 inline result_type operator()() { return Generate(); }
0052
0053
0054 static void Fill(absl::Span<result_type> data);
0055
0056 protected:
0057
0058 static result_type Generate();
0059 };
0060
0061 extern template class RandenPool<uint8_t>;
0062 extern template class RandenPool<uint16_t>;
0063 extern template class RandenPool<uint32_t>;
0064 extern template class RandenPool<uint64_t>;
0065
0066
0067
0068
0069 template <typename T, size_t kBufferSize>
0070 class PoolURBG {
0071
0072 using unsigned_type = typename make_unsigned_bits<T>::type;
0073 using PoolType = RandenPool<unsigned_type>;
0074 using SpanType = absl::Span<unsigned_type>;
0075
0076 static constexpr size_t kInitialBuffer = kBufferSize + 1;
0077 static constexpr size_t kHalfBuffer = kBufferSize / 2;
0078
0079 public:
0080 using result_type = T;
0081
0082 static_assert(std::is_unsigned<result_type>::value,
0083 "PoolURBG must be parameterized by an unsigned integer type");
0084
0085 static_assert(kBufferSize > 1,
0086 "PoolURBG must be parameterized by a buffer-size > 1");
0087
0088 static_assert(kBufferSize <= 256,
0089 "PoolURBG must be parameterized by a buffer-size <= 256");
0090
0091 static constexpr result_type(min)() {
0092 return (std::numeric_limits<result_type>::min)();
0093 }
0094
0095 static constexpr result_type(max)() {
0096 return (std::numeric_limits<result_type>::max)();
0097 }
0098
0099 PoolURBG() : next_(kInitialBuffer) {}
0100
0101
0102 PoolURBG(const PoolURBG&) : next_(kInitialBuffer) {}
0103 const PoolURBG& operator=(const PoolURBG&) {
0104 next_ = kInitialBuffer;
0105 return *this;
0106 }
0107
0108
0109 PoolURBG(PoolURBG&&) = default;
0110 PoolURBG& operator=(PoolURBG&&) = default;
0111
0112 inline result_type operator()() {
0113 if (next_ >= kBufferSize) {
0114 next_ = (kBufferSize > 2 && next_ > kBufferSize) ? kHalfBuffer : 0;
0115 PoolType::Fill(SpanType(reinterpret_cast<unsigned_type*>(state_ + next_),
0116 kBufferSize - next_));
0117 }
0118 return state_[next_++];
0119 }
0120
0121 private:
0122
0123 size_t next_;
0124 result_type state_[kBufferSize];
0125 };
0126
0127 }
0128 ABSL_NAMESPACE_END
0129 }
0130
0131 #endif