1#ifndef AARAND_AARAND_HPP
2#define AARAND_AARAND_HPP
33template<
typename Output_ =
double,
class Engine_>
35 typedef typename Engine_::result_type R;
36 static_assert(std::numeric_limits<R>::is_integer,
"RNG engine must yield integer results");
40 static_assert(!std::numeric_limits<R>::is_signed,
"RNG engine must yield unsigned integers");
45 constexpr Output_ ONE = 1;
46 constexpr Output_ factor = ONE / (
static_cast<Output_
>(Engine_::max() - Engine_::min()) + ONE);
52 result =
static_cast<Output_
>(eng() - Engine_::min()) * factor;
53 }
while (result == ONE);
66template<
typename Output_,
class Engine_>
67Output_ non_zero_uniform(Engine_& eng) {
88template<
typename Output_ =
double,
class Engine_>
90 constexpr Output_ PI = 3.14159265358979323846;
91 constexpr Output_ TWO = 2;
94 const Output_ constant = std::sqrt(-TWO * std::log(non_zero_uniform<Output_>(eng)));
96 return std::make_pair(constant * std::sin(angle), constant * std::cos(angle));
110template<
typename Output_ =
double,
class Engine_>
112 return -std::log(non_zero_uniform<Output_>(eng));
125template<
typename Output_ =
int,
class Engine_>
127 static_assert(std::numeric_limits<Output_>::is_integer);
129 throw std::runtime_error(
"'bound' should be a positive integer");
132 typedef typename Engine_::result_type R;
133 static_assert(std::numeric_limits<R>::is_integer);
134 static_assert(!std::numeric_limits<R>::is_signed);
136 constexpr R range = Engine_::max() - Engine_::min();
137 if (
static_cast<typename std::make_unsigned<Output_>::type
>(bound) > range) {
138 throw std::runtime_error(
"'bound' should be less than the RNG range");
141 R draw = eng() - Engine_::min();
147 if (draw > range - bound) {
157 const R limit = range - ((range % bound) + 1);
161 while (draw > limit) {
162 draw = eng() - Engine_::min();
180template<
class InputIterator_,
typename Length_,
class Engine_>
181void shuffle(
const InputIterator_ values,
const Length_ n, Engine_& eng) {
186 const Length_ last = n - 1;
187 for (Length_ i = 0; i < last; ++i) {
190 const auto current = values + i;
192 swap(*current, *(current + chosen));
212template<
class InputIterator_,
typename Length_,
class OutputIterator_,
class Engine_>
213void sample(InputIterator_ values,
const Length_ n,
const Length_ s, OutputIterator_ output, Engine_& eng) {
219 for (Length_ i = 0; i < n; ++i, ++values) {
220 const Length_ denom = n - i;
221 const double threshold =
static_cast<double>(remaining) / denom;
222 if (threshold >= 1) {
225 std::copy_n(values, denom, output);
254template<
typename Length_,
class OutputIterator_,
class Engine_>
255void sample(
const Length_ bound,
const Length_ s, OutputIterator_ output, Engine_& eng) {
261 for (Length_ i = 0; i < bound; ++i) {
262 const Length_ denom = bound - i;
263 const double threshold =
static_cast<double>(remaining) / denom;
264 if (threshold >= 1) {
267 std::iota(output, output + denom, i);
Aaron's random distribution functions.
void sample(InputIterator_ values, const Length_ n, const Length_ s, OutputIterator_ output, Engine_ &eng)
Definition aarand.hpp:213
void shuffle(const InputIterator_ values, const Length_ n, Engine_ &eng)
Definition aarand.hpp:181
std::pair< Output_, Output_ > standard_normal(Engine_ &eng)
Definition aarand.hpp:89
Output_ standard_exponential(Engine_ &eng)
Definition aarand.hpp:111
Output_ discrete_uniform(Engine_ &eng, const Output_ bound)
Definition aarand.hpp:126
Output_ standard_uniform(Engine_ &eng)
Definition aarand.hpp:34