11#include " components/rng/PCG.h"
22
3- Pinetime::Controllers::RNG::State Pinetime::Controllers::RNG::Seed (Pinetime::Controllers::RNG::rng_uint s,
4- Pinetime::Controllers::RNG::rng_uint i) {
5- return rng = State (s, i);
6- }
3+ using namespace Pinetime ::Controllers;
74
8- Pinetime::Controllers::RNG::State Pinetime::Controllers::RNG::Seed () {
9- using namespace Pinetime ::Controllers;
10- Pinetime::Controllers::RNG::State new_rng ((uint64_t ) Generate () << 32 ^ (uint64_t ) Generate (),
11- (uint64_t ) Generate () << 32 ^ (uint64_t ) Generate ());
12- return new_rng;
13- }
5+ RNG::RNG (result_type value) {
6+ // pcg32_srandom_r(&rng, 0x853c49e6748fea9bULL, value);
7+ rng.state = 0U ;
8+ rng.inc = (value << 1u ) | 1u ;
9+ (*this )(); // pcg32_random_r(rng);
10+ rng.state += 0x853c49e6748fea9bULL ;
11+ (*this )(); // pcg32_random_r(rng);
12+ };
13+
14+ RNG& RNG::operator =(const pcg32_random_t & other) {
15+ rng.state = other.state ;
16+ rng.inc = other.inc | 1 ;
17+ return *this ;
18+ };
19+
20+ template <class SeedSeq >
21+ RNG::RNG (SeedSeq& seq) {
22+ seed (seq);
23+ };
24+
25+ /*
26+ RNG::RNG(const RNG& other) {
27+ RNG tmp = other;
28+ RNG::result_type* ptr = (RNG::result_type*) this;
29+ tmp.generate(ptr, ptr + (sizeof(RNG) / sizeof(RNG::result_type)));
30+ };
31+ */
32+ template <typename SeedSeq>
33+ void RNG::seed (SeedSeq& seq) {
34+ RNG::result_type* ptr = (RNG::result_type*) this ;
35+ seq.generate (ptr, ptr + (sizeof (RNG) / sizeof (RNG::result_type)));
36+ rng.inc |= 1 ;
37+ };
38+
39+ void RNG::seed (RNG& other) {
40+ RNG::result_type* ptr = (RNG::result_type*) this ;
41+ other.generate (ptr, ptr + (sizeof (RNG) / sizeof (RNG::result_type)));
42+ rng.inc |= 1 ;
43+ };
44+
45+ RNG::result_type RNG::operator ()() {
46+ // return pcg32_random_r(&rng);
47+ uint64_t oldstate = rng.state ;
48+ rng.state = oldstate * 6364136223846793005ULL + rng.inc ;
49+ uint32_t xorshifted = ((oldstate >> 18u ) ^ oldstate) >> 27u ;
50+ uint32_t rot = oldstate >> 59u ;
51+ return (xorshifted >> rot) | (xorshifted << ((-rot) & 31 ));
52+ };
53+
54+ RNG::result_type RNG::operator ()(RNG::result_type bound) {
55+ // return pcg32_boundedrand_r(&rng, bounds);
56+ // To avoid bias, we need to make the range of the RNG a multiple of
57+ // bound, which we do by dropping output less than a threshold.
58+ // A naive scheme to calculate the threshold would be to do
59+ //
60+ // uint32_t threshold = 0x100000000ull % bound;
61+ //
62+ // but 64-bit div/mod is slower than 32-bit div/mod (especially on
63+ // 32-bit platforms). In essence, we do
64+ //
65+ // uint32_t threshold = (0x100000000ull-bound) % bound;
66+ //
67+ // because this version will calculate the same modulus, but the LHS
68+ // value is less than 2^32.
69+
70+ uint32_t threshold = -bound % bound;
71+
72+ // Uniformity guarantees that this loop will terminate. In practice, it
73+ // should usually terminate quickly; on average (assuming all bounds are
74+ // equally likely), 82.25% of the time, we can expect it to require just
75+ // one iteration. In the worst case, someone passes a bound of 2^31 + 1
76+ // (i.e., 2147483649), which invalidates almost 50% of the range. In
77+ // practice, bounds are typically small and only a tiny amount of the range
78+ // is eliminated.
79+ for (;;) {
80+ uint32_t r = (*this )(); // pcg32_random_r(rng);
81+ if (r >= threshold)
82+ return r % bound;
83+ }
84+ };
85+
86+ // std::seed_seq interface
87+ template <typename It>
88+ void RNG::generate (It start, It end) {
89+ for (; start != end; ++start)
90+ *start = (*this )();
91+ };
1492
15- Pinetime::Controllers::RNG::rng_out Pinetime::Controllers:: RNG::Generate () {
16- return rng ( );
93+ std:: size_t RNG::size () const noexcept {
94+ return sizeof ( rng) / sizeof (RNG::result_type );
1795};
1896
19- // See pcg-cpp/sample/codebook.cpp
20- Pinetime::Controllers::RNG::rng_out Pinetime::Controllers::RNG::GenerateBounded (Pinetime::Controllers::RNG::rng_out range) {
21- return rng (range);
97+ template <class OutputIt >
98+ void RNG::param (OutputIt dest) const {
99+ std::size_t i = 0 ;
100+ const std::size_t n = size ();
101+ RNG::result_type* ptr = (RNG::result_type*) this ;
102+ for (; i < n; ++i, ++dest, ++ptr) {
103+ *dest = ptr;
104+ }
22105};
0 commit comments