-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Flesh out std::rand::distributions a little more #9810
Conversation
Big ticket items I'm not sure about:
(On that note, I'm planning to implement more distributions like Gamma, Poisson etc, would these go in std or extra?) |
pub mod range; | ||
|
||
/// Types that can be used to create a random instance of `Support`. | ||
pub trait Sample<Support> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you even want to implement this for Support
where it does not ascribe to Rand
? It seems like a little bit of an unnecessary bound, but it might be kind of nice to indicate that it's still a random-ish output? If there are use cases for something like this though, then that's probably fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, very much so. This trait is basically half-designed for things that don't have a sensible Rand
, e.g. ~[T]
. (The other half is for (statistical) distributions with parameters.)
This all looks really good to me, nice job! I agree though that this is breaching into the realm of "too much for std", so I'm curious if we could start extracting some of the fancier functionality to an extra module. I think that everything have to do with |
I think this is the type of thing we do want to have in FWIW, C++11 includes a rich random number library despite the C++ standard library being quite minimal. |
Imitating C++11 is a goal. How about: move *Although |
Hm, I wouldn't classify myself as a heavy user of random number generators, and if it's a thing to put this in the standard library then I don't really have much problem with that. In that case, I think that if you remove the XXX this is r+-able |
Rebased. |
These are a "parameterised" Rand.
Complete the implementation of Exp and Normal started by Exp1 and StandardNormal by creating types implementing Sample & IndependentSample with the appropriate parameters.
This reifies the computations required for uniformity done by (the old) `Rng.gen_integer_range` (now Rng.gen_range), so that they can be amortised over many invocations, if it is called in a loop. Also, it makes it correct, but using a trait + impls for each type, rather than trying to coerce `Int` + `u64` to do the right thing. This also makes it more extensible, e.g. big integers could & should implement SampleRange.
Most importantly, links to the papers/references for the core algorithms (the RNG ones & the distribution ones).
Before: test rand::distributions::bench::rand_exp ... bench: 1399 ns/iter (+/- 124) = 571 MB/s test rand::distributions::bench::rand_normal ... bench: 1611 ns/iter (+/- 123) = 496 MB/s After: test rand::distributions::bench::rand_exp ... bench: 712 ns/iter (+/- 43) = 1123 MB/s test rand::distributions::bench::rand_normal ... bench: 1007 ns/iter (+/- 81) = 794 MB/s
This makes them more representative, as the `bh.iter` is a smaller percentage of the total time.
A user constructs the WeightedChoice distribution and then samples from it, which allows it to use binary search internally.
- Adds the `Sample` and `IndependentSample` traits for generating numbers where there are parameters (e.g. a list of elements to draw from, or the mean/variance of a normal distribution). The former takes `&mut self` and the latter takes `&self` (this is the only difference). - Adds proper `Normal` and `Exp`-onential distributions - Adds `Range` which generates `[lo, hi)` generically & properly (via a new trait) replacing the incorrect behaviour of `Rng.gen_integer_range` (this has become `Rng.gen_range` for convenience, it's far more efficient to use `Range` itself) - Move the `Weighted` struct from `std::rand` to `std::rand::distributions` & improve it - optimisations and docs
Sample
andIndependentSample
traits for generating numbers where there are parameters (e.g. a list of elements to draw from, or the mean/variance of a normal distribution). The former takes&mut self
and the latter takes&self
(this is the only difference).Normal
andExp
-onential distributionsRange
which generates[lo, hi)
generically & properly (via a new trait) replacing the incorrect behaviour ofRng.gen_integer_range
(this has becomeRng.gen_range
for convenience, it's far more efficient to useRange
itself)Weighted
struct fromstd::rand
tostd::rand::distributions
& improve it