123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- 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;
- /// Trait for some basic operations on integers
- #[doc(hidden)]
- pub trait Int:
- Copy
- + PartialEq
- + PartialOrd
- + ops::AddAssign
- + ops::BitAndAssign
- + ops::BitOrAssign
- + ops::BitXorAssign
- + 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>
- {
- /// Type with the same width but other signedness
- type OtherSign: Int;
- /// Unsigned version of Self
- type UnsignedInt: Int;
- /// The bitwidth of the int type
- const BITS: u32;
- const ZERO: Self;
- const ONE: Self;
- const MIN: 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;
- /// Extracts the sign from self and returns a tuple.
- ///
- /// # Examples
- ///
- /// ```rust,ignore
- /// let i = -25_i32;
- /// let (sign, u) = i.extract_sign();
- /// assert_eq!(sign, true);
- /// assert_eq!(u, 25_u32);
- /// ```
- fn extract_sign(self) -> (bool, Self::UnsignedInt);
- 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;
- // copied from primitive integers, but put in a trait
- fn is_zero(self) -> bool;
- fn max_value() -> Self;
- fn min_value() -> Self;
- 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 aborting_div(self, other: Self) -> Self;
- fn aborting_rem(self, other: Self) -> Self;
- fn leading_zeros(self) -> u32;
- fn count_ones(self) -> u32;
- }
- fn unwrap<T>(t: Option<T>) -> T {
- match t {
- Some(t) => t,
- None => ::abort(),
- }
- }
- macro_rules! int_impl_common {
- ($ty:ty, $bits:expr) => {
- const BITS: u32 = $bits;
- const ZERO: Self = 0;
- const ONE: Self = 1;
- const MIN: Self = <Self>::MIN;
- 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))
- }
- };
- 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 max_value() -> Self {
- <Self>::max_value()
- }
- fn min_value() -> Self {
- <Self>::min_value()
- }
- fn wrapping_neg(self) -> Self {
- <Self>::wrapping_neg(self)
- }
- fn wrapping_add(self, other: Self) -> Self {
- <Self>::wrapping_add(self, other)
- }
- fn wrapping_mul(self, other: Self) -> Self {
- <Self>::wrapping_mul(self, other)
- }
- fn wrapping_sub(self, other: Self) -> Self {
- <Self>::wrapping_sub(self, other)
- }
- fn wrapping_shl(self, other: u32) -> Self {
- <Self>::wrapping_shl(self, other)
- }
- fn wrapping_shr(self, other: u32) -> Self {
- <Self>::wrapping_shr(self, other)
- }
- fn rotate_left(self, other: u32) -> Self {
- <Self>::rotate_left(self, other)
- }
- fn overflowing_add(self, other: Self) -> (Self, bool) {
- <Self>::overflowing_add(self, other)
- }
- fn aborting_div(self, other: Self) -> Self {
- unwrap(<Self>::checked_div(self, other))
- }
- fn aborting_rem(self, other: Self) -> Self {
- unwrap(<Self>::checked_rem(self, other))
- }
- fn leading_zeros(self) -> u32 {
- <Self>::leading_zeros(self)
- }
- fn count_ones(self) -> u32 {
- <Self>::count_ones(self)
- }
- };
- }
- macro_rules! int_impl {
- ($ity:ty, $uty:ty, $bits:expr) => {
- impl Int for $uty {
- type OtherSign = $ity;
- type UnsignedInt = $uty;
- fn extract_sign(self) -> (bool, $uty) {
- (false, self)
- }
- fn unsigned(self) -> $uty {
- self
- }
- fn from_unsigned(me: $uty) -> Self {
- me
- }
- int_impl_common!($uty, $bits);
- }
- impl Int for $ity {
- type OtherSign = $uty;
- type UnsignedInt = $uty;
- fn extract_sign(self) -> (bool, $uty) {
- if self < 0 {
- (true, (!(self as $uty)).wrapping_add(1))
- } else {
- (false, self as $uty)
- }
- }
- fn unsigned(self) -> $uty {
- self as $uty
- }
- fn from_unsigned(me: $uty) -> Self {
- me as $ity
- }
- int_impl_common!($ity, $bits);
- }
- };
- }
- int_impl!(isize, usize, usize::MAX.count_ones());
- int_impl!(i8, u8, 8);
- int_impl!(i16, u16, 16);
- int_impl!(i32, u32, 32);
- int_impl!(i64, u64, 64);
- int_impl!(i128, u128, 128);
- /// 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
- );
- /// Trait to convert an integer to/from smaller parts
- pub(crate) trait LargeInt: Int {
- type LowHalf: Int;
- type HighHalf: Int;
- fn low(self) -> Self::LowHalf;
- fn low_as_high(low: Self::LowHalf) -> Self::HighHalf;
- fn high(self) -> Self::HighHalf;
- fn high_as_low(low: Self::HighHalf) -> Self::LowHalf;
- fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
- }
- macro_rules! large_int {
- ($ty:ty, $tylow:ty, $tyhigh:ty, $halfbits:expr) => {
- impl LargeInt for $ty {
- type LowHalf = $tylow;
- type HighHalf = $tyhigh;
- fn low(self) -> $tylow {
- self as $tylow
- }
- fn low_as_high(low: $tylow) -> $tyhigh {
- low as $tyhigh
- }
- fn high(self) -> $tyhigh {
- (self >> $halfbits) as $tyhigh
- }
- fn high_as_low(high: $tyhigh) -> $tylow {
- high as $tylow
- }
- fn from_parts(low: $tylow, high: $tyhigh) -> $ty {
- low as $ty | ((high as $ty) << $halfbits)
- }
- }
- };
- }
- large_int!(u32, u16, u16, 16);
- large_int!(i32, u16, i16, 16);
- large_int!(u64, u32, u32, 32);
- large_int!(i64, u32, i32, 32);
- large_int!(u128, u64, u64, 64);
- large_int!(i128, u64, i64, 64);
- /// Trait to express (possibly lossy) casting of integers
- pub(crate) trait CastInto<T: Copy>: Copy {
- fn cast(self) -> T;
- }
- macro_rules! cast_into {
- ($ty:ty) => {
- cast_into!($ty; usize, isize, u32, i32, u64, i64, u128, i128);
- };
- ($ty:ty; $($into:ty),*) => {$(
- impl CastInto<$into> for $ty {
- fn cast(self) -> $into {
- self as $into
- }
- }
- )*};
- }
- cast_into!(u32);
- cast_into!(i32);
- cast_into!(u64);
- cast_into!(i64);
- cast_into!(u128);
- cast_into!(i128);
- pub(crate) trait WideInt: Int {
- type Output: Int;
- fn wide_mul(self, other: Self) -> (Self, Self);
- fn wide_shift_left(&mut self, low: &mut Self, count: i32);
- fn wide_shift_right_with_sticky(&mut self, low: &mut Self, count: i32);
- }
- macro_rules! impl_wide_int {
- ($ty:ty, $tywide:ty, $bits:expr) => {
- impl WideInt for $ty {
- type Output = $ty;
- fn wide_mul(self, other: Self) -> (Self, Self) {
- let product = (self as $tywide).wrapping_mul(other as $tywide);
- ((product >> ($bits as $ty)) as $ty, product as $ty)
- }
- fn wide_shift_left(&mut self, low: &mut Self, count: i32) {
- *self = (*self << count) | (*low >> ($bits - count));
- *low = *low << count;
- }
- fn wide_shift_right_with_sticky(&mut self, low: &mut Self, count: i32) {
- if count < $bits {
- let sticky = *low << ($bits - count);
- *low = *self << ($bits - count) | *low >> count | sticky;
- *self = *self >> count;
- } else if count < 2 * $bits {
- let sticky = *self << (2 * $bits - count) | *low;
- *low = *self >> (count - $bits) | sticky;
- *self = 0;
- } else {
- let sticky = *self | *low;
- *self = sticky;
- *self = 0;
- }
- }
- }
- };
- }
- impl_wide_int!(u32, u64, 32);
- impl_wide_int!(u64, u128, 64);
|