Skip to content
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

Merged
merged 8 commits into from
Oct 23, 2013
Merged

Conversation

huonw
Copy link
Member

@huonw huonw commented Oct 11, 2013

  • 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

@huonw
Copy link
Member Author

huonw commented Oct 11, 2013

Big ticket items I'm not sure about:

  • having the separate traits Sample and IndependentSample. There are use-cases for both (the former can be used for something like cycling through a finite list of elements that gets shuffled and reused each time it's exhausted, the latter is because things being non-mut when they can be feels nicer), but having two seems a little silly.
  • the name & behaviour of Range, it really should be Uniform but then it should be implemented as [lo, hi] inclusive.
  • putting all this in std.

(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> {
Copy link
Member

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.

Copy link
Member Author

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.)

@alexcrichton
Copy link
Member

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 task_rng should stay within std, but most else probably doesn't need to be so core to the standard library.

@thestinger
Copy link
Contributor

I think this is the type of thing we do want to have in std, because it's easy to standardize on a stable API.

FWIW, C++11 includes a rich random number library despite the C++ standard library being quite minimal.

@huonw
Copy link
Member Author

huonw commented Oct 12, 2013

Imitating C++11 is a goal.

How about: move std::rand::distributions almost-wholesale (I think Range is appropriate to std*; at least, it's required for Rng.gen_range) to extra::rand::distributions for now, aiming to work out what's wanted/what about the API needs to change and then move (some subset) back to std. (The back-to-std move sounds like something for after 1.0, since this stuff isn't super-important.)

*Although Range really needs the Sample/IndependentSample traits to work nicely, but a method for sampling can just go as a normal non-trait method, and Sample etc implemented for it in extra.

@alexcrichton
Copy link
Member

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

@huonw
Copy link
Member Author

huonw commented Oct 22, 2013

Rebased.

huonw added 8 commits October 23, 2013 10:40
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.
bors added a commit that referenced this pull request Oct 23, 2013
- 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
@bors bors closed this Oct 23, 2013
@bors bors merged commit 0bba73c into rust-lang:master Oct 23, 2013
@huonw huonw deleted the rand3 branch October 23, 2013 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants