#include "random/random.h" #include #include #include #include #include "random/device.h" #include "random/distribution.h" #include "random/tape.h" #define IMPLEMENT_RANDOM(T) \ template T Random::operator()(Distribution const &) const; namespace engine::random { class DefaultDevice : public Device { public: result_type operator()() final { return rng(); } private: std::mt19937 rng{std::random_device{}()}; }; Random::Random() : impl_(std::make_shared()) {} Random::Random(Random const & other, std::shared_ptr with_tape) : impl_(other.impl_), tape_(with_tape) {} Random::Random(Random const & other, Tape & with_tape) : impl_(other.impl_), tape_(&with_tape, [](void *) {}) {} template Rand Random::operator()(Distribution const & dist) const { return tape_ ? tape_->apply(dist, impl_->apply(dist)) : impl_->apply(dist); } scope_exit Random::record(std::shared_ptr tape) { assert(tape && !tape_); tape_ = tape; return [this]() { tape_.reset(); }; } IMPLEMENT_DEVICE(IMPLEMENT_RANDOM) }