8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- //! A distribution uniformly generating numbers within a given range.
11
+ //! A distribution uniformly sampling numbers within a given range.
12
12
//!
13
- //! [`Uniform`] is the standard distribution to sample from uniform ranges, and
14
- //! forms the basis for [`Rng::gen_range`].
13
+ //! [`Uniform`] is the standard distribution to sample uniformly from a range;
14
+ //! e.g. `Uniform::new_inclusive(1, 6)` can sample integers from 1 to 6, like a
15
+ //! standard die. [`Rng::gen_range`] simply uses [`Uniform::sample_single`],
16
+ //! thus supports any type supported by [`Uniform`].
15
17
//!
16
- //! To make sampling from a uniform range also possible for custom types
17
- //! [`Uniform`] depends on the [`SampleUniform`] and [`UniformImpl`] traits.
18
+ //! This distribution is provided with support for several primitive types
19
+ //! (all integer and floating-point types) as well as `std::time::Duration`,
20
+ //! and supports extension to user-defined types via a type-specific *back-end*
21
+ //! implementation.
18
22
//!
19
- //! Rand comes with an implementation of [`Uniform`] for sampling from integers
20
- //! and from floats, via [`UniformInt`] and [`UniformFloat`]. They are mostly an
21
- //! implementation detail and should not be used directly, but may be useful
22
- //! when you want to reuse the logic to implement range sampling for a custom
23
- //! type.
23
+ //! The types [`UniformInt`], [`UniformFloat`] and [`UniformDuration`] are the
24
+ //! back-ends supporting sampling from primitive integer and floating-point
25
+ //! ranges as well as from `std::time::Duration`; these types do not normally
26
+ //! need to be used directly (unless implementing a derived back-end).
24
27
//!
25
- //! Also implemented is a distribution for `Duration`.
28
+ //! # Example usage
26
29
//!
27
- //! # Implementing `Uniform` for a custom type
30
+ //! ```
31
+ //! use rand::{Rng, thread_rng};
32
+ //! use rand::distributions::Uniform;
33
+ //!
34
+ //! let mut rng = thread_rng();
35
+ //! let side = Uniform::new(-10.0, 10.0);
36
+ //!
37
+ //! // sample between 1 and 10 points
38
+ //! for _ in 0..rng.gen_range(1, 11) {
39
+ //! // sample a point from the square with sides -10 - 10 in two dimensions
40
+ //! let (x, y) = (rng.sample(side), rng.sample(side));
41
+ //! println!("Point: {}, {}", x, y);
42
+ //! }
43
+ //! ```
28
44
//!
29
- //! For the type you will need to create a struct that holds the lower and upper
30
- //! bounds of the range, and possibly some helper variables. The struct has to
31
- //! implement the [`UniformImpl`] trait to do the uniform range sampling.
45
+ //! # Extending `Uniform` to support a custom type
32
46
//!
33
- //! Additionally the type must implement the [`SampleUniform`] trait, which
34
- //! doesn't do anything but point to the struct implementing [`UniformImpl`].
47
+ //! To extend [`Uniform`] to support your own types, write a back-end which
48
+ //! implements the [`UniformImpl`] trait, then implement the [`SampleUniform`]
49
+ //! helper trait to "register" your back-end. See the `MyF32` example below.
35
50
//!
36
- //! ## Examples
51
+ //! At a minimum, the back-end needs to store any parameters needed for sampling
52
+ //! (e.g. the target range) and implement `new`, `new_inclusive` and `sample`.
53
+ //! The example below merely wraps another back-end.
37
54
//!
38
55
//! ```
39
56
//! use rand::{Rng, thread_rng};
73
90
//! ```
74
91
//!
75
92
//! [`Uniform`]: struct.Uniform.html
93
+ //! [`Uniform::sample_single`]: struct.Uniform.html#method.sample_single
76
94
//! [`Rng::gen_range`]: ../../trait.Rng.html#method.gen_range
77
95
//! [`SampleUniform`]: trait.SampleUniform.html
78
96
//! [`UniformImpl`]: trait.UniformImpl.html
79
97
//! [`UniformInt`]: struct.UniformInt.html
80
98
//! [`UniformFloat`]: struct.UniformFloat.html
99
+ //! [`UniformDuration`]: struct.UniformDuration.html
81
100
82
101
#[ cfg( feature = "std" ) ]
83
102
use std:: time:: Duration ;
@@ -88,26 +107,30 @@ use distributions::float::IntoFloat;
88
107
89
108
/// Sample values uniformly between two bounds.
90
109
///
91
- /// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a `Uniform`
92
- /// distribution sampling from the closed-open and the closed (inclusive) range.
93
- /// Some preparations are performed up front to make sampling values faster.
94
- /// [`Uniform::sample_single`] is optimized for sampling values once or only a
95
- /// limited number of times from a range.
110
+ /// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform
111
+ /// distribution sampling from the given range; these functions may do extra
112
+ /// work up front to make sampling of multiple values faster.
96
113
///
97
- /// If you need to sample many values from a range, consider using [`new`] or
98
- /// [`new_inclusive`]. This is also the best choice if the range is constant,
99
- /// because then the preparations can be evaluated at compile-time.
100
- /// Otherwise [`sample_single`] may be the best choice.
114
+ /// [`Uniform::sample_single`] instead samples directly from the given range,
115
+ /// and (depending on the back-end) may be faster when sampling a very small
116
+ /// number of values or only a single value from this range.
101
117
///
102
- /// Sampling uniformly from a range can be surprisingly complicated to be both
103
- /// generic and correct. Consider for example edge cases like `low = 0u8`,
104
- /// `high = 170u8`, for which a naive modulo operation would return numbers less
105
- /// than 85 with double the probability to those greater than 85 .
118
+ /// When sampling from a constant range, many calculations can happen at
119
+ /// compile-time and all methods should be fast; for floating-point ranges and
120
+ /// the full range of integer types this should have comparable performance to
121
+ /// the `Standard` distribution .
106
122
///
107
- /// Types should attempt to sample in `[low, high)` for `Uniform::new(low, high)`,
108
- /// i.e., excluding `high`, but this may be very difficult. All the primitive
109
- /// integer types satisfy this property, and the float types normally satisfy
110
- /// it, but rounding may mean `high` can occur.
123
+ /// Steps are taken to avoid bias which might be present in naive
124
+ /// implementations; for example `rng.gen::<u8>() % 170` samples from the range
125
+ /// `[0, 169]` but is twice as likely to select numbers less than 85 than other
126
+ /// values. Further, the implementations here give more weight to the high-bits
127
+ /// generated by the RNG than the low bits, since with some RNGs the low-bits
128
+ /// are of lower quality than the high bits.
129
+ ///
130
+ /// Implementations should attempt to sample in `[low, high)` for
131
+ /// `Uniform::new(low, high)`, i.e., excluding `high`, but this may be very
132
+ /// difficult. All the primitive integer types satisfy this property, and the
133
+ /// float types normally satisfy it, but rounding may mean `high` can occur.
111
134
///
112
135
/// # Example
113
136
///
@@ -184,8 +207,12 @@ pub trait SampleUniform: PartialOrd+Sized {
184
207
/// See the [module documentation] on how to implement [`Uniform`] range
185
208
/// sampling for a custom type.
186
209
///
210
+ /// Implementation of [`sample_single`] is optional, and is only useful when
211
+ /// the implementation can be faster than `Self::new(low, high).sample(rng)`.
212
+ ///
187
213
/// [module documentation]: index.html
188
214
/// [`Uniform`]: struct.Uniform.html
215
+ /// [`sample_single`]: struct.UniformImpl.html#method.sample_single
189
216
pub trait UniformImpl : Sized {
190
217
/// The type sampled by this implementation.
191
218
type X : PartialOrd ;
@@ -200,8 +227,8 @@ pub trait UniformImpl: Sized {
200
227
/// Construct self, with inclusive bounds `[low, high]`.
201
228
///
202
229
/// Usually users should not call this directly but instead use
203
- /// `Uniform::new_inclusive`, which asserts that `low < high` before calling
204
- /// this.
230
+ /// `Uniform::new_inclusive`, which asserts that `low <= high` before
231
+ /// calling this.
205
232
fn new_inclusive ( low : Self :: X , high : Self :: X ) -> Self ;
206
233
207
234
/// Sample a value.
@@ -226,7 +253,7 @@ pub trait UniformImpl: Sized {
226
253
}
227
254
}
228
255
229
- /// Implementation of [`UniformImpl`] for integer types.
256
+ /// The back-end implementing [`UniformImpl`] for integer types.
230
257
///
231
258
/// Unless you are implementing [`UniformImpl`] for your own type, this type
232
259
/// should not be used directly, use [`Uniform`] instead.
@@ -483,7 +510,7 @@ wmul_impl_usize! { u64 }
483
510
484
511
485
512
486
- /// Implementation of [`UniformImpl`] for float types.
513
+ /// The back-end implementing [`UniformImpl`] for floating-point types.
487
514
///
488
515
/// Unless you are implementing [`UniformImpl`] for your own type, this type
489
516
/// should not be used directly, use [`Uniform`] instead.
0 commit comments