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

Uniform<f32/f64> should honor high/low limits #476

Closed
sicking opened this issue May 24, 2018 · 5 comments
Closed

Uniform<f32/f64> should honor high/low limits #476

sicking opened this issue May 24, 2018 · 5 comments

Comments

@sicking
Copy link
Contributor

sicking commented May 24, 2018

We should require that all Uniform distributions stick to the high/low limits, even in the face of rounding issues. Users are likely to see unexpected and hard-to-reproduce bugs if the returned value on rare occasions will be outside of the specified limits.

One example that I ran into was while implementing choose_weighted for dhardy#82. If the generated number can be slightly higher than high, that means that we risk iterating through the whole item-set without selecting any item to return.

The simplest approach is to simply check the generated value against high/low and loop if it doesn't fit withing the desired boundaries. However that runs into problem when scale rounds to infinity, since then we'll just loop forever.

Looking into some alternative approaches instead.

sicking added a commit to sicking/rand that referenced this issue May 25, 2018
@dhardy
Copy link
Member

dhardy commented May 25, 2018

Probably either rejection sampling or clamping will be needed...

I'd rather see a complete solution for one particular problem (e.g. choose_weighted), and then discuss whether to adjust Uniform sampling. Use guard functions for the sampling if necessary.

@pitdicker
Copy link
Contributor

pitdicker commented May 25, 2018

I'd rather see a complete solution for one particular problem (e.g. choose_weighted), and then discuss whether to adjust Uniform sampling.

Just wanted to write the same. Good that you thought about this corner case! But I can see other users complaining about the performance drop in gen_range, for a reason they don't cure much about. Maybe it is better to do the rejection sampling outside of gen_range?

@dhardy It can be a simple function, but what do you think of some method to make rejection sampling extra simple (i.e. that allows users to not write the loop)? Not thought it through though...

@dhardy
Copy link
Member

dhardy commented May 25, 2018

So something like Uniform::new(low, high).sample_strict(&mut rng)? I suppose that could work.

@pitdicker
Copy link
Contributor

I was thinking more in the direction of:

pub trait Distribution<T> {
    /* ... */

    fn rejection_sample<R: Rng + ?Sized>(&self, rng: &mut R, min: T, max: T)
        -> T where T: PartialOrd<T>;
}

let val = Uniform::new(low, high).rejection_sample(&mut rng, low, high);

Hmmm, doesn't look great. Maybe some iterator adapter:

let val = Uniform::new(low, high).sample_iter(&mut rng).accept_if(|x| x >= low && x < high);

Also ugly. And does the same as:

let val = Uniform::new(low, high).sample_iter(&mut rng).filter(|x| x >= low && x < high).next();

@dhardy
Copy link
Member

dhardy commented May 25, 2018

Yes, a new method on Uniform was the only way I could think of not having to specify the limits twice.

Not sure if it's worth it, but it could be an unobtrusive layer on top of the current sample at least.

sicking added a commit to sicking/rand that referenced this issue Jun 8, 2018
sicking added a commit to sicking/rand that referenced this issue Jun 8, 2018
sicking added a commit to sicking/rand that referenced this issue Jun 12, 2018
sicking added a commit to sicking/rand that referenced this issue Jul 2, 2018
sicking added a commit to sicking/rand that referenced this issue Jul 2, 2018
sicking added a commit to sicking/rand that referenced this issue Jul 2, 2018
sicking added a commit to sicking/rand that referenced this issue Jul 2, 2018
sicking added a commit to sicking/rand that referenced this issue Jul 2, 2018
sicking added a commit to sicking/rand that referenced this issue Jul 12, 2018
sicking added a commit to sicking/rand that referenced this issue Jul 12, 2018
sicking added a commit to sicking/rand that referenced this issue Jul 12, 2018
@dhardy dhardy closed this as completed in 6d2b7e5 Jul 12, 2018
dhardy added a commit that referenced this issue Jul 12, 2018
Make Uniform<f32/f64> and gen_range<f32/f64> honor limits strictly. Resolves #476
pitdicker pushed a commit to pitdicker/rand that referenced this issue Jul 20, 2018
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

No branches or pull requests

3 participants