Skip to content
This repository was archived by the owner on Dec 21, 2023. It is now read-only.

Commit 374cc26

Browse files
author
Hoyt Koepke
committed
Updated random number library to use c++11 random library instead of boost.
1 parent a918b2d commit 374cc26

File tree

4 files changed

+85
-194
lines changed

4 files changed

+85
-194
lines changed

src/core/random/random.cpp

Lines changed: 25 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
#include <fstream>
99
#include <chrono>
1010

11-
#include <boost/random.hpp>
12-
#include <boost/integer_traits.hpp>
1311

1412
#include <core/parallel/pthread_tools.hpp>
1513
#include <core/parallel/atomic.hpp>
@@ -29,31 +27,6 @@
2927
namespace turi {
3028
namespace random {
3129

32-
/** Get as close to a true source of randomness as possible.
33-
*
34-
* nanoseconds clock from program start. This should be pretty good.
35-
*
36-
* In case subsequent calls on a platform that does not support nanosecond resolution
37-
* happen, also increment a base count to make sure that subsequent seeds
38-
* are never the same.
39-
*
40-
* hash all these together to get a final seed hash.
41-
*/
42-
uint64_t pure_random_seed() {
43-
static auto base_start_time = std::chrono::high_resolution_clock::now();
44-
static uint64_t base_seed = hash64(time(NULL));
45-
static atomic<uint64_t> base_count = 0;
46-
47-
48-
++base_count;
49-
50-
auto now = std::chrono::high_resolution_clock::now();
51-
52-
uint64_t cur_seed = std::chrono::duration_cast<std::chrono::nanoseconds>(now-base_start_time).count();
53-
54-
return hash64(base_seed, hash64(cur_seed, base_count));
55-
}
56-
5730
/**
5831
* A truely nondeterministic generator
5932
*/
@@ -64,81 +37,33 @@ namespace turi {
6437
return global_gen;
6538
}
6639

67-
typedef size_t result_type;
68-
BOOST_STATIC_CONSTANT(result_type, min_value =
69-
boost::integer_traits<result_type>::const_min);
70-
BOOST_STATIC_CONSTANT(result_type, max_value =
71-
boost::integer_traits<result_type>::const_max);
72-
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return min_value; }
73-
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return max_value; }
74-
75-
nondet_generator() {
76-
#ifndef _WIN32
77-
rnd_dev.open("/dev/urandom", std::ios::binary | std::ios::in);
78-
ASSERT_TRUE(rnd_dev.good());
79-
#else
80-
auto rnd_dev_ret = CryptAcquireContext(&rnd_dev,
81-
NULL,
82-
NULL,
83-
PROV_RSA_FULL,
84-
0);
85-
if(!rnd_dev_ret) {
86-
auto err_code = GetLastError();
87-
if(err_code == NTE_BAD_KEYSET) {
88-
if(!CryptAcquireContext(&rnd_dev,
89-
NULL,
90-
NULL,
91-
PROV_RSA_FULL,
92-
CRYPT_NEWKEYSET)) {
93-
} else {
94-
err_code = GetLastError();
95-
log_and_throw(get_last_err_str(err_code));
96-
}
97-
} else {
98-
log_and_throw(get_last_err_str(err_code));
99-
}
100-
}
101-
#endif
102-
}
103-
// Close the random number generator
104-
#ifndef _WIN32
105-
~nondet_generator() { rnd_dev.close(); }
106-
#else
107-
~nondet_generator() { CryptReleaseContext(rnd_dev, 0); }
108-
#endif
40+
nondet_generator()
41+
: _random_devices(thread::cpu_count())
42+
{}
43+
44+
typedef unsigned int result_type;
45+
46+
static constexpr result_type min() { return std::numeric_limits<unsigned int>::min(); }
47+
static constexpr result_type max() { return std::numeric_limits<unsigned int>::max(); }
48+
10949
// read a size_t from the source
110-
result_type operator()() {
111-
// read a machine word into result
112-
result_type result(0);
113-
#ifndef _WIN32
114-
mut.lock();
115-
ASSERT_TRUE(rnd_dev.good());
116-
rnd_dev.read(reinterpret_cast<char*>(&result), sizeof(result_type));
117-
ASSERT_TRUE(rnd_dev.good());
118-
mut.unlock();
119-
// std::cerr << result << std::endl;
120-
return result;
121-
#else
122-
mut.lock();
123-
ASSERT_TRUE(CryptGenRandom(rnd_dev,8,(BYTE *)&result));
124-
mut.unlock();
125-
return result;
126-
#endif
50+
inline result_type operator()() {
51+
int thread_id = thread::thread_id();
52+
53+
return _random_devices.at(thread_id)();
12754
}
128-
private:
129-
#ifndef _WIN32
130-
std::ifstream rnd_dev;
131-
#else
132-
HCRYPTPROV rnd_dev;
133-
#endif
134-
mutex mut;
55+
56+
std::vector<std::random_device> _random_devices;
13557
};
13658
//nondet_generator global_nondet_rng;
13759

138-
139-
140-
141-
60+
/** Use the C++11 standard generato to get as close to a true source of randomness as possible.
61+
*
62+
* Returns a 64 bit truely random seed.
63+
*/
64+
uint64_t pure_random_seed() {
65+
return hash64_combine(hash64(nondet_generator::global()()), hash64(nondet_generator::global()()));
66+
}
14267

14368
/**
14469
* This class represents a master registery of all active random
@@ -301,12 +226,10 @@ namespace turi {
301226
// Get the global nondeterministic random number generator.
302227
nondet_generator& nondet_rnd(nondet_generator::global());
303228
mut.lock();
229+
304230
// std::cerr << "initializing real rng" << std::endl;
305-
real_rng.seed(static_cast<uint32_t>(nondet_rnd()));
306-
// std::cerr << "initializing discrete rng" << std::endl;
307-
discrete_rng.seed(static_cast<uint32_t>(nondet_rnd()));
308-
// std::cerr << "initializing fast discrete rng" << std::endl;
309-
fast_discrete_rng.seed(static_cast<uint32_t>(nondet_rnd()));
231+
m_rng.seed(static_cast<uint32_t>(nondet_rnd()));
232+
310233
mut.unlock();
311234
}
312235

0 commit comments

Comments
 (0)