@@ -12,13 +12,15 @@ pub mod udiv;
12
12
pub use self :: leading_zeros:: __clzsi2;
13
13
14
14
/// Trait for some basic operations on integers
15
- pub ( crate ) trait Int :
15
+ #[ doc( hidden) ]
16
+ pub trait Int :
16
17
Copy
17
18
+ PartialEq
18
19
+ PartialOrd
19
20
+ ops:: AddAssign
20
21
+ ops:: BitAndAssign
21
22
+ ops:: BitOrAssign
23
+ + ops:: BitXorAssign
22
24
+ ops:: ShlAssign < i32 >
23
25
+ ops:: ShrAssign < u32 >
24
26
+ ops:: Add < Output = Self >
@@ -41,6 +43,14 @@ pub(crate) trait Int:
41
43
42
44
const ZERO : Self ;
43
45
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 ;
44
54
45
55
/// Extracts the sign from self and returns a tuple.
46
56
///
@@ -59,17 +69,25 @@ pub(crate) trait Int:
59
69
60
70
fn from_bool ( b : bool ) -> Self ;
61
71
72
+ /// Prevents the need for excessive conversions between signed and unsigned
73
+ fn logical_shr ( self , other : u32 ) -> Self ;
74
+
62
75
// copied from primitive integers, but put in a trait
76
+ fn is_zero ( self ) -> bool ;
63
77
fn max_value ( ) -> Self ;
64
78
fn min_value ( ) -> Self ;
79
+ fn wrapping_neg ( self ) -> Self ;
65
80
fn wrapping_add ( self , other : Self ) -> Self ;
66
81
fn wrapping_mul ( self , other : Self ) -> Self ;
67
82
fn wrapping_sub ( self , other : Self ) -> Self ;
68
83
fn wrapping_shl ( self , other : u32 ) -> Self ;
84
+ fn wrapping_shr ( self , other : u32 ) -> Self ;
85
+ fn rotate_left ( self , other : u32 ) -> Self ;
69
86
fn overflowing_add ( self , other : Self ) -> ( Self , bool ) ;
70
87
fn aborting_div ( self , other : Self ) -> Self ;
71
88
fn aborting_rem ( self , other : Self ) -> Self ;
72
89
fn leading_zeros ( self ) -> u32 ;
90
+ fn count_ones ( self ) -> u32 ;
73
91
}
74
92
75
93
fn unwrap < T > ( t : Option < T > ) -> T {
@@ -85,11 +103,78 @@ macro_rules! int_impl_common {
85
103
86
104
const ZERO : Self = 0 ;
87
105
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
+ } ;
88
165
89
166
fn from_bool( b: bool ) -> Self {
90
167
b as $ty
91
168
}
92
169
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
+
93
178
fn max_value( ) -> Self {
94
179
<Self >:: max_value( )
95
180
}
@@ -98,6 +183,10 @@ macro_rules! int_impl_common {
98
183
<Self >:: min_value( )
99
184
}
100
185
186
+ fn wrapping_neg( self ) -> Self {
187
+ <Self >:: wrapping_neg( self )
188
+ }
189
+
101
190
fn wrapping_add( self , other: Self ) -> Self {
102
191
<Self >:: wrapping_add( self , other)
103
192
}
@@ -114,6 +203,14 @@ macro_rules! int_impl_common {
114
203
<Self >:: wrapping_shl( self , other)
115
204
}
116
205
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
+
117
214
fn overflowing_add( self , other: Self ) -> ( Self , bool ) {
118
215
<Self >:: overflowing_add( self , other)
119
216
}
@@ -129,6 +226,10 @@ macro_rules! int_impl_common {
129
226
fn leading_zeros( self ) -> u32 {
130
227
<Self >:: leading_zeros( self )
131
228
}
229
+
230
+ fn count_ones( self ) -> u32 {
231
+ <Self >:: count_ones( self )
232
+ }
132
233
} ;
133
234
}
134
235
@@ -178,11 +279,111 @@ macro_rules! int_impl {
178
279
} ;
179
280
}
180
281
282
+ int_impl ! ( isize , usize , usize :: MAX . count_ones( ) ) ;
283
+ int_impl ! ( i8 , u8 , 8 ) ;
181
284
int_impl ! ( i16 , u16 , 16 ) ;
182
285
int_impl ! ( i32 , u32 , 32 ) ;
183
286
int_impl ! ( i64 , u64 , 64 ) ;
184
287
int_impl ! ( i128 , u128 , 128 ) ;
185
288
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
+
186
387
/// Trait to convert an integer to/from smaller parts
187
388
pub ( crate ) trait LargeInt : Int {
188
389
type LowHalf : Int ;
0 commit comments