@@ -162,19 +162,15 @@ namespace gf {
162
162
163
163
Vec2F Random::compute_position (const RectF& area)
164
164
{
165
- std::uniform_real_distribution<float > dist_x (area.offset .x , area.offset .x + area.extent .x );
166
- std::uniform_real_distribution<float > dist_y (area.offset .y , area.offset .y + area.extent .y );
167
- const float x = dist_x (m_engine);
168
- const float y = dist_y (m_engine);
165
+ const float x = compute_uniform_float (area.offset .x , area.offset .x + area.extent .w );
166
+ const float y = compute_uniform_float (area.offset .y , area.offset .y + area.extent .h );
169
167
return { x, y };
170
168
}
171
169
172
170
Vec2I Random::compute_position (const RectI& area)
173
171
{
174
- std::uniform_int_distribution<int > dist_x (area.offset .x , area.offset .x + area.extent .x - 1 );
175
- std::uniform_int_distribution<int > dist_y (area.offset .y , area.offset .y + area.extent .y - 1 );
176
- const int x = dist_x (m_engine);
177
- const int y = dist_y (m_engine);
172
+ const int x = compute_uniform_integer (area.offset .x , area.offset .x + area.extent .w );
173
+ const int y = compute_uniform_integer (area.offset .y , area.offset .y + area.extent .h );
178
174
return { x, y };
179
175
}
180
176
@@ -187,22 +183,47 @@ namespace gf {
187
183
188
184
float Random::compute_radius (float radius_min, float radius_max)
189
185
{
190
- std::uniform_real_distribution<float > dist (gf::square (radius_min), gf::square (radius_max));
191
- return std::sqrt (dist (m_engine));
186
+ return std::sqrt (compute_uniform_float (gf::square (radius_min), gf::square (radius_max)));
192
187
}
193
188
194
189
float Random::compute_angle ()
195
190
{
196
- std::uniform_real_distribution<float > dist (0 .0f , 2 .0f * gf::Pi);
197
- return dist (m_engine);
191
+ return compute_uniform_float (2 .0f * gf::Pi);
198
192
}
199
193
200
194
Id Random::compute_id ()
201
195
{
202
- using Type = std::underlying_type_t <Id>;
203
- const Type lo = std::numeric_limits<Type>::min () + 1 ;
204
- const Type hi = std::numeric_limits<Type>::max ();
205
- return static_cast <Id>(compute_uniform_integer (lo, hi));
196
+ uint64_t id = m_engine ();
197
+
198
+ while (id == 0 ) {
199
+ id = m_engine ();
200
+ }
201
+
202
+ return Id{ id };
203
+ }
204
+
205
+ // using "Debiased Modulo (Once) — Java's Method" from
206
+ // https://www.pcg-random.org/posts/bounded-rands.html
207
+ uint64_t Random::compute_raw_integer (uint64_t max)
208
+ {
209
+ assert (max > 0 );
210
+
211
+ uint64_t x = 0 ;
212
+ uint64_t r = 0 ;
213
+ const uint64_t threshold = std::numeric_limits<uint64_t >::max () - max + 1 ;
214
+
215
+ do { // NOLINT(cppcoreguidelines-avoid-do-while)
216
+ x = m_engine ();
217
+ r = x % max;
218
+ } while (x - r > threshold);
219
+
220
+ return r;
221
+ }
222
+
223
+ double Random::compute_raw_float ()
224
+ {
225
+ const uint64_t value = m_engine ();
226
+ return double (value >> 11 ) * 0x1 .0p-53 ;
206
227
}
207
228
208
229
} // namespace gf
0 commit comments