@@ -40,6 +40,75 @@ pub const N: u32 = if cfg!(target_arch = "x86_64") && !cfg!(debug_assertions) {
4040    10_000 
4141} ; 
4242
43+ /// Additional constants that determine how the integer gets fuzzed. 
44+ trait  FuzzInt :  MinInt  { 
45+     /// LUT used for maximizing the space covered and minimizing the computational cost of fuzzing 
46+ /// in `builtins-test`. For example, Self = u128 produces [0,1,2,7,8,15,16,31,32,63,64,95,96, 
47+ /// 111,112,119,120,125,126,127]. 
48+ const  FUZZ_LENGTHS :  [ u8 ;  20 ]  = make_fuzz_lengths ( Self :: BITS ) ; 
49+ 
50+     /// The number of entries of `FUZZ_LENGTHS` actually used. The maximum is 20 for u128. 
51+ const  FUZZ_NUM :  usize  = { 
52+         let  log2 = Self :: BITS . ilog2 ( )  as  usize ; 
53+         if  log2 == 3  { 
54+             // case for u8 
55+             6 
56+         }  else  { 
57+             // 3 entries on each extreme, 2 in the middle, and 4 for each scale of intermediate 
58+             // boundaries. 
59+             8  + ( 4  *  ( log2 - 4 ) ) 
60+         } 
61+     } ; 
62+ } 
63+ 
64+ impl < I >  FuzzInt  for  I  where  I :  MinInt  { } 
65+ 
66+ const  fn  make_fuzz_lengths ( bits :  u32 )  -> [ u8 ;  20 ]  { 
67+     let  mut  v = [ 0u8 ;  20 ] ; 
68+     v[ 0 ]  = 0 ; 
69+     v[ 1 ]  = 1 ; 
70+     v[ 2 ]  = 2 ;  // important for parity and the iX::MIN case when reversed 
71+     let  mut  i = 3 ; 
72+ 
73+     // No need for any more until the byte boundary, because there should be no algorithms 
74+     // that are sensitive to anything not next to byte boundaries after 2. We also scale 
75+     // in powers of two, which is important to prevent u128 corner tests from getting too 
76+     // big. 
77+     let  mut  l = 8 ; 
78+     loop  { 
79+         if  l >= ( ( bits / 2 )  as  u8 )  { 
80+             break ; 
81+         } 
82+         // get both sides of the byte boundary 
83+         v[ i]  = l - 1 ; 
84+         i += 1 ; 
85+         v[ i]  = l; 
86+         i += 1 ; 
87+         l *= 2 ; 
88+     } 
89+ 
90+     if  bits != 8  { 
91+         // add the lower side of the middle boundary 
92+         v[ i]  = ( ( bits / 2 )  - 1 )  as  u8 ; 
93+         i += 1 ; 
94+     } 
95+ 
96+     // We do not want to jump directly from the Self::BITS/2 boundary to the Self::BITS 
97+     // boundary because of algorithms that split the high part up. We reverse the scaling 
98+     // as we go to Self::BITS. 
99+     let  mid = i; 
100+     let  mut  j = 1 ; 
101+     loop  { 
102+         v[ i]  = ( bits as  u8 )  - ( v[ mid - j] )  - 1 ; 
103+         if  j == mid { 
104+             break ; 
105+         } 
106+         i += 1 ; 
107+         j += 1 ; 
108+     } 
109+     v
110+ } 
111+ 
43112/// Random fuzzing step. When run several times, it results in excellent fuzzing entropy such as: 
44113/// 11110101010101011110111110011111 
45114/// 10110101010100001011101011001010 
@@ -92,10 +161,9 @@ fn fuzz_step<I: Int>(rng: &mut Xoshiro128StarStar, x: &mut I) {
92161macro_rules!  edge_cases { 
93162    ( $I: ident,  $case: ident,  $inner: block)  => { 
94163        for  i0 in 0 ..$I:: FUZZ_NUM  { 
95-             let  mask_lo = ( !$I:: UnsignedInt :: ZERO ) . wrapping_shr( $I:: FUZZ_LENGTHS [ i0]  as  u32 ) ; 
164+             let  mask_lo = ( !$I:: Unsigned :: ZERO ) . wrapping_shr( $I:: FUZZ_LENGTHS [ i0]  as  u32 ) ; 
96165            for  i1 in i0..I :: FUZZ_NUM  { 
97-                 let  mask_hi =
98-                     ( !$I:: UnsignedInt :: ZERO ) . wrapping_shl( $I:: FUZZ_LENGTHS [ i1 - i0]  as  u32 ) ; 
166+                 let  mask_hi = ( !$I:: Unsigned :: ZERO ) . wrapping_shl( $I:: FUZZ_LENGTHS [ i1 - i0]  as  u32 ) ; 
99167                let  $case = I :: from_unsigned( mask_lo &  mask_hi) ; 
100168                $inner
101169            } 
@@ -107,7 +175,7 @@ macro_rules! edge_cases {
107175/// edge cases, followed by a more random fuzzer that runs `n` times. 
108176pub  fn  fuzz < I :  Int ,  F :  FnMut ( I ) > ( n :  u32 ,  mut  f :  F ) 
109177where 
110-     <I  as  MinInt >:: UnsignedInt :  Int , 
178+     <I  as  MinInt >:: Unsigned :  Int , 
111179{ 
112180    // edge case tester. Calls `f` 210 times for u128. 
113181    // zero gets skipped by the loop 
@@ -128,7 +196,7 @@ where
128196/// The same as `fuzz`, except `f` has two inputs. 
129197pub  fn  fuzz_2 < I :  Int ,  F :  Fn ( I ,  I ) > ( n :  u32 ,  f :  F ) 
130198where 
131-     <I  as  MinInt >:: UnsignedInt :  Int , 
199+     <I  as  MinInt >:: Unsigned :  Int , 
132200{ 
133201    // Check cases where the first and second inputs are zero. Both call `f` 210 times for `u128`. 
134202    edge_cases ! ( I ,  case,  { 
0 commit comments