neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
random.hpp
Go to the documentation of this file.
1// random.hpp - v2.1
2/*
3 * Copyright (c) 2007 Leigh Johnston.
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * * Neither the name of Leigh Johnston nor the names of any
19 * other contributors to this software may be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37
38#include <neolib/neolib.hpp>
39#include <random>
40#include <thread>
41
42namespace neolib
43{
44 template <typename T = uint32_t, typename Gen = std::mt19937>
46 {
47 public:
48 typedef T value_type;
49 typedef Gen generator_type;
50 typedef typename generator_type::result_type generator_result_type;
51 static const std::size_t state_size = generator_type::state_size;
52 private:
53 template <bool IsInteger>
54 struct distribution_selector;
55 template <>
56 struct distribution_selector<true>
57 {
59 typedef std::uniform_int_distribution<interval_value_type> distribution_type;
60 static std::pair<interval_value_type, interval_value_type> interval(interval_value_type aLower, interval_value_type aUpper)
61 {
62 return std::make_pair(aLower, aUpper);
63 }
64 };
65 template <>
66 struct distribution_selector<false>
67 {
69 typedef std::uniform_real_distribution<interval_value_type> distribution_type;
70 static std::pair<interval_value_type, interval_value_type> interval(interval_value_type aLower, interval_value_type aUpper)
71 {
72 return std::make_pair(aLower, std::nextafter(aUpper, std::numeric_limits<interval_value_type>::max()));
73 }
74 };
75 typedef typename distribution_selector<std::is_integral<value_type>::value> distribution_selector_type;
76 public:
77 typedef typename distribution_selector_type::distribution_type distribution_type;
78 typedef typename distribution_selector_type::interval_value_type interval_value_type;
79 public:
80 static std::pair<interval_value_type, interval_value_type> interval(value_type aLower, value_type aUpper)
81 {
82 return distribution_selector_type::interval(static_cast<interval_value_type>(aLower), static_cast<interval_value_type>(aUpper));
83 }
84 };
85
86 template <typename T = uint32_t, typename Gen = std::mt19937, typename Traits = random_traits<T, Gen>>
88 {
89 // types
90 public:
91 typedef Traits traits_type;
92 typedef typename traits_type::value_type value_type;
93 typedef typename traits_type::distribution_type distribution_type;
94 private:
95 typedef typename traits_type::generator_type generator_type;
96 typedef typename traits_type::generator_result_type generator_result_type;
97
98 // construction
99 public:
100 basic_random() : iGen{ std::random_device{}() }, iSecure{ true }, iCounter{ 0 }
101 {
102 }
103 template <typename T2>
104 basic_random(T2 aSeed) : iGen{ static_cast<generator_result_type>(aSeed) }, iSecure{ false }, iCounter{ 0 }
105 {
106 }
107 basic_random(std::thread::id aSeed) : iGen{ static_cast<generator_result_type>(std::hash<std::thread::id>{}(aSeed)) }, iSecure{ false }, iCounter{ 0 }
108 {
109 }
110 // operations
111 public:
112 template <typename T2>
113 void seed(T2 aSeed)
114 {
115 iSecure = false;
116 iCounter = 0;
117 iGen.seed(static_cast<generator_result_type>(aSeed));
118 }
119 bool is_secure() const
120 {
121 return iSecure;
122 }
123 void set_secure(bool aSecure)
124 {
125 iSecure = aSecure;
126 }
127 template <typename T2>
129 {
130 return get(aUpper);
131 }
132 template <typename T2>
133 value_type operator()(T2 aLower, T2 aUpper)
134 {
135 return get(aLower, aUpper);
136 }
137 template <typename T2>
138 value_type get(T2 aUpper)
139 {
140 increment_counter();
141 return static_cast<value_type>(distribution(static_cast<value_type>(0), static_cast<value_type>(aUpper))(iGen));
142 }
143 template <typename T2>
144 value_type get(T2 aLower, T2 aUpper)
145 {
146 increment_counter();
147 return static_cast<value_type>(distribution(static_cast<value_type>(aLower), static_cast<value_type>(aUpper))(iGen));
148 }
149 // implementation
150 private:
151 distribution_type distribution(value_type aLower, value_type aUpper)
152 {
153 auto interval = traits_type::interval(aLower, aUpper);
154 return distribution_type{ interval.first, interval.second };
155 }
156 void increment_counter()
157 {
158 if (iSecure && ++iCounter > traits_type::state_size)
159 {
160 iCounter = 0;
161 iGen.seed(std::random_device{}());
162 }
163 }
164 // attributes
165 private:
166 generator_type iGen;
167 bool iSecure;
168 std::size_t iCounter;
169 };
170
172
173 template <typename T>
174 struct primes
175 {
176 static const T sPrimes[];
177 };
178
179 template <typename T>
180 const T primes<T>::sPrimes[] =
181 {
182 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
183 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79,
184 83, 89, 97, 103, 109, 113, 127, 137, 139, 149,
185 157, 167, 179, 193, 199, 211, 227, 241, 257,
186 277, 293, 313, 337, 359, 383, 409, 439, 467,
187 503, 541, 577, 619, 661, 709, 761, 823, 887,
188 953, 1031, 1109, 1193, 1289, 1381, 1493, 1613,
189 1741, 1879, 2029, 2179, 2357, 2549, 2753, 2971,
190 3209, 3469, 3739, 4027, 4349, 4703, 5087, 5503,
191 5953, 6427, 6949, 7517, 8123, 8783, 9497, 10273,
192 11113, 12011, 12983, 14033, 15173, 16411, 17749,
193 19183, 20753, 22447, 24281, 26267, 28411, 30727,
194 33223, 35933, 38873, 42043, 45481, 49201, 53201,
195 57557, 62233, 67307, 72817, 78779, 85229, 92203,
196 99733, 107897, 116731, 126271, 136607, 147793,
197 159871, 172933, 187091, 202409, 218971, 236897,
198 256279, 277261, 299951, 324503, 351061, 379787,
199 410857, 444487, 480881, 520241, 562841, 608903,
200 658753, 712697, 771049, 834181, 902483, 976369,
201 1056323, 1142821, 1236397, 1337629, 1447153, 1565659,
202 1693859, 1832561, 1982627, 2144977, 2320627, 2510653,
203 2716249, 2938679, 3179303, 3439651, 3721303, 4026031,
204 4355707, 4712381, 5098259, 5515729, 5967347, 6456007,
205 6984629, 7556579, 8175383, 8844859, 9569143, 10352717,
206 11200489, 12117689, 13109983, 14183539, 15345007,
207 16601593, 17961079, 19431899, 21023161, 22744717,
208 24607243, 26622317, 28802401, 31160981, 33712729,
209 36473443, 39460231, 42691603, 46187573, 49969847,
210 54061849, 58488943, 63278561, 68460391, 74066549,
211 80131819, 86693767, 93793069, 101473717, 109783337,
212 118773397, 128499677, 139022417, 150406843, 162723577,
213 176048909, 190465427, 206062531, 222936881, 241193053,
214 260944219, 282312799, 305431229, 330442829, 357502601,
215 386778277, 418451333, 452718089, 489790921, 529899637,
216 573292817, 620239453, 671030513, 725980837, 785430967,
217 849749479, 919334987, 994618837, 1076067617, 1164186217,
218 1259520799, 1362662261, 1474249943, 1594975441,
219 1725587117, 1866894511, 2019773507
220 };
221
223 {
224 // types
225 public:
226 typedef unsigned int value_type;
227 // construction
228 public:
229 random_traversal(random& aRandom, value_type aNumElements) : iRandom{ aRandom }, iNumElements{ aNumElements }
230 {
231 reset();
232 }
233 // operations
234 public:
235 bool done() const { return iSearches == iPrime || iNumElements == 0; }
236 unsigned int percent() const { return iSearches * 100 / iPrime; }
237 int next()
238 {
239 if (done())
240 return -1;
241
242 bool found = false;
243 value_type nextPosition = iCurrentPosition;
244 while (!found)
245 {
246 nextPosition = nextPosition + iSkip;
247 nextPosition %= iPrime;
248 iSearches++;
249 if (nextPosition < iNumElements)
250 {
251 iCurrentPosition = nextPosition;
252 found = true;
253 }
254 }
255 return iCurrentPosition;
256 }
257 int operator()() { return next(); }
258 void reset()
259 {
260 const value_type* nextPrime = primes<value_type>::sPrimes;
261 while(*nextPrime < iNumElements)
262 nextPrime++;
263 iPrime = *nextPrime;
264 value_type a = iRandom.get(1, 13);
265 value_type b = iRandom.get(1, 7);
266 value_type c = iRandom.get(1, 5);
267 iSkip = (a * iNumElements * iNumElements) + (b * iNumElements) + c;
268 iSkip &= ~0xC0000000;
269 if (iSkip % iPrime == 0)
270 iSkip++;
271 iCurrentPosition = iRandom.get(iNumElements-1);
272 iSearches = 0;
273 }
275 {
276 iNumElements = aOther.iNumElements;
277 iPrime = aOther.iPrime;
278 iSkip = aOther.iSkip;
279 iCurrentPosition = aOther.iCurrentPosition;
280 iSearches = aOther.iSearches;
281 return *this;
282 }
283 // attributes
284 private:
285 neolib::random& iRandom;
286 value_type iNumElements;
287 value_type iPrime;
288 value_type iSkip;
289 value_type iCurrentPosition;
290 value_type iSearches;
291 };
292}
bool is_secure() const
Definition random.hpp:119
traits_type::distribution_type distribution_type
Definition random.hpp:93
value_type operator()(T2 aLower, T2 aUpper)
Definition random.hpp:133
value_type operator()(T2 aUpper)
Definition random.hpp:128
value_type get(T2 aLower, T2 aUpper)
Definition random.hpp:144
void set_secure(bool aSecure)
Definition random.hpp:123
void seed(T2 aSeed)
Definition random.hpp:113
basic_random(std::thread::id aSeed)
Definition random.hpp:107
value_type get(T2 aUpper)
Definition random.hpp:138
basic_random(T2 aSeed)
Definition random.hpp:104
traits_type::value_type value_type
Definition random.hpp:92
static std::pair< interval_value_type, interval_value_type > interval(value_type aLower, value_type aUpper)
Definition random.hpp:80
generator_type::result_type generator_result_type
Definition random.hpp:50
distribution_selector_type::interval_value_type interval_value_type
Definition random.hpp:78
static const std::size_t state_size
Definition random.hpp:51
distribution_selector_type::distribution_type distribution_type
Definition random.hpp:77
unsigned int value_type
Definition random.hpp:226
unsigned int percent() const
Definition random.hpp:236
random_traversal & operator=(const random_traversal &aOther)
Definition random.hpp:274
random_traversal(random &aRandom, value_type aNumElements)
Definition random.hpp:229
basic_random< uint32_t > random
Definition random.hpp:171
Definition plf_hive.h:79