Skip to content

Commit f32928c

Browse files
authored
Merge pull request #11641 from erikarvstedt/fixup_rand_float_improvement
Minor fixes for random float generation
2 parents 24633b5 + 23ef7a8 commit f32928c

File tree

2 files changed

+14
-11
lines changed

2 files changed

+14
-11
lines changed

lib/std/rand.zig

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -247,19 +247,21 @@ 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.
257256
// If all 41 bits are zero, generate additional random bits, until a
258257
// set bit is found, or 126 bits have been generated.
259258
const rand = r.int(u64);
260-
var rand_lz = @clz(u64, rand | 0x7FFFFF);
261-
if (rand_lz == 41) {
262-
rand_lz += @clz(u64, r.int(u64));
259+
var rand_lz = @clz(u64, rand);
260+
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.)
264+
rand_lz = 41 + @clz(u64, r.int(u64));
263265
if (rand_lz == 41 + 64) {
264266
// It is astronomically unlikely to reach this point.
265267
rand_lz += @clz(u32, r.int(u32) | 0x7FF);
@@ -274,8 +276,9 @@ pub const Random = struct {
274276
// If all 12 bits are zero, generate additional random bits, until a
275277
// set bit is found, or 1022 bits have been generated.
276278
const rand = r.int(u64);
277-
var rand_lz: u64 = @clz(u64, rand | 0xFFFFFFFFFFFFF);
278-
if (rand_lz == 12) {
279+
var rand_lz: u64 = @clz(u64, rand);
280+
if (rand_lz >= 12) {
281+
rand_lz = 12;
279282
while (true) {
280283
// It is astronomically unlikely for this loop to execute more than once.
281284
const addl_rand_lz = @clz(u64, r.int(u64));

lib/std/rand/test.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

0 commit comments

Comments
 (0)