8
8
9
9
//! Basic floating-point number distributions
10
10
11
- use crate :: distributions:: utils:: FloatSIMDUtils ;
11
+ use crate :: distributions:: utils:: { IntAsSIMD , FloatAsSIMD , FloatSIMDUtils } ;
12
12
use crate :: distributions:: { Distribution , Standard } ;
13
13
use crate :: Rng ;
14
14
use core:: mem;
15
- #[ cfg( feature = "simd_support" ) ] use packed_simd :: * ;
15
+ #[ cfg( feature = "simd_support" ) ] use core :: simd :: * ;
16
16
17
17
#[ cfg( feature = "serde1" ) ]
18
18
use serde:: { Serialize , Deserialize } ;
@@ -99,7 +99,7 @@ macro_rules! float_impls {
99
99
// The exponent is encoded using an offset-binary representation
100
100
let exponent_bits: $u_scalar =
101
101
( ( $exponent_bias + exponent) as $u_scalar) << $fraction_bits;
102
- $ty:: from_bits( self | exponent_bits)
102
+ $ty:: from_bits( self | $uty :: splat ( exponent_bits) )
103
103
}
104
104
}
105
105
@@ -108,13 +108,13 @@ macro_rules! float_impls {
108
108
// Multiply-based method; 24/53 random bits; [0, 1) interval.
109
109
// We use the most significant bits because for simple RNGs
110
110
// those are usually more random.
111
- let float_size = mem:: size_of:: <$f_scalar>( ) as u32 * 8 ;
111
+ let float_size = mem:: size_of:: <$f_scalar>( ) as $u_scalar * 8 ;
112
112
let precision = $fraction_bits + 1 ;
113
113
let scale = 1.0 / ( ( 1 as $u_scalar << precision) as $f_scalar) ;
114
114
115
115
let value: $uty = rng. gen ( ) ;
116
- let value = value >> ( float_size - precision) ;
117
- scale * $ty:: cast_from_int( value)
116
+ let value = value >> $uty :: splat ( float_size - precision) ;
117
+ $ty :: splat ( scale) * $ty:: cast_from_int( value)
118
118
}
119
119
}
120
120
@@ -123,14 +123,14 @@ macro_rules! float_impls {
123
123
// Multiply-based method; 24/53 random bits; (0, 1] interval.
124
124
// We use the most significant bits because for simple RNGs
125
125
// those are usually more random.
126
- let float_size = mem:: size_of:: <$f_scalar>( ) as u32 * 8 ;
126
+ let float_size = mem:: size_of:: <$f_scalar>( ) as $u_scalar * 8 ;
127
127
let precision = $fraction_bits + 1 ;
128
128
let scale = 1.0 / ( ( 1 as $u_scalar << precision) as $f_scalar) ;
129
129
130
130
let value: $uty = rng. gen ( ) ;
131
- let value = value >> ( float_size - precision) ;
131
+ let value = value >> $uty :: splat ( float_size - precision) ;
132
132
// Add 1 to shift up; will not overflow because of right-shift:
133
- scale * $ty:: cast_from_int( value + 1 )
133
+ $ty :: splat ( scale) * $ty:: cast_from_int( value + $uty :: splat ( 1 ) )
134
134
}
135
135
}
136
136
@@ -140,11 +140,11 @@ macro_rules! float_impls {
140
140
// We use the most significant bits because for simple RNGs
141
141
// those are usually more random.
142
142
use core:: $f_scalar:: EPSILON ;
143
- let float_size = mem:: size_of:: <$f_scalar>( ) as u32 * 8 ;
143
+ let float_size = mem:: size_of:: <$f_scalar>( ) as $u_scalar * 8 ;
144
144
145
145
let value: $uty = rng. gen ( ) ;
146
- let fraction = value >> ( float_size - $fraction_bits) ;
147
- fraction. into_float_with_exponent( 0 ) - ( 1.0 - EPSILON / 2.0 )
146
+ let fraction = value >> $uty :: splat ( float_size - $fraction_bits) ;
147
+ fraction. into_float_with_exponent( 0 ) - $ty :: splat ( 1.0 - EPSILON / 2.0 )
148
148
}
149
149
}
150
150
}
@@ -169,10 +169,10 @@ float_impls! { f64x4, u64x4, f64, u64, 52, 1023 }
169
169
#[ cfg( feature = "simd_support" ) ]
170
170
float_impls ! { f64x8, u64x8, f64 , u64 , 52 , 1023 }
171
171
172
-
173
172
#[ cfg( test) ]
174
173
mod tests {
175
174
use super :: * ;
175
+ use crate :: distributions:: utils:: FloatAsSIMD ;
176
176
use crate :: rngs:: mock:: StepRng ;
177
177
178
178
const EPSILON32 : f32 = :: core:: f32:: EPSILON ;
@@ -182,29 +182,31 @@ mod tests {
182
182
( $fnn: ident, $ty: ident, $ZERO: expr, $EPSILON: expr) => {
183
183
#[ test]
184
184
fn $fnn( ) {
185
+ let two = $ty:: splat( 2.0 ) ;
186
+
185
187
// Standard
186
188
let mut zeros = StepRng :: new( 0 , 0 ) ;
187
189
assert_eq!( zeros. gen :: <$ty>( ) , $ZERO) ;
188
190
let mut one = StepRng :: new( 1 << 8 | 1 << ( 8 + 32 ) , 0 ) ;
189
- assert_eq!( one. gen :: <$ty>( ) , $EPSILON / 2.0 ) ;
191
+ assert_eq!( one. gen :: <$ty>( ) , $EPSILON / two ) ;
190
192
let mut max = StepRng :: new( !0 , 0 ) ;
191
- assert_eq!( max. gen :: <$ty>( ) , 1.0 - $EPSILON / 2.0 ) ;
193
+ assert_eq!( max. gen :: <$ty>( ) , $ty :: splat ( 1.0 ) - $EPSILON / two ) ;
192
194
193
195
// OpenClosed01
194
196
let mut zeros = StepRng :: new( 0 , 0 ) ;
195
- assert_eq!( zeros. sample:: <$ty, _>( OpenClosed01 ) , 0.0 + $EPSILON / 2.0 ) ;
197
+ assert_eq!( zeros. sample:: <$ty, _>( OpenClosed01 ) , $ZERO + $EPSILON / two ) ;
196
198
let mut one = StepRng :: new( 1 << 8 | 1 << ( 8 + 32 ) , 0 ) ;
197
199
assert_eq!( one. sample:: <$ty, _>( OpenClosed01 ) , $EPSILON) ;
198
200
let mut max = StepRng :: new( !0 , 0 ) ;
199
- assert_eq!( max. sample:: <$ty, _>( OpenClosed01 ) , $ZERO + 1.0 ) ;
201
+ assert_eq!( max. sample:: <$ty, _>( OpenClosed01 ) , $ZERO + $ty :: splat ( 1.0 ) ) ;
200
202
201
203
// Open01
202
204
let mut zeros = StepRng :: new( 0 , 0 ) ;
203
- assert_eq!( zeros. sample:: <$ty, _>( Open01 ) , 0.0 + $EPSILON / 2.0 ) ;
205
+ assert_eq!( zeros. sample:: <$ty, _>( Open01 ) , $ZERO + $EPSILON / two ) ;
204
206
let mut one = StepRng :: new( 1 << 9 | 1 << ( 9 + 32 ) , 0 ) ;
205
- assert_eq!( one. sample:: <$ty, _>( Open01 ) , $EPSILON / 2.0 * 3.0 ) ;
207
+ assert_eq!( one. sample:: <$ty, _>( Open01 ) , $EPSILON / two * $ty :: splat ( 3.0 ) ) ;
206
208
let mut max = StepRng :: new( !0 , 0 ) ;
207
- assert_eq!( max. sample:: <$ty, _>( Open01 ) , 1.0 - $EPSILON / 2.0 ) ;
209
+ assert_eq!( max. sample:: <$ty, _>( Open01 ) , $ty :: splat ( 1.0 ) - $EPSILON / two ) ;
208
210
}
209
211
} ;
210
212
}
@@ -222,29 +224,31 @@ mod tests {
222
224
( $fnn: ident, $ty: ident, $ZERO: expr, $EPSILON: expr) => {
223
225
#[ test]
224
226
fn $fnn( ) {
227
+ let two = $ty:: splat( 2.0 ) ;
228
+
225
229
// Standard
226
230
let mut zeros = StepRng :: new( 0 , 0 ) ;
227
231
assert_eq!( zeros. gen :: <$ty>( ) , $ZERO) ;
228
232
let mut one = StepRng :: new( 1 << 11 , 0 ) ;
229
- assert_eq!( one. gen :: <$ty>( ) , $EPSILON / 2.0 ) ;
233
+ assert_eq!( one. gen :: <$ty>( ) , $EPSILON / two ) ;
230
234
let mut max = StepRng :: new( !0 , 0 ) ;
231
- assert_eq!( max. gen :: <$ty>( ) , 1.0 - $EPSILON / 2.0 ) ;
235
+ assert_eq!( max. gen :: <$ty>( ) , $ty :: splat ( 1.0 ) - $EPSILON / two ) ;
232
236
233
237
// OpenClosed01
234
238
let mut zeros = StepRng :: new( 0 , 0 ) ;
235
- assert_eq!( zeros. sample:: <$ty, _>( OpenClosed01 ) , 0.0 + $EPSILON / 2.0 ) ;
239
+ assert_eq!( zeros. sample:: <$ty, _>( OpenClosed01 ) , $ZERO + $EPSILON / two ) ;
236
240
let mut one = StepRng :: new( 1 << 11 , 0 ) ;
237
241
assert_eq!( one. sample:: <$ty, _>( OpenClosed01 ) , $EPSILON) ;
238
242
let mut max = StepRng :: new( !0 , 0 ) ;
239
- assert_eq!( max. sample:: <$ty, _>( OpenClosed01 ) , $ZERO + 1.0 ) ;
243
+ assert_eq!( max. sample:: <$ty, _>( OpenClosed01 ) , $ZERO + $ty :: splat ( 1.0 ) ) ;
240
244
241
245
// Open01
242
246
let mut zeros = StepRng :: new( 0 , 0 ) ;
243
- assert_eq!( zeros. sample:: <$ty, _>( Open01 ) , 0.0 + $EPSILON / 2.0 ) ;
247
+ assert_eq!( zeros. sample:: <$ty, _>( Open01 ) , $ZERO + $EPSILON / two ) ;
244
248
let mut one = StepRng :: new( 1 << 12 , 0 ) ;
245
- assert_eq!( one. sample:: <$ty, _>( Open01 ) , $EPSILON / 2.0 * 3.0 ) ;
249
+ assert_eq!( one. sample:: <$ty, _>( Open01 ) , $EPSILON / two * $ty :: splat ( 3.0 ) ) ;
246
250
let mut max = StepRng :: new( !0 , 0 ) ;
247
- assert_eq!( max. sample:: <$ty, _>( Open01 ) , 1.0 - $EPSILON / 2.0 ) ;
251
+ assert_eq!( max. sample:: <$ty, _>( Open01 ) , $ty :: splat ( 1.0 ) - $EPSILON / two ) ;
248
252
}
249
253
} ;
250
254
}
@@ -296,16 +300,16 @@ mod tests {
296
300
// non-SIMD types; we assume this pattern continues across all
297
301
// SIMD types.
298
302
299
- test_samples ( & Standard , f32x2:: new ( 0.0 , 0.0 ) , & [
300
- f32x2:: new ( 0.0035963655 , 0.7346052 ) ,
301
- f32x2:: new ( 0.09778172 , 0.20298547 ) ,
302
- f32x2:: new ( 0.34296435 , 0.81664366 ) ,
303
+ test_samples ( & Standard , f32x2:: from ( [ 0.0 , 0.0 ] ) , & [
304
+ f32x2:: from ( [ 0.0035963655 , 0.7346052 ] ) ,
305
+ f32x2:: from ( [ 0.09778172 , 0.20298547 ] ) ,
306
+ f32x2:: from ( [ 0.34296435 , 0.81664366 ] ) ,
303
307
] ) ;
304
308
305
- test_samples ( & Standard , f64x2:: new ( 0.0 , 0.0 ) , & [
306
- f64x2:: new ( 0.7346051961657583 , 0.20298547462974248 ) ,
307
- f64x2:: new ( 0.8166436635290655 , 0.7423708925400552 ) ,
308
- f64x2:: new ( 0.16387782224016323 , 0.9087068770169618 ) ,
309
+ test_samples ( & Standard , f64x2:: from ( [ 0.0 , 0.0 ] ) , & [
310
+ f64x2:: from ( [ 0.7346051961657583 , 0.20298547462974248 ] ) ,
311
+ f64x2:: from ( [ 0.8166436635290655 , 0.7423708925400552 ] ) ,
312
+ f64x2:: from ( [ 0.16387782224016323 , 0.9087068770169618 ] ) ,
309
313
] ) ;
310
314
}
311
315
}
0 commit comments