55#include " components/motor/MotorController.h"
66#include " components/motion/MotionController.h"
77
8+ namespace PCG {
9+ uint32_t pcg32_random_r (pcg32_random_t * rng) {
10+ uint64_t oldstate = rng->state ;
11+ // Advance internal state
12+ rng->state = oldstate * 6364136223846793005ULL + (rng->inc | 1 );
13+ // Calculate output function (XSH RR), uses old state for max ILP
14+ uint32_t xorshifted = ((oldstate >> 18u ) ^ oldstate) >> 27u ;
15+ uint32_t rot = oldstate >> 59u ;
16+ return (xorshifted >> rot) | (xorshifted << ((-rot) & 31 ));
17+ }
18+
19+ // Lemire's Method (slight rewrite) [0, range)
20+ uint32_t bounded_rand (pcg32_random_t & rng, uint32_t range) {
21+ uint64_t m;
22+ uint32_t t = (-range) % range;
23+ uint32_t l;
24+ do {
25+ uint32_t x = pcg32_random_r (&rng);
26+ m = uint64_t (x) * uint64_t (range);
27+ l = uint32_t (m);
28+ } while (l < t);
29+ return m >> 32 ;
30+ }
31+ };
32+
833using namespace Pinetime ::Applications::Screens;
934
1035namespace {
@@ -43,11 +68,13 @@ Dice::Dice(Controllers::MotionController& motionController,
4368 Controllers::MotorController& motorController,
4469 Controllers::Settings& settingsController)
4570 : motorController {motorController}, motionController {motionController}, settingsController {settingsController} {
46- std::seed_seq sseq {static_cast <uint32_t >(xTaskGetTickCount ()),
47- static_cast <uint32_t >(motionController.X ()),
48- static_cast <uint32_t >(motionController.Y ()),
49- static_cast <uint32_t >(motionController.Z ())};
50- gen.seed (sseq);
71+ rng.state =
72+ (static_cast <uint64_t >(xTaskGetTickCount ()) << 32 ) ^ (static_cast <uint64_t >(motionController.NbSteps ()) << 16 ) ^ (uint64_t ) &rng;
73+ rng.inc = (static_cast <uint64_t >(motionController.X ()) << 32 ) ^ (static_cast <uint64_t >(motionController.Y ()) << 16 ) ^
74+ static_cast <uint64_t >(motionController.Z ());
75+ uint8_t discard = PCG::pcg32_random_r (&rng);
76+ for (uint32_t i = 0 ; i < discard; i++)
77+ PCG::pcg32_random_r (&rng);
5178
5279 lv_obj_t * nCounterLabel = MakeLabel (&jetbrains_mono_bold_20,
5380 LV_COLOR_WHITE,
@@ -79,8 +106,7 @@ Dice::Dice(Controllers::MotionController& motionController,
79106 lv_obj_align (dCounter.GetObject (), dCounterLabel, LV_ALIGN_OUT_BOTTOM_MID, 0 , 10 );
80107 dCounter.SetValue (6 );
81108
82- std::uniform_int_distribution<> distrib (0 , resultColors.size () - 1 );
83- currentColorIndex = distrib (gen);
109+ currentColorIndex = PCG::bounded_rand (rng, resultColors.size ());
84110
85111 resultTotalLabel = MakeLabel (&jetbrains_mono_42,
86112 resultColors[currentColorIndex],
@@ -157,12 +183,10 @@ void Dice::Refresh() {
157183void Dice::Roll () {
158184 uint8_t resultIndividual;
159185 uint16_t resultTotal = 0 ;
160- std::uniform_int_distribution<> distrib (1 , dCounter.GetValue ());
161-
162186 lv_label_set_text (resultIndividualLabel, " " );
163187
164188 if (nCounter.GetValue () == 1 ) {
165- resultTotal = distrib (gen) ;
189+ resultTotal = PCG::bounded_rand (rng, dCounter. GetValue ()) + 1 ;
166190 if (dCounter.GetValue () == 2 ) {
167191 switch (resultTotal) {
168192 case 1 :
@@ -175,7 +199,7 @@ void Dice::Roll() {
175199 }
176200 } else {
177201 for (uint8_t i = 0 ; i < nCounter.GetValue (); i++) {
178- resultIndividual = distrib (gen) ;
202+ resultIndividual = PCG::bounded_rand (rng, dCounter. GetValue ()) + 1 ;
179203 resultTotal += resultIndividual;
180204 lv_label_ins_text (resultIndividualLabel, LV_LABEL_POS_LAST, std::to_string (resultIndividual).c_str ());
181205 if (i < (nCounter.GetValue () - 1 )) {
0 commit comments