30 #include <boost/random.hpp>
31 #include <boost/integer_traits.hpp>
33 #include <graphlab/parallel/pthread_tools.hpp>
34 #include <graphlab/logger/assertions.hpp>
35 #include <graphlab/util/timer.hpp>
37 #include <graphlab/util/random.hpp>
42 #include <graphlab/macros_def.hpp>
49 class nondet_generator {
51 static nondet_generator& global() {
52 static nondet_generator global_gen;
56 typedef size_t result_type;
57 BOOST_STATIC_CONSTANT(result_type, min_value =
58 boost::integer_traits<result_type>::const_min);
59 BOOST_STATIC_CONSTANT(result_type, max_value =
60 boost::integer_traits<result_type>::const_max);
61 result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
const {
return min_value; }
62 result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
const {
return max_value; }
65 rnd_dev.open(
"/dev/urandom", std::ios::binary | std::ios::in);
66 ASSERT_TRUE(rnd_dev.good());
69 ~nondet_generator() { rnd_dev.close(); }
71 result_type operator()() {
73 result_type result(0);
75 ASSERT_TRUE(rnd_dev.good());
76 rnd_dev.read(reinterpret_cast<char*>(&result),
sizeof(result_type));
77 ASSERT_TRUE(rnd_dev.good());
83 std::ifstream rnd_dev;
97 struct source_registry {
98 std::set<generator*> generators;
102 static source_registry& global() {
103 static source_registry registry;
113 ASSERT_TRUE(generator != NULL);
114 generator->
seed(master);
124 master.nondet_seed();
126 ASSERT_TRUE(generator != NULL);
127 generator->
seed(master);
140 ASSERT_TRUE(generator != NULL);
141 generator->
seed(master);
150 void seed(
const size_t number) {
154 ASSERT_TRUE(generator != NULL);
155 generator->
seed(master);
164 void register_generator(
generator* tls_ptr) {
165 ASSERT_TRUE(tls_ptr != NULL);
167 generators.insert(tls_ptr);
168 tls_ptr->
seed(master);
177 void unregister_source(
generator* tls_ptr) {
179 generators.erase(tls_ptr);
202 if(tls_rnd_ptr != NULL) {
203 source_registry::global().unregister_source(tls_rnd_ptr);
213 struct tls_key_creator {
214 pthread_key_t TLS_RANDOM_SOURCE_KEY;
215 tls_key_creator() : TLS_RANDOM_SOURCE_KEY(0) {
216 pthread_key_create(&TLS_RANDOM_SOURCE_KEY,
222 static pthread_key_t get_random_source_key() {
223 static const tls_key_creator key;
224 return key.TLS_RANDOM_SOURCE_KEY;
227 static pthread_key_t __unused_init_keys__(get_random_source_key());
246 (pthread_getspecific(get_random_source_key()));
248 if(tls_rnd_ptr == NULL) {
250 assert(tls_rnd_ptr != NULL);
252 source_registry::global().register_generator(tls_rnd_ptr);
253 pthread_setspecific(get_random_source_key(),
262 void seed() { source_registry::global().seed(); }
266 void time_seed() { source_registry::global().time_seed(); }
268 void seed(
const size_t seed_value) {
269 source_registry::global().seed(seed_value);
275 nondet_generator& nondet_rnd(nondet_generator::global());
278 real_rng.seed(nondet_rnd());
280 discrete_rng.seed(nondet_rnd());
282 fast_discrete_rng.seed(nondet_rnd());
289 for(
size_t i = 0; i < pdf.size(); ++i) Z += pdf[i];
290 for(
size_t i = 0; i < pdf.size(); ++i)
291 pdf[i] = pdf[i]/Z + ((i>0)? pdf[i-1] : 0);