1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
3 #ifndef DISTIRITBIONHPP
4 #define DISTIRITBIONHPP
10 #include <boost/random/mersenne_twister.hpp>
11 #include <boost/random/uniform_int.hpp>
12 #include <boost/random/uniform_real.hpp>
13 #include <boost/scoped_ptr.hpp>
14 #include <boost/tuple/tuple.hpp>
16 typedef boost::mt11213b rngen_t;
21 virtual T operator()() = 0;
22 virtual ~Distribution() {}
25 template <typename T, typename U, typename V, typename W>
26 class FourTupleDist : public Distribution<boost::tuple<T, U, V, W> > {
27 boost::scoped_ptr<Distribution<T> > t;
28 boost::scoped_ptr<Distribution<U> > u;
29 boost::scoped_ptr<Distribution<V> > v;
30 boost::scoped_ptr<Distribution<W> > w;
37 : t(t), u(u), v(v), w(w) {}
38 boost::tuple<T, U, V, W> operator()() override {
39 return boost::make_tuple((*t)(), (*u)(), (*v)(), (*w)());
44 class RandomDist : public Distribution<T> {
46 std::map<uint64_t, T> contents;
48 RandomDist(const rngen_t &rng, std::set<T> &initial) : rng(rng) {
50 for (typename std::set<T>::iterator i = initial.begin();
53 contents.insert(std::make_pair(count, *i));
56 T operator()() override {
57 assert(contents.size());
58 boost::uniform_int<> value(0, contents.size() - 1);
59 return contents.find(value(rng))->second;
64 class WeightedDist : public Distribution<T> {
67 std::map<double, T> contents;
69 WeightedDist(const rngen_t &rng, const std::set<std::pair<double, T> > &initial)
70 : rng(rng), total(0) {
71 for (typename std::set<std::pair<double, T> >::const_iterator i =
76 contents.insert(std::make_pair(total, i->second));
79 T operator()() override {
80 return contents.lower_bound(
81 boost::uniform_real<>(0, total)(rng))->second;
85 template <typename T, typename U>
86 class SequentialDist : public Distribution<T> {
88 std::vector<T> contents;
89 typename std::vector<T>::iterator cur;
91 SequentialDist(rngen_t rng, U &initial) : rng(rng) {
92 contents.insert(initial.begin(), initial.end());
93 cur = contents.begin();
95 virtual T operator()() {
96 assert(contents.size());
97 if (cur == contents.end())
98 cur = contents.begin();
103 class UniformRandom : public Distribution<uint64_t> {
108 UniformRandom(const rngen_t &rng, uint64_t min, uint64_t max) :
109 rng(rng), min(min), max(max) {}
110 uint64_t operator()() override {
111 return boost::uniform_int<uint64_t>(min, max)(rng);
115 class Align : public Distribution<uint64_t> {
116 boost::scoped_ptr<Distribution<uint64_t> > dist;
119 Align(Distribution<uint64_t> *dist, uint64_t align) :
120 dist(dist), align(align) {}
121 uint64_t operator()() override {
122 uint64_t ret = (*dist)();
123 return ret - (ret % align);
127 class Uniform : public Distribution<uint64_t> {
130 explicit Uniform(uint64_t val) : val(val) {}
131 uint64_t operator()() override {