aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-05-13 16:50:18 -0400
committerGitHub <noreply@github.com>2022-05-13 16:50:18 -0400
commitf32928c50dabde1dee40b7137beef0fe72e89b49 (patch)
tree9ce6911652a2044c1efc6951bd9519d194789cab /lib
parent24633b561369b5847e33d54ac02b77f23c9f8519 (diff)
parent23ef7a80601d553bc9cce24500c9d079883867a4 (diff)
downloadzig-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.zig19
-rw-r--r--lib/std/rand/test.zig6
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;