Added random_real
[ail.git] / ail / random.hpp
blob92ad14ce93b8fe138996aeae0869a5bc27e854cb
1 #pragma once
3 #include <ail/exception.hpp>
4 #include <ail/types.hpp>
6 #include <boost/random.hpp>
7 #include <boost/random/uniform_real.hpp>
9 namespace ail
11 typedef boost::mt19937 random_algorithm_type;
13 void seed_check();
15 extern random_algorithm_type prng_algorithm;
16 extern bool prng_has_been_seeded;
18 template <typename integer_type>
19 integer_type random_integer(integer_type minimum, integer_type maximum)
21 seed_check();
23 typedef boost::uniform_int<integer_type> distribution_type;
25 distribution_type distribution(minimum, maximum);
26 boost::variate_generator<random_algorithm_type &, distribution_type> generator(prng_algorithm, distribution);
28 return generator();
31 template <class real_type>
32 real_type random_real(real_type minimum = 0, real_type maximum = 1)
34 seed_check();
36 typedef boost::uniform_real<real_type> distribution_type;
38 distribution_type distribution(minimum, maximum);
39 boost::variate_generator<random_algorithm_type &, distribution_type> generator(prng_algorithm, distribution);
40 return generator();
43 template <class element_type, std::size_t array_size>
44 element_type & random_pick(element_type (&array)[array_size])
46 std::size_t index = random_integer<std::size_t>(0, array_size - 1);
47 return array[index];
50 template <class type>
51 class random_scale
53 public:
54 random_scale():
55 total_weight(0)
59 void add(type object, ulong weight)
61 if(weight == 0)
62 throw exception("Element weight can't be zero");
63 elements.push_back(element(object, total_weight, total_weight + weight - 1));
64 total_weight += weight;
67 type random()
69 return make_choice()->object;
72 private:
74 struct element
76 type object;
78 ulong minimum;
79 ulong maximum;
81 element()
85 element(type object, ulong minimum, ulong maximum):
86 object(object),
87 minimum(minimum),
88 maximum(maximum)
92 bool operator==(ulong input) const
94 return input >= minimum && input <= maximum;
98 std::vector<element> elements;
99 ulong total_weight;
101 typename std::vector<element>::iterator make_choice()
103 if(total_weight == 0)
104 throw exception("Random scale object doesn't contain any elements yet");
105 ulong choice = random_integer<ulong>(0, total_weight - 1);
106 typename std::vector<element>::iterator iterator = std::find(elements.begin(), elements.end(), choice);
107 if(iterator == elements.end())
108 throw exception("Unable to match weight, code must be broken");
109 return iterator;