-
-
Notifications
You must be signed in to change notification settings - Fork 456
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
Replace distribution::Sample with Distribution + polymorphism over Rng #256
Conversation
To be clear, there are alternatives to this PR:
Also to be clear, impl<T> Distribution<Option<T>> for Uniform where Uniform: Distribution<T> {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<T> {
// UFCS is needed here: https://github.com/rust-lang/rust/issues/24066
if rng.gen::<bool>() {
Some(rng.gen())
} else {
None
}
}
} |
@dhardy Just a ping to let you know I'll dig through this, but it might take a few days :) |
@sbarral commented on Reddit that it may be worth keeping a distribution trait allowing mutable state since some genuine distribution sampling algorithms use it (e.g. Box-Muller generates two Gaussian samples simultaneously). Since this usage is the exception we agree that the primary distribution trait should not allow mutable state. I'm not sure what the best approach is here but see no reason why we can't leave this to later (i.e. another PR adding |
You could also treat pub trait DistributionMut<T> {
fn sample<R: Rng + ?Sized>(&mut self, rng: &mut R) -> T;
}
impl<T, D: Distribution<T>> DistributionMut<T> for D {
fn sample_mut<R: Rng + ?Sized>(&mut self, rng: &mut R) -> T {
self.sample(rng)
}
} Sorry I've been out of the loop on Something I'm not so sure on are the virtues of the |
Thanks @KodrAus. There's some discussion in #244 (this PR just merges that one). As noted in the first post, it seems Regarding mutable (state-full) distributions, my conclusion from the discussion on reddit is that they won't be needed in the vast majority of cases, and since there's no reason the trait can't be defined externally, I'd rather leave it out of |
Ahh I see, the |
Also, if in the future there is some need for mutable distributions, this can still be implemented in |
This is heavily inspired by #27 by @GrahamDennis but simpler trait and maintains backwards compatibility with deprecations.
Replaces rng.gen() to seed new RNGs with from_rng(&mut rng)
Move default sampling to Default distribution Make Open01 and Closed01 distributions instead of wrappers
This breaks rand_derive because gen() no longer supports derived types.
Rebased after merge of #265. |
Shouldn't |
Why? It doesn't need |
Yes, but it has the same problems that |
That is true. Why don't you open a new PR removing it so that it can be discussed there? It's independent of this PR.
|
Yeah, I'm not so happy with
Will do.
The deprecations are related, but it works as a follow-up I guess. |
I get what you mean about |
I like the idea of |
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.
I know you already merged this PR.
It looks really good, and I only have two questions.
let mut rng = ::test::rng(210); | ||
for _ in 0..1000 { | ||
norm.sample(&mut rng); | ||
norm.ind_sample(&mut rng); | ||
norm.sample(&mut rng); |
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.
Is this still a useful part of the test (here and all the similar tests that used ind_sample
)?
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.
The duplication is not useful. I noticed this when merging these changes into dhardy/master but didn't fix yet.
As for the tests themselves — good question. I just opened #267.
|
||
macro_rules! float_impls { | ||
($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => { | ||
mod $mod_name { |
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.
Why create modules here?
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.
I simply moved this code from rand_impls.rs
. But I think it does have a purpose — SCALE
is a local constant.
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.
Good reason. Then I feel free to remove them 😄
Replace distribution::Sample with Distribution + polymorphism over Rng
If #244 was controversial, this is even more so. There are many commits because there are many changes here, and these are bundled together to make
Distribution::sample
run-time polymorphic overRng
from the start without affectingRand
.Sample
andIndependentSample
withDistribution
Uniform
distribution and move allRand
implementations to itRng::gen()
to useUniform
and deprecateRand
andrand_derive
SampleRng
trait code (required to avoid having to type(&mut rng).gen()
in all implementations)sample<R: Rng>(..) -> T
tosample<R: Rng + ?Sized>(..) -> T
This PR is closely related to dhardy#83. We could potentially keep
Rand
and fixrand_derive
to useRand::rand(rng)
notrng.gen()
, or we could even keepRand
overUniform
but make change the method:rand<R: Rng + ?Sized>(..) -> T
(breaking existing implementations, but it's still a smaller change for users than deprecatingRand
like in this PR). I think I prefer approach sinceUniform
is a real distribution (uniformity, and maybe someday supporting currying of distributions) and avoids redundant feature overlap.Comments please on whether you want
rand
to go in this direction!