32 #ifndef MCKL_RANDOM_UNIFORM_BITS_DISTRIBUTION_HPP 33 #define MCKL_RANDOM_UNIFORM_BITS_DISTRIBUTION_HPP 41 template <
typename UIntType,
typename RNGType>
43 RNGType &rng, std::size_t n, UIntType *r, std::false_type, std::false_type)
46 for (std::size_t i = 0; i != n; ++i) {
51 template <
typename UIntType,
typename RNGType,
bool DownCast>
53 UIntType *r, std::true_type, std::integral_constant<bool, DownCast>)
56 constexpr
int ubits = std::numeric_limits<UIntType>::digits;
57 constexpr std::size_t rate = ubits / rbits;
58 const std::size_t m = n * rate;
59 rand(rng, m, reinterpret_cast<typename RNGType::result_type *>(r));
62 template <
typename UIntType,
typename RNGType>
64 RNGType &rng, std::size_t n, UIntType *r, std::false_type, std::true_type)
67 alignas(
MCKL_ALIGNMENT) std::array<typename RNGType::result_type, k> s;
69 rand(rng, k, s.data());
70 std::copy_n(s.data(), k, r);
74 rand(rng, n, s.data());
75 std::copy_n(s.data(), n, r);
80 template <
typename UIntType,
typename RNGType>
84 constexpr
int ubits = std::numeric_limits<UIntType>::digits;
86 std::numeric_limits<typename RNGType::result_type>::digits;
87 constexpr std::size_t ualign =
alignof(UIntType);
88 constexpr std::size_t talign =
alignof(UIntType);
89 constexpr
bool direct =
95 ubits >= tbits && ubits % tbits == 0 &&
97 ualign >= talign && ualign % talign == 0;
98 constexpr
bool downcast =
105 std::integral_constant<bool, direct>(),
106 std::integral_constant<bool, downcast>());
109 template <
typename UIntType,
typename RNGType>
123 template <
typename UIntType>
131 result_type min()
const {
return std::numeric_limits<result_type>::min(); }
138 template <
typename RNGType>
143 return generate(rng, std::integral_constant<bool, patch>());
146 template <
typename RNGType>
147 static UIntType generate(RNGType &rng, std::false_type)
149 std::independent_bits_engine<RNGType,
150 std::numeric_limits<UIntType>::digits, UIntType>
153 rng = std::move(eng.base());
158 template <
typename RNGType>
159 static UIntType generate(RNGType &rng, std::true_type)
161 constexpr
int w = std::numeric_limits<UIntType>::digits;
164 return generate_patch(rng, std::integral_constant<
bool, (w <= r)>());
167 template <
typename RNGType>
168 static UIntType generate_patch(RNGType &rng, std::true_type)
170 return static_cast<UIntType
>(rng() - RNGType::min());
173 template <
typename RNGType>
174 static UIntType generate_patch(RNGType &rng, std::false_type)
176 #if MCKL_HAS_LITTLE_ENDIAN || !MCKL_REQUIRE_ENDIANNESS_NEUTURAL 177 return patch_le<0>(rng, std::true_type());
178 #elif MCKL_HAS_BIG_ENDIAN 179 return patch_be<0>(rng, std::true_type());
182 patch_le<0>(rng, std::true_type());
186 template <
int,
typename RNGType>
187 static UIntType patch_le(RNGType &, std::false_type)
192 template <
int N,
typename RNGType>
193 static UIntType patch_le(RNGType &rng, std::true_type)
195 constexpr
int w = std::numeric_limits<UIntType>::digits;
197 constexpr
int p = r * N;
198 constexpr
int q = r * N + r;
200 UIntType u =
static_cast<UIntType
>(rng() - RNGType::min())
201 << static_cast<UIntType>(p);
204 patch_le<N + 1>(rng, std::integral_constant<bool, (q < w)>());
207 template <
int N,
typename RNGType>
208 static UIntType patch_be(RNGType &, std::false_type)
213 template <
int N,
typename RNGType>
214 static UIntType patch_be(RNGType &rng, std::true_type)
216 constexpr
int w = std::numeric_limits<UIntType>::digits;
218 constexpr
int q = r * N + r;
219 constexpr
int pl = q < w ? w - q : 0;
220 constexpr
int pr = q < w ? 0 : q - w;
222 UIntType u =
static_cast<UIntType
>(rng() - RNGType::min());
223 u <<= static_cast<UIntType>(pl);
224 u >>=
static_cast<UIntType
>(pr);
227 patch_be<N + 1>(rng, std::integral_constant<bool, (q < w)>());
235 #endif // MCKL_RANDOM_UNIFORM_BITS_DISTRIBUTION_HPP
void uniform_bits_distribution_impl(RNGType &rng, std::size_t n, UIntType *r, std::false_type, std::false_type)
void uniform_bits_distribution(RNGType &rng, std::size_t n, UIntType *r)
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_RAND(Name, T)
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_0(Name, name, T)
void rand(RNGType &rng, ArcsineDistribution< RealType > &distribution, std::size_t N, RealType *r)
#define MCKL_ALIGNMENT
The default alignment for scalar type.
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_MEMBER_0
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_ASSERT_UINT_TYPE(Name, MinBits)