diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-05-13 16:50:18 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-05-13 16:50:18 -0400 |
| commit | f32928c50dabde1dee40b7137beef0fe72e89b49 (patch) | |
| tree | 9ce6911652a2044c1efc6951bd9519d194789cab /lib | |
| parent | 24633b561369b5847e33d54ac02b77f23c9f8519 (diff) | |
| parent | 23ef7a80601d553bc9cce24500c9d079883867a4 (diff) | |
| download | zig-f32928c50dabde1dee40b7137beef0fe72e89b49.tar.gz zig-f32928c50dabde1dee40b7137beef0fe72e89b49.zip | |
Merge pull request #11641 from erikarvstedt/fixup_rand_float_improvement
Minor fixes for random float generation
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/rand.zig | 19 | ||||
| -rw-r--r-- | lib/std/rand/test.zig | 6 |
2 files changed, 14 insertions, 11 deletions
diff --git a/lib/std/rand.zig b/lib/std/rand.zig index 01397085f7..980722cdff 100644 --- a/lib/std/rand.zig +++ b/lib/std/rand.zig @@ -247,19 +247,21 @@ pub const Random = struct { /// Return a floating point value evenly distributed in the range [0, 1). pub fn float(r: Random, comptime T: type) T { - // Generate a uniformly random value between for the mantissa. + // Generate a uniformly random value for the mantissa. // Then generate an exponentially biased random value for the exponent. - // Over the previous method, this has the advantage of being able to - // represent every possible value in the available range. + // This covers every possible value in the range. switch (T) { f32 => { // Use 23 random bits for the mantissa, and the rest for the exponent. // If all 41 bits are zero, generate additional random bits, until a // set bit is found, or 126 bits have been generated. const rand = r.int(u64); - var rand_lz = @clz(u64, rand | 0x7FFFFF); - if (rand_lz == 41) { - rand_lz += @clz(u64, r.int(u64)); + var rand_lz = @clz(u64, rand); + if (rand_lz >= 41) { + // TODO: when #5177 or #489 is implemented, + // tell the compiler it is unlikely (1/2^41) to reach this point. + // (Same for the if branch and the f64 calculations below.) + rand_lz = 41 + @clz(u64, r.int(u64)); if (rand_lz == 41 + 64) { // It is astronomically unlikely to reach this point. rand_lz += @clz(u32, r.int(u32) | 0x7FF); @@ -274,8 +276,9 @@ pub const Random = struct { // If all 12 bits are zero, generate additional random bits, until a // set bit is found, or 1022 bits have been generated. const rand = r.int(u64); - var rand_lz: u64 = @clz(u64, rand | 0xFFFFFFFFFFFFF); - if (rand_lz == 12) { + var rand_lz: u64 = @clz(u64, rand); + if (rand_lz >= 12) { + rand_lz = 12; while (true) { // It is astronomically unlikely for this loop to execute more than once. const addl_rand_lz = @clz(u64, r.int(u64)); diff --git a/lib/std/rand/test.zig b/lib/std/rand/test.zig index 6915e028f2..7c2016901f 100644 --- a/lib/std/rand/test.zig +++ b/lib/std/rand/test.zig @@ -336,13 +336,13 @@ test "Random float chi-square goodness of fit" { if (f32_put.found_existing) { f32_put.value_ptr.* += 1; } else { - f32_put.value_ptr.* = 0; + f32_put.value_ptr.* = 1; } var f64_put = try f64_hist.getOrPut(@floatToInt(u32, rand_f64 * @intToFloat(f64, num_buckets))); if (f64_put.found_existing) { f64_put.value_ptr.* += 1; } else { - f64_put.value_ptr.* = 0; + f64_put.value_ptr.* = 1; } } @@ -371,7 +371,7 @@ test "Random float chi-square goodness of fit" { } } - // Corresponds to a p-value > 0.05. + // Accept p-values >= 0.05. // Critical value is calculated by opening a Python interpreter and running: // scipy.stats.chi2.isf(0.05, num_buckets - 1) const critical_value = 1073.6426506574246; |
