pub fn real(bits: impl FnMut() -> u64) -> f64Expand description
Port of random_real from random_real.c: interprets an unbounded
stream of random bits as the binary expansion of a real number in
[0 . . 1] and rounds it to the nearest f64, with a sticky bit avoiding
ties. Every float in [2⁻¹⁰²⁴ . . 1] is reachable; 0 is returned after
1024 zero bits (probability 2⁻¹⁰²⁴, i.e., only if the source is broken),
and the subnormals below 2⁻¹⁰²⁴ cannot occur.
This documentation differs from the comments in the C original, which claims to reach every float in [0 . . 1] and to return 0 only when the result is guaranteed to round to zero: the all-zeros cutoff fires one word too early (after 16 rather than 17 zero words) discarding continuations as large as ≈2⁻¹⁰²⁴ that would round to smaller subnormals. This is a minor bug we found while porting and reported to the author; it affects an event of probability 2⁻¹⁰²⁴, and the code below is left faithful to the original.
Consumes one 64-bit word, plus one more with probability 1/2 (when the first word has leading zeros), plus one word per 64 leading zero bits. The expected number of words per call is ≈1.5.
The C original scales by ldexp(significand, exponent); Rust has no
ldexp in the standard library, and a single multiplication cannot
replace it, since 2^exponent can be as small as 2⁻¹⁰⁸⁷, which is not
representable. The port multiplies by 2⁻⁹⁶⁰ first (exact, since the
intermediate result stays normal) and then by 2^(exponent + 960),
which is always representable, so the result is rounded once, exactly
as in ldexp. On x86-64 compiled with AVX-512F the port uses instead
the hardware ldexp (a single vscalefsd instruction) via inline
assembly.