randomgen: distribution + related concepts

This commit is contained in:
Roland Conybeare 2023-10-17 14:54:27 -04:00
commit a4c264d8db
3 changed files with 98 additions and 0 deletions

View file

@ -0,0 +1,35 @@
/* @file distribution_concept.hpp */
#pragma once
#include <concepts>
namespace xo {
namespace rng {
template <class Distribution, class Engine>
concept distribution_concept = requires(Distribution dist, typename Distribution::param_type p) {
typename Distribution::result_type;
typename Distribution::param_type;
{ Distribution() };
{ Distribution(p) };
{ dist.reset() };
{ dist.param() };
{ dist.param(p) };
// { dist(g) }; // generator g satisfying engine_concept
// { dist(g, p) };
{ dist.min() };
{ dist.max() };
{ dist == dist };
{ dist != dist };
// os << dist
// is >> dist
} && std::copyable<Distribution>
&& std::copyable<typename Distribution::param_type>
&& std::equality_comparable<typename Distribution::param_type>;
} /*namespace rng*/
} /*namespace xo*/
/* end distribution_concept.hpp */

View file

@ -0,0 +1,49 @@
/* @file generator.hpp */
#pragma once
#include "engine_concept.hpp"
#include "distribution_concept.hpp"
#include <utility>
namespace xo {
namespace rng {
/* Engine: uniform integer random number generator, e.g. xoshiro256ss
* Distribution: random number distribution, e.g. std::normal_distribution
*/
template <class Engine, class Distribution> requires engine_concept<Engine> && distribution_concept<Distribution, Engine>
class generator {
public:
using result_type = typename Distribution::result_type;
using engine_type = Engine;
public:
generator(Engine & e, Distribution const & d)
: engine_{e},
distribution_{d} {}
generator(Engine && e, Distribution && d)
: engine_{std::move(e)},
distribution_{std::move(d)} {}
static generator make(Engine e, Distribution d) {
return generator(e, d);
}
result_type operator()() { return this->distribution_(this->engine_); }
private:
/* random number generator; generates uniformly-distributed integers */
Engine engine_;
/* distribution object */
Distribution distribution_;
}; /*generator*/
template <class Engine, class Distribution>
generator<Engine, Distribution> make_generator(Engine e, Distribution d) {
return generator<Engine, Distribution>::make(std::move(e),
std::move(d));
} /*make_generator*/
} /*namespace rng*/
} /*namespace xo*/
/* end generator.hpp */

View file

@ -0,0 +1,14 @@
/* @file normalgen.hpp */
#pragma once
#include "generator.hpp"
#include <random>
namespace xo {
namespace rng {
/* Engine: e.g. xo::rng::xoshiro256 or std::mt19937 */
template <class Engine>
using normalgen = generator<Engine, std::normal_distribution<double>>;
} /*namespace rng*/
} /*namespace xo*/