50
50
//!
51
51
//! At a minimum, the back-end needs to store any parameters needed for sampling
52
52
//! (e.g. the target range) and implement `new`, `new_inclusive` and `sample`.
53
- //! The example below merely wraps another back-end.
53
+ //! Those methods should include an assert to check the range is valid (i.e.
54
+ //! `low < high`). The example below merely wraps another back-end.
54
55
//!
55
56
//! ```
56
57
//! use rand::{Rng, thread_rng};
@@ -163,21 +164,18 @@ impl<X: SampleUniform> Uniform<X> {
163
164
/// Create a new `Uniform` instance which samples uniformly from the half
164
165
/// open range `[low, high)` (excluding `high`). Panics if `low >= high`.
165
166
pub fn new ( low : X , high : X ) -> Uniform < X > {
166
- assert ! ( low < high, "Uniform::new called with `low >= high`" ) ;
167
167
Uniform { inner : X :: Sampler :: new ( low, high) }
168
168
}
169
169
170
170
/// Create a new `Uniform` instance which samples uniformly from the closed
171
171
/// range `[low, high]` (inclusive). Panics if `low > high`.
172
172
pub fn new_inclusive ( low : X , high : X ) -> Uniform < X > {
173
- assert ! ( low <= high, "Uniform::new_inclusive called with `low > high`" ) ;
174
173
Uniform { inner : X :: Sampler :: new_inclusive ( low, high) }
175
174
}
176
175
177
176
/// Sample a single value uniformly from `[low, high)`.
178
177
/// Panics if `low >= high`.
179
178
pub fn sample_single < R : Rng + ?Sized > ( low : X , high : X , rng : & mut R ) -> X {
180
- assert ! ( low < high, "Uniform::sample_single called with low >= high" ) ;
181
179
X :: Sampler :: sample_single ( low, high, rng)
182
180
}
183
181
}
@@ -197,7 +195,7 @@ impl<X: SampleUniform> Distribution<X> for Uniform<X> {
197
195
/// [`UniformSampler`]: trait.UniformSampler.html
198
196
/// [module documentation]: index.html
199
197
/// [`Uniform`]: struct.Uniform.html
200
- pub trait SampleUniform : PartialOrd + Sized {
198
+ pub trait SampleUniform : Sized {
201
199
/// The `UniformSampler` implementation supporting type `X`.
202
200
type Sampler : UniformSampler < X = Self > ;
203
201
}
@@ -215,7 +213,7 @@ pub trait SampleUniform: PartialOrd+Sized {
215
213
/// [`sample_single`]: trait.UniformSampler.html#method.sample_single
216
214
pub trait UniformSampler : Sized {
217
215
/// The type sampled by this implementation.
218
- type X : PartialOrd ;
216
+ type X ;
219
217
220
218
/// Construct self, with inclusive lower bound and exclusive upper bound
221
219
/// `[low, high)`.
@@ -322,12 +320,16 @@ macro_rules! uniform_int_impl {
322
320
#[ inline] // if the range is constant, this helps LLVM to do the
323
321
// calculations at compile-time.
324
322
fn new( low: Self :: X , high: Self :: X ) -> Self {
323
+ assert!( low < high,
324
+ "Uniform::new_inclusive called with `low >= high`" ) ;
325
325
UniformSampler :: new_inclusive( low, high - 1 )
326
326
}
327
327
328
328
#[ inline] // if the range is constant, this helps LLVM to do the
329
329
// calculations at compile-time.
330
330
fn new_inclusive( low: Self :: X , high: Self :: X ) -> Self {
331
+ assert!( low <= high,
332
+ "Uniform::new_inclusive called with `low > high`" ) ;
331
333
let unsigned_max: $u_large = :: core:: $u_large:: MAX ;
332
334
333
335
let range = ( high as $u_large)
@@ -375,6 +377,8 @@ macro_rules! uniform_int_impl {
375
377
high: Self :: X ,
376
378
rng: & mut R ) -> Self :: X
377
379
{
380
+ assert!( low < high,
381
+ "Uniform::sample_single called with low >= high" ) ;
378
382
let range = ( high as $u_large)
379
383
. wrapping_sub( low as $u_large) ;
380
384
let zone =
@@ -551,6 +555,7 @@ macro_rules! uniform_float_impl {
551
555
type X = $ty;
552
556
553
557
fn new( low: Self :: X , high: Self :: X ) -> Self {
558
+ assert!( low < high, "Uniform::new called with `low >= high`" ) ;
554
559
let scale = high - low;
555
560
let offset = low - scale;
556
561
UniformFloat {
@@ -560,7 +565,13 @@ macro_rules! uniform_float_impl {
560
565
}
561
566
562
567
fn new_inclusive( low: Self :: X , high: Self :: X ) -> Self {
563
- UniformSampler :: new( low, high)
568
+ assert!( low <= high, "Uniform::new called with `low > high`" ) ;
569
+ let scale = high - low;
570
+ let offset = low - scale;
571
+ UniformFloat {
572
+ scale: scale,
573
+ offset: offset,
574
+ }
564
575
}
565
576
566
577
fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> Self :: X {
@@ -578,6 +589,8 @@ macro_rules! uniform_float_impl {
578
589
fn sample_single<R : Rng + ?Sized >( low: Self :: X ,
579
590
high: Self :: X ,
580
591
rng: & mut R ) -> Self :: X {
592
+ assert!( low < high,
593
+ "Uniform::sample_single called with low >= high" ) ;
581
594
let scale = high - low;
582
595
let offset = low - scale;
583
596
// Generate a value in the range [1, 2)
@@ -631,11 +644,13 @@ impl UniformSampler for UniformDuration {
631
644
632
645
#[ inline]
633
646
fn new ( low : Duration , high : Duration ) -> UniformDuration {
647
+ assert ! ( low < high, "Uniform::new called with `low >= high`" ) ;
634
648
UniformDuration :: new_inclusive ( low, high - Duration :: new ( 0 , 1 ) )
635
649
}
636
650
637
651
#[ inline]
638
652
fn new_inclusive ( low : Duration , high : Duration ) -> UniformDuration {
653
+ assert ! ( low <= high, "Uniform::new called with `low > high`" ) ;
639
654
let size = high - low;
640
655
let nanos = size
641
656
. as_secs ( )
0 commit comments