Module rand::distributions::uniform
source · [−]Expand description
A distribution uniformly sampling numbers within a given range.
Uniform
is the standard distribution to sample uniformly from a range;
e.g. Uniform::new_inclusive(1, 6)
can sample integers from 1 to 6, like a
standard die. Rng::gen_range
supports any type supported by
Uniform
.
This distribution is provided with support for several primitive types
(all integer and floating-point types) as well as std::time::Duration
,
and supports extension to user-defined types via a type-specific back-end
implementation.
The types UniformInt
, UniformFloat
and UniformDuration
are the
back-ends supporting sampling from primitive integer and floating-point
ranges as well as from std::time::Duration
; these types do not normally
need to be used directly (unless implementing a derived back-end).
Example usage
use rand::{Rng, thread_rng};
use rand::distributions::Uniform;
let mut rng = thread_rng();
let side = Uniform::new(-10.0, 10.0);
// sample between 1 and 10 points
for _ in 0..rng.gen_range(1, 11) {
// sample a point from the square with sides -10 - 10 in two dimensions
let (x, y) = (rng.sample(side), rng.sample(side));
println!("Point: {}, {}", x, y);
}
Extending Uniform
to support a custom type
To extend Uniform
to support your own types, write a back-end which
implements the UniformSampler
trait, then implement the SampleUniform
helper trait to “register” your back-end. See the MyF32
example below.
At a minimum, the back-end needs to store any parameters needed for sampling
(e.g. the target range) and implement new
, new_inclusive
and sample
.
Those methods should include an assert to check the range is valid (i.e.
low < high
). The example below merely wraps another back-end.
The new
, new_inclusive
and sample_single
functions use arguments of
type SampleBorrowSampleBorrow::borrow
, or you can choose
to copy or clone the value, whatever is appropriate for your type.
use rand::prelude::*;
use rand::distributions::uniform::{Uniform, SampleUniform,
UniformSampler, UniformFloat, SampleBorrow};
struct MyF32(f32);
#[derive(Clone, Copy, Debug)]
struct UniformMyF32 {
inner: UniformFloat<f32>,
}
impl UniformSampler for UniformMyF32 {
type X = MyF32;
fn new<B1, B2>(low: B1, high: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
{
UniformMyF32 {
inner: UniformFloat::<f32>::new(low.borrow().0, high.borrow().0),
}
}
fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
where B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized
{
UniformSampler::new(low, high)
}
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
MyF32(self.inner.sample(rng))
}
}
impl SampleUniform for MyF32 {
type Sampler = UniformMyF32;
}
let (low, high) = (MyF32(17.0f32), MyF32(22.0f32));
let uniform = Uniform::new(low, high);
let x = uniform.sample(&mut thread_rng());
Structs
Sample values uniformly between two bounds.
The back-end implementing UniformSampler
for Duration
.
The back-end implementing UniformSampler
for floating-point types.
The back-end implementing UniformSampler
for integer types.
Traits
Helper trait similar to Borrow
but implemented
only for SampleUniform and references to SampleUniform in
order to resolve ambiguity issues.
Helper trait for creating objects using the correct implementation of
UniformSampler
for the sampling type.
Helper trait handling actual uniform sampling.