@@ -1232,3 +1232,154 @@ mod impl_schemars {
1232
1232
}
1233
1233
}
1234
1234
}
1235
+
1236
+ #[ cfg( all( feature = "std" , feature = "rand" ) ) ]
1237
+ mod impl_rand {
1238
+ use super :: { NotNan , OrderedFloat } ;
1239
+ use rand:: distributions:: { Distribution , Open01 , OpenClosed01 , Standard } ;
1240
+ use rand:: distributions:: uniform:: * ;
1241
+ use rand:: Rng ;
1242
+
1243
+ macro_rules! impl_distribution {
1244
+ ( $dist: ident, $( $f: ty) ,+) => {
1245
+ $(
1246
+ impl Distribution <NotNan <$f>> for $dist {
1247
+ fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> NotNan <$f> {
1248
+ // 'rand' never generates NaN values in the Standard, Open01, or
1249
+ // OpenClosed01 distributions. Using 'unchecked_new' is therefore
1250
+ // safe.
1251
+ unsafe { NotNan :: unchecked_new( self . sample( rng) ) }
1252
+ }
1253
+ }
1254
+
1255
+ impl Distribution <OrderedFloat <$f>> for $dist {
1256
+ fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> OrderedFloat <$f> {
1257
+ OrderedFloat ( self . sample( rng) )
1258
+ }
1259
+ }
1260
+ ) *
1261
+ }
1262
+ }
1263
+
1264
+ impl_distribution ! { Standard , f32 , f64 }
1265
+ impl_distribution ! { Open01 , f32 , f64 }
1266
+ impl_distribution ! { OpenClosed01 , f32 , f64 }
1267
+
1268
+ pub struct UniformNotNan < T > ( UniformFloat < T > ) ;
1269
+ impl SampleUniform for NotNan < f32 > {
1270
+ type Sampler = UniformNotNan < f32 > ;
1271
+ }
1272
+ impl SampleUniform for NotNan < f64 > {
1273
+ type Sampler = UniformNotNan < f64 > ;
1274
+ }
1275
+
1276
+ pub struct UniformOrdered < T > ( UniformFloat < T > ) ;
1277
+ impl SampleUniform for OrderedFloat < f32 > {
1278
+ type Sampler = UniformOrdered < f32 > ;
1279
+ }
1280
+ impl SampleUniform for OrderedFloat < f64 > {
1281
+ type Sampler = UniformOrdered < f64 > ;
1282
+ }
1283
+
1284
+ macro_rules! impl_uniform_sampler {
1285
+ ( $f: ty) => {
1286
+ impl UniformSampler for UniformNotNan <$f> {
1287
+ type X = NotNan <$f>;
1288
+ fn new<B1 , B2 >( low: B1 , high: B2 ) -> Self
1289
+ where B1 : SampleBorrow <Self :: X > + Sized ,
1290
+ B2 : SampleBorrow <Self :: X > + Sized
1291
+ {
1292
+ UniformNotNan ( UniformFloat :: <$f>:: new( low. borrow( ) . 0 , high. borrow( ) . 0 ) )
1293
+ }
1294
+ fn new_inclusive<B1 , B2 >( low: B1 , high: B2 ) -> Self
1295
+ where B1 : SampleBorrow <Self :: X > + Sized ,
1296
+ B2 : SampleBorrow <Self :: X > + Sized
1297
+ {
1298
+ UniformSampler :: new( low, high)
1299
+ }
1300
+ fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> Self :: X {
1301
+ unsafe { NotNan :: unchecked_new( self . 0 . sample( rng) ) }
1302
+ }
1303
+ }
1304
+
1305
+ impl UniformSampler for UniformOrdered <$f> {
1306
+ type X = OrderedFloat <$f>;
1307
+ fn new<B1 , B2 >( low: B1 , high: B2 ) -> Self
1308
+ where B1 : SampleBorrow <Self :: X > + Sized ,
1309
+ B2 : SampleBorrow <Self :: X > + Sized
1310
+ {
1311
+ UniformOrdered ( UniformFloat :: <$f>:: new( low. borrow( ) . 0 , high. borrow( ) . 0 ) )
1312
+ }
1313
+ fn new_inclusive<B1 , B2 >( low: B1 , high: B2 ) -> Self
1314
+ where B1 : SampleBorrow <Self :: X > + Sized ,
1315
+ B2 : SampleBorrow <Self :: X > + Sized
1316
+ {
1317
+ UniformSampler :: new( low, high)
1318
+ }
1319
+ fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> Self :: X {
1320
+ OrderedFloat ( self . 0 . sample( rng) )
1321
+ }
1322
+ }
1323
+ }
1324
+ }
1325
+
1326
+ impl_uniform_sampler ! { f32 }
1327
+ impl_uniform_sampler ! { f64 }
1328
+
1329
+ #[ cfg( test) ]
1330
+ fn sample_fuzz < T > ( )
1331
+ where
1332
+ Standard : Distribution < NotNan < T > > ,
1333
+ Open01 : Distribution < NotNan < T > > ,
1334
+ OpenClosed01 : Distribution < NotNan < T > > ,
1335
+ Standard : Distribution < OrderedFloat < T > > ,
1336
+ Open01 : Distribution < OrderedFloat < T > > ,
1337
+ OpenClosed01 : Distribution < OrderedFloat < T > > ,
1338
+ T : super :: Float ,
1339
+ {
1340
+ let mut rng = rand:: thread_rng ( ) ;
1341
+ let f1: NotNan < T > = rng. sample ( Standard ) ;
1342
+ let f2: NotNan < T > = rng. sample ( Open01 ) ;
1343
+ let f3: NotNan < T > = rng. sample ( OpenClosed01 ) ;
1344
+ let _: OrderedFloat < T > = rng. sample ( Standard ) ;
1345
+ let _: OrderedFloat < T > = rng. sample ( Open01 ) ;
1346
+ let _: OrderedFloat < T > = rng. sample ( OpenClosed01 ) ;
1347
+ assert ! ( !f1. into_inner( ) . is_nan( ) ) ;
1348
+ assert ! ( !f2. into_inner( ) . is_nan( ) ) ;
1349
+ assert ! ( !f3. into_inner( ) . is_nan( ) ) ;
1350
+ }
1351
+
1352
+ #[ test]
1353
+ fn sampling_f32_does_not_panic ( ) {
1354
+ sample_fuzz :: < f32 > ( ) ;
1355
+ }
1356
+
1357
+ #[ test]
1358
+ fn sampling_f64_does_not_panic ( ) {
1359
+ sample_fuzz :: < f64 > ( ) ;
1360
+ }
1361
+
1362
+ #[ test]
1363
+ #[ should_panic]
1364
+ fn uniform_sampling_panic_on_infinity_notnan ( ) {
1365
+ let ( low, high) = ( NotNan :: new ( 0f64 ) . unwrap ( ) , NotNan :: new ( f64:: INFINITY ) . unwrap ( ) ) ;
1366
+ let uniform = Uniform :: new ( low, high) ;
1367
+ let _ = uniform. sample ( & mut rand:: thread_rng ( ) ) ;
1368
+ }
1369
+
1370
+ #[ test]
1371
+ #[ should_panic]
1372
+ fn uniform_sampling_panic_on_infinity_ordered ( ) {
1373
+ let ( low, high) = ( OrderedFloat ( 0f64 ) , OrderedFloat ( f64:: INFINITY ) ) ;
1374
+ let uniform = Uniform :: new ( low, high) ;
1375
+ let _ = uniform. sample ( & mut rand:: thread_rng ( ) ) ;
1376
+ }
1377
+
1378
+ #[ test]
1379
+ #[ should_panic]
1380
+ fn uniform_sampling_panic_on_nan_ordered ( ) {
1381
+ let ( low, high) = ( OrderedFloat ( 0f64 ) , OrderedFloat ( f64:: NAN ) ) ;
1382
+ let uniform = Uniform :: new ( low, high) ;
1383
+ let _ = uniform. sample ( & mut rand:: thread_rng ( ) ) ;
1384
+ }
1385
+ }
0 commit comments