Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/uuid/seed_rng.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 // Boost seed_rng.hpp header file ----------------------------------------------// | |
2 | |
3 // Copyright 2007 Andy Tompkins. | |
4 // Distributed under the Boost Software License, Version 1.0. (See | |
5 // accompanying file LICENSE_1_0.txt or copy at | |
6 // http://www.boost.org/LICENSE_1_0.txt) | |
7 | |
8 // Revision History | |
9 // 09 Nov 2007 - Initial Revision | |
10 // 25 Feb 2008 - moved to namespace boost::uuids::detail | |
11 // 28 Nov 2009 - disabled deprecated warnings for MSVC | |
12 | |
13 // seed_rng models a UniformRandomNumberGenerator (see Boost.Random). | |
14 // Random number generators are hard to seed well. This is intended to provide | |
15 // good seed values for random number generators. | |
16 // It creates random numbers from a sha1 hash of data from a variary of sources, | |
17 // all of which are standard function calls. It produces random numbers slowly. | |
18 // Peter Dimov provided the details of sha1_random_digest_(). | |
19 // see http://archives.free.net.ph/message/20070507.175609.4c4f503a.en.html | |
20 | |
21 #ifndef BOOST_UUID_SEED_RNG_HPP | |
22 #define BOOST_UUID_SEED_RNG_HPP | |
23 | |
24 #include <boost/config.hpp> | |
25 #include <cstring> // for memcpy | |
26 #include <limits> | |
27 #include <ctime> // for time_t, time, clock_t, clock | |
28 #include <cstdlib> // for rand | |
29 #include <cstdio> // for FILE, fopen, fread, fclose | |
30 #include <boost/uuid/sha1.hpp> | |
31 //#include <boost/nondet_random.hpp> //forward declare boost::random::random_device | |
32 | |
33 // can't use boost::generator_iterator since boost::random number seed(Iter&, Iter) | |
34 // functions need a last iterator | |
35 //#include <boost/generator_iterator.hpp> | |
36 # include <boost/iterator/iterator_facade.hpp> | |
37 | |
38 #if defined(_MSC_VER) | |
39 #pragma warning(push) // Save warning settings. | |
40 #pragma warning(disable : 4996) // Disable deprecated std::fopen | |
41 #endif | |
42 | |
43 #ifdef BOOST_NO_STDC_NAMESPACE | |
44 namespace std { | |
45 using ::memcpy; | |
46 using ::time_t; | |
47 using ::time; | |
48 using ::clock_t; | |
49 using ::clock; | |
50 using ::rand; | |
51 using ::FILE; | |
52 using ::fopen; | |
53 using ::fread; | |
54 using ::fclose; | |
55 } //namespace std | |
56 #endif | |
57 | |
58 // forward declare random number generators | |
59 namespace boost { namespace random { | |
60 class random_device; | |
61 }} //namespace boost::random | |
62 | |
63 namespace boost { | |
64 namespace uuids { | |
65 namespace detail { | |
66 | |
67 // should this be part of Boost.Random? | |
68 class seed_rng | |
69 { | |
70 public: | |
71 typedef unsigned int result_type; | |
72 BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); | |
73 //BOOST_STATIC_CONSTANT(unsigned int, min_value = 0); | |
74 //BOOST_STATIC_CONSTANT(unsigned int, max_value = UINT_MAX); | |
75 | |
76 public: | |
77 // note: rd_ intentionally left uninitialized | |
78 seed_rng() | |
79 : rd_index_(5) | |
80 , random_(std::fopen( "/dev/urandom", "rb" )) | |
81 {} | |
82 | |
83 ~seed_rng() | |
84 { | |
85 if (random_) { | |
86 std::fclose(random_); | |
87 } | |
88 } | |
89 | |
90 result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const | |
91 { | |
92 return (std::numeric_limits<result_type>::min)(); | |
93 } | |
94 result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const | |
95 { | |
96 return (std::numeric_limits<result_type>::max)(); | |
97 } | |
98 | |
99 result_type operator()() | |
100 { | |
101 if (rd_index_ >= 5) { | |
102 //get new digest | |
103 sha1_random_digest_(); | |
104 | |
105 rd_index_ = 0; | |
106 } | |
107 | |
108 return rd_[rd_index_++]; | |
109 } | |
110 | |
111 private: | |
112 inline void ignore_size(size_t) {} | |
113 | |
114 static unsigned int * sha1_random_digest_state_() | |
115 { | |
116 static unsigned int state[ 5 ]; | |
117 return state; | |
118 } | |
119 | |
120 void sha1_random_digest_() | |
121 { | |
122 boost::uuids::detail::sha1 sha; | |
123 | |
124 unsigned int * ps = sha1_random_digest_state_(); | |
125 | |
126 unsigned int state[ 5 ]; | |
127 std::memcpy( state, ps, sizeof( state ) ); // harmless data race | |
128 | |
129 sha.process_bytes( (unsigned char const*)state, sizeof( state ) ); | |
130 sha.process_bytes( (unsigned char const*)&ps, sizeof( ps ) ); | |
131 | |
132 { | |
133 std::time_t tm = std::time( 0 ); | |
134 sha.process_bytes( (unsigned char const*)&tm, sizeof( tm ) ); | |
135 } | |
136 | |
137 { | |
138 std::clock_t ck = std::clock(); | |
139 sha.process_bytes( (unsigned char const*)&ck, sizeof( ck ) ); | |
140 } | |
141 | |
142 { | |
143 unsigned int rn[] = | |
144 { static_cast<unsigned int>(std::rand()) | |
145 , static_cast<unsigned int>(std::rand()) | |
146 , static_cast<unsigned int>(std::rand()) | |
147 }; | |
148 sha.process_bytes( (unsigned char const*)rn, sizeof( rn ) ); | |
149 } | |
150 | |
151 { | |
152 // intentionally left uninitialized | |
153 unsigned char buffer[ 20 ]; | |
154 | |
155 if(random_) | |
156 { | |
157 ignore_size(std::fread( buffer, 1, 20, random_ )); | |
158 } | |
159 | |
160 // using an uninitialized buffer[] if fopen fails | |
161 // intentional, we rely on its contents being random | |
162 sha.process_bytes( buffer, sizeof( buffer ) ); | |
163 } | |
164 | |
165 { | |
166 // *p is intentionally left uninitialized | |
167 unsigned int * p = new unsigned int; | |
168 | |
169 sha.process_bytes( (unsigned char const*)p, sizeof( *p ) ); | |
170 sha.process_bytes( (unsigned char const*)&p, sizeof( p ) ); | |
171 | |
172 delete p; | |
173 } | |
174 | |
175 sha.process_bytes( (unsigned char const*)rd_, sizeof( rd_ ) ); | |
176 | |
177 unsigned int digest[ 5 ]; | |
178 sha.get_digest( digest ); | |
179 | |
180 for( int i = 0; i < 5; ++i ) | |
181 { | |
182 // harmless data race | |
183 ps[ i ] ^= digest[ i ]; | |
184 rd_[ i ] ^= digest[ i ]; | |
185 } | |
186 } | |
187 | |
188 private: | |
189 unsigned int rd_[5]; | |
190 int rd_index_; | |
191 std::FILE * random_; | |
192 | |
193 private: // make seed_rng noncopyable | |
194 seed_rng(seed_rng const&); | |
195 seed_rng& operator=(seed_rng const&); | |
196 }; | |
197 | |
198 // almost a copy of boost::generator_iterator | |
199 // but default constructor sets m_g to NULL | |
200 template <class Generator> | |
201 class generator_iterator | |
202 : public iterator_facade< | |
203 generator_iterator<Generator> | |
204 , typename Generator::result_type | |
205 , single_pass_traversal_tag | |
206 , typename Generator::result_type const& | |
207 > | |
208 { | |
209 typedef iterator_facade< | |
210 generator_iterator<Generator> | |
211 , typename Generator::result_type | |
212 , single_pass_traversal_tag | |
213 , typename Generator::result_type const& | |
214 > super_t; | |
215 | |
216 public: | |
217 generator_iterator() : m_g(NULL), m_value(0) {} | |
218 generator_iterator(Generator* g) : m_g(g), m_value((*m_g)()) {} | |
219 | |
220 void increment() | |
221 { | |
222 m_value = (*m_g)(); | |
223 } | |
224 | |
225 const typename Generator::result_type& | |
226 dereference() const | |
227 { | |
228 return m_value; | |
229 } | |
230 | |
231 bool equal(generator_iterator const& y) const | |
232 { | |
233 return this->m_g == y.m_g && this->m_value == y.m_value; | |
234 } | |
235 | |
236 private: | |
237 Generator* m_g; | |
238 typename Generator::result_type m_value; | |
239 }; | |
240 | |
241 // seed() seeds a random number generator with good seed values | |
242 | |
243 template <typename UniformRandomNumberGenerator> | |
244 inline void seed(UniformRandomNumberGenerator& rng) | |
245 { | |
246 seed_rng seed_gen; | |
247 generator_iterator<seed_rng> begin(&seed_gen); | |
248 generator_iterator<seed_rng> end; | |
249 rng.seed(begin, end); | |
250 } | |
251 | |
252 // random_device does not / can not be seeded | |
253 template <> | |
254 inline void seed<boost::random::random_device>(boost::random::random_device&) {} | |
255 | |
256 // random_device does not / can not be seeded | |
257 template <> | |
258 inline void seed<seed_rng>(seed_rng&) {} | |
259 | |
260 }}} //namespace boost::uuids::detail | |
261 | |
262 #if defined(_MSC_VER) | |
263 #pragma warning(pop) // Restore warnings to previous state. | |
264 #endif | |
265 | |
266 #endif |