Completely replace LargeInt
This commit is contained in:
@@ -1,25 +1,16 @@
|
||||
use int::Int;
|
||||
use int::LargeInt;
|
||||
use int::{DInt, Int};
|
||||
|
||||
trait UAddSub: LargeInt {
|
||||
trait UAddSub: DInt {
|
||||
fn uadd(self, other: Self) -> Self {
|
||||
let (low, carry) = self.low().overflowing_add(other.low());
|
||||
let high = self.high().wrapping_add(other.high());
|
||||
let carry = if carry {
|
||||
Self::HighHalf::ONE
|
||||
} else {
|
||||
Self::HighHalf::ZERO
|
||||
};
|
||||
Self::from_parts(low, high.wrapping_add(carry))
|
||||
let (lo, carry) = self.lo().overflowing_add(other.lo());
|
||||
let hi = self.hi().wrapping_add(other.hi());
|
||||
let carry = if carry { Self::H::ONE } else { Self::H::ZERO };
|
||||
Self::from_lo_hi(lo, hi.wrapping_add(carry))
|
||||
}
|
||||
fn uadd_one(self) -> Self {
|
||||
let (low, carry) = self.low().overflowing_add(Self::LowHalf::ONE);
|
||||
let carry = if carry {
|
||||
Self::HighHalf::ONE
|
||||
} else {
|
||||
Self::HighHalf::ZERO
|
||||
};
|
||||
Self::from_parts(low, self.high().wrapping_add(carry))
|
||||
let (lo, carry) = self.lo().overflowing_add(Self::H::ONE);
|
||||
let carry = if carry { Self::H::ONE } else { Self::H::ZERO };
|
||||
Self::from_lo_hi(lo, self.hi().wrapping_add(carry))
|
||||
}
|
||||
fn usub(self, other: Self) -> Self {
|
||||
let uneg = (!other).uadd_one();
|
||||
@@ -48,19 +39,9 @@ trait Addo: AddSub
|
||||
where
|
||||
<Self as Int>::UnsignedInt: UAddSub,
|
||||
{
|
||||
fn addo(self, other: Self, overflow: &mut i32) -> Self {
|
||||
*overflow = 0;
|
||||
let result = AddSub::add(self, other);
|
||||
if other >= Self::ZERO {
|
||||
if result < self {
|
||||
*overflow = 1;
|
||||
}
|
||||
} else {
|
||||
if result >= self {
|
||||
*overflow = 1;
|
||||
}
|
||||
}
|
||||
result
|
||||
fn addo(self, other: Self) -> (Self, bool) {
|
||||
let sum = AddSub::add(self, other);
|
||||
(sum, (other < Self::ZERO) != (sum < self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,19 +52,9 @@ trait Subo: AddSub
|
||||
where
|
||||
<Self as Int>::UnsignedInt: UAddSub,
|
||||
{
|
||||
fn subo(self, other: Self, overflow: &mut i32) -> Self {
|
||||
*overflow = 0;
|
||||
let result = AddSub::sub(self, other);
|
||||
if other >= Self::ZERO {
|
||||
if result > self {
|
||||
*overflow = 1;
|
||||
}
|
||||
} else {
|
||||
if result <= self {
|
||||
*overflow = 1;
|
||||
}
|
||||
}
|
||||
result
|
||||
fn subo(self, other: Self) -> (Self, bool) {
|
||||
let sum = AddSub::sub(self, other);
|
||||
(sum, (other < Self::ZERO) != (self < sum))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,43 +63,34 @@ impl Subo for u128 {}
|
||||
|
||||
intrinsics! {
|
||||
pub extern "C" fn __rust_i128_add(a: i128, b: i128) -> i128 {
|
||||
__rust_u128_add(a as _, b as _) as _
|
||||
AddSub::add(a,b)
|
||||
}
|
||||
|
||||
pub extern "C" fn __rust_i128_addo(a: i128, b: i128) -> (i128, bool) {
|
||||
let mut oflow = 0;
|
||||
let r = a.addo(b, &mut oflow);
|
||||
(r, oflow != 0)
|
||||
a.addo(b)
|
||||
}
|
||||
|
||||
pub extern "C" fn __rust_u128_add(a: u128, b: u128) -> u128 {
|
||||
a.add(b)
|
||||
AddSub::add(a,b)
|
||||
}
|
||||
|
||||
pub extern "C" fn __rust_u128_addo(a: u128, b: u128) -> (u128, bool) {
|
||||
let mut oflow = 0;
|
||||
let r = a.addo(b, &mut oflow);
|
||||
(r, oflow != 0)
|
||||
a.addo(b)
|
||||
}
|
||||
|
||||
|
||||
pub extern "C" fn __rust_i128_sub(a: i128, b: i128) -> i128 {
|
||||
__rust_u128_sub(a as _, b as _) as _
|
||||
AddSub::sub(a,b)
|
||||
}
|
||||
|
||||
pub extern "C" fn __rust_i128_subo(a: i128, b: i128) -> (i128, bool) {
|
||||
let mut oflow = 0;
|
||||
let r = a.subo(b, &mut oflow);
|
||||
(r, oflow != 0)
|
||||
a.subo(b)
|
||||
}
|
||||
|
||||
pub extern "C" fn __rust_u128_sub(a: u128, b: u128) -> u128 {
|
||||
a.sub(b)
|
||||
AddSub::sub(a,b)
|
||||
}
|
||||
|
||||
pub extern "C" fn __rust_u128_subo(a: u128, b: u128) -> (u128, bool) {
|
||||
let mut oflow = 0;
|
||||
let r = a.subo(b, &mut oflow);
|
||||
(r, oflow != 0)
|
||||
a.subo(b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,50 +384,6 @@ impl_h_int!(
|
||||
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;
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
use int::LargeInt;
|
||||
use int::{DInt, HInt, Int};
|
||||
|
||||
trait Mul: LargeInt {
|
||||
fn mul(self, other: Self) -> Self {
|
||||
let half_bits = Self::BITS / 4;
|
||||
let lower_mask = !<<Self as LargeInt>::LowHalf>::ZERO >> half_bits;
|
||||
let mut low = (self.low() & lower_mask).wrapping_mul(other.low() & lower_mask);
|
||||
let mut t = low >> half_bits;
|
||||
low &= lower_mask;
|
||||
t += (self.low() >> half_bits).wrapping_mul(other.low() & lower_mask);
|
||||
low += (t & lower_mask) << half_bits;
|
||||
let mut high = Self::low_as_high(t >> half_bits);
|
||||
t = low >> half_bits;
|
||||
low &= lower_mask;
|
||||
t += (other.low() >> half_bits).wrapping_mul(self.low() & lower_mask);
|
||||
low += (t & lower_mask) << half_bits;
|
||||
high += Self::low_as_high(t >> half_bits);
|
||||
high += Self::low_as_high((self.low() >> half_bits).wrapping_mul(other.low() >> half_bits));
|
||||
high = high
|
||||
.wrapping_add(self.high().wrapping_mul(Self::low_as_high(other.low())))
|
||||
.wrapping_add(Self::low_as_high(self.low()).wrapping_mul(other.high()));
|
||||
Self::from_parts(low, high)
|
||||
trait Mul: DInt
|
||||
where
|
||||
Self::H: DInt,
|
||||
{
|
||||
fn mul(self, rhs: Self) -> Self {
|
||||
// In order to prevent infinite recursion, we cannot use the `widen_mul` in this:
|
||||
//self.lo().widen_mul(rhs.lo())
|
||||
// .wrapping_add(self.lo().wrapping_mul(rhs.hi()).widen_hi())
|
||||
// .wrapping_add(self.hi().wrapping_mul(rhs.lo()).widen_hi())
|
||||
|
||||
let lhs_lo = self.lo();
|
||||
let rhs_lo = rhs.lo();
|
||||
// construct the widening multiplication using only `Self::H` sized multiplications
|
||||
let tmp_0 = lhs_lo.lo().zero_widen_mul(rhs_lo.lo());
|
||||
let tmp_1 = lhs_lo.lo().zero_widen_mul(rhs_lo.hi());
|
||||
let tmp_2 = lhs_lo.hi().zero_widen_mul(rhs_lo.lo());
|
||||
let tmp_3 = lhs_lo.hi().zero_widen_mul(rhs_lo.hi());
|
||||
// sum up all widening partials
|
||||
let mul = Self::from_lo_hi(tmp_0, tmp_3)
|
||||
.wrapping_add(tmp_1.zero_widen() << (Self::BITS / 4))
|
||||
.wrapping_add(tmp_2.zero_widen() << (Self::BITS / 4));
|
||||
// add the higher partials
|
||||
mul.wrapping_add(lhs_lo.wrapping_mul(rhs.hi()).widen_hi())
|
||||
.wrapping_add(self.hi().wrapping_mul(rhs_lo).widen_hi())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
use int::{Int, LargeInt};
|
||||
use int::{DInt, HInt, Int};
|
||||
|
||||
trait Ashl: Int + LargeInt {
|
||||
trait Ashl: DInt {
|
||||
/// Returns `a << b`, requires `b < Self::BITS`
|
||||
fn ashl(self, offset: u32) -> Self
|
||||
where
|
||||
Self: LargeInt<HighHalf = <Self as LargeInt>::LowHalf>,
|
||||
{
|
||||
let half_bits = Self::BITS / 2;
|
||||
if offset & half_bits != 0 {
|
||||
Self::from_parts(Int::ZERO, self.low() << (offset - half_bits))
|
||||
} else if offset == 0 {
|
||||
fn ashl(self, shl: u32) -> Self {
|
||||
let n_h = Self::H::BITS;
|
||||
if shl & n_h != 0 {
|
||||
// we only need `self.lo()` because `self.hi()` will be shifted out entirely
|
||||
(self.lo() << (shl - n_h)).widen_hi()
|
||||
} else if shl == 0 {
|
||||
self
|
||||
} else {
|
||||
Self::from_parts(
|
||||
self.low() << offset,
|
||||
(self.high() << offset) | (self.low() >> (half_bits - offset)),
|
||||
Self::from_lo_hi(
|
||||
self.lo() << shl,
|
||||
self.lo().logical_shr(n_h - shl) | (self.hi() << shl),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -24,25 +22,22 @@ impl Ashl for u32 {}
|
||||
impl Ashl for u64 {}
|
||||
impl Ashl for u128 {}
|
||||
|
||||
trait Ashr: Int + LargeInt {
|
||||
trait Ashr: DInt {
|
||||
/// Returns arithmetic `a >> b`, requires `b < Self::BITS`
|
||||
fn ashr(self, offset: u32) -> Self
|
||||
where
|
||||
Self: LargeInt<LowHalf = <<Self as LargeInt>::HighHalf as Int>::UnsignedInt>,
|
||||
{
|
||||
let half_bits = Self::BITS / 2;
|
||||
if offset & half_bits != 0 {
|
||||
Self::from_parts(
|
||||
(self.high() >> (offset - half_bits)).unsigned(),
|
||||
self.high() >> (half_bits - 1),
|
||||
fn ashr(self, shr: u32) -> Self {
|
||||
let n_h = Self::H::BITS;
|
||||
if shr & n_h != 0 {
|
||||
Self::from_lo_hi(
|
||||
self.hi() >> (shr - n_h),
|
||||
// smear the sign bit
|
||||
self.hi() >> (n_h - 1),
|
||||
)
|
||||
} else if offset == 0 {
|
||||
} else if shr == 0 {
|
||||
self
|
||||
} else {
|
||||
let high_unsigned = self.high().unsigned();
|
||||
Self::from_parts(
|
||||
(high_unsigned << (half_bits - offset)) | (self.low() >> offset),
|
||||
self.high() >> offset,
|
||||
Self::from_lo_hi(
|
||||
self.lo().logical_shr(shr) | (self.hi() << (n_h - shr)),
|
||||
self.hi() >> shr,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -52,21 +47,18 @@ impl Ashr for i32 {}
|
||||
impl Ashr for i64 {}
|
||||
impl Ashr for i128 {}
|
||||
|
||||
trait Lshr: Int + LargeInt {
|
||||
trait Lshr: DInt {
|
||||
/// Returns logical `a >> b`, requires `b < Self::BITS`
|
||||
fn lshr(self, offset: u32) -> Self
|
||||
where
|
||||
Self: LargeInt<HighHalf = <Self as LargeInt>::LowHalf>,
|
||||
{
|
||||
let half_bits = Self::BITS / 2;
|
||||
if offset & half_bits != 0 {
|
||||
Self::from_parts(self.high() >> (offset - half_bits), Int::ZERO)
|
||||
} else if offset == 0 {
|
||||
fn lshr(self, shr: u32) -> Self {
|
||||
let n_h = Self::H::BITS;
|
||||
if shr & n_h != 0 {
|
||||
self.hi().logical_shr(shr - n_h).zero_widen()
|
||||
} else if shr == 0 {
|
||||
self
|
||||
} else {
|
||||
Self::from_parts(
|
||||
(self.high() << (half_bits - offset)) | (self.low() >> offset),
|
||||
self.high() >> offset,
|
||||
Self::from_lo_hi(
|
||||
self.lo().logical_shr(shr) | (self.hi() << (n_h - shr)),
|
||||
self.hi().logical_shr(shr),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,16 +284,16 @@ pub mod win64_128bit_abi_hack {
|
||||
|
||||
impl From<i128> for U64x2 {
|
||||
fn from(i: i128) -> U64x2 {
|
||||
use int::LargeInt;
|
||||
use int::DInt;
|
||||
let j = i as u128;
|
||||
U64x2(j.low(), j.high())
|
||||
U64x2(j.lo(), j.hi())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u128> for U64x2 {
|
||||
fn from(i: u128) -> U64x2 {
|
||||
use int::LargeInt;
|
||||
U64x2(i.low(), i.high())
|
||||
use int::DInt;
|
||||
U64x2(i.lo(), i.hi())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user