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
@@ -85,70 +86,7 @@ pub(crate) trait IntoFloat {
85
86
}
86
87
87
88
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
- #[ cfg( feature="simd_support" ) ]
150
- macro_rules! simd_float_impls {
151
- ( $ty: ident, $uty: ident, $f_scalar: ty, $u_scalar: ty,
89
+ ( $ty: ident, $uty: ident, $f_scalar: ident, $u_scalar: ty,
152
90
$fraction_bits: expr, $exponent_bias: expr) => {
153
91
impl IntoFloat for $uty {
154
92
type F = $ty;
@@ -157,7 +95,7 @@ macro_rules! simd_float_impls {
157
95
// The exponent is encoded using an offset-binary representation
158
96
let exponent_bits: $u_scalar =
159
97
( ( $exponent_bias + exponent) as $u_scalar) << $fraction_bits;
160
- unsafe { mem :: transmute ( self | $uty :: splat ( exponent_bits) ) }
98
+ $ty :: from_bits ( self | exponent_bits)
161
99
}
162
100
}
163
101
@@ -168,11 +106,11 @@ macro_rules! simd_float_impls {
168
106
// those are usually more random.
169
107
let float_size = mem:: size_of:: <$f_scalar>( ) * 8 ;
170
108
let precision = $fraction_bits + 1 ;
171
- let scale = $ty :: splat ( 1.0 / ( ( 1 as $u_scalar << precision) as $f_scalar) ) ;
109
+ let scale = 1.0 / ( ( 1 as $u_scalar << precision) as $f_scalar) ;
172
110
173
111
let value: $uty = rng. gen ( ) ;
174
- let value = $ty :: from ( value >> ( float_size - precision) ) ;
175
- scale * value
112
+ let value = value >> ( float_size - precision) ;
113
+ scale * $ty :: cast_from_int ( value)
176
114
}
177
115
}
178
116
@@ -183,12 +121,12 @@ macro_rules! simd_float_impls {
183
121
// those are usually more random.
184
122
let float_size = mem:: size_of:: <$f_scalar>( ) * 8 ;
185
123
let precision = $fraction_bits + 1 ;
186
- let scale = $ty :: splat ( 1.0 / ( ( 1 as $u_scalar << precision) as $f_scalar) ) ;
124
+ let scale = 1.0 / ( ( 1 as $u_scalar << precision) as $f_scalar) ;
187
125
188
126
let value: $uty = rng. gen ( ) ;
127
+ let value = value >> ( float_size - precision) ;
189
128
// 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
129
+ scale * $ty:: cast_from_int( value + 1 )
192
130
}
193
131
}
194
132
@@ -197,32 +135,35 @@ macro_rules! simd_float_impls {
197
135
// Transmute-based method; 23/52 random bits; (0, 1) interval.
198
136
// We use the most significant bits because for simple RNGs
199
137
// those are usually more random.
200
- const EPSILON : $f_scalar = 1.0 / ( 1u64 << $fraction_bits ) as $f_scalar ;
138
+ use core :: $f_scalar:: EPSILON ;
201
139
let float_size = mem:: size_of:: <$f_scalar>( ) * 8 ;
202
140
203
141
let value: $uty = rng. gen ( ) ;
204
142
let fraction = value >> ( float_size - $fraction_bits) ;
205
- fraction. into_float_with_exponent( 0 ) - $ty :: splat ( 1.0 - EPSILON / 2.0 )
143
+ fraction. into_float_with_exponent( 0 ) - ( 1.0 - EPSILON / 2.0 )
206
144
}
207
145
}
208
146
}
209
147
}
210
148
149
+ float_impls ! { f32 , u32 , f32 , u32 , 23 , 127 }
150
+ float_impls ! { f64 , u64 , f64 , u64 , 52 , 1023 }
151
+
211
152
#[ cfg( feature="simd_support" ) ]
212
- simd_float_impls ! { f32x2, u32x2, f32 , u32 , 23 , 127 }
153
+ float_impls ! { f32x2, u32x2, f32 , u32 , 23 , 127 }
213
154
#[ cfg( feature="simd_support" ) ]
214
- simd_float_impls ! { f32x4, u32x4, f32 , u32 , 23 , 127 }
155
+ float_impls ! { f32x4, u32x4, f32 , u32 , 23 , 127 }
215
156
#[ cfg( feature="simd_support" ) ]
216
- simd_float_impls ! { f32x8, u32x8, f32 , u32 , 23 , 127 }
157
+ float_impls ! { f32x8, u32x8, f32 , u32 , 23 , 127 }
217
158
#[ cfg( feature="simd_support" ) ]
218
- simd_float_impls ! { f32x16, u32x16, f32 , u32 , 23 , 127 }
159
+ float_impls ! { f32x16, u32x16, f32 , u32 , 23 , 127 }
219
160
220
161
#[ cfg( feature="simd_support" ) ]
221
- simd_float_impls ! { f64x2, u64x2, f64 , u64 , 52 , 1023 }
162
+ float_impls ! { f64x2, u64x2, f64 , u64 , 52 , 1023 }
222
163
#[ cfg( feature="simd_support" ) ]
223
- simd_float_impls ! { f64x4, u64x4, f64 , u64 , 52 , 1023 }
164
+ float_impls ! { f64x4, u64x4, f64 , u64 , 52 , 1023 }
224
165
#[ cfg( feature="simd_support" ) ]
225
- simd_float_impls ! { f64x8, u64x8, f64 , u64 , 52 , 1023 }
166
+ float_impls ! { f64x8, u64x8, f64 , u64 , 52 , 1023 }
226
167
227
168
228
169
#[ cfg( test) ]
@@ -267,7 +208,7 @@ mod tests {
267
208
}
268
209
}
269
210
}
270
- test_f32 ! { f32_edge_cases, f32 , 0.0 , :: core :: f32 :: EPSILON }
211
+ test_f32 ! { f32_edge_cases, f32 , 0.0 , EPSILON32 }
271
212
#[ cfg( feature="simd_support" ) ]
272
213
test_f32 ! { f32x2_edge_cases, f32x2, f32x2:: splat( 0.0 ) , f32x2:: splat( EPSILON32 ) }
273
214
#[ cfg( feature="simd_support" ) ]
0 commit comments