authorgravatar for erik.arvstedt@gmail.comErik Arvstedt <erik.arvstedt@gmail.com> 2022-05-12 14:13:20+02:00
committergravatar for erik.arvstedt@gmail.comErik Arvstedt <erik.arvstedt@gmail.com> 2022-05-12 15:39:19+02:00
log1d5ea10bee39c6378c5d41597ed477075c3c667f
tree92fa79b1cbaf0eb4673f7c9f69b848ebb733aa41
parent7bedeb9659af84daab33a4804c54b4c8811c0c5d

std.rand: fixup 'improve random float generation'

- Test: Fix bucket counting. Previously, the first hit was not counted. This off-by-one error slightly increased the mean of `*_total_variance`, which decreased the acceptance rate for a particular random seed from 95% to 92.6%. (Irrelevant for test failure because the seed is fixed.) - Improve comments

2 files changed, 8 insertions(+), 6 deletions(-)

lib/std/rand.zig+5-3
......@@ -247,10 +247,9 @@ pub const Random = struct {
247247
248248 /// Return a floating point value evenly distributed in the range [0, 1).
249249 pub fn float(r: Random, comptime T: type) T {
250 // Generate a uniformly random value between for the mantissa.
250 // Generate a uniformly random value for the mantissa.
251251 // Then generate an exponentially biased random value for the exponent.
252 // Over the previous method, this has the advantage of being able to
253 // represent every possible value in the available range.
252 // This covers every possible value in the range.
254253 switch (T) {
255254 f32 => {
256255 // Use 23 random bits for the mantissa, and the rest for the exponent.
......@@ -259,6 +258,9 @@ pub const Random = struct {
259258 const rand = r.int(u64);
260259 var rand_lz = @clz(u64, rand | 0x7FFFFF);
261260 if (rand_lz == 41) {
261 // TODO: when #5177 or #489 is implemented,
262 // tell the compiler it is unlikely (1/2^41) to reach this point.
263 // (Same for the if branch and the f64 calculations below.)
262264 rand_lz += @clz(u64, r.int(u64));
263265 if (rand_lz == 41 + 64) {
264266 // It is astronomically unlikely to reach this point.
lib/std/rand/test.zig+3-3
......@@ -336,13 +336,13 @@ test "Random float chi-square goodness of fit" {
336336 if (f32_put.found_existing) {
337337 f32_put.value_ptr.* += 1;
338338 } else {
339 f32_put.value_ptr.* = 0;
339 f32_put.value_ptr.* = 1;
340340 }
341341 var f64_put = try f64_hist.getOrPut(@floatToInt(u32, rand_f64 * @intToFloat(f64, num_buckets)));
342342 if (f64_put.found_existing) {
343343 f64_put.value_ptr.* += 1;
344344 } else {
345 f64_put.value_ptr.* = 0;
345 f64_put.value_ptr.* = 1;
346346 }
347347 }
348348
......@@ -371,7 +371,7 @@ test "Random float chi-square goodness of fit" {
371371 }
372372 }
373373
374 // Corresponds to a p-value > 0.05.
374 // Accept p-values >= 0.05.
375375 // Critical value is calculated by opening a Python interpreter and running:
376376 // scipy.stats.chi2.isf(0.05, num_buckets - 1)
377377 const critical_value = 1073.6426506574246;