| ... | @@ -247,19 +247,21 @@ pub const Random = struct { | ... | @@ -247,19 +247,21 @@ pub const Random = struct { |
| 247 | | 247 | |
| 248 | /// Return a floating point value evenly distributed in the range [0, 1). | 248 | /// Return a floating point value evenly distributed in the range [0, 1). |
| 249 | pub fn float(r: Random, comptime T: type) T { | 249 | 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. |
| 251 | // Then generate an exponentially biased random value for the exponent. | 251 | // Then generate an exponentially biased random value for the exponent. |
| 252 | // Over the previous method, this has the advantage of being able to | 252 | // This covers every possible value in the range. |
| 253 | // represent every possible value in the available range. | | |
| 254 | switch (T) { | 253 | switch (T) { |
| 255 | f32 => { | 254 | f32 => { |
| 256 | // Use 23 random bits for the mantissa, and the rest for the exponent. | 255 | // Use 23 random bits for the mantissa, and the rest for the exponent. |
| 257 | // If all 41 bits are zero, generate additional random bits, until a | 256 | // If all 41 bits are zero, generate additional random bits, until a |
| 258 | // set bit is found, or 126 bits have been generated. | 257 | // set bit is found, or 126 bits have been generated. |
| 259 | const rand = r.int(u64); | 258 | const rand = r.int(u64); |
| 260 | var rand_lz = @clz(u64, rand | 0x7FFFFF); | 259 | var rand_lz = @clz(u64, rand); |
| 261 | if (rand_lz == 41) { | 260 | if (rand_lz >= 41) { |
| 262 | rand_lz += @clz(u64, r.int(u64)); | 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)); |
| 263 | if (rand_lz == 41 + 64) { | 265 | if (rand_lz == 41 + 64) { |
| 264 | // It is astronomically unlikely to reach this point. | 266 | // It is astronomically unlikely to reach this point. |
| 265 | rand_lz += @clz(u32, r.int(u32) | 0x7FF); | 267 | rand_lz += @clz(u32, r.int(u32) | 0x7FF); |
| ... | @@ -274,8 +276,9 @@ pub const Random = struct { | ... | @@ -274,8 +276,9 @@ pub const Random = struct { |
| 274 | // If all 12 bits are zero, generate additional random bits, until a | 276 | // If all 12 bits are zero, generate additional random bits, until a |
| 275 | // set bit is found, or 1022 bits have been generated. | 277 | // set bit is found, or 1022 bits have been generated. |
| 276 | const rand = r.int(u64); | 278 | const rand = r.int(u64); |
| 277 | var rand_lz: u64 = @clz(u64, rand | 0xFFFFFFFFFFFFF); | 279 | var rand_lz: u64 = @clz(u64, rand); |
| 278 | if (rand_lz == 12) { | 280 | if (rand_lz >= 12) { |
| | 281 | rand_lz = 12; |
| 279 | while (true) { | 282 | while (true) { |
| 280 | // It is astronomically unlikely for this loop to execute more than once. | 283 | // It is astronomically unlikely for this loop to execute more than once. |
| 281 | const addl_rand_lz = @clz(u64, r.int(u64)); | 284 | const addl_rand_lz = @clz(u64, r.int(u64)); |