@@ -12,13 +12,15 @@ pub mod udiv;
1212pub use self :: leading_zeros:: __clzsi2;
1313
1414/// Trait for some basic operations on integers
15- pub ( crate ) trait Int :
15+ #[ doc( hidden) ]
16+ pub trait Int :
1617 Copy
1718 + PartialEq
1819 + PartialOrd
1920 + ops:: AddAssign
2021 + ops:: BitAndAssign
2122 + ops:: BitOrAssign
23+ + ops:: BitXorAssign
2224 + ops:: ShlAssign < i32 >
2325 + ops:: ShrAssign < u32 >
2426 + ops:: Add < Output = Self >
@@ -41,6 +43,14 @@ pub(crate) trait Int:
4143
4244 const ZERO : Self ;
4345 const ONE : Self ;
46+ const MIN : Self ;
47+
48+ /// LUT used for maximizing the space covered and minimizing the computational cost of fuzzing
49+ /// in `testcrate`. For example, Self = u128 produces [0,1,2,7,8,15,16,31,32,63,64,95,96,111,
50+ /// 112,119,120,125,126,127].
51+ const FUZZ_LENGTHS : [ u8 ; 20 ] ;
52+ /// The number of entries of `FUZZ_LENGTHS` actually used. The maximum is 20 for u128.
53+ const FUZZ_NUM : usize ;
4454
4555 /// Extracts the sign from self and returns a tuple.
4656 ///
@@ -59,17 +69,25 @@ pub(crate) trait Int:
5969
6070 fn from_bool ( b : bool ) -> Self ;
6171
72+ /// Prevents the need for excessive conversions between signed and unsigned
73+ fn logical_shr ( self , other : u32 ) -> Self ;
74+
6275 // copied from primitive integers, but put in a trait
76+ fn is_zero ( self ) -> bool ;
6377 fn max_value ( ) -> Self ;
6478 fn min_value ( ) -> Self ;
79+ fn wrapping_neg ( self ) -> Self ;
6580 fn wrapping_add ( self , other : Self ) -> Self ;
6681 fn wrapping_mul ( self , other : Self ) -> Self ;
6782 fn wrapping_sub ( self , other : Self ) -> Self ;
6883 fn wrapping_shl ( self , other : u32 ) -> Self ;
84+ fn wrapping_shr ( self , other : u32 ) -> Self ;
85+ fn rotate_left ( self , other : u32 ) -> Self ;
6986 fn overflowing_add ( self , other : Self ) -> ( Self , bool ) ;
7087 fn aborting_div ( self , other : Self ) -> Self ;
7188 fn aborting_rem ( self , other : Self ) -> Self ;
7289 fn leading_zeros ( self ) -> u32 ;
90+ fn count_ones ( self ) -> u32 ;
7391}
7492
7593fn unwrap < T > ( t : Option < T > ) -> T {
@@ -85,11 +103,78 @@ macro_rules! int_impl_common {
85103
86104 const ZERO : Self = 0 ;
87105 const ONE : Self = 1 ;
106+ const MIN : Self = <Self >:: MIN ;
107+
108+ const FUZZ_LENGTHS : [ u8 ; 20 ] = {
109+ let bits = <Self as Int >:: BITS ;
110+ let mut v = [ 0u8 ; 20 ] ;
111+ v[ 0 ] = 0 ;
112+ v[ 1 ] = 1 ;
113+ v[ 2 ] = 2 ; // important for parity and the iX::MIN case when reversed
114+ let mut i = 3 ;
115+ // No need for any more until the byte boundary, because there should be no algorithms
116+ // that are sensitive to anything not next to byte boundaries after 2. We also scale
117+ // in powers of two, which is important to prevent u128 corner tests from getting too
118+ // big.
119+ let mut l = 8 ;
120+ loop {
121+ if l >= ( ( bits / 2 ) as u8 ) {
122+ break ;
123+ }
124+ // get both sides of the byte boundary
125+ v[ i] = l - 1 ;
126+ i += 1 ;
127+ v[ i] = l;
128+ i += 1 ;
129+ l *= 2 ;
130+ }
131+
132+ if bits != 8 {
133+ // add the lower side of the middle boundary
134+ v[ i] = ( ( bits / 2 ) - 1 ) as u8 ;
135+ i += 1 ;
136+ }
137+
138+ // We do not want to jump directly from the Self::BITS/2 boundary to the Self::BITS
139+ // boundary because of algorithms that split the high part up. We reverse the scaling
140+ // as we go to Self::BITS.
141+ let mid = i;
142+ let mut j = 1 ;
143+ loop {
144+ v[ i] = ( bits as u8 ) - ( v[ mid - j] ) - 1 ;
145+ if j == mid {
146+ break ;
147+ }
148+ i += 1 ;
149+ j += 1 ;
150+ }
151+ v
152+ } ;
153+
154+ const FUZZ_NUM : usize = {
155+ let log2 = ( <Self as Int >:: BITS - 1 ) . count_ones( ) as usize ;
156+ if log2 == 3 {
157+ // case for u8
158+ 6
159+ } else {
160+ // 3 entries on each extreme, 2 in the middle, and 4 for each scale of intermediate
161+ // boundaries.
162+ 8 + ( 4 * ( log2 - 4 ) )
163+ }
164+ } ;
88165
89166 fn from_bool( b: bool ) -> Self {
90167 b as $ty
91168 }
92169
170+ fn logical_shr( self , other: u32 ) -> Self {
171+ Self :: from_unsigned( self . unsigned( ) . wrapping_shr( other) )
172+ }
173+
174+ fn is_zero( self ) -> bool {
175+ self == Self :: ZERO
176+ }
177+
93178 fn max_value( ) -> Self {
94179 <Self >:: max_value( )
95180 }
@@ -98,6 +183,10 @@ macro_rules! int_impl_common {
98183 <Self >:: min_value( )
99184 }
100185
186+ fn wrapping_neg( self ) -> Self {
187+ <Self >:: wrapping_neg( self )
188+ }
189+
101190 fn wrapping_add( self , other: Self ) -> Self {
102191 <Self >:: wrapping_add( self , other)
103192 }
@@ -114,6 +203,14 @@ macro_rules! int_impl_common {
114203 <Self >:: wrapping_shl( self , other)
115204 }
116205
206+ fn wrapping_shr( self , other: u32 ) -> Self {
207+ <Self >:: wrapping_shr( self , other)
208+ }
209+
210+ fn rotate_left( self , other: u32 ) -> Self {
211+ <Self >:: rotate_left( self , other)
212+ }
213+
117214 fn overflowing_add( self , other: Self ) -> ( Self , bool ) {
118215 <Self >:: overflowing_add( self , other)
119216 }
@@ -129,6 +226,10 @@ macro_rules! int_impl_common {
129226 fn leading_zeros( self ) -> u32 {
130227 <Self >:: leading_zeros( self )
131228 }
229+
230+ fn count_ones( self ) -> u32 {
231+ <Self >:: count_ones( self )
232+ }
132233 } ;
133234}
134235
@@ -178,11 +279,111 @@ macro_rules! int_impl {
178279 } ;
179280}
180281
282+ int_impl ! ( isize , usize , usize :: MAX . count_ones( ) ) ;
283+ int_impl ! ( i8 , u8 , 8 ) ;
181284int_impl ! ( i16 , u16 , 16 ) ;
182285int_impl ! ( i32 , u32 , 32 ) ;
183286int_impl ! ( i64 , u64 , 64 ) ;
184287int_impl ! ( i128 , u128 , 128 ) ;
185288
289+ /// Trait for integers twice the bit width of another integer. This is implemented for all
290+ /// primitives except for `u8`, because there is not a smaller primitive.
291+ #[ doc( hidden) ]
292+ pub trait DInt : Int {
293+ /// Integer that is half the bit width of the integer this trait is implemented for
294+ type H : HInt < D = Self > + Int ;
295+
296+ /// Returns the low half of `self`
297+ fn lo ( self ) -> Self :: H ;
298+ /// Returns the high half of `self`
299+ fn hi ( self ) -> Self :: H ;
300+ /// Returns the low and high halves of `self` as a tuple
301+ fn lo_hi ( self ) -> ( Self :: H , Self :: H ) ;
302+ /// Constructs an integer using lower and higher half parts
303+ fn from_lo_hi ( lo : Self :: H , hi : Self :: H ) -> Self ;
304+ }
305+
306+ /// Trait for integers half the bit width of another integer. This is implemented for all
307+ /// primitives except for `u128`, because it there is not a larger primitive.
308+ #[ doc( hidden) ]
309+ pub trait HInt : Int {
310+ /// Integer that is double the bit width of the integer this trait is implemented for
311+ type D : DInt < H = Self > + Int ;
312+
313+ /// Widens (using default extension) the integer to have double bit width
314+ fn widen ( self ) -> Self :: D ;
315+ /// Widens (zero extension only) the integer to have double bit width. This is needed to get
316+ /// around problems with associated type bounds (such as `Int<Othersign: DInt>`) being unstable
317+ fn zero_widen ( self ) -> Self :: D ;
318+ /// Widens the integer to have double bit width and shifts the integer into the higher bits
319+ fn widen_hi ( self ) -> Self :: D ;
320+ /// Widening multiplication with zero widening. This cannot overflow.
321+ fn zero_widen_mul ( self , rhs : Self ) -> Self :: D ;
322+ /// Widening multiplication. This cannot overflow.
323+ fn widen_mul ( self , rhs : Self ) -> Self :: D ;
324+ }
325+
326+ macro_rules! impl_d_int {
327+ ( $( $X: ident $D: ident) ,* ) => {
328+ $(
329+ impl DInt for $D {
330+ type H = $X;
331+
332+ fn lo( self ) -> Self :: H {
333+ self as $X
334+ }
335+ fn hi( self ) -> Self :: H {
336+ ( self >> <$X as Int >:: BITS ) as $X
337+ }
338+ fn lo_hi( self ) -> ( Self :: H , Self :: H ) {
339+ ( self . lo( ) , self . hi( ) )
340+ }
341+ fn from_lo_hi( lo: Self :: H , hi: Self :: H ) -> Self {
342+ lo. zero_widen( ) | hi. widen_hi( )
343+ }
344+ }
345+ ) *
346+ } ;
347+ }
348+
349+ macro_rules! impl_h_int {
350+ ( $( $H: ident $uH: ident $X: ident) ,* ) => {
351+ $(
352+ impl HInt for $H {
353+ type D = $X;
354+
355+ fn widen( self ) -> Self :: D {
356+ self as $X
357+ }
358+ fn zero_widen( self ) -> Self :: D {
359+ ( self as $uH) as $X
360+ }
361+ fn widen_hi( self ) -> Self :: D {
362+ ( self as $X) << <$H as Int >:: BITS
363+ }
364+ fn zero_widen_mul( self , rhs: Self ) -> Self :: D {
365+ self . zero_widen( ) . wrapping_mul( rhs. zero_widen( ) )
366+ }
367+ fn widen_mul( self , rhs: Self ) -> Self :: D {
368+ self . widen( ) . wrapping_mul( rhs. widen( ) )
369+ }
370+ }
371+ ) *
372+ } ;
373+ }
374+
375+ impl_d_int ! ( u8 u16 , u16 u32 , u32 u64 , u64 u128 , i8 i16 , i16 i32 , i32 i64 , i64 i128 ) ;
376+ impl_h_int ! (
377+ u8 u8 u16 ,
378+ u16 u16 u32 ,
379+ u32 u32 u64 ,
380+ u64 u64 u128 ,
381+ i8 u8 i16 ,
382+ i16 u16 i32 ,
383+ i32 u32 i64 ,
384+ i64 u64 i128
385+ ) ;
386+
186387/// Trait to convert an integer to/from smaller parts
187388pub ( crate ) trait LargeInt : Int {
188389 type LowHalf : Int ;
0 commit comments