@@ -14,6 +14,60 @@ use core::mem;
1414use Rng ;
1515use distributions:: { Distribution , Standard } ;
1616
17+ /// A distribution to sample floating point numbers uniformly in the half-open
18+ /// interval `(0, 1]`, i.e. including 1 but not 0.
19+ ///
20+ /// All values that can be generated are of the form `n * ε/2`. For `f32`
21+ /// the 23 most significant random bits of a `u32` are used and for `f64` the
22+ /// 53 most significant bits of a `u64` are used. The conversion uses the
23+ /// multiplicative method.
24+ ///
25+ /// See also: [`Standard`] which samples from `[0, 1)`, [`Open01`]
26+ /// which samples from `(0, 1)` and [`Uniform`] which samples from arbitrary
27+ /// ranges.
28+ ///
29+ /// # Example
30+ /// ```rust
31+ /// use rand::{thread_rng, Rng};
32+ /// use rand::distributions::OpenClosed01;
33+ ///
34+ /// let val: f32 = thread_rng().sample(OpenClosed01);
35+ /// println!("f32 from (0, 1): {}", val);
36+ /// ```
37+ ///
38+ /// [`Standard`]: struct.Standard.html
39+ /// [`Open01`]: struct.Open01.html
40+ /// [`Uniform`]: uniform/struct.Uniform.html
41+ #[ derive( Clone , Copy , Debug ) ]
42+ pub struct OpenClosed01 ;
43+
44+ /// A distribution to sample floating point numbers uniformly in the open
45+ /// interval `(0, 1)`, i.e. not including either endpoint.
46+ ///
47+ /// All values that can be generated are of the form `n * ε + ε/2`. For `f32`
48+ /// the 22 most significant random bits of an `u32` are used, for `f64` 52 from
49+ /// an `u64`. The conversion uses a transmute-based method.
50+ ///
51+ /// See also: [`Standard`] which samples from `[0, 1)`, [`OpenClosed01`]
52+ /// which samples from `(0, 1]` and [`Uniform`] which samples from arbitrary
53+ /// ranges.
54+ ///
55+ /// # Example
56+ /// ```rust
57+ /// use rand::{thread_rng, Rng};
58+ /// use rand::distributions::Open01;
59+ ///
60+ /// let val: f32 = thread_rng().sample(Open01);
61+ /// println!("f32 from (0, 1): {}", val);
62+ /// ```
63+ ///
64+ /// [`Standard`]: struct.Standard.html
65+ /// [`OpenClosed01`]: struct.OpenClosed01.html
66+ /// [`Uniform`]: uniform/struct.Uniform.html
67+ #[ derive( Clone , Copy , Debug ) ]
68+ pub struct Open01 ;
69+
70+
1771pub ( crate ) trait IntoFloat {
1872 type F ;
1973
@@ -29,8 +83,7 @@ pub(crate) trait IntoFloat {
2983}
3084
3185macro_rules! float_impls {
32- ( $ty: ty, $uty: ty, $fraction_bits: expr, $exponent_bias: expr,
33- $next_u: ident) => {
86+ ( $ty: ty, $uty: ty, $fraction_bits: expr, $exponent_bias: expr) => {
3487 impl IntoFloat for $uty {
3588 type F = $ty;
3689 #[ inline( always) ]
@@ -43,47 +96,111 @@ macro_rules! float_impls {
4396 }
4497
4598 impl Distribution <$ty> for Standard {
46- /// Generate a floating point number in the open interval `(0, 1)`
47- /// (not including either endpoint) with a uniform distribution.
4899 fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> $ty {
100+ // Multiply-based method; 24/53 random bits; [0, 1) interval.
101+ // We use the most significant bits because for simple RNGs
102+ // those are usually more random.
103+ let float_size = mem:: size_of:: <$ty>( ) * 8 ;
104+ let precision = $fraction_bits + 1 ;
105+ let scale = 1.0 / ( ( 1 as $uty << precision) as $ty) ;
106+
107+ let value: $uty = rng. gen ( ) ;
108+ scale * ( value >> ( float_size - precision) ) as $ty
109+ }
110+ }
111+
112+ impl Distribution <$ty> for OpenClosed01 {
113+ fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> $ty {
114+ // Multiply-based method; 24/53 random bits; (0, 1] interval.
115+ // We use the most significant bits because for simple RNGs
116+ // those are usually more random.
117+ let float_size = mem:: size_of:: <$ty>( ) * 8 ;
118+ let precision = $fraction_bits + 1 ;
119+ let scale = 1.0 / ( ( 1 as $uty << precision) as $ty) ;
120+
121+ let value: $uty = rng. gen ( ) ;
122+ let value = value >> ( float_size - precision) ;
123+ // Add 1 to shift up; will not overflow because of right-shift:
124+ scale * ( value + 1 ) as $ty
125+ }
126+ }
127+
128+ impl Distribution <$ty> for Open01 {
129+ fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> $ty {
130+ // Transmute-based method; 23/52 random bits; (0, 1) interval.
131+ // We use the most significant bits because for simple RNGs
132+ // those are usually more random.
49133 const EPSILON : $ty = 1.0 / ( 1u64 << $fraction_bits) as $ty;
50134 let float_size = mem:: size_of:: <$ty>( ) * 8 ;
51135
52- let value = rng. $next_u ( ) ;
136+ let value: $uty = rng. gen ( ) ;
53137 let fraction = value >> ( float_size - $fraction_bits) ;
54138 fraction. into_float_with_exponent( 0 ) - ( 1.0 - EPSILON / 2.0 )
55139 }
56140 }
57141 }
58142}
59- float_impls ! { f32 , u32 , 23 , 127 , next_u32 }
60- float_impls ! { f64 , u64 , 52 , 1023 , next_u64 }
143+ float_impls ! { f32 , u32 , 23 , 127 }
144+ float_impls ! { f64 , u64 , 52 , 1023 }
61145
62146
63147#[ cfg( test) ]
64148mod tests {
65149 use Rng ;
150+ use distributions:: { Open01 , OpenClosed01 } ;
66151 use mock:: StepRng ;
67152
68153 const EPSILON32 : f32 = :: core:: f32:: EPSILON ;
69154 const EPSILON64 : f64 = :: core:: f64:: EPSILON ;
70155
71156 #[ test]
72- fn floating_point_edge_cases ( ) {
157+ fn standard_fp_edge_cases ( ) {
73158 let mut zeros = StepRng :: new ( 0 , 0 ) ;
74- assert_eq ! ( zeros. gen :: <f32 >( ) , 0.0 + EPSILON32 / 2.0 ) ;
75- assert_eq ! ( zeros. gen :: <f64 >( ) , 0.0 + EPSILON64 / 2.0 ) ;
159+ assert_eq ! ( zeros. gen :: <f32 >( ) , 0.0 ) ;
160+ assert_eq ! ( zeros. gen :: <f64 >( ) , 0.0 ) ;
76161
77- let mut one = StepRng :: new ( 1 << 9 , 0 ) ;
78- let one32 = one. gen :: < f32 > ( ) ;
79- assert ! ( EPSILON32 < one32 && one32 < EPSILON32 * 2.0 ) ;
162+ let mut one32 = StepRng :: new ( 1 << 8 , 0 ) ;
163+ assert_eq ! ( one32. gen :: <f32 >( ) , EPSILON32 / 2.0 ) ;
80164
81- let mut one = StepRng :: new ( 1 << 12 , 0 ) ;
82- let one64 = one. gen :: < f64 > ( ) ;
83- assert ! ( EPSILON64 < one64 && one64 < EPSILON64 * 2.0 ) ;
165+ let mut one64 = StepRng :: new ( 1 << 11 , 0 ) ;
166+ assert_eq ! ( one64. gen :: <f64 >( ) , EPSILON64 / 2.0 ) ;
84167
85168 let mut max = StepRng :: new ( !0 , 0 ) ;
86169 assert_eq ! ( max. gen :: <f32 >( ) , 1.0 - EPSILON32 / 2.0 ) ;
87170 assert_eq ! ( max. gen :: <f64 >( ) , 1.0 - EPSILON64 / 2.0 ) ;
88171 }
172+
173+ #[ test]
174+ fn openclosed01_edge_cases ( ) {
175+ let mut zeros = StepRng :: new ( 0 , 0 ) ;
176+ assert_eq ! ( zeros. sample:: <f32 , _>( OpenClosed01 ) , 0.0 + EPSILON32 / 2.0 ) ;
177+ assert_eq ! ( zeros. sample:: <f64 , _>( OpenClosed01 ) , 0.0 + EPSILON64 / 2.0 ) ;
178+
179+ let mut one32 = StepRng :: new ( 1 << 8 , 0 ) ;
180+ assert_eq ! ( one32. sample:: <f32 , _>( OpenClosed01 ) , EPSILON32 ) ;
181+
182+ let mut one64 = StepRng :: new ( 1 << 11 , 0 ) ;
183+ assert_eq ! ( one64. sample:: <f64 , _>( OpenClosed01 ) , EPSILON64 ) ;
184+
185+ let mut max = StepRng :: new ( !0 , 0 ) ;
186+ assert_eq ! ( max. sample:: <f32 , _>( OpenClosed01 ) , 1.0 ) ;
187+ assert_eq ! ( max. sample:: <f64 , _>( OpenClosed01 ) , 1.0 ) ;
188+ }
189+
190+ #[ test]
191+ fn open01_edge_cases ( ) {
192+ let mut zeros = StepRng :: new ( 0 , 0 ) ;
193+ assert_eq ! ( zeros. sample:: <f32 , _>( Open01 ) , 0.0 + EPSILON32 / 2.0 ) ;
194+ assert_eq ! ( zeros. sample:: <f64 , _>( Open01 ) , 0.0 + EPSILON64 / 2.0 ) ;
195+
196+ let mut one32 = StepRng :: new ( 1 << 9 , 0 ) ;
197+ assert_eq ! ( one32. sample:: <f32 , _>( Open01 ) , EPSILON32 / 2.0 * 3.0 ) ;
198+
199+ let mut one64 = StepRng :: new ( 1 << 12 , 0 ) ;
200+ assert_eq ! ( one64. sample:: <f64 , _>( Open01 ) , EPSILON64 / 2.0 * 3.0 ) ;
201+
202+ let mut max = StepRng :: new ( !0 , 0 ) ;
203+ assert_eq ! ( max. sample:: <f32 , _>( Open01 ) , 1.0 - EPSILON32 / 2.0 ) ;
204+ assert_eq ! ( max. sample:: <f64 , _>( Open01 ) , 1.0 - EPSILON64 / 2.0 ) ;
205+ }
89206}
0 commit comments