2017-06-22 22:03:07 -07:00
|
|
|
use core::ops;
|
|
|
|
|
|
2020-07-11 12:15:10 -05:00
|
|
|
mod specialized_div_rem;
|
2016-08-17 15:50:24 -05:00
|
|
|
|
2017-11-25 07:00:26 -08:00
|
|
|
pub mod addsub;
|
2020-07-28 13:09:18 -05:00
|
|
|
pub mod leading_zeros;
|
2016-08-17 15:50:24 -05:00
|
|
|
pub mod mul;
|
|
|
|
|
pub mod sdiv;
|
|
|
|
|
pub mod shift;
|
|
|
|
|
pub mod udiv;
|
|
|
|
|
|
2020-07-28 13:09:18 -05:00
|
|
|
pub use self::leading_zeros::__clzsi2;
|
|
|
|
|
|
2016-08-17 15:50:24 -05:00
|
|
|
/// Trait for some basic operations on integers
|
2020-10-12 17:58:02 -05:00
|
|
|
#[doc(hidden)]
|
|
|
|
|
pub trait Int:
|
2019-05-14 14:33:08 -07:00
|
|
|
Copy
|
2020-12-08 19:28:05 -06:00
|
|
|
+ core::fmt::Debug
|
2019-05-14 14:33:08 -07:00
|
|
|
+ PartialEq
|
|
|
|
|
+ PartialOrd
|
|
|
|
|
+ ops::AddAssign
|
2020-12-08 19:28:05 -06:00
|
|
|
+ ops::SubAssign
|
2019-05-14 14:33:08 -07:00
|
|
|
+ ops::BitAndAssign
|
|
|
|
|
+ ops::BitOrAssign
|
2020-10-12 17:58:02 -05:00
|
|
|
+ ops::BitXorAssign
|
2019-05-14 14:33:08 -07:00
|
|
|
+ ops::ShlAssign<i32>
|
|
|
|
|
+ ops::ShrAssign<u32>
|
|
|
|
|
+ ops::Add<Output = Self>
|
|
|
|
|
+ ops::Sub<Output = Self>
|
|
|
|
|
+ ops::Div<Output = Self>
|
|
|
|
|
+ ops::Shl<u32, Output = Self>
|
|
|
|
|
+ ops::Shr<u32, Output = Self>
|
|
|
|
|
+ ops::BitOr<Output = Self>
|
|
|
|
|
+ ops::BitXor<Output = Self>
|
|
|
|
|
+ ops::BitAnd<Output = Self>
|
|
|
|
|
+ ops::Not<Output = Self>
|
2017-06-22 22:03:07 -07:00
|
|
|
{
|
2017-01-05 02:22:44 +01:00
|
|
|
/// Type with the same width but other signedness
|
2017-06-22 22:03:07 -07:00
|
|
|
type OtherSign: Int;
|
2016-12-06 05:16:19 +01:00
|
|
|
/// Unsigned version of Self
|
2017-06-22 22:03:07 -07:00
|
|
|
type UnsignedInt: Int;
|
2016-12-06 05:16:19 +01:00
|
|
|
|
2020-12-08 19:28:05 -06:00
|
|
|
/// If `Self` is a signed integer
|
|
|
|
|
const SIGNED: bool;
|
|
|
|
|
|
2017-09-13 21:01:40 +02:00
|
|
|
/// The bitwidth of the int type
|
|
|
|
|
const BITS: u32;
|
2016-12-06 05:16:19 +01:00
|
|
|
|
2017-09-13 21:01:40 +02:00
|
|
|
const ZERO: Self;
|
|
|
|
|
const ONE: Self;
|
2020-10-12 17:58:02 -05:00
|
|
|
const MIN: Self;
|
2020-12-08 19:28:05 -06:00
|
|
|
const MAX: Self;
|
2020-10-12 17:58:02 -05:00
|
|
|
|
|
|
|
|
/// 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;
|
2017-06-22 22:03:07 -07:00
|
|
|
|
|
|
|
|
fn unsigned(self) -> Self::UnsignedInt;
|
2017-06-22 23:09:28 -07:00
|
|
|
fn from_unsigned(unsigned: Self::UnsignedInt) -> Self;
|
2017-06-22 22:36:37 -07:00
|
|
|
|
2017-09-14 16:32:50 +02:00
|
|
|
fn from_bool(b: bool) -> Self;
|
|
|
|
|
|
2020-10-12 17:58:02 -05:00
|
|
|
/// Prevents the need for excessive conversions between signed and unsigned
|
|
|
|
|
fn logical_shr(self, other: u32) -> Self;
|
|
|
|
|
|
2020-12-07 23:25:42 -06:00
|
|
|
/// Absolute difference between two integers.
|
|
|
|
|
fn abs_diff(self, other: Self) -> Self::UnsignedInt;
|
|
|
|
|
|
2017-06-22 22:36:37 -07:00
|
|
|
// copied from primitive integers, but put in a trait
|
2020-10-12 17:58:02 -05:00
|
|
|
fn is_zero(self) -> bool;
|
|
|
|
|
fn wrapping_neg(self) -> Self;
|
2017-06-22 22:36:37 -07:00
|
|
|
fn wrapping_add(self, other: Self) -> Self;
|
|
|
|
|
fn wrapping_mul(self, other: Self) -> Self;
|
2017-06-22 23:09:28 -07:00
|
|
|
fn wrapping_sub(self, other: Self) -> Self;
|
2017-09-14 16:32:50 +02:00
|
|
|
fn wrapping_shl(self, other: u32) -> Self;
|
2020-10-12 17:58:02 -05:00
|
|
|
fn wrapping_shr(self, other: u32) -> Self;
|
|
|
|
|
fn rotate_left(self, other: u32) -> Self;
|
2017-11-25 04:21:05 -08:00
|
|
|
fn overflowing_add(self, other: Self) -> (Self, bool);
|
2017-09-14 16:32:50 +02:00
|
|
|
fn leading_zeros(self) -> u32;
|
2017-06-23 21:31:54 -07:00
|
|
|
}
|
|
|
|
|
|
2017-09-14 17:39:25 +02:00
|
|
|
macro_rules! int_impl_common {
|
2021-02-05 23:40:17 +01:00
|
|
|
($ty:ty) => {
|
|
|
|
|
const BITS: u32 = <Self>::BITS;
|
2020-12-08 19:28:05 -06:00
|
|
|
const SIGNED: bool = Self::MIN != Self::ZERO;
|
2017-06-22 22:36:37 -07:00
|
|
|
|
2020-04-29 15:30:10 -05:00
|
|
|
const ZERO: Self = 0;
|
|
|
|
|
const ONE: Self = 1;
|
2020-10-12 17:58:02 -05:00
|
|
|
const MIN: Self = <Self>::MIN;
|
2020-12-08 19:28:05 -06:00
|
|
|
const MAX: Self = <Self>::MAX;
|
2020-10-12 17:58:02 -05:00
|
|
|
|
|
|
|
|
const FUZZ_LENGTHS: [u8; 20] = {
|
|
|
|
|
let bits = <Self as Int>::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 = (<Self as Int>::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))
|
|
|
|
|
}
|
|
|
|
|
};
|
2016-12-06 05:16:19 +01:00
|
|
|
|
2020-04-29 15:30:10 -05:00
|
|
|
fn from_bool(b: bool) -> Self {
|
|
|
|
|
b as $ty
|
|
|
|
|
}
|
2017-09-14 16:32:50 +02:00
|
|
|
|
2020-10-12 17:58:02 -05:00
|
|
|
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 {
|
|
|
|
|
<Self>::wrapping_neg(self)
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-29 15:30:10 -05:00
|
|
|
fn wrapping_add(self, other: Self) -> Self {
|
|
|
|
|
<Self>::wrapping_add(self, other)
|
|
|
|
|
}
|
2017-06-22 22:36:37 -07:00
|
|
|
|
2020-04-29 15:30:10 -05:00
|
|
|
fn wrapping_mul(self, other: Self) -> Self {
|
|
|
|
|
<Self>::wrapping_mul(self, other)
|
|
|
|
|
}
|
2017-06-22 23:09:28 -07:00
|
|
|
|
2020-04-29 15:30:10 -05:00
|
|
|
fn wrapping_sub(self, other: Self) -> Self {
|
|
|
|
|
<Self>::wrapping_sub(self, other)
|
|
|
|
|
}
|
2017-06-22 23:09:28 -07:00
|
|
|
|
2020-04-29 15:30:10 -05:00
|
|
|
fn wrapping_shl(self, other: u32) -> Self {
|
|
|
|
|
<Self>::wrapping_shl(self, other)
|
|
|
|
|
}
|
2017-09-14 16:32:50 +02:00
|
|
|
|
2020-10-12 17:58:02 -05:00
|
|
|
fn wrapping_shr(self, other: u32) -> Self {
|
|
|
|
|
<Self>::wrapping_shr(self, other)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn rotate_left(self, other: u32) -> Self {
|
|
|
|
|
<Self>::rotate_left(self, other)
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-29 15:30:10 -05:00
|
|
|
fn overflowing_add(self, other: Self) -> (Self, bool) {
|
|
|
|
|
<Self>::overflowing_add(self, other)
|
|
|
|
|
}
|
2017-11-25 04:21:05 -08:00
|
|
|
|
2020-04-29 15:30:10 -05:00
|
|
|
fn leading_zeros(self) -> u32 {
|
|
|
|
|
<Self>::leading_zeros(self)
|
|
|
|
|
}
|
|
|
|
|
};
|
2017-09-14 17:39:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! int_impl {
|
2021-02-05 23:40:17 +01:00
|
|
|
($ity:ty, $uty:ty) => {
|
2017-09-14 17:39:25 +02:00
|
|
|
impl Int for $uty {
|
|
|
|
|
type OtherSign = $ity;
|
|
|
|
|
type UnsignedInt = $uty;
|
|
|
|
|
|
|
|
|
|
fn unsigned(self) -> $uty {
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn from_unsigned(me: $uty) -> Self {
|
|
|
|
|
me
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-07 23:25:42 -06:00
|
|
|
fn abs_diff(self, other: Self) -> Self {
|
2020-12-10 17:00:45 -06:00
|
|
|
if self < other {
|
|
|
|
|
other.wrapping_sub(self)
|
|
|
|
|
} else {
|
|
|
|
|
self.wrapping_sub(other)
|
|
|
|
|
}
|
2020-12-07 23:25:42 -06:00
|
|
|
}
|
|
|
|
|
|
2021-02-05 23:40:17 +01:00
|
|
|
int_impl_common!($uty);
|
2017-01-04 01:52:47 +01:00
|
|
|
}
|
2016-12-06 05:16:19 +01:00
|
|
|
|
2017-03-06 12:17:10 -05:00
|
|
|
impl Int for $ity {
|
|
|
|
|
type OtherSign = $uty;
|
|
|
|
|
type UnsignedInt = $uty;
|
2016-12-06 05:16:19 +01:00
|
|
|
|
2017-06-22 22:03:07 -07:00
|
|
|
fn unsigned(self) -> $uty {
|
|
|
|
|
self as $uty
|
|
|
|
|
}
|
2017-06-22 22:36:37 -07:00
|
|
|
|
2017-06-22 23:09:28 -07:00
|
|
|
fn from_unsigned(me: $uty) -> Self {
|
|
|
|
|
me as $ity
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-07 23:25:42 -06:00
|
|
|
fn abs_diff(self, other: Self) -> $uty {
|
|
|
|
|
self.wrapping_sub(other).wrapping_abs() as $uty
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-05 23:40:17 +01:00
|
|
|
int_impl_common!($ity);
|
2016-12-06 05:16:19 +01:00
|
|
|
}
|
2019-05-14 14:33:08 -07:00
|
|
|
};
|
2016-12-06 05:16:19 +01:00
|
|
|
}
|
2017-01-04 01:52:47 +01:00
|
|
|
|
2021-02-05 23:40:17 +01:00
|
|
|
int_impl!(isize, usize);
|
|
|
|
|
int_impl!(i8, u8);
|
|
|
|
|
int_impl!(i16, u16);
|
|
|
|
|
int_impl!(i32, u32);
|
|
|
|
|
int_impl!(i64, u64);
|
|
|
|
|
int_impl!(i128, u128);
|
2017-03-06 12:17:10 -05:00
|
|
|
|
2020-10-12 17:58:02 -05:00
|
|
|
/// 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.
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
|
pub trait DInt: Int {
|
|
|
|
|
/// Integer that is half the bit width of the integer this trait is implemented for
|
|
|
|
|
type H: HInt<D = Self> + 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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.
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
|
pub trait HInt: Int {
|
|
|
|
|
/// Integer that is double the bit width of the integer this trait is implemented for
|
|
|
|
|
type D: DInt<H = Self> + 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<Othersign: DInt>`) 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
|
|
|
|
|
);
|
|
|
|
|
|
2017-09-14 14:59:32 +02:00
|
|
|
/// Trait to express (possibly lossy) casting of integers
|
2020-12-08 19:28:05 -06:00
|
|
|
#[doc(hidden)]
|
|
|
|
|
pub trait CastInto<T: Copy>: Copy {
|
2017-09-14 14:59:32 +02:00
|
|
|
fn cast(self) -> T;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! cast_into {
|
|
|
|
|
($ty:ty) => {
|
2020-12-08 19:28:05 -06:00
|
|
|
cast_into!($ty; usize, isize, u8, i8, u16, i16, u32, i32, u64, i64, u128, i128);
|
2017-09-14 14:59:32 +02:00
|
|
|
};
|
|
|
|
|
($ty:ty; $($into:ty),*) => {$(
|
|
|
|
|
impl CastInto<$into> for $ty {
|
|
|
|
|
fn cast(self) -> $into {
|
|
|
|
|
self as $into
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)*};
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-08 19:28:05 -06:00
|
|
|
cast_into!(usize);
|
|
|
|
|
cast_into!(isize);
|
|
|
|
|
cast_into!(u8);
|
|
|
|
|
cast_into!(i8);
|
|
|
|
|
cast_into!(u16);
|
|
|
|
|
cast_into!(i16);
|
2017-09-14 14:59:32 +02:00
|
|
|
cast_into!(u32);
|
|
|
|
|
cast_into!(i32);
|
|
|
|
|
cast_into!(u64);
|
|
|
|
|
cast_into!(i64);
|
|
|
|
|
cast_into!(u128);
|
|
|
|
|
cast_into!(i128);
|