std::rand: correct an off-by-one in the Ziggurat code. #10196
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The code was using (in the notation of Doornik 2005)
f(x_{i+1}) - f(x_{i+2})
rather thanf(x_i) - f(x_{i+1})
. This corrects that, andremoves the F_DIFF tables which caused this problem in the first place.
They
F_DIFF
tables are a micro-optimisation (in theory, they couldeasily be a micro-pessimisation): that
if
gets hit about 1% of thetime for Exp/Normal, and the rest of the condition involves RNG calls
and a floating point
exp
, so it is unlikely that saving a single FPsubtraction will be very useful (especially as more tables means more
memory reads and higher cache pressure, as well as taking up space in
the binary (although only ~2k in this case)).
Closes #10084. Notably, unlike that issue suggests, this wasn't a
problem with the Exp tables. It affected Normal too, but since it is
symmetric, there was no bias in the mean (as the bias was equal on the
positive and negative sides and so cancelled out) but it was visible as
a variance slightly lower than it should be.
New plot:
I've started writing some tests in huonw/random-tests (not in the main repo because they can and do fail occasionally, due to randomness, but it is on Travis and Rust-CI so it will hopefully track the language), unsurprisingly, they're currently failing (note that both exp and norm are failing, the former due to both mean and variance the latter due to just variance), but pass at the 0.01 level reliably with this change.
(Currently the only test is essentially a quantitative version of the plots I've been showing, which is run on the
f64
Rand
instance (uniform 0 to 1), and the Normal and Exp distributions.)