use core::ops; mod specialized_div_rem; pub mod addsub; pub mod leading_zeros; pub mod mul; pub mod sdiv; pub mod shift; pub mod udiv; pub use self::leading_zeros::__clzsi2; public_test_dep! { /// Trait for some basic operations on integers pub(crate) trait Int: Copy + core::fmt::Debug + PartialEq + PartialOrd + ops::AddAssign + ops::SubAssign + ops::BitAndAssign + ops::BitOrAssign + ops::BitXorAssign + ops::ShlAssign + ops::ShrAssign + ops::Add + ops::Sub + ops::Div + ops::Shl + ops::Shr + ops::BitOr + ops::BitXor + ops::BitAnd + ops::Not { /// Type with the same width but other signedness type OtherSign: Int; /// Unsigned version of Self type UnsignedInt: Int; /// If `Self` is a signed integer const SIGNED: bool; /// The bitwidth of the int type const BITS: u32; const ZERO: Self; const ONE: Self; const MIN: Self; const MAX: Self; /// LUT used for maximizing the space covered and minimizing the computational cost of fuzzing /// in `testcrate`. For example, Self = u128 produces [0,1,2,7,8,15,16,31,32,63,64,95,96,111, /// 112,119,120,125,126,127]. const FUZZ_LENGTHS: [u8; 20]; /// The number of entries of `FUZZ_LENGTHS` actually used. The maximum is 20 for u128. const FUZZ_NUM: usize; fn unsigned(self) -> Self::UnsignedInt; fn from_unsigned(unsigned: Self::UnsignedInt) -> Self; fn from_bool(b: bool) -> Self; /// Prevents the need for excessive conversions between signed and unsigned fn logical_shr(self, other: u32) -> Self; /// Absolute difference between two integers. fn abs_diff(self, other: Self) -> Self::UnsignedInt; // copied from primitive integers, but put in a trait fn is_zero(self) -> bool; fn wrapping_neg(self) -> Self; fn wrapping_add(self, other: Self) -> Self; fn wrapping_mul(self, other: Self) -> Self; fn wrapping_sub(self, other: Self) -> Self; fn wrapping_shl(self, other: u32) -> Self; fn wrapping_shr(self, other: u32) -> Self; fn rotate_left(self, other: u32) -> Self; fn overflowing_add(self, other: Self) -> (Self, bool); fn leading_zeros(self) -> u32; } } macro_rules! int_impl_common { ($ty:ty) => { const BITS: u32 = ::ZERO.count_zeros(); const SIGNED: bool = Self::MIN != Self::ZERO; const ZERO: Self = 0; const ONE: Self = 1; const MIN: Self = ::MIN; const MAX: Self = ::MAX; const FUZZ_LENGTHS: [u8; 20] = { let bits = ::BITS; let mut v = [0u8; 20]; v[0] = 0; v[1] = 1; v[2] = 2; // important for parity and the iX::MIN case when reversed let mut i = 3; // No need for any more until the byte boundary, because there should be no algorithms // that are sensitive to anything not next to byte boundaries after 2. We also scale // in powers of two, which is important to prevent u128 corner tests from getting too // big. let mut l = 8; loop { if l >= ((bits / 2) as u8) { break; } // get both sides of the byte boundary v[i] = l - 1; i += 1; v[i] = l; i += 1; l *= 2; } if bits != 8 { // add the lower side of the middle boundary v[i] = ((bits / 2) - 1) as u8; i += 1; } // We do not want to jump directly from the Self::BITS/2 boundary to the Self::BITS // boundary because of algorithms that split the high part up. We reverse the scaling // as we go to Self::BITS. let mid = i; let mut j = 1; loop { v[i] = (bits as u8) - (v[mid - j]) - 1; if j == mid { break; } i += 1; j += 1; } v }; const FUZZ_NUM: usize = { let log2 = (::BITS - 1).count_ones() as usize; if log2 == 3 { // case for u8 6 } else { // 3 entries on each extreme, 2 in the middle, and 4 for each scale of intermediate // boundaries. 8 + (4 * (log2 - 4)) } }; fn from_bool(b: bool) -> Self { b as $ty } fn logical_shr(self, other: u32) -> Self { Self::from_unsigned(self.unsigned().wrapping_shr(other)) } fn is_zero(self) -> bool { self == Self::ZERO } fn wrapping_neg(self) -> Self { ::wrapping_neg(self) } fn wrapping_add(self, other: Self) -> Self { ::wrapping_add(self, other) } fn wrapping_mul(self, other: Self) -> Self { ::wrapping_mul(self, other) } fn wrapping_sub(self, other: Self) -> Self { ::wrapping_sub(self, other) } fn wrapping_shl(self, other: u32) -> Self { ::wrapping_shl(self, other) } fn wrapping_shr(self, other: u32) -> Self { ::wrapping_shr(self, other) } fn rotate_left(self, other: u32) -> Self { ::rotate_left(self, other) } fn overflowing_add(self, other: Self) -> (Self, bool) { ::overflowing_add(self, other) } fn leading_zeros(self) -> u32 { ::leading_zeros(self) } }; } macro_rules! int_impl { ($ity:ty, $uty:ty) => { impl Int for $uty { type OtherSign = $ity; type UnsignedInt = $uty; fn unsigned(self) -> $uty { self } // It makes writing macros easier if this is implemented for both signed and unsigned #[allow(clippy::wrong_self_convention)] fn from_unsigned(me: $uty) -> Self { me } fn abs_diff(self, other: Self) -> Self { if self < other { other.wrapping_sub(self) } else { self.wrapping_sub(other) } } int_impl_common!($uty); } impl Int for $ity { type OtherSign = $uty; type UnsignedInt = $uty; fn unsigned(self) -> $uty { self as $uty } fn from_unsigned(me: $uty) -> Self { me as $ity } fn abs_diff(self, other: Self) -> $uty { self.wrapping_sub(other).wrapping_abs() as $uty } int_impl_common!($ity); } }; } int_impl!(isize, usize); int_impl!(i8, u8); int_impl!(i16, u16); int_impl!(i32, u32); int_impl!(i64, u64); int_impl!(i128, u128); public_test_dep! { /// Trait for integers twice the bit width of another integer. This is implemented for all /// primitives except for `u8`, because there is not a smaller primitive. pub(crate) trait DInt: Int { /// Integer that is half the bit width of the integer this trait is implemented for type H: HInt + Int; /// Returns the low half of `self` fn lo(self) -> Self::H; /// Returns the high half of `self` fn hi(self) -> Self::H; /// Returns the low and high halves of `self` as a tuple fn lo_hi(self) -> (Self::H, Self::H); /// Constructs an integer using lower and higher half parts fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self; } } public_test_dep! { /// Trait for integers half the bit width of another integer. This is implemented for all /// primitives except for `u128`, because it there is not a larger primitive. pub(crate) trait HInt: Int { /// Integer that is double the bit width of the integer this trait is implemented for type D: DInt + Int; /// Widens (using default extension) the integer to have double bit width fn widen(self) -> Self::D; /// Widens (zero extension only) the integer to have double bit width. This is needed to get /// around problems with associated type bounds (such as `Int`) being unstable fn zero_widen(self) -> Self::D; /// Widens the integer to have double bit width and shifts the integer into the higher bits fn widen_hi(self) -> Self::D; /// Widening multiplication with zero widening. This cannot overflow. fn zero_widen_mul(self, rhs: Self) -> Self::D; /// Widening multiplication. This cannot overflow. fn widen_mul(self, rhs: Self) -> Self::D; } } macro_rules! impl_d_int { ($($X:ident $D:ident),*) => { $( impl DInt for $D { type H = $X; fn lo(self) -> Self::H { self as $X } fn hi(self) -> Self::H { (self >> <$X as Int>::BITS) as $X } fn lo_hi(self) -> (Self::H, Self::H) { (self.lo(), self.hi()) } fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self { lo.zero_widen() | hi.widen_hi() } } )* }; } macro_rules! impl_h_int { ($($H:ident $uH:ident $X:ident),*) => { $( impl HInt for $H { type D = $X; fn widen(self) -> Self::D { self as $X } fn zero_widen(self) -> Self::D { (self as $uH) as $X } fn widen_hi(self) -> Self::D { (self as $X) << <$H as Int>::BITS } fn zero_widen_mul(self, rhs: Self) -> Self::D { self.zero_widen().wrapping_mul(rhs.zero_widen()) } fn widen_mul(self, rhs: Self) -> Self::D { self.widen().wrapping_mul(rhs.widen()) } } )* }; } impl_d_int!(u8 u16, u16 u32, u32 u64, u64 u128, i8 i16, i16 i32, i32 i64, i64 i128); impl_h_int!( u8 u8 u16, u16 u16 u32, u32 u32 u64, u64 u64 u128, i8 u8 i16, i16 u16 i32, i32 u32 i64, i64 u64 i128 ); public_test_dep! { /// Trait to express (possibly lossy) casting of integers pub(crate) trait CastInto: Copy { fn cast(self) -> T; } } macro_rules! cast_into { ($ty:ty) => { cast_into!($ty; usize, isize, u8, i8, u16, i16, u32, i32, u64, i64, u128, i128); }; ($ty:ty; $($into:ty),*) => {$( impl CastInto<$into> for $ty { fn cast(self) -> $into { self as $into } } )*}; } cast_into!(usize); cast_into!(isize); cast_into!(u8); cast_into!(i8); cast_into!(u16); cast_into!(i16); cast_into!(u32); cast_into!(i32); cast_into!(u64); cast_into!(i64); cast_into!(u128); cast_into!(i128);