1- // Copyright 2018 Developers of the Rand project.
1+ // Copyright 2018-2020 Developers of the Rand project.
22// Copyright 2017 The Rust Project Developers.
33//
44// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
3434//! let side = Uniform::new(-10.0, 10.0);
3535//!
3636//! // sample between 1 and 10 points
37- //! for _ in 0..rng.gen_range(1, 11 ) {
37+ //! for _ in 0..rng.gen_range(1..=10 ) {
3838//! // sample a point from the square with sides -10 - 10 in two dimensions
3939//! let (x, y) = (rng.sample(side), rng.sample(side));
4040//! println!("Point: {}, {}", x, y);
105105
106106#[ cfg( not( feature = "std" ) ) ] use core:: time:: Duration ;
107107#[ cfg( feature = "std" ) ] use std:: time:: Duration ;
108+ use core:: ops:: { Range , RangeInclusive } ;
108109
109110use crate :: distributions:: float:: IntoFloat ;
110111use crate :: distributions:: utils:: { BoolAsSIMD , FloatAsSIMD , FloatSIMDUtils , WideningMultiply } ;
111112use crate :: distributions:: Distribution ;
112- use crate :: Rng ;
113+ use crate :: { Rng , RngCore } ;
113114
114115#[ cfg( not( feature = "std" ) ) ]
115116#[ allow( unused_imports) ] // rustc doesn't detect that this is actually used
@@ -124,7 +125,8 @@ use serde::{Serialize, Deserialize};
124125///
125126/// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform
126127/// distribution sampling from the given range; these functions may do extra
127- /// work up front to make sampling of multiple values faster.
128+ /// work up front to make sampling of multiple values faster. If only one sample
129+ /// from the range is required, [`Rng::gen_range`] can be more efficient.
128130///
129131/// When sampling from a constant range, many calculations can happen at
130132/// compile-time and all methods should be fast; for floating-point ranges and
@@ -139,27 +141,35 @@ use serde::{Serialize, Deserialize};
139141/// are of lower quality than the high bits.
140142///
141143/// Implementations must sample in `[low, high)` range for
142- /// `Uniform::new(low, high)`, i.e., excluding `high`. In particular care must
144+ /// `Uniform::new(low, high)`, i.e., excluding `high`. In particular, care must
143145/// be taken to ensure that rounding never results values `< low` or `>= high`.
144146///
145147/// # Example
146148///
147149/// ```
148150/// use rand::distributions::{Distribution, Uniform};
149151///
150- /// fn main() {
151- /// let between = Uniform::from(10..10000);
152- /// let mut rng = rand::thread_rng();
153- /// let mut sum = 0;
154- /// for _ in 0..1000 {
155- /// sum += between.sample(&mut rng);
156- /// }
157- /// println!("{}", sum);
152+ /// let between = Uniform::from(10..10000);
153+ /// let mut rng = rand::thread_rng();
154+ /// let mut sum = 0;
155+ /// for _ in 0..1000 {
156+ /// sum += between.sample(&mut rng);
158157/// }
158+ /// println!("{}", sum);
159+ /// ```
160+ ///
161+ /// For a single sample, [`Rng::gen_range`] may be prefered:
162+ ///
163+ /// ```
164+ /// use rand::Rng;
165+ ///
166+ /// let mut rng = rand::thread_rng();
167+ /// println!("{}", rng.gen_range(0..10));
159168/// ```
160169///
161170/// [`new`]: Uniform::new
162171/// [`new_inclusive`]: Uniform::new_inclusive
172+ /// [`Rng::gen_range`]: Rng::gen_range
163173#[ derive( Clone , Copy , Debug ) ]
164174#[ cfg_attr( feature = "serde1" , derive( Serialize , Deserialize ) ) ]
165175pub struct Uniform < X : SampleUniform > ( X :: Sampler ) ;
@@ -287,18 +297,19 @@ pub trait UniformSampler: Sized {
287297 }
288298}
289299
290- impl < X : SampleUniform > From < :: core :: ops :: Range < X > > for Uniform < X > {
300+ impl < X : SampleUniform > From < Range < X > > for Uniform < X > {
291301 fn from ( r : :: core:: ops:: Range < X > ) -> Uniform < X > {
292302 Uniform :: new ( r. start , r. end )
293303 }
294304}
295305
296- impl < X : SampleUniform > From < :: core :: ops :: RangeInclusive < X > > for Uniform < X > {
306+ impl < X : SampleUniform > From < RangeInclusive < X > > for Uniform < X > {
297307 fn from ( r : :: core:: ops:: RangeInclusive < X > ) -> Uniform < X > {
298308 Uniform :: new_inclusive ( r. start ( ) , r. end ( ) )
299309 }
300310}
301311
312+
302313/// Helper trait similar to [`Borrow`] but implemented
303314/// only for SampleUniform and references to SampleUniform in
304315/// order to resolve ambiguity issues.
@@ -327,6 +338,43 @@ where Borrowed: SampleUniform
327338 }
328339}
329340
341+ /// Range that supports generating a single sample efficiently.
342+ ///
343+ /// Any type implementing this trait can be used to specify the sampled range
344+ /// for `Rng::gen_range`.
345+ pub trait SampleRange < T > {
346+ /// Generate a sample from the given range.
347+ fn sample_single < R : RngCore + ?Sized > ( self , rng : & mut R ) -> T ;
348+
349+ /// Check whether the range is empty.
350+ fn is_empty ( & self ) -> bool ;
351+ }
352+
353+ impl < T : SampleUniform + PartialOrd > SampleRange < T > for Range < T > {
354+ #[ inline]
355+ fn sample_single < R : RngCore + ?Sized > ( self , rng : & mut R ) -> T {
356+ T :: Sampler :: sample_single ( self . start , self . end , rng)
357+ }
358+
359+ #[ inline]
360+ fn is_empty ( & self ) -> bool {
361+ !( self . start < self . end )
362+ }
363+ }
364+
365+ impl < T : SampleUniform + PartialOrd > SampleRange < T > for RangeInclusive < T > {
366+ #[ inline]
367+ fn sample_single < R : RngCore + ?Sized > ( self , rng : & mut R ) -> T {
368+ T :: Sampler :: sample_single_inclusive ( self . start ( ) , self . end ( ) , rng)
369+ }
370+
371+ #[ inline]
372+ fn is_empty ( & self ) -> bool {
373+ !( self . start ( ) <= self . end ( ) )
374+ }
375+ }
376+
377+
330378////////////////////////////////////////////////////////////////////////////////
331379
332380// What follows are all back-ends.
@@ -425,7 +473,7 @@ macro_rules! uniform_int_impl {
425473 } ;
426474
427475 UniformInt {
428- low: low ,
476+ low,
429477 // These are really $unsigned values, but store as $ty:
430478 range: range as $ty,
431479 z: ints_to_reject as $unsigned as $ty,
@@ -570,7 +618,7 @@ macro_rules! uniform_simd_int_impl {
570618 let zone = unsigned_max - ints_to_reject;
571619
572620 UniformInt {
573- low: low ,
621+ low,
574622 // These are really $unsigned values, but store as $ty:
575623 range: range. cast( ) ,
576624 z: zone. cast( ) ,
@@ -985,7 +1033,7 @@ impl UniformSampler for UniformDuration {
9851033 max_nanos,
9861034 secs,
9871035 } => {
988- // constant folding means this is at least as fast as `gen_range `
1036+ // constant folding means this is at least as fast as `Rng::sample(Range) `
9891037 let nano_range = Uniform :: new ( 0 , 1_000_000_000 ) ;
9901038 loop {
9911039 let s = secs. sample ( rng) ;
@@ -1112,7 +1160,7 @@ mod tests {
11121160 }
11131161
11141162 for _ in 0 ..1000 {
1115- let v: $ty = rng . gen_range ( low, high) ;
1163+ let v = < $ty as SampleUniform > :: Sampler :: sample_single ( low, high, & mut rng ) ;
11161164 assert!( $le( low, v) && $lt( v, high) ) ;
11171165 }
11181166 }
@@ -1194,7 +1242,8 @@ mod tests {
11941242 assert!( low_scalar <= v && v < high_scalar) ;
11951243 let v = rng. sample( my_incl_uniform) . extract( lane) ;
11961244 assert!( low_scalar <= v && v <= high_scalar) ;
1197- let v = rng. gen_range( low, high) . extract( lane) ;
1245+ let v = <$ty as SampleUniform >:: Sampler
1246+ :: sample_single( low, high, & mut rng) . extract( lane) ;
11981247 assert!( low_scalar <= v && v < high_scalar) ;
11991248 }
12001249
@@ -1205,7 +1254,9 @@ mod tests {
12051254
12061255 assert_eq!( zero_rng. sample( my_uniform) . extract( lane) , low_scalar) ;
12071256 assert_eq!( zero_rng. sample( my_incl_uniform) . extract( lane) , low_scalar) ;
1208- assert_eq!( zero_rng. gen_range( low, high) . extract( lane) , low_scalar) ;
1257+ assert_eq!( <$ty as SampleUniform >:: Sampler
1258+ :: sample_single( low, high, & mut zero_rng)
1259+ . extract( lane) , low_scalar) ;
12091260 assert!( max_rng. sample( my_uniform) . extract( lane) < high_scalar) ;
12101261 assert!( max_rng. sample( my_incl_uniform) . extract( lane) <= high_scalar) ;
12111262
@@ -1218,7 +1269,9 @@ mod tests {
12181269 ( -1i64 << $bits_shifted) as u64 ,
12191270 ) ;
12201271 assert!(
1221- lowering_max_rng. gen_range( low, high) . extract( lane) < high_scalar
1272+ <$ty as SampleUniform >:: Sampler
1273+ :: sample_single( low, high, & mut lowering_max_rng)
1274+ . extract( lane) < high_scalar
12221275 ) ;
12231276 }
12241277 }
@@ -1266,7 +1319,7 @@ mod tests {
12661319 use std:: panic:: catch_unwind;
12671320 fn range < T : SampleUniform > ( low : T , high : T ) {
12681321 let mut rng = crate :: test:: rng ( 253 ) ;
1269- rng . gen_range ( low, high) ;
1322+ T :: Sampler :: sample_single ( low, high, & mut rng ) ;
12701323 }
12711324
12721325 macro_rules! t {
0 commit comments