99
99
//! [`UniformFloat`]: struct.UniformFloat.html
100
100
//! [`UniformDuration`]: struct.UniformDuration.html
101
101
102
+ use core:: num:: Wrapping ;
102
103
#[ cfg( feature = "std" ) ]
103
104
use std:: time:: Duration ;
104
105
@@ -507,6 +508,139 @@ wmul_impl_usize! { u64 }
507
508
508
509
509
510
511
+ /// The back-end implementing [`UniformSampler`] for `Wrapping<T>`.
512
+ ///
513
+ /// Unless you are implementing [`UniformSampler`] for your own types, this type
514
+ /// should not be used directly, use [`Uniform`] instead.
515
+ ///
516
+ /// The method used is the same as for [`UniformInt`], with one exception: it is
517
+ /// not required that `low <= high`. If `low` is greater than `high`, the range
518
+ /// to sample from contains both `low..MAX` and `MIN..high`, i.e. the range
519
+ /// wraps around.
520
+ ///
521
+ /// [`UniformSampler`]: trait.UniformSampler.html
522
+ /// [`Uniform`]: struct.Uniform.html
523
+ /// [`UniformInt`]: struct.UniformInt.html
524
+ #[ derive( Clone , Copy , Debug ) ]
525
+ pub struct UniformWrapping < X > {
526
+ low : X ,
527
+ range : X ,
528
+ zone : X ,
529
+ }
530
+
531
+ macro_rules! uniform_wrapping_int_impl {
532
+ ( $ty: ty, $signed: ty, $unsigned: ident,
533
+ $i_large: ident, $u_large: ident) => {
534
+ impl SampleUniform for Wrapping <$ty> {
535
+ type Sampler = UniformWrapping <$ty>;
536
+ }
537
+
538
+ impl UniformSampler for UniformWrapping <$ty> {
539
+ // We play free and fast with unsigned vs signed here
540
+ // (when $ty is signed), but that's fine, since the
541
+ // contract of this macro is for $ty and $unsigned to be
542
+ // "bit-equal", so casting between them is a no-op.
543
+
544
+ type X = Wrapping <$ty>;
545
+
546
+ #[ inline] // if the range is constant, this helps LLVM to do the
547
+ // calculations at compile-time.
548
+ fn new( low: Self :: X , high: Self :: X ) -> Self {
549
+ UniformSampler :: new_inclusive( low, high - Wrapping ( 1 ) )
550
+ }
551
+
552
+ #[ inline] // if the range is constant, this helps LLVM to do the
553
+ // calculations at compile-time.
554
+ fn new_inclusive( low: Self :: X , high: Self :: X ) -> Self {
555
+ let unsigned_max = :: core:: $unsigned:: MAX ;
556
+
557
+ let range =
558
+ high. 0 . wrapping_sub( low. 0 ) . wrapping_add( 1 ) as $unsigned;
559
+ let ints_to_reject =
560
+ if range > 0 {
561
+ ( unsigned_max - range + 1 ) % range
562
+ } else {
563
+ 0
564
+ } ;
565
+ let zone = unsigned_max - ints_to_reject;
566
+
567
+ UniformWrapping {
568
+ low: low. 0 ,
569
+ // These are really $unsigned values, but store as $ty:
570
+ range: range as $ty,
571
+ zone: zone as $ty
572
+ }
573
+ }
574
+
575
+ fn sample<R : Rng + ?Sized >( & self , rng: & mut R ) -> Self :: X {
576
+ let range = self . range as $unsigned as $u_large;
577
+ if range > 0 {
578
+ // Grow `zone` to fit a type of at least 32 bits, by
579
+ // sign-extending it (the first bit is always 1, so are all
580
+ // the preceding bits of the larger type).
581
+ // For types that already have the right size, all the
582
+ // casting is a no-op.
583
+ let zone = self . zone as $signed as $i_large as $u_large;
584
+ loop {
585
+ let v: $u_large = rng. gen ( ) ;
586
+ let ( hi, lo) = v. wmul( range) ;
587
+ if lo <= zone {
588
+ return Wrapping ( self . low. wrapping_add( hi as $ty) ) ;
589
+ }
590
+ }
591
+ } else {
592
+ // Sample from the entire integer range.
593
+ rng. gen ( )
594
+ }
595
+ }
596
+
597
+ fn sample_single<R : Rng + ?Sized >( low: Self :: X ,
598
+ high: Self :: X ,
599
+ rng: & mut R ) -> Self :: X
600
+ {
601
+ let range = high. 0 . wrapping_sub( low. 0 ) as $unsigned as $u_large;
602
+ let zone =
603
+ if :: core:: $unsigned:: MAX <= :: core:: u16 :: MAX as $unsigned {
604
+ // Using a modulus is faster than the approximation for
605
+ // i8 and i16. I suppose we trade the cost of one
606
+ // modulus for near-perfect branch prediction.
607
+ let unsigned_max: $u_large = :: core:: $u_large:: MAX ;
608
+ let ints_to_reject = ( unsigned_max - range + 1 ) % range;
609
+ unsigned_max - ints_to_reject
610
+ } else {
611
+ // conservative but fast approximation
612
+ range << range. leading_zeros( )
613
+ } ;
614
+
615
+ loop {
616
+ let v: $u_large = rng. gen ( ) ;
617
+ let ( hi, lo) = v. wmul( range) ;
618
+ if lo <= zone {
619
+ return Wrapping ( low. 0 . wrapping_add( hi as $ty) ) ;
620
+ }
621
+ }
622
+ }
623
+ }
624
+ }
625
+ }
626
+
627
+ uniform_wrapping_int_impl ! { i8 , i8 , u8 , i32 , u32 }
628
+ uniform_wrapping_int_impl ! { i16 , i16 , u16 , i32 , u32 }
629
+ uniform_wrapping_int_impl ! { i32 , i32 , u32 , i32 , u32 }
630
+ uniform_wrapping_int_impl ! { i64 , i64 , u64 , i64 , u64 }
631
+ #[ cfg( feature = "i128_support" ) ]
632
+ uniform_wrapping_int_impl ! { i128 , i128 , u128 , u128 , u128 }
633
+ uniform_wrapping_int_impl ! { isize , isize , usize , isize , usize }
634
+ uniform_wrapping_int_impl ! { u8 , i8 , u8 , i32 , u32 }
635
+ uniform_wrapping_int_impl ! { u16 , i16 , u16 , i32 , u32 }
636
+ uniform_wrapping_int_impl ! { u32 , i32 , u32 , i32 , u32 }
637
+ uniform_wrapping_int_impl ! { u64 , i64 , u64 , i64 , u64 }
638
+ uniform_wrapping_int_impl ! { usize , isize , usize , isize , usize }
639
+ #[ cfg( feature = "i128_support" ) ]
640
+ uniform_wrapping_int_impl ! { u128 , u128 , u128 , i128 , u128 }
641
+
642
+
643
+
510
644
/// The back-end implementing [`UniformSampler`] for floating-point types.
511
645
///
512
646
/// Unless you are implementing [`UniformSampler`] for your own type, this type
@@ -548,7 +682,7 @@ macro_rules! uniform_float_impl {
548
682
type X = $ty;
549
683
550
684
fn new( low: Self :: X , high: Self :: X ) -> Self {
551
- assert!( low < high, "Uniform::new called with `low >= high`" ) ;
685
+ assert!( low <= high, "Uniform::new called with `low >= high`" ) ; // FIXME
552
686
let scale = high - low;
553
687
let offset = low - scale;
554
688
UniformFloat {
@@ -697,6 +831,7 @@ impl UniformSampler for UniformDuration {
697
831
mod tests {
698
832
use Rng ;
699
833
use distributions:: uniform:: { Uniform , UniformSampler , UniformFloat , SampleUniform } ;
834
+ use core:: num:: Wrapping ;
700
835
701
836
#[ should_panic]
702
837
#[ test]
@@ -746,10 +881,10 @@ mod tests {
746
881
macro_rules! t {
747
882
( $( $ty: ident) ,* ) => { {
748
883
$(
749
- let v: & [ ( $ty, $ty) ] = & [ ( 0 , 10 ) ,
750
- ( 10 , 127 ) ,
751
- ( :: core:: $ty:: MIN , :: core:: $ty:: MAX ) ] ;
752
- for & ( low, high) in v. iter( ) {
884
+ let v: & [ ( $ty, $ty) ] = & [ ( 0 , 10 ) ,
885
+ ( 10 , 127 ) ,
886
+ ( :: core:: $ty:: MIN , :: core:: $ty:: MAX ) ] ;
887
+ for & ( low, high) in v. iter( ) {
753
888
let my_uniform = Uniform :: new( low, high) ;
754
889
for _ in 0 ..1000 {
755
890
let v: $ty = rng. sample( my_uniform) ;
@@ -776,6 +911,65 @@ mod tests {
776
911
t ! ( i128 , u128 )
777
912
}
778
913
914
+ #[ test]
915
+ fn test_wrapping ( ) {
916
+ let mut rng = :: test:: rng ( 251 ) ;
917
+ macro_rules! t {
918
+ ( $( $ty: ident) ,* ) => { {
919
+ $(
920
+ let v: & [ ( Wrapping <$ty>, Wrapping <$ty>) ] =
921
+ & [ ( Wrapping ( 0 ) , Wrapping ( 10 ) ) ,
922
+ ( Wrapping ( 10 ) , Wrapping ( 127 ) ) ,
923
+ ( Wrapping ( :: core:: $ty:: MIN ) , Wrapping ( :: core:: $ty:: MAX ) ) ] ;
924
+ for & ( low, high) in v. iter( ) {
925
+ let my_uniform = Uniform :: new( low, high) ;
926
+ for _ in 0 ..1000 {
927
+ let v: Wrapping <$ty> = rng. sample( my_uniform) ;
928
+ assert!( low <= v && v < high) ;
929
+ }
930
+
931
+ let my_uniform = Uniform :: new_inclusive( low, high) ;
932
+ for _ in 0 ..1000 {
933
+ let v: Wrapping <$ty> = rng. sample( my_uniform) ;
934
+ assert!( low <= v && v <= high) ;
935
+ }
936
+
937
+ for _ in 0 ..1000 {
938
+ let v: Wrapping <$ty> =
939
+ Uniform :: sample_single( low, high, & mut rng) ;
940
+ assert!( low <= v && v < high) ;
941
+ }
942
+ }
943
+
944
+ // Switch the bounds to test wrapping around
945
+ for & ( low, high) in v. iter( ) {
946
+ let my_uniform = Uniform :: new( high, low) ;
947
+ for _ in 0 ..1000 {
948
+ let v: Wrapping <$ty> = rng. sample( my_uniform) ;
949
+ assert!( v >= high || v < low) ;
950
+ }
951
+
952
+ let my_uniform = Uniform :: new_inclusive( high, low) ;
953
+ for _ in 0 ..1000 {
954
+ let v: Wrapping <$ty> = rng. sample( my_uniform) ;
955
+ assert!( v >= high || v <= low) ;
956
+ }
957
+
958
+ for _ in 0 ..1000 {
959
+ let v: Wrapping <$ty> =
960
+ Uniform :: sample_single( high, low, & mut rng) ;
961
+ assert!( v >= high || v < low) ;
962
+ }
963
+ }
964
+ ) *
965
+ } }
966
+ }
967
+ t ! ( i8 , i16 , i32 , i64 , isize ,
968
+ u8 , u16 , u32 , u64 , usize ) ;
969
+ #[ cfg( feature = "i128_support" ) ]
970
+ t ! ( i128 , u128 )
971
+ }
972
+
779
973
#[ test]
780
974
fn test_floats ( ) {
781
975
let mut rng = :: test:: rng ( 252 ) ;
0 commit comments