13
13
use core:: mem;
14
14
use Rng ;
15
15
use distributions:: { Distribution , Standard } ;
16
+ use distributions:: math_helpers:: CastFromInt ;
16
17
#[ cfg( feature="simd_support" ) ]
17
18
use core:: simd:: * ;
18
19
@@ -84,71 +85,9 @@ pub(crate) trait IntoFloat {
84
85
fn into_float_with_exponent ( self , exponent : i32 ) -> Self :: F ;
85
86
}
86
87
87
- macro_rules! float_impls {
88
- ( $ty: ty, $uty: ty, $fraction_bits: expr, $exponent_bias: expr) => {
89
- impl IntoFloat for $uty {
90
- type F = $ty;
91
- #[ inline( always) ]
92
- fn into_float_with_exponent( self , exponent: i32 ) -> $ty {
93
- // The exponent is encoded using an offset-binary representation
94
- let exponent_bits =
95
- ( ( $exponent_bias + exponent) as $uty) << $fraction_bits;
96
- unsafe { mem:: transmute( self | exponent_bits) }
97
- }
98
- }
99
-
100
- impl Distribution <$ty> for Standard {
101
- fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> $ty {
102
- // Multiply-based method; 24/53 random bits; [0, 1) interval.
103
- // We use the most significant bits because for simple RNGs
104
- // those are usually more random.
105
- let float_size = mem:: size_of:: <$ty>( ) * 8 ;
106
- let precision = $fraction_bits + 1 ;
107
- let scale = 1.0 / ( ( 1 as $uty << precision) as $ty) ;
108
-
109
- let value: $uty = rng. gen ( ) ;
110
- scale * ( value >> ( float_size - precision) ) as $ty
111
- }
112
- }
113
-
114
- impl Distribution <$ty> for OpenClosed01 {
115
- fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> $ty {
116
- // Multiply-based method; 24/53 random bits; (0, 1] interval.
117
- // We use the most significant bits because for simple RNGs
118
- // those are usually more random.
119
- let float_size = mem:: size_of:: <$ty>( ) * 8 ;
120
- let precision = $fraction_bits + 1 ;
121
- let scale = 1.0 / ( ( 1 as $uty << precision) as $ty) ;
122
-
123
- let value: $uty = rng. gen ( ) ;
124
- let value = value >> ( float_size - precision) ;
125
- // Add 1 to shift up; will not overflow because of right-shift:
126
- scale * ( value + 1 ) as $ty
127
- }
128
- }
129
-
130
- impl Distribution <$ty> for Open01 {
131
- fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> $ty {
132
- // Transmute-based method; 23/52 random bits; (0, 1) interval.
133
- // We use the most significant bits because for simple RNGs
134
- // those are usually more random.
135
- const EPSILON : $ty = 1.0 / ( 1u64 << $fraction_bits) as $ty;
136
- let float_size = mem:: size_of:: <$ty>( ) * 8 ;
137
-
138
- let value: $uty = rng. gen ( ) ;
139
- let fraction = value >> ( float_size - $fraction_bits) ;
140
- fraction. into_float_with_exponent( 0 ) - ( 1.0 - EPSILON / 2.0 )
141
- }
142
- }
143
- }
144
- }
145
- float_impls ! { f32 , u32 , 23 , 127 }
146
- float_impls ! { f64 , u64 , 52 , 1023 }
147
-
148
-
149
88
#[ cfg( feature="simd_support" ) ]
150
- macro_rules! simd_float_impls {
151
- ( $ty: ident, $uty: ident, $f_scalar: ty , $u_scalar: ty,
89
+ macro_rules! float_impls {
90
+ ( $ty: ident, $uty: ident, $f_scalar: ident , $u_scalar: ty,
152
91
$fraction_bits: expr, $exponent_bias: expr) => {
153
92
impl IntoFloat for $uty {
154
93
type F = $ty;
@@ -157,7 +96,7 @@ macro_rules! simd_float_impls {
157
96
// The exponent is encoded using an offset-binary representation
158
97
let exponent_bits: $u_scalar =
159
98
( ( $exponent_bias + exponent) as $u_scalar) << $fraction_bits;
160
- unsafe { mem :: transmute ( self | $uty :: splat ( exponent_bits) ) }
99
+ $ty :: from_bits ( self | exponent_bits)
161
100
}
162
101
}
163
102
@@ -168,11 +107,11 @@ macro_rules! simd_float_impls {
168
107
// those are usually more random.
169
108
let float_size = mem:: size_of:: <$f_scalar>( ) * 8 ;
170
109
let precision = $fraction_bits + 1 ;
171
- let scale = $ty :: splat ( 1.0 / ( ( 1 as $u_scalar << precision) as $f_scalar) ) ;
110
+ let scale = 1.0 / ( ( 1 as $u_scalar << precision) as $f_scalar) ;
172
111
173
112
let value: $uty = rng. gen ( ) ;
174
- let value = $ty :: from ( value >> ( float_size - precision) ) ;
175
- scale * value
113
+ let value = value >> ( float_size - precision) ;
114
+ scale * $ty :: cast_from_int ( value)
176
115
}
177
116
}
178
117
@@ -183,12 +122,12 @@ macro_rules! simd_float_impls {
183
122
// those are usually more random.
184
123
let float_size = mem:: size_of:: <$f_scalar>( ) * 8 ;
185
124
let precision = $fraction_bits + 1 ;
186
- let scale = $ty :: splat ( 1.0 / ( ( 1 as $u_scalar << precision) as $f_scalar) ) ;
125
+ let scale = 1.0 / ( ( 1 as $u_scalar << precision) as $f_scalar) ;
187
126
188
127
let value: $uty = rng. gen ( ) ;
128
+ let value = value >> ( float_size - precision) ;
189
129
// Add 1 to shift up; will not overflow because of right-shift:
190
- let value = $ty:: from( ( value >> ( float_size - precision) ) + 1 ) ;
191
- scale * value
130
+ scale * $ty:: cast_from_int( value + 1 )
192
131
}
193
132
}
194
133
@@ -197,32 +136,35 @@ macro_rules! simd_float_impls {
197
136
// Transmute-based method; 23/52 random bits; (0, 1) interval.
198
137
// We use the most significant bits because for simple RNGs
199
138
// those are usually more random.
200
- const EPSILON : $f_scalar = 1.0 / ( 1u64 << $fraction_bits ) as $f_scalar ;
139
+ use core :: $f_scalar:: EPSILON ;
201
140
let float_size = mem:: size_of:: <$f_scalar>( ) * 8 ;
202
141
203
142
let value: $uty = rng. gen ( ) ;
204
143
let fraction = value >> ( float_size - $fraction_bits) ;
205
- fraction. into_float_with_exponent( 0 ) - $ty :: splat ( 1.0 - EPSILON / 2.0 )
144
+ fraction. into_float_with_exponent( 0 ) - ( 1.0 - EPSILON / 2.0 )
206
145
}
207
146
}
208
147
}
209
148
}
210
149
150
+ float_impls ! { f32 , u32 , f32 , u32 , 23 , 127 }
151
+ float_impls ! { f64 , u64 , f64 , u64 , 52 , 1023 }
152
+
211
153
#[ cfg( feature="simd_support" ) ]
212
- simd_float_impls ! { f32x2, u32x2, f32 , u32 , 23 , 127 }
154
+ float_impls ! { f32x2, u32x2, f32 , u32 , 23 , 127 }
213
155
#[ cfg( feature="simd_support" ) ]
214
- simd_float_impls ! { f32x4, u32x4, f32 , u32 , 23 , 127 }
156
+ float_impls ! { f32x4, u32x4, f32 , u32 , 23 , 127 }
215
157
#[ cfg( feature="simd_support" ) ]
216
- simd_float_impls ! { f32x8, u32x8, f32 , u32 , 23 , 127 }
158
+ float_impls ! { f32x8, u32x8, f32 , u32 , 23 , 127 }
217
159
#[ cfg( feature="simd_support" ) ]
218
- simd_float_impls ! { f32x16, u32x16, f32 , u32 , 23 , 127 }
160
+ float_impls ! { f32x16, u32x16, f32 , u32 , 23 , 127 }
219
161
220
162
#[ cfg( feature="simd_support" ) ]
221
- simd_float_impls ! { f64x2, u64x2, f64 , u64 , 52 , 1023 }
163
+ float_impls ! { f64x2, u64x2, f64 , u64 , 52 , 1023 }
222
164
#[ cfg( feature="simd_support" ) ]
223
- simd_float_impls ! { f64x4, u64x4, f64 , u64 , 52 , 1023 }
165
+ float_impls ! { f64x4, u64x4, f64 , u64 , 52 , 1023 }
224
166
#[ cfg( feature="simd_support" ) ]
225
- simd_float_impls ! { f64x8, u64x8, f64 , u64 , 52 , 1023 }
167
+ float_impls ! { f64x8, u64x8, f64 , u64 , 52 , 1023 }
226
168
227
169
228
170
#[ cfg( test) ]
0 commit comments