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 {
96
109
//! [`UniformInt`]: struct.UniformInt.html
97
110
//! [`UniformFloat`]: struct.UniformFloat.html
98
111
//! [`UniformDuration`]: struct.UniformDuration.html
112
+ //! [`Borrow::borrow`]: https://doc.rust-lang.org/std/borrow/trait.Borrow.html
99
113
100
114
#[ cfg( feature = "std" ) ]
101
115
use std:: time:: Duration ;
116
+ use core:: borrow:: Borrow ;
102
117
103
118
use Rng ;
104
119
use distributions:: Distribution ;
@@ -155,13 +170,19 @@ pub struct Uniform<X: SampleUniform> {
155
170
impl < X : SampleUniform > Uniform < X > {
156
171
/// Create a new `Uniform` instance which samples uniformly from the half
157
172
/// open range `[low, high)` (excluding `high`). Panics if `low >= high`.
158
- pub fn new ( low : X , high : X ) -> Uniform < X > {
173
+ pub fn new < B1 , B2 > ( low : B1 , high : B2 ) -> Uniform < X >
174
+ where B1 : Borrow < X > + Sized ,
175
+ B2 : Borrow < X > + Sized
176
+ {
159
177
Uniform { inner : X :: Sampler :: new ( low, high) }
160
178
}
161
179
162
180
/// Create a new `Uniform` instance which samples uniformly from the closed
163
181
/// range `[low, high]` (inclusive). Panics if `low > high`.
164
- pub fn new_inclusive ( low : X , high : X ) -> Uniform < X > {
182
+ pub fn new_inclusive < B1 , B2 > ( low : B1 , high : B2 ) -> Uniform < X >
183
+ where B1 : Borrow < X > + Sized ,
184
+ B2 : Borrow < X > + Sized
185
+ {
165
186
Uniform { inner : X :: Sampler :: new_inclusive ( low, high) }
166
187
}
167
188
}
@@ -206,14 +227,18 @@ pub trait UniformSampler: Sized {
206
227
///
207
228
/// Usually users should not call this directly but instead use
208
229
/// `Uniform::new`, which asserts that `low < high` before calling this.
209
- fn new ( low : Self :: X , high : Self :: X ) -> Self ;
230
+ fn new < B1 , B2 > ( low : B1 , high : B2 ) -> Self
231
+ where B1 : Borrow < Self :: X > + Sized ,
232
+ B2 : Borrow < Self :: X > + Sized ;
210
233
211
234
/// Construct self, with inclusive bounds `[low, high]`.
212
235
///
213
236
/// Usually users should not call this directly but instead use
214
237
/// `Uniform::new_inclusive`, which asserts that `low <= high` before
215
238
/// calling this.
216
- fn new_inclusive ( low : Self :: X , high : Self :: X ) -> Self ;
239
+ fn new_inclusive < B1 , B2 > ( low : B1 , high : B2 ) -> Self
240
+ where B1 : Borrow < Self :: X > + Sized ,
241
+ B2 : Borrow < Self :: X > + Sized ;
217
242
218
243
/// Sample a value.
219
244
fn sample < R : Rng + ?Sized > ( & self , rng : & mut R ) -> Self :: X ;
@@ -229,8 +254,10 @@ pub trait UniformSampler: Sized {
229
254
/// sampling only a single value from the specified range. The default
230
255
/// implementation simply calls `UniformSampler::new` then `sample` on the
231
256
/// result.
232
- fn sample_single < R : Rng + ?Sized > ( low : Self :: X , high : Self :: X , rng : & mut R )
257
+ fn sample_single < R : Rng + ?Sized , B1 , B2 > ( low : B1 , high : B2 , rng : & mut R )
233
258
-> Self :: X
259
+ where B1 : Borrow < Self :: X > + Sized ,
260
+ B2 : Borrow < Self :: X > + Sized
234
261
{
235
262
let uniform: Self = UniformSampler :: new ( low, high) ;
236
263
uniform. sample ( rng)
@@ -311,14 +338,24 @@ macro_rules! uniform_int_impl {
311
338
312
339
#[ inline] // if the range is constant, this helps LLVM to do the
313
340
// calculations at compile-time.
314
- fn new( low: Self :: X , high: Self :: X ) -> Self {
341
+ fn new<B1 , B2 >( low_b: B1 , high_b: B2 ) -> Self
342
+ where B1 : Borrow <Self :: X > + Sized ,
343
+ B2 : Borrow <Self :: X > + Sized
344
+ {
345
+ let low = * low_b. borrow( ) ;
346
+ let high = * high_b. borrow( ) ;
315
347
assert!( low < high, "Uniform::new called with `low >= high`" ) ;
316
348
UniformSampler :: new_inclusive( low, high - 1 )
317
349
}
318
350
319
351
#[ inline] // if the range is constant, this helps LLVM to do the
320
352
// calculations at compile-time.
321
- fn new_inclusive( low: Self :: X , high: Self :: X ) -> Self {
353
+ fn new_inclusive<B1 , B2 >( low_b: B1 , high_b: B2 ) -> Self
354
+ where B1 : Borrow <Self :: X > + Sized ,
355
+ B2 : Borrow <Self :: X > + Sized
356
+ {
357
+ let low = * low_b. borrow( ) ;
358
+ let high = * high_b. borrow( ) ;
322
359
assert!( low <= high,
323
360
"Uniform::new_inclusive called with `low > high`" ) ;
324
361
let unsigned_max = :: core:: $unsigned:: MAX ;
@@ -362,10 +399,13 @@ macro_rules! uniform_int_impl {
362
399
}
363
400
}
364
401
365
- fn sample_single<R : Rng + ?Sized >( low: Self :: X ,
366
- high: Self :: X ,
367
- rng: & mut R ) -> Self :: X
402
+ fn sample_single<R : Rng + ?Sized , B1 , B2 >( low_b: B1 , high_b: B2 , rng: & mut R )
403
+ -> Self :: X
404
+ where B1 : Borrow <Self :: X > + Sized ,
405
+ B2 : Borrow <Self :: X > + Sized
368
406
{
407
+ let low = * low_b. borrow( ) ;
408
+ let high = * high_b. borrow( ) ;
369
409
assert!( low < high,
370
410
"Uniform::sample_single called with low >= high" ) ;
371
411
let range = high. wrapping_sub( low) as $unsigned as $u_large;
@@ -532,7 +572,12 @@ macro_rules! uniform_float_impl {
532
572
impl UniformSampler for UniformFloat <$ty> {
533
573
type X = $ty;
534
574
535
- fn new( low: Self :: X , high: Self :: X ) -> Self {
575
+ fn new<B1 , B2 >( low_b: B1 , high_b: B2 ) -> Self
576
+ where B1 : Borrow <Self :: X > + Sized ,
577
+ B2 : Borrow <Self :: X > + Sized
578
+ {
579
+ let low = * low_b. borrow( ) ;
580
+ let high = * high_b. borrow( ) ;
536
581
assert!( low < high, "Uniform::new called with `low >= high`" ) ;
537
582
let scale = high - low;
538
583
let offset = low - scale;
@@ -542,7 +587,12 @@ macro_rules! uniform_float_impl {
542
587
}
543
588
}
544
589
545
- fn new_inclusive( low: Self :: X , high: Self :: X ) -> Self {
590
+ fn new_inclusive<B1 , B2 >( low_b: B1 , high_b: B2 ) -> Self
591
+ where B1 : Borrow <Self :: X > + Sized ,
592
+ B2 : Borrow <Self :: X > + Sized
593
+ {
594
+ let low = * low_b. borrow( ) ;
595
+ let high = * high_b. borrow( ) ;
546
596
assert!( low <= high,
547
597
"Uniform::new_inclusive called with `low > high`" ) ;
548
598
let scale = high - low;
@@ -565,9 +615,13 @@ macro_rules! uniform_float_impl {
565
615
value1_2 * self . scale + self . offset
566
616
}
567
617
568
- fn sample_single<R : Rng + ?Sized >( low: Self :: X ,
569
- high: Self :: X ,
570
- rng: & mut R ) -> Self :: X {
618
+ fn sample_single<R : Rng + ?Sized , B1 , B2 >( low_b: B1 , high_b: B2 , rng: & mut R )
619
+ -> Self :: X
620
+ where B1 : Borrow <Self :: X > + Sized ,
621
+ B2 : Borrow <Self :: X > + Sized
622
+ {
623
+ let low = * low_b. borrow( ) ;
624
+ let high = * high_b. borrow( ) ;
571
625
assert!( low < high,
572
626
"Uniform::sample_single called with low >= high" ) ;
573
627
let scale = high - low;
@@ -624,13 +678,23 @@ impl UniformSampler for UniformDuration {
624
678
type X = Duration ;
625
679
626
680
#[ inline]
627
- fn new ( low : Duration , high : Duration ) -> UniformDuration {
681
+ fn new < B1 , B2 > ( low_b : B1 , high_b : B2 ) -> Self
682
+ where B1 : Borrow < Self :: X > + Sized ,
683
+ B2 : Borrow < Self :: X > + Sized
684
+ {
685
+ let low = * low_b. borrow ( ) ;
686
+ let high = * high_b. borrow ( ) ;
628
687
assert ! ( low < high, "Uniform::new called with `low >= high`" ) ;
629
688
UniformDuration :: new_inclusive ( low, high - Duration :: new ( 0 , 1 ) )
630
689
}
631
690
632
691
#[ inline]
633
- fn new_inclusive ( low : Duration , high : Duration ) -> UniformDuration {
692
+ fn new_inclusive < B1 , B2 > ( low_b : B1 , high_b : B2 ) -> Self
693
+ where B1 : Borrow < Self :: X > + Sized ,
694
+ B2 : Borrow < Self :: X > + Sized
695
+ {
696
+ let low = * low_b. borrow ( ) ;
697
+ let high = * high_b. borrow ( ) ;
634
698
assert ! ( low <= high, "Uniform::new_inclusive called with `low > high`" ) ;
635
699
let size = high - low;
636
700
let nanos = size
@@ -750,6 +814,18 @@ mod tests {
750
814
assert!( low <= v && v <= high) ;
751
815
}
752
816
817
+ let my_uniform = Uniform :: new( & low, high) ;
818
+ for _ in 0 ..1000 {
819
+ let v: $ty = rng. sample( my_uniform) ;
820
+ assert!( low <= v && v < high) ;
821
+ }
822
+
823
+ let my_uniform = Uniform :: new_inclusive( & low, & high) ;
824
+ for _ in 0 ..1000 {
825
+ let v: $ty = rng. sample( my_uniform) ;
826
+ assert!( low <= v && v <= high) ;
827
+ }
828
+
753
829
for _ in 0 ..1000 {
754
830
let v: $ty = rng. gen_range( low, high) ;
755
831
assert!( low <= v && v < high) ;
@@ -809,6 +885,7 @@ mod tests {
809
885
810
886
#[ test]
811
887
fn test_custom_uniform ( ) {
888
+ use core:: borrow:: Borrow ;
812
889
#[ derive( Clone , Copy , PartialEq , PartialOrd ) ]
813
890
struct MyF32 {
814
891
x : f32 ,
@@ -819,12 +896,18 @@ mod tests {
819
896
}
820
897
impl UniformSampler for UniformMyF32 {
821
898
type X = MyF32 ;
822
- fn new ( low : Self :: X , high : Self :: X ) -> Self {
899
+ fn new < B1 , B2 > ( low : B1 , high : B2 ) -> Self
900
+ where B1 : Borrow < Self :: X > + Sized ,
901
+ B2 : Borrow < Self :: X > + Sized
902
+ {
823
903
UniformMyF32 {
824
- inner : UniformFloat :: < f32 > :: new ( low. x , high. x ) ,
904
+ inner : UniformFloat :: < f32 > :: new ( low. borrow ( ) . x , high. borrow ( ) . x ) ,
825
905
}
826
906
}
827
- fn new_inclusive ( low : Self :: X , high : Self :: X ) -> Self {
907
+ fn new_inclusive < B1 , B2 > ( low : B1 , high : B2 ) -> Self
908
+ where B1 : Borrow < Self :: X > + Sized ,
909
+ B2 : Borrow < Self :: X > + Sized
910
+ {
828
911
UniformSampler :: new ( low, high)
829
912
}
830
913
fn sample < R : Rng + ?Sized > ( & self , rng : & mut R ) -> Self :: X {
0 commit comments