19 template <
typename INTEGER = u
int64_t,
typename RANDOM = std::default_random_engine>
22 static std::uniform_int_distribution<INTEGER>
dist;
26 template <
typename REAL =
double,
typename RANDOM = std::default_random_engine>
29 static std::uniform_real_distribution<REAL>
dist;
33 template <
typename REAL =
double,
typename RANDOM = std::default_random_engine>
36 static std::normal_distribution<REAL>
dist;
40 template <
typename RANDOM = std::default_random_engine>
44 std::uniform_int_distribution<uint64_t>
dist{ 0,
n_sided - 1 };
48 template <
typename RANDOM = std::default_random_engine>
52 std::uniform_int_distribution<uint64_t>
dist{ 0,
n_sided - 1 };
59 template <u
int64_t N_SIDED,
typename RANDOM = std::default_random_engine>
63 static std::uniform_int_distribution<uint64_t>
dist{ 0,
N_SIDED - 1 };
67 template <u
int64_t N_DICE, u
int64_t N_SIDED,
typename RANDOM = std::default_random_engine>
71 static std::uniform_int_distribution<uint64_t>
dist{ 0,
N_SIDED - 1 };
78 template <
typename RANDOM = std::default_random_engine>
81 std::uniform_int_distribution<uint64_t>
dist{ 0, 1 };
97 template <
class T,
class...
TYPES>
98 constexpr inline bool is_any_of_v = std::disjunction_v<std::is_same<T, TYPES>...>;
100 template <
typename RANDOM = std::default_random_engine,
typename T>
104 if (from >=
to)
return T{};
105 std::uniform_int_distribution<T>
dist{ from,
to };
109 template <
typename RANDOM = std::default_random_engine, std::
floating_po
int T>
112 if (from >=
to)
return T{};
113 std::uniform_real_distribution<T>
dist{ from,
to };
117 template <
typename RANDOM = std::default_random_engine,
typename T>
120 if (from >=
to)
return T{};
122 if constexpr (std::is_enum_v<T>)
124 std::uniform_int_distribution<std::underlying_type_t<T>>
dist(from,
to);
127 else if constexpr (std::is_floating_point_v<T>)
128 return in_real_range(from,
to,
rng);
130 return in_integer_range(from,
to,
rng);
140 const auto i =
to - from;
141 const auto r = ::ghassanpl::random::in_range(
decltype(
i){},
i);
148 template <std::
floating_po
int T =
float>
156 result +=
fraction * (index % base);
162 template <
typename RANDOM = std::default_random_engine>
168 template <
typename RANDOM = std::default_random_engine>
171 auto res = result = percentage(
rng);
175 template <
typename RANDOM = std::default_random_engine>
178 if (
n == 0)
return false;
179 return with_probability(1.0 /
double(
n),
rng);
182 template <
typename RANDOM = std::default_random_engine,
typename T>
190 template <
typename RANDOM = std::default_random_engine,
typename T>
191 requires std::ranges::sized_range<T>
199 template <
typename RANDOM = std::default_random_engine,
typename T,
typename PRED>
200 requires std::ranges::sized_range<T>
220 template <
typename RANDOM = std::default_random_engine,
typename T>
223 return std::distance(begin(
cont), iterator(
cont,
rng));
226 template <
typename RANDOM = std::default_random_engine,
typename T,
typename PRED>
229 return std::distance(begin(
cont), iterator_if(
cont, std::forward<PRED>(
pred),
rng));
232 template <
typename RANDOM = std::default_random_engine,
typename T>
236 auto result = iterator(
cont,
rng);
237 return (result != end(
cont)) ? std::to_address(result) :
nullptr;
240 template <
typename RANDOM = std::default_random_engine,
typename T,
typename PRED>
245 return (result != end(
cont)) ? std::to_address(result) :
nullptr;
248 template <
typename... T>
249 auto one_of(T&&... values)
252 static_assert(
sizeof...(values) > 0,
"at least one value must be provided");
253 auto v = std::array{ std::forward<T>(values)... };
257 template <
typename RANDOM = std::default_random_engine,
typename T>
260 if (values.size() == 0)
throw std::invalid_argument(
"values");
261 return *element(values,
rng);
269 template <
typename RANDOM = std::default_random_engine,
typename T>
275 Randomizer(RANDOM& rng, T& container)
278 for (
auto it = std::begin(container); it != std::end(container); ++it)
279 mIterators.push_back(it);
280 mCurrent = mIterators.end();
282 auto Next() {
if (mCurrent == mIterators.end()) { Shuffle(); }
return *mCurrent++; }
283 void Shuffle() { std::ranges::shuffle(mIterators, mRNG); mCurrent = mIterators.begin(); }
286 std::vector<Iterator> mIterators;
287 typename std::vector<Iterator>::iterator mCurrent;
296 template <std::convertible_to<
double> T,
typename RANDOM>
307 template <
typename RANGE,
typename FUNC,
typename RANDOM>
310 static_assert(std::ranges::forward_range<RANGE>,
"range must be forward range");
311 static_assert(std::is_invocable_v<FUNC, std::ranges::range_reference_t<RANGE>>);
312 static_assert(std::convertible_to<std::invoke_result_t<FUNC, std::ranges::range_reference_t<RANGE>>,
double>);
317 for (
auto it = std::ranges::begin(
range);
it != std::ranges::end(
range); ++
it)
325 return std::ranges::end(
range);
constexpr auto bit_count
Equal to the number of bits in the type.
constexpr CONTAINER to(RANGE &&range, TYPES &&... args)
to<container>();
constexpr T halton_sequence(size_t index, size_t base=2)
TODO: Should we move the below to random_seq?
size_t option_with_probability(std::span< T const > option_probabilities, RANDOM &rng=::ghassanpl::random::default_random_engine)
When probability calculations are known ahead of time or expensive \complexity O(N) space,...
auto iterator_with_probability(RANGE &&range, FUNC &&prob_func, RANDOM &rng=::ghassanpl::random::default_random_engine)
For cheap probability functions.
auto make_bag_randomizer(T &container, RANDOM &rng=::ghassanpl::random::default_random_engine)
TODO: random_range()
thread_local std::default_random_engine default_random_engine
TODO: Tests check out https://github.com/effolkronium/random/.