@@ -465,6 +465,8 @@ macro_rules! uniform_int_64_impl {
465
465
( $ty: ty, $unsigned: ident) => {
466
466
impl UniformInt <$ty> {
467
467
/// Sample, Canon's method variant
468
+ ///
469
+ /// Variant: potential increase to bias (uses a single `u64` sample).
468
470
#[ inline]
469
471
pub fn sample_canon_64<R : Rng + ?Sized >( & self , rng: & mut R ) -> $ty {
470
472
let range = self . range as $unsigned as u64 ;
@@ -476,6 +478,35 @@ macro_rules! uniform_int_64_impl {
476
478
// bias is at most 1 in 2.pow(56) for i8, 1 in 2.pow(48) for i16
477
479
self . low. wrapping_add( result as $ty)
478
480
}
481
+
482
+ /// Sample single inclusive, using Canon's method variant
483
+ ///
484
+ /// Variant: potential increase to bias (uses a single `u64` sample).
485
+ #[ inline]
486
+ pub fn sample_single_inclusive_canon_64<R : Rng + ?Sized , B1 , B2 >(
487
+ low_b: B1 , high_b: B2 , rng: & mut R ,
488
+ ) -> $ty
489
+ where
490
+ B1 : SampleBorrow <$ty> + Sized ,
491
+ B2 : SampleBorrow <$ty> + Sized ,
492
+ {
493
+ let low = * low_b. borrow( ) ;
494
+ let high = * high_b. borrow( ) ;
495
+ assert!(
496
+ low <= high,
497
+ "UniformSampler::sample_single_inclusive: low > high"
498
+ ) ;
499
+ let range = high. wrapping_sub( low) . wrapping_add( 1 ) as $unsigned as u64 ;
500
+ if range == 0 {
501
+ // Range is MAX+1 (unrepresentable), so we need a special case
502
+ return rng. gen ( ) ;
503
+ }
504
+
505
+ // generate a sample using a sensible integer type
506
+ let ( result, _lo1) = rng. gen :: <u64 >( ) . wmul( range) ;
507
+ // bias is at most 1 in 2.pow(56) for i8, 1 in 2.pow(48) for i16
508
+ low. wrapping_add( result as $ty)
509
+ }
479
510
}
480
511
}
481
512
}
@@ -490,6 +521,18 @@ macro_rules! uniform_int_64void_impl {
490
521
pub fn sample_canon_64<R : Rng + ?Sized >( & self , _rng: & mut R ) -> $ty {
491
522
Default :: default ( ) // not used
492
523
}
524
+
525
+ /// Sample single inclusive, using Canon's method variant
526
+ #[ inline]
527
+ pub fn sample_single_inclusive_canon_64<R : Rng + ?Sized , B1 , B2 >(
528
+ _low_b: B1 , _high_b: B2 , _rng: & mut R ,
529
+ ) -> $ty
530
+ where
531
+ B1 : SampleBorrow <$ty> + Sized ,
532
+ B2 : SampleBorrow <$ty> + Sized ,
533
+ {
534
+ Default :: default ( ) // not used
535
+ }
493
536
}
494
537
}
495
538
}
@@ -519,6 +562,44 @@ impl UniformInt<i128> {
519
562
520
563
self . low . wrapping_add ( result as i128 )
521
564
}
565
+
566
+ /// Sample single inclusive, using Canon's method variant
567
+ ///
568
+ /// Variant: potential increase to bias (uses a single `u64` sample).
569
+ #[ inline]
570
+ pub fn sample_single_inclusive_canon_64 < R : Rng + ?Sized , B1 , B2 > (
571
+ low_b : B1 , high_b : B2 , rng : & mut R ,
572
+ ) -> i128
573
+ where
574
+ B1 : SampleBorrow < i128 > + Sized ,
575
+ B2 : SampleBorrow < i128 > + Sized ,
576
+ {
577
+ let low = * low_b. borrow ( ) ;
578
+ let high = * high_b. borrow ( ) ;
579
+ assert ! (
580
+ low <= high,
581
+ "UniformSampler::sample_single_inclusive: low > high"
582
+ ) ;
583
+ let range = high. wrapping_sub ( low) . wrapping_add ( 1 ) as u128 ;
584
+ if range == 0 {
585
+ // Range is MAX+1 (unrepresentable), so we need a special case
586
+ return rng. gen ( ) ;
587
+ }
588
+
589
+ // generate a sample using a sensible integer type
590
+ let ( mut result, lo1) = rng. gen :: < u128 > ( ) . wmul ( range) ;
591
+
592
+ if lo1 > range. wrapping_neg ( ) {
593
+ // Generate more bits. Sample is multiplied by 2.pow(-192), so
594
+ // hi2 is multiplied by 2.pow(-64):
595
+ let ( hi2, lo2) = ( rng. gen :: < u64 > ( ) as u128 ) . wmul ( range) ;
596
+ debug_assert_eq ! ( hi2 >> 64 , 0u128 ) ;
597
+ let is_overflow = lo1. checked_add ( ( hi2 << 64 ) | ( lo2 >> 64 ) ) . is_none ( ) ;
598
+ result += is_overflow as u128 ;
599
+ }
600
+
601
+ low. wrapping_add ( result as i128 )
602
+ }
522
603
}
523
604
524
605
#[ cfg( feature = "simd_support" ) ]
0 commit comments