53
53
//! Those methods should include an assert to check the range is valid (i.e.
54
54
//! `low < high`). The example below merely wraps another back-end.
55
55
//!
56
+ //! The `new`, `new_inclusive` and `sample_single` functions use arguments of
57
+ //! type Borrow<X> in order to support passing in values by reference or by
58
+ //! value. In the implementation of these functions, you can choose to simply
59
+ //! use the reference returned by `Borrow::borrow`, or you can choose to copy
60
+ //! or clone the value, whatever is appropriate for your type.
61
+ //!
56
62
//! ```
57
63
//! use rand::prelude::*;
58
64
//! use rand::distributions::uniform::{Uniform, SampleUniform,
59
65
//! UniformSampler, UniformFloat};
66
+ //! use std::borrow::Borrow;
60
67
//!
61
68
//! struct MyF32(f32);
62
69
//!
67
74
//!
68
75
//! impl UniformSampler for UniformMyF32 {
69
76
//! type X = MyF32;
70
- //! fn new(low: Self::X, high: Self::X) -> Self {
77
+ //! fn new<B1, B2>(low: B1, high: B2) -> Self
78
+ //! where B1: Borrow<Self::X> + Sized,
79
+ //! B2: Borrow<Self::X> + Sized
80
+ //! {
71
81
//! UniformMyF32 {
72
- //! inner: UniformFloat::<f32>::new(low.0, high.0),
82
+ //! inner: UniformFloat::<f32>::new(low.borrow(). 0, high.borrow() .0),
73
83
//! }
74
84
//! }
75
- //! fn new_inclusive(low: Self::X, high: Self::X) -> Self {
85
+ //! fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
86
+ //! where B1: Borrow<Self::X> + Sized,
87
+ //! B2: Borrow<Self::X> + Sized
88
+ //! {
76
89
//! UniformSampler::new(low, high)
77
90
//! }
78
91
//! fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
99
112
100
113
#[ cfg( feature = "std" ) ]
101
114
use std:: time:: Duration ;
115
+ use core:: borrow:: Borrow ;
102
116
103
117
use Rng ;
104
118
use distributions:: Distribution ;
@@ -155,13 +169,19 @@ pub struct Uniform<X: SampleUniform> {
155
169
impl < X : SampleUniform > Uniform < X > {
156
170
/// Create a new `Uniform` instance which samples uniformly from the half
157
171
/// open range `[low, high)` (excluding `high`). Panics if `low >= high`.
158
- pub fn new ( low : X , high : X ) -> Uniform < X > {
172
+ pub fn new < B1 , B2 > ( low : B1 , high : B2 ) -> Uniform < X >
173
+ where B1 : Borrow < X > + Sized ,
174
+ B2 : Borrow < X > + Sized
175
+ {
159
176
Uniform { inner : X :: Sampler :: new ( low, high) }
160
177
}
161
178
162
179
/// Create a new `Uniform` instance which samples uniformly from the closed
163
180
/// range `[low, high]` (inclusive). Panics if `low > high`.
164
- pub fn new_inclusive ( low : X , high : X ) -> Uniform < X > {
181
+ pub fn new_inclusive < B1 , B2 > ( low : B1 , high : B2 ) -> Uniform < X >
182
+ where B1 : Borrow < X > + Sized ,
183
+ B2 : Borrow < X > + Sized
184
+ {
165
185
Uniform { inner : X :: Sampler :: new_inclusive ( low, high) }
166
186
}
167
187
}
@@ -206,14 +226,18 @@ pub trait UniformSampler: Sized {
206
226
///
207
227
/// Usually users should not call this directly but instead use
208
228
/// `Uniform::new`, which asserts that `low < high` before calling this.
209
- fn new ( low : Self :: X , high : Self :: X ) -> Self ;
229
+ fn new < B1 , B2 > ( low : B1 , high : B2 ) -> Self
230
+ where B1 : Borrow < Self :: X > + Sized ,
231
+ B2 : Borrow < Self :: X > + Sized ;
210
232
211
233
/// Construct self, with inclusive bounds `[low, high]`.
212
234
///
213
235
/// Usually users should not call this directly but instead use
214
236
/// `Uniform::new_inclusive`, which asserts that `low <= high` before
215
237
/// calling this.
216
- fn new_inclusive ( low : Self :: X , high : Self :: X ) -> Self ;
238
+ fn new_inclusive < B1 , B2 > ( low : B1 , high : B2 ) -> Self
239
+ where B1 : Borrow < Self :: X > + Sized ,
240
+ B2 : Borrow < Self :: X > + Sized ;
217
241
218
242
/// Sample a value.
219
243
fn sample < R : Rng + ?Sized > ( & self , rng : & mut R ) -> Self :: X ;
@@ -229,8 +253,10 @@ pub trait UniformSampler: Sized {
229
253
/// sampling only a single value from the specified range. The default
230
254
/// implementation simply calls `UniformSampler::new` then `sample` on the
231
255
/// result.
232
- fn sample_single < R : Rng + ?Sized > ( low : Self :: X , high : Self :: X , rng : & mut R )
256
+ fn sample_single < R : Rng + ?Sized , B1 , B2 > ( low : B1 , high : B2 , rng : & mut R )
233
257
-> Self :: X
258
+ where B1 : Borrow < Self :: X > + Sized ,
259
+ B2 : Borrow < Self :: X > + Sized
234
260
{
235
261
let uniform: Self = UniformSampler :: new ( low, high) ;
236
262
uniform. sample ( rng)
@@ -311,14 +337,24 @@ macro_rules! uniform_int_impl {
311
337
312
338
#[ inline] // if the range is constant, this helps LLVM to do the
313
339
// calculations at compile-time.
314
- fn new( low: Self :: X , high: Self :: X ) -> Self {
340
+ fn new<B1 , B2 >( low_b: B1 , high_b: B2 ) -> Self
341
+ where B1 : Borrow <Self :: X > + Sized ,
342
+ B2 : Borrow <Self :: X > + Sized
343
+ {
344
+ let low = * low_b. borrow( ) ;
345
+ let high = * high_b. borrow( ) ;
315
346
assert!( low < high, "Uniform::new called with `low >= high`" ) ;
316
347
UniformSampler :: new_inclusive( low, high - 1 )
317
348
}
318
349
319
350
#[ inline] // if the range is constant, this helps LLVM to do the
320
351
// calculations at compile-time.
321
- fn new_inclusive( low: Self :: X , high: Self :: X ) -> Self {
352
+ fn new_inclusive<B1 , B2 >( low_b: B1 , high_b: B2 ) -> Self
353
+ where B1 : Borrow <Self :: X > + Sized ,
354
+ B2 : Borrow <Self :: X > + Sized
355
+ {
356
+ let low = * low_b. borrow( ) ;
357
+ let high = * high_b. borrow( ) ;
322
358
assert!( low <= high,
323
359
"Uniform::new_inclusive called with `low > high`" ) ;
324
360
let unsigned_max = :: core:: $unsigned:: MAX ;
@@ -362,10 +398,13 @@ macro_rules! uniform_int_impl {
362
398
}
363
399
}
364
400
365
- fn sample_single<R : Rng + ?Sized >( low: Self :: X ,
366
- high: Self :: X ,
367
- rng: & mut R ) -> Self :: X
401
+ fn sample_single<R : Rng + ?Sized , B1 , B2 >( low_b: B1 , high_b: B2 , rng: & mut R )
402
+ -> Self :: X
403
+ where B1 : Borrow <Self :: X > + Sized ,
404
+ B2 : Borrow <Self :: X > + Sized
368
405
{
406
+ let low = * low_b. borrow( ) ;
407
+ let high = * high_b. borrow( ) ;
369
408
assert!( low < high,
370
409
"Uniform::sample_single called with low >= high" ) ;
371
410
let range = high. wrapping_sub( low) as $unsigned as $u_large;
@@ -532,7 +571,12 @@ macro_rules! uniform_float_impl {
532
571
impl UniformSampler for UniformFloat <$ty> {
533
572
type X = $ty;
534
573
535
- fn new( low: Self :: X , high: Self :: X ) -> Self {
574
+ fn new<B1 , B2 >( low_b: B1 , high_b: B2 ) -> Self
575
+ where B1 : Borrow <Self :: X > + Sized ,
576
+ B2 : Borrow <Self :: X > + Sized
577
+ {
578
+ let low = * low_b. borrow( ) ;
579
+ let high = * high_b. borrow( ) ;
536
580
assert!( low < high, "Uniform::new called with `low >= high`" ) ;
537
581
let scale = high - low;
538
582
let offset = low - scale;
@@ -542,7 +586,12 @@ macro_rules! uniform_float_impl {
542
586
}
543
587
}
544
588
545
- fn new_inclusive( low: Self :: X , high: Self :: X ) -> Self {
589
+ fn new_inclusive<B1 , B2 >( low_b: B1 , high_b: B2 ) -> Self
590
+ where B1 : Borrow <Self :: X > + Sized ,
591
+ B2 : Borrow <Self :: X > + Sized
592
+ {
593
+ let low = * low_b. borrow( ) ;
594
+ let high = * high_b. borrow( ) ;
546
595
assert!( low <= high,
547
596
"Uniform::new_inclusive called with `low > high`" ) ;
548
597
let scale = high - low;
@@ -565,9 +614,13 @@ macro_rules! uniform_float_impl {
565
614
value1_2 * self . scale + self . offset
566
615
}
567
616
568
- fn sample_single<R : Rng + ?Sized >( low: Self :: X ,
569
- high: Self :: X ,
570
- rng: & mut R ) -> Self :: X {
617
+ fn sample_single<R : Rng + ?Sized , B1 , B2 >( low_b: B1 , high_b: B2 , rng: & mut R )
618
+ -> Self :: X
619
+ where B1 : Borrow <Self :: X > + Sized ,
620
+ B2 : Borrow <Self :: X > + Sized
621
+ {
622
+ let low = * low_b. borrow( ) ;
623
+ let high = * high_b. borrow( ) ;
571
624
assert!( low < high,
572
625
"Uniform::sample_single called with low >= high" ) ;
573
626
let scale = high - low;
@@ -624,13 +677,23 @@ impl UniformSampler for UniformDuration {
624
677
type X = Duration ;
625
678
626
679
#[ inline]
627
- fn new ( low : Duration , high : Duration ) -> UniformDuration {
680
+ fn new < B1 , B2 > ( low_b : B1 , high_b : B2 ) -> Self
681
+ where B1 : Borrow < Self :: X > + Sized ,
682
+ B2 : Borrow < Self :: X > + Sized
683
+ {
684
+ let low = * low_b. borrow ( ) ;
685
+ let high = * high_b. borrow ( ) ;
628
686
assert ! ( low < high, "Uniform::new called with `low >= high`" ) ;
629
687
UniformDuration :: new_inclusive ( low, high - Duration :: new ( 0 , 1 ) )
630
688
}
631
689
632
690
#[ inline]
633
- fn new_inclusive ( low : Duration , high : Duration ) -> UniformDuration {
691
+ fn new_inclusive < B1 , B2 > ( low_b : B1 , high_b : B2 ) -> Self
692
+ where B1 : Borrow < Self :: X > + Sized ,
693
+ B2 : Borrow < Self :: X > + Sized
694
+ {
695
+ let low = * low_b. borrow ( ) ;
696
+ let high = * high_b. borrow ( ) ;
634
697
assert ! ( low <= high, "Uniform::new_inclusive called with `low > high`" ) ;
635
698
let size = high - low;
636
699
let nanos = size
@@ -750,6 +813,18 @@ mod tests {
750
813
assert!( low <= v && v <= high) ;
751
814
}
752
815
816
+ let my_uniform = Uniform :: new( & low, high) ;
817
+ for _ in 0 ..1000 {
818
+ let v: $ty = rng. sample( my_uniform) ;
819
+ assert!( low <= v && v < high) ;
820
+ }
821
+
822
+ let my_uniform = Uniform :: new_inclusive( & low, & high) ;
823
+ for _ in 0 ..1000 {
824
+ let v: $ty = rng. sample( my_uniform) ;
825
+ assert!( low <= v && v <= high) ;
826
+ }
827
+
753
828
for _ in 0 ..1000 {
754
829
let v: $ty = rng. gen_range( low, high) ;
755
830
assert!( low <= v && v < high) ;
@@ -809,6 +884,7 @@ mod tests {
809
884
810
885
#[ test]
811
886
fn test_custom_uniform ( ) {
887
+ use core:: borrow:: Borrow ;
812
888
#[ derive( Clone , Copy , PartialEq , PartialOrd ) ]
813
889
struct MyF32 {
814
890
x : f32 ,
@@ -819,12 +895,18 @@ mod tests {
819
895
}
820
896
impl UniformSampler for UniformMyF32 {
821
897
type X = MyF32 ;
822
- fn new ( low : Self :: X , high : Self :: X ) -> Self {
898
+ fn new < B1 , B2 > ( low : B1 , high : B2 ) -> Self
899
+ where B1 : Borrow < Self :: X > + Sized ,
900
+ B2 : Borrow < Self :: X > + Sized
901
+ {
823
902
UniformMyF32 {
824
- inner : UniformFloat :: < f32 > :: new ( low. x , high. x ) ,
903
+ inner : UniformFloat :: < f32 > :: new ( low. borrow ( ) . x , high. borrow ( ) . x ) ,
825
904
}
826
905
}
827
- fn new_inclusive ( low : Self :: X , high : Self :: X ) -> Self {
906
+ fn new_inclusive < B1 , B2 > ( low : B1 , high : B2 ) -> Self
907
+ where B1 : Borrow < Self :: X > + Sized ,
908
+ B2 : Borrow < Self :: X > + Sized
909
+ {
828
910
UniformSampler :: new ( low, high)
829
911
}
830
912
fn sample < R : Rng + ?Sized > ( & self , rng : & mut R ) -> Self :: X {
0 commit comments