15 #ifndef ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_
16 #define ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_
21 #include <type_traits>
23 #include "absl/base/config.h"
24 #include "absl/meta/type_traits.h"
25 #include "absl/random/internal/traits.h"
29 namespace random_internal {
32 template <
typename UIntType>
34 return (
n == 0) || ((
n & (
n - 1)) == 0);
40 template <
typename URBG>
45 (
URBG::min)() == std::numeric_limits<result_type>::lowest())
51 template <
typename UIntType>
58 template <
typename URBG>
60 return RangeSize<URBG>() == 0
61 ? std::numeric_limits<typename URBG::result_type>::digits
67 template <
typename UIntType>
69 return ((
n % std::numeric_limits<UIntType>::digits) == 0)
71 : (UIntType{1} <<
n) - UIntType{1};
88 template <
typename UIntType = u
int64_t>
98 template <
typename URBG>
103 "Class-template FastUniformBits<> must be parameterized using "
104 "an unsigned type.");
109 template <
typename URBG>
113 template <
typename URBG>
118 template <
typename UIntType>
119 template <
typename URBG>
126 "URBG::max and URBG::min may not be equal.");
130 return Generate(
g,
tag{});
133 template <
typename UIntType>
134 template <
typename URBG>
142 "incorrect Generate tag for URBG instance");
144 static constexpr
size_t kResultBits =
145 std::numeric_limits<result_type>::digits;
146 static constexpr
size_t kUrbgBits = NumBits<URBG>();
147 static constexpr
size_t kIters =
148 (kResultBits / kUrbgBits) + (kResultBits % kUrbgBits != 0);
149 static constexpr
size_t kShift = (
kIters == 1) ? 0 : kUrbgBits;
150 static constexpr
auto kMin = (
URBG::min)();
154 r = (r << kShift) + static_cast<result_type>(
g() - kMin);
159 template <
typename UIntType>
160 template <
typename URBG>
165 "incorrect Generate tag for URBG instance");
185 static constexpr
size_t kResultBits =
186 std::numeric_limits<result_type>::digits;
187 static constexpr urbg_result_type kUrbgRange = RangeSize<URBG>();
188 static constexpr
size_t kUrbgBits = NumBits<URBG>();
192 static constexpr
size_t kA =
193 (kResultBits / kUrbgBits) + ((kResultBits % kUrbgBits) != 0);
195 static constexpr
size_t kABits = kResultBits / kA;
196 static constexpr urbg_result_type kARejection =
197 ((kUrbgRange >> kABits) << kABits);
200 static constexpr
size_t kTotalIters =
201 ((kUrbgRange - kARejection) <= (kARejection / kA)) ? kA : (kA + 1);
204 static constexpr
size_t kSmallIters =
205 kTotalIters - (kResultBits % kTotalIters);
206 static constexpr
size_t kSmallBits = kResultBits / kTotalIters;
207 static constexpr urbg_result_type kSmallRejection =
208 ((kUrbgRange >> kSmallBits) << kSmallBits);
210 static constexpr
size_t kLargeBits = kSmallBits + 1;
211 static constexpr urbg_result_type kLargeRejection =
212 ((kUrbgRange >> kLargeBits) << kLargeBits);
228 static_assert(kResultBits == kSmallIters * kSmallBits +
229 (kTotalIters - kSmallIters) * kLargeBits,
230 "Error in looping constant calculations.");
235 static constexpr
size_t kSmallShift = kSmallBits % kResultBits;
236 static constexpr
auto kSmallMask =
237 MaskFromShift<urbg_result_type>(kSmallShift);
238 static constexpr
size_t kLargeShift = kLargeBits % kResultBits;
239 static constexpr
auto kLargeMask =
240 MaskFromShift<urbg_result_type>(kLargeShift);
242 static constexpr
auto kMin = (
URBG::min)();
245 for (
size_t n = 0;
n < kSmallIters; ++
n) {
249 }
while (
v >= kSmallRejection);
251 s = (s << kSmallShift) + static_cast<result_type>(
v & kSmallMask);
254 for (
size_t n = kSmallIters;
n < kTotalIters; ++
n) {
258 }
while (
v >= kLargeRejection);
260 s = (s << kLargeShift) + static_cast<result_type>(
v & kLargeMask);
269 #endif // ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_