Embedded Template Library 1.0
Loading...
Searching...
No Matches
random.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2017 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_RANDOM_INCLUDED
32#define ETL_RANDOM_INCLUDED
33
34#include "platform.h"
35#include "binary.h"
36
37#include <stdint.h>
38
39namespace etl
40{
41#if defined(ETL_POLYMORPHIC_RANDOM)
42 //***************************************************************************
44 //***************************************************************************
45 class random
46 {
47 public:
48
49 virtual ~random() {}
50
51 virtual void initialise(uint32_t seed) = 0;
52 virtual uint32_t operator()() = 0;
53 virtual uint32_t range(uint32_t low, uint32_t high) = 0;
54 };
55#else
56 //***************************************************************************
59 //***************************************************************************
60 class random
61 {
62 protected:
63
64 random() {}
65
66 ~random() {}
67 };
68#endif
69
70 //***************************************************************************
74 //***************************************************************************
75 class random_xorshift : public random
76 {
77 public:
78
79 //***************************************************************************
82 //***************************************************************************
84 {
85 // An attempt to come up with a unique non-zero seed,
86 // based on the address of the instance.
87 uintptr_t n = reinterpret_cast<uintptr_t>(this);
88 uint32_t seed = static_cast<uint32_t>(n);
89 initialise(seed);
90 }
91
92 //***************************************************************************
95 //***************************************************************************
96 random_xorshift(uint32_t seed)
97 {
98 initialise(seed);
99 }
100
101 //***************************************************************************
104 //***************************************************************************
105 void initialise(uint32_t seed)
106 {
107 // Add the first four primes to ensure that the seed isn't zero.
108 state[0] = seed + 3;
109 state[1] = seed + 5;
110 state[2] = seed + 7;
111 state[3] = seed + 11;
112 }
113
114 //***************************************************************************
116 //***************************************************************************
117 uint32_t operator()()
118 {
119 uint32_t n = state[3];
120 n ^= n << 11U;
121 n ^= n >> 8U;
122 state[3] = state[2];
123 state[2] = state[1];
124 state[1] = state[0];
125 n ^= state[0];
126 n ^= state[0] >> 19U;
127 state[0] = n;
128
129 return n;
130 }
131
132 //***************************************************************************
134 //***************************************************************************
135 uint32_t range(uint32_t low, uint32_t high)
136 {
137 uint32_t r = high - low + 1UL;
138 uint32_t n = operator()();
139 n %= r;
140 n += low;
141
142 return n;
143 }
144
145 private:
146
147 uint32_t state[4];
148 };
149
150 //***************************************************************************
154 //***************************************************************************
155 class random_lcg : public random
156 {
157 public:
158
159 //***************************************************************************
162 //***************************************************************************
164 {
165 // An attempt to come up with a unique non-zero seed,
166 // based on the address of the instance.
167 uintptr_t n = reinterpret_cast<uintptr_t>(this);
168 uint32_t seed = static_cast<uint32_t>(n);
169 initialise(seed);
170 }
171
172 //***************************************************************************
175 //***************************************************************************
176 random_lcg(uint32_t seed)
177 {
178 initialise(seed);
179 }
180
181 //***************************************************************************
184 //***************************************************************************
185 void initialise(uint32_t seed)
186 {
187 seed = (seed == 0) ? 1 : seed;
188 value = (seed > m) ? m : seed;
189 }
190
191 //***************************************************************************
193 //***************************************************************************
194 uint32_t operator()()
195 {
196 value = (a * value) % m;
197
198 return value;
199 }
200
201 //***************************************************************************
203 //***************************************************************************
204 uint32_t range(uint32_t low, uint32_t high)
205 {
206 uint32_t r = high - low + 1UL;
207 uint32_t n = operator()();
208 n %= r;
209 n += low;
210
211 return n;
212 }
213
214 private:
215
216 static ETL_CONSTANT uint32_t a = 40014U;
217 static ETL_CONSTANT uint32_t m = 2147483563UL;
218
219 uint32_t value;
220 };
221
222 //***************************************************************************
226 //***************************************************************************
227 class random_clcg : public random
228 {
229 public:
230
231 //***************************************************************************
234 //***************************************************************************
236 {
237 // An attempt to come up with a unique non-zero seed,
238 // based on the address of the instance.
239 uintptr_t n = reinterpret_cast<uintptr_t>(this);
240 uint32_t seed = static_cast<uint32_t>(n);
241 initialise(seed);
242 }
243
244 //***************************************************************************
247 //***************************************************************************
248 random_clcg(uint32_t seed)
249 {
250 initialise(seed);
251 }
252
253 //***************************************************************************
256 //***************************************************************************
257 void initialise(uint32_t seed)
258 {
259 seed = (seed == 0) ? 1 : seed;
260 value1 = (seed > m1) ? m1 : seed;
261 value2 = (seed > m1) ? m1 : seed;
262 }
263
264 //***************************************************************************
266 //***************************************************************************
267 uint32_t operator()()
268 {
269 static ETL_CONSTANT uint32_t m = ((m1 > m2) ? m1 : m2);
270
271 value1 = (a1 * value1) % m1;
272 value2 = (a2 * value2) % m2;
273
274 return (value1 + value2) % m;
275 }
276
277 //***************************************************************************
279 //***************************************************************************
280 uint32_t range(uint32_t low, uint32_t high)
281 {
282 uint32_t r = high - low + 1UL;
283 uint32_t n = operator()();
284 n %= r;
285 n += low;
286
287 return n;
288 }
289
290 private:
291
292 static ETL_CONSTANT uint32_t a1 = 40014U;
293 static ETL_CONSTANT uint32_t m1 = 2147483563UL;
294
295 static ETL_CONSTANT uint32_t a2 = 40692U;
296 static ETL_CONSTANT uint32_t m2 = 2147483399UL;
297
298 uint32_t value1;
299 uint32_t value2;
300 };
301
302 //***************************************************************************
307 //***************************************************************************
308 class random_lsfr : public random
309 {
310 public:
311
312 //***************************************************************************
315 //***************************************************************************
317 {
318 // An attempt to come up with a unique non-zero seed,
319 // based on the address of the instance.
320 uintptr_t n = reinterpret_cast<uintptr_t>(this);
321 uint32_t seed = static_cast<uint32_t>(n);
322 initialise(seed);
323 }
324
325 //***************************************************************************
328 //***************************************************************************
329 random_lsfr(uint32_t seed)
330 {
331 initialise(seed);
332 }
333
334 //***************************************************************************
337 //***************************************************************************
338 void initialise(uint32_t seed)
339 {
340 value = seed;
341 }
342
343 //***************************************************************************
345 //***************************************************************************
346 uint32_t operator()()
347 {
348 static ETL_CONSTANT uint32_t polynomial = 0x80200003UL;
349
350 value >>= 1U;
351
352 if ((value & 1UL) == 1UL)
353 {
354 value ^= polynomial;
355 }
356
357 return value;
358 }
359
360 //***************************************************************************
362 //***************************************************************************
363 uint32_t range(uint32_t low, uint32_t high)
364 {
365 uint32_t r = high - low + 1UL;
366 uint32_t n = operator()();
367 n %= r;
368 n += low;
369
370 return n;
371 }
372
373 private:
374
375 uint32_t value;
376 };
377
378 //***************************************************************************
381 //***************************************************************************
382 class random_mwc : public random
383 {
384 public:
385
386 //***************************************************************************
389 //***************************************************************************
391 {
392 // An attempt to come up with a unique non-zero seed,
393 // based on the address of the instance.
394 uintptr_t n = reinterpret_cast<uintptr_t>(this);
395 uint32_t seed = static_cast<uint32_t>(n);
396 initialise(seed);
397 }
398
399 //***************************************************************************
402 //***************************************************************************
403 random_mwc(uint32_t seed)
404 {
405 initialise(seed);
406 }
407
408 //***************************************************************************
411 //***************************************************************************
412 void initialise(uint32_t seed)
413 {
414 value1 = seed;
415 value2 = seed;
416 }
417
418 //***************************************************************************
420 //***************************************************************************
421 uint32_t operator()()
422 {
423 value1 = 36969UL * (value1 & 0xFFFFUL) + (value1 >> 16U);
424 value2 = 18000UL * (value2 & 0xFFFFUL) + (value2 >> 16U);
425
426 return (value1 << 16U) + value2;
427 }
428
429 //***************************************************************************
431 //***************************************************************************
432 uint32_t range(uint32_t low, uint32_t high)
433 {
434 uint32_t r = high - low + 1UL;
435 uint32_t n = operator()();
436 n %= r;
437 n += low;
438
439 return n;
440 }
441
442 private:
443
444 uint32_t value1;
445 uint32_t value2;
446 };
447
448#if ETL_USING_64BIT_TYPES
449 //***************************************************************************
453 //***************************************************************************
454 class random_pcg : public random
455 {
456 public:
457
458 random_pcg()
459 {
461 // An attempt to come up with a unique non-zero seed,
462 // based on the address of the instance.
463 uintptr_t n = reinterpret_cast<uintptr_t>(this);
464 value = static_cast<uint64_t>(n);
465 #include "private/diagnostic_pop.h"
466 }
467
468 //***************************************************************************
471 //***************************************************************************
472 random_pcg(uint32_t seed)
473 {
474 initialise(seed);
475 }
476
477 //***************************************************************************
480 //***************************************************************************
481 void initialise(uint32_t seed)
482 {
483 value = uint64_t(seed) | (uint64_t(seed) << 32U);
484 }
485
486 //***************************************************************************
488 //***************************************************************************
489 uint32_t operator()()
490 {
491 uint64_t x = value;
492 unsigned count = (unsigned)(value >> 59U);
493
494 value = (x * multiplier) + increment;
495 x ^= x >> 18U;
496 return etl::rotate_right((uint32_t)(x >> 27U), count);
497 }
498
499 //***************************************************************************
501 //***************************************************************************
502 uint32_t range(uint32_t low, uint32_t high)
503 {
504 uint32_t r = high - low + 1UL;
505 uint32_t n = operator()();
506 n %= r;
507 n += low;
508
509 return n;
510 }
511
512 private:
513
514 static ETL_CONSTANT uint64_t multiplier = 6364136223846793005ULL;
515 static ETL_CONSTANT uint64_t increment = 1ULL;
516
517 uint64_t value;
518 };
519#endif
520
521#if ETL_USING_8BIT_TYPES
522 //***************************************************************************
527 //***************************************************************************
528 template <typename THash>
529 class random_hash : public random
530 {
531 public:
532
533 random_hash()
534 {
535 // An attempt to come up with a unique non-zero seed,
536 // based on the address of the instance.
537 uintptr_t n = reinterpret_cast<uintptr_t>(this);
538 value = static_cast<uint32_t>(n);
539 }
540
541 //***************************************************************************
544 //***************************************************************************
545 random_hash(uint32_t seed)
546 {
547 initialise(seed);
548 }
549
550 //***************************************************************************
553 //***************************************************************************
554 void initialise(uint32_t seed)
555 {
556 value = seed;
557 }
558
559 //***************************************************************************
561 //***************************************************************************
562 uint32_t operator()()
563 {
564 ++value;
565 hash.add(value);
566 return hash.value();
567 }
568
569 //***************************************************************************
571 //***************************************************************************
572 uint32_t range(uint32_t low, uint32_t high)
573 {
574 uint32_t r = high - low + 1UL;
575 uint32_t n = operator()();
576 n %= r;
577 n += low;
578
579 return n;
580 }
581
582 private:
583
584 THash hash;
585 uint8_t value;
586 };
587#endif
588} // namespace etl
589
590#endif
random_clcg()
Definition random.h:235
void initialise(uint32_t seed)
Definition random.h:257
random_clcg(uint32_t seed)
Definition random.h:248
uint32_t range(uint32_t low, uint32_t high)
Get the next random_clcg number in a specified inclusive range.
Definition random.h:280
uint32_t operator()()
Get the next random_clcg number.
Definition random.h:267
random_lcg(uint32_t seed)
Definition random.h:176
random_lcg()
Definition random.h:163
void initialise(uint32_t seed)
Definition random.h:185
uint32_t operator()()
Get the next random_clcg number.
Definition random.h:194
uint32_t range(uint32_t low, uint32_t high)
Get the next random_clcg number in a specified inclusive range.
Definition random.h:204
random_lsfr(uint32_t seed)
Definition random.h:329
random_lsfr()
Definition random.h:316
void initialise(uint32_t seed)
Definition random.h:338
uint32_t range(uint32_t low, uint32_t high)
Get the next random_lsfr number in a specified inclusive range.
Definition random.h:363
uint32_t operator()()
Get the next random_lsfr number.
Definition random.h:346
random_mwc()
Definition random.h:390
uint32_t range(uint32_t low, uint32_t high)
Get the next random_lsfr number in a specified inclusive range.
Definition random.h:432
uint32_t operator()()
Get the next random_lsfr number.
Definition random.h:421
random_mwc(uint32_t seed)
Definition random.h:403
void initialise(uint32_t seed)
Definition random.h:412
random_pcg(uint32_t seed)
Definition random.h:472
void initialise(uint32_t seed)
Definition random.h:481
uint32_t operator()()
Get the next random_lsfr number.
Definition random.h:489
uint32_t range(uint32_t low, uint32_t high)
Get the next random_lsfr number in a specified inclusive range.
Definition random.h:502
uint32_t operator()()
Get the next random_xorshift number.
Definition random.h:117
random_xorshift(uint32_t seed)
Definition random.h:96
random_xorshift()
Definition random.h:83
uint32_t range(uint32_t low, uint32_t high)
Get the next random_xorshift number in a specified inclusive range.
Definition random.h:135
void initialise(uint32_t seed)
Definition random.h:105
Definition random.h:61
ETL_CONSTEXPR14 T rotate_right(T value)
Definition binary.h:162
bitset_ext
Definition absolute.h:40