// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- #ifndef DISTIRITBIONHPP #define DISTIRITBIONHPP #include #include #include #include #include #include #include #include #include typedef boost::mt11213b rngen_t; template class Distribution { public: virtual T operator()() = 0; virtual ~Distribution() {} }; template class FourTupleDist : public Distribution > { boost::scoped_ptr > t; boost::scoped_ptr > u; boost::scoped_ptr > v; boost::scoped_ptr > w; public: FourTupleDist( Distribution *t, Distribution *u, Distribution *v, Distribution *w) : t(t), u(u), v(v), w(w) {} boost::tuple operator()() override { return boost::make_tuple((*t)(), (*u)(), (*v)(), (*w)()); } }; template class RandomDist : public Distribution { rngen_t rng; std::map contents; public: RandomDist(const rngen_t &rng, std::set &initial) : rng(rng) { uint64_t count = 0; for (typename std::set::iterator i = initial.begin(); i != initial.end(); ++i, ++count) { contents.insert(std::make_pair(count, *i)); } } T operator()() override { assert(contents.size()); boost::uniform_int<> value(0, contents.size() - 1); return contents.find(value(rng))->second; } }; template class WeightedDist : public Distribution { rngen_t rng; double total; std::map contents; public: WeightedDist(const rngen_t &rng, const std::set > &initial) : rng(rng), total(0) { for (typename std::set >::const_iterator i = initial.begin(); i != initial.end(); ++i) { total += i->first; contents.insert(std::make_pair(total, i->second)); } } T operator()() override { return contents.lower_bound( boost::uniform_real<>(0, total)(rng))->second; } }; template class SequentialDist : public Distribution { rngen_t rng; std::vector contents; typename std::vector::iterator cur; public: SequentialDist(rngen_t rng, U &initial) : rng(rng) { contents.insert(initial.begin(), initial.end()); cur = contents.begin(); } virtual T operator()() { assert(contents.size()); if (cur == contents.end()) cur = contents.begin(); return *(cur++); } }; class UniformRandom : public Distribution { rngen_t rng; uint64_t min; uint64_t max; public: UniformRandom(const rngen_t &rng, uint64_t min, uint64_t max) : rng(rng), min(min), max(max) {} uint64_t operator()() override { return boost::uniform_int(min, max)(rng); } }; class Align : public Distribution { boost::scoped_ptr > dist; uint64_t align; public: Align(Distribution *dist, uint64_t align) : dist(dist), align(align) {} uint64_t operator()() override { uint64_t ret = (*dist)(); return ret - (ret % align); } }; class Uniform : public Distribution { uint64_t val; public: explicit Uniform(uint64_t val) : val(val) {} uint64_t operator()() override { return val; } }; #endif