2017-06-23 13:03:07 +08:00
|
|
|
use core::ops;
|
|
|
|
|
2017-01-05 09:22:44 +08:00
|
|
|
macro_rules! hty {
|
|
|
|
($ty:ty) => {
|
|
|
|
<$ty as LargeInt>::HighHalf
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! os_ty {
|
|
|
|
($ty:ty) => {
|
|
|
|
<$ty as Int>::OtherSign
|
|
|
|
}
|
|
|
|
}
|
2016-08-18 04:50:24 +08:00
|
|
|
|
2017-11-25 23:00:26 +08:00
|
|
|
pub mod addsub;
|
2016-08-18 04:50:24 +08:00
|
|
|
pub mod mul;
|
|
|
|
pub mod sdiv;
|
|
|
|
pub mod shift;
|
|
|
|
pub mod udiv;
|
|
|
|
|
|
|
|
/// Trait for some basic operations on integers
|
2017-06-23 13:03:07 +08:00
|
|
|
pub trait Int:
|
|
|
|
Copy +
|
2017-06-23 13:36:37 +08:00
|
|
|
PartialEq +
|
|
|
|
PartialOrd +
|
|
|
|
ops::AddAssign +
|
2017-09-14 22:32:50 +08:00
|
|
|
ops::BitAndAssign +
|
|
|
|
ops::BitOrAssign +
|
2017-09-14 23:33:44 +08:00
|
|
|
ops::ShlAssign<i32> +
|
2017-09-14 22:32:50 +08:00
|
|
|
ops::ShrAssign<u32> +
|
2017-06-23 13:36:37 +08:00
|
|
|
ops::Add<Output = Self> +
|
|
|
|
ops::Sub<Output = Self> +
|
|
|
|
ops::Div<Output = Self> +
|
2017-06-23 13:03:07 +08:00
|
|
|
ops::Shl<u32, Output = Self> +
|
|
|
|
ops::Shr<u32, Output = Self> +
|
|
|
|
ops::BitOr<Output = Self> +
|
2017-06-23 13:36:37 +08:00
|
|
|
ops::BitXor<Output = Self> +
|
|
|
|
ops::BitAnd<Output = Self> +
|
|
|
|
ops::Not<Output = Self> +
|
2017-06-23 13:03:07 +08:00
|
|
|
{
|
2017-01-05 09:22:44 +08:00
|
|
|
/// Type with the same width but other signedness
|
2017-06-23 13:03:07 +08:00
|
|
|
type OtherSign: Int;
|
2016-12-06 12:16:19 +08:00
|
|
|
/// Unsigned version of Self
|
2017-06-23 13:03:07 +08:00
|
|
|
type UnsignedInt: Int;
|
2016-12-06 12:16:19 +08:00
|
|
|
|
2017-09-14 03:01:40 +08:00
|
|
|
/// The bitwidth of the int type
|
|
|
|
const BITS: u32;
|
2016-12-06 12:16:19 +08:00
|
|
|
|
2017-09-14 03:01:40 +08:00
|
|
|
const ZERO: Self;
|
|
|
|
const ONE: Self;
|
2017-06-23 13:03:07 +08:00
|
|
|
|
2016-12-06 12:16:19 +08:00
|
|
|
/// 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);
|
2017-06-23 13:03:07 +08:00
|
|
|
|
|
|
|
fn unsigned(self) -> Self::UnsignedInt;
|
2017-06-23 14:09:28 +08:00
|
|
|
fn from_unsigned(unsigned: Self::UnsignedInt) -> Self;
|
2017-06-23 13:36:37 +08:00
|
|
|
|
2017-09-14 22:32:50 +08:00
|
|
|
fn from_bool(b: bool) -> Self;
|
|
|
|
|
2017-06-23 13:36:37 +08:00
|
|
|
// copied from primitive integers, but put in a trait
|
|
|
|
fn max_value() -> Self;
|
|
|
|
fn min_value() -> Self;
|
|
|
|
fn wrapping_add(self, other: Self) -> Self;
|
|
|
|
fn wrapping_mul(self, other: Self) -> Self;
|
2017-06-23 14:09:28 +08:00
|
|
|
fn wrapping_sub(self, other: Self) -> Self;
|
2017-09-14 22:32:50 +08:00
|
|
|
fn wrapping_shl(self, other: u32) -> Self;
|
2017-11-25 20:21:05 +08:00
|
|
|
fn overflowing_add(self, other: Self) -> (Self, bool);
|
2017-06-24 12:31:54 +08:00
|
|
|
fn aborting_div(self, other: Self) -> Self;
|
|
|
|
fn aborting_rem(self, other: Self) -> Self;
|
2017-09-14 22:32:50 +08:00
|
|
|
fn leading_zeros(self) -> u32;
|
2017-06-24 12:31:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn unwrap<T>(t: Option<T>) -> T {
|
|
|
|
match t {
|
|
|
|
Some(t) => t,
|
|
|
|
None => ::abort(),
|
|
|
|
}
|
2016-08-18 04:50:24 +08:00
|
|
|
}
|
|
|
|
|
2017-09-14 23:39:25 +08:00
|
|
|
macro_rules! int_impl_common {
|
|
|
|
($ty:ty, $bits:expr) => {
|
2017-09-14 03:01:40 +08:00
|
|
|
const BITS: u32 = $bits;
|
2017-06-23 13:36:37 +08:00
|
|
|
|
2017-09-14 03:01:40 +08:00
|
|
|
const ZERO: Self = 0;
|
|
|
|
const ONE: Self = 1;
|
2016-12-06 12:16:19 +08:00
|
|
|
|
2017-09-14 22:32:50 +08:00
|
|
|
fn from_bool(b: bool) -> Self {
|
2017-09-14 23:39:25 +08:00
|
|
|
b as $ty
|
2017-09-14 22:32:50 +08:00
|
|
|
}
|
|
|
|
|
2017-06-23 13:36:37 +08:00
|
|
|
fn max_value() -> Self {
|
|
|
|
<Self>::max_value()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn min_value() -> Self {
|
|
|
|
<Self>::min_value()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn wrapping_add(self, other: Self) -> Self {
|
|
|
|
<Self>::wrapping_add(self, other)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn wrapping_mul(self, other: Self) -> Self {
|
|
|
|
<Self>::wrapping_mul(self, other)
|
|
|
|
}
|
2017-06-23 14:09:28 +08:00
|
|
|
|
|
|
|
fn wrapping_sub(self, other: Self) -> Self {
|
|
|
|
<Self>::wrapping_sub(self, other)
|
|
|
|
}
|
|
|
|
|
2017-09-14 22:32:50 +08:00
|
|
|
fn wrapping_shl(self, other: u32) -> Self {
|
|
|
|
<Self>::wrapping_shl(self, other)
|
|
|
|
}
|
|
|
|
|
2017-11-25 20:21:05 +08:00
|
|
|
fn overflowing_add(self, other: Self) -> (Self, bool) {
|
|
|
|
<Self>::overflowing_add(self, other)
|
|
|
|
}
|
|
|
|
|
2017-06-24 12:31:54 +08:00
|
|
|
fn aborting_div(self, other: Self) -> Self {
|
|
|
|
unwrap(<Self>::checked_div(self, other))
|
2017-06-23 14:09:28 +08:00
|
|
|
}
|
|
|
|
|
2017-06-24 12:31:54 +08:00
|
|
|
fn aborting_rem(self, other: Self) -> Self {
|
|
|
|
unwrap(<Self>::checked_rem(self, other))
|
2017-06-23 14:09:28 +08:00
|
|
|
}
|
2017-09-14 22:32:50 +08:00
|
|
|
|
|
|
|
fn leading_zeros(self) -> u32 {
|
|
|
|
<Self>::leading_zeros(self)
|
|
|
|
}
|
2017-09-14 23:39:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2017-01-04 08:52:47 +08:00
|
|
|
}
|
2016-12-06 12:16:19 +08:00
|
|
|
|
2017-03-07 01:17:10 +08:00
|
|
|
impl Int for $ity {
|
|
|
|
type OtherSign = $uty;
|
|
|
|
type UnsignedInt = $uty;
|
2016-12-06 12:16:19 +08:00
|
|
|
|
2017-03-07 01:17:10 +08:00
|
|
|
fn extract_sign(self) -> (bool, $uty) {
|
|
|
|
if self < 0 {
|
2017-05-08 10:03:16 +08:00
|
|
|
(true, (!(self as $uty)).wrapping_add(1))
|
2017-03-07 01:17:10 +08:00
|
|
|
} else {
|
|
|
|
(false, self as $uty)
|
|
|
|
}
|
|
|
|
}
|
2017-06-23 13:03:07 +08:00
|
|
|
|
|
|
|
fn unsigned(self) -> $uty {
|
|
|
|
self as $uty
|
|
|
|
}
|
2017-06-23 13:36:37 +08:00
|
|
|
|
2017-06-23 14:09:28 +08:00
|
|
|
fn from_unsigned(me: $uty) -> Self {
|
|
|
|
me as $ity
|
|
|
|
}
|
|
|
|
|
2017-09-14 23:39:25 +08:00
|
|
|
int_impl_common!($ity, $bits);
|
2016-12-06 12:16:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-01-04 08:52:47 +08:00
|
|
|
|
2017-03-07 01:17:10 +08:00
|
|
|
int_impl!(i32, u32, 32);
|
|
|
|
int_impl!(i64, u64, 64);
|
|
|
|
int_impl!(i128, u128, 128);
|
|
|
|
|
2016-08-18 04:50:24 +08:00
|
|
|
/// Trait to convert an integer to/from smaller parts
|
2017-06-23 13:03:07 +08:00
|
|
|
pub trait LargeInt: Int {
|
|
|
|
type LowHalf: Int;
|
|
|
|
type HighHalf: Int;
|
2016-08-18 04:50:24 +08:00
|
|
|
|
|
|
|
fn low(self) -> Self::LowHalf;
|
2017-06-23 13:36:37 +08:00
|
|
|
fn low_as_high(low: Self::LowHalf) -> Self::HighHalf;
|
2016-08-18 04:50:24 +08:00
|
|
|
fn high(self) -> Self::HighHalf;
|
2017-06-23 13:36:37 +08:00
|
|
|
fn high_as_low(low: Self::HighHalf) -> Self::LowHalf;
|
2016-08-18 04:50:24 +08:00
|
|
|
fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
|
|
|
|
}
|
|
|
|
|
2017-01-04 08:52:47 +08:00
|
|
|
macro_rules! large_int {
|
|
|
|
($ty:ty, $tylow:ty, $tyhigh:ty, $halfbits:expr) => {
|
|
|
|
impl LargeInt for $ty {
|
|
|
|
type LowHalf = $tylow;
|
|
|
|
type HighHalf = $tyhigh;
|
2016-08-18 04:50:24 +08:00
|
|
|
|
2017-01-04 08:52:47 +08:00
|
|
|
fn low(self) -> $tylow {
|
|
|
|
self as $tylow
|
|
|
|
}
|
2017-06-23 13:36:37 +08:00
|
|
|
fn low_as_high(low: $tylow) -> $tyhigh {
|
|
|
|
low as $tyhigh
|
|
|
|
}
|
2017-01-04 08:52:47 +08:00
|
|
|
fn high(self) -> $tyhigh {
|
|
|
|
(self >> $halfbits) as $tyhigh
|
|
|
|
}
|
2017-06-23 13:36:37 +08:00
|
|
|
fn high_as_low(high: $tyhigh) -> $tylow {
|
|
|
|
high as $tylow
|
|
|
|
}
|
2017-01-04 08:52:47 +08:00
|
|
|
fn from_parts(low: $tylow, high: $tyhigh) -> $ty {
|
|
|
|
low as $ty | ((high as $ty) << $halfbits)
|
|
|
|
}
|
|
|
|
}
|
2016-08-18 04:50:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-04 08:52:47 +08:00
|
|
|
large_int!(u64, u32, u32, 32);
|
|
|
|
large_int!(i64, u32, i32, 32);
|
|
|
|
large_int!(u128, u64, u64, 64);
|
|
|
|
large_int!(i128, u64, i64, 64);
|
2017-09-14 20:59:32 +08:00
|
|
|
|
|
|
|
/// Trait to express (possibly lossy) casting of integers
|
|
|
|
pub 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);
|
2017-11-09 06:36:34 +08:00
|
|
|
|
|
|
|
pub 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);
|