Skip to content

Commit 86051f7

Browse files
committed
Completely replace LargeInt
1 parent 51a9a2d commit 86051f7

File tree

5 files changed

+83
-170
lines changed

5 files changed

+83
-170
lines changed

src/int/addsub.rs

+23-61
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
1-
use int::Int;
2-
use int::LargeInt;
1+
use int::{DInt, Int};
32

4-
trait UAddSub: LargeInt {
3+
trait UAddSub: DInt {
54
fn uadd(self, other: Self) -> Self {
6-
let (low, carry) = self.low().overflowing_add(other.low());
7-
let high = self.high().wrapping_add(other.high());
8-
let carry = if carry {
9-
Self::HighHalf::ONE
10-
} else {
11-
Self::HighHalf::ZERO
12-
};
13-
Self::from_parts(low, high.wrapping_add(carry))
5+
let (lo, carry) = self.lo().overflowing_add(other.lo());
6+
let hi = self.hi().wrapping_add(other.hi());
7+
let carry = if carry { Self::H::ONE } else { Self::H::ZERO };
8+
Self::from_lo_hi(lo, hi.wrapping_add(carry))
149
}
1510
fn uadd_one(self) -> Self {
16-
let (low, carry) = self.low().overflowing_add(Self::LowHalf::ONE);
17-
let carry = if carry {
18-
Self::HighHalf::ONE
19-
} else {
20-
Self::HighHalf::ZERO
21-
};
22-
Self::from_parts(low, self.high().wrapping_add(carry))
11+
let (lo, carry) = self.lo().overflowing_add(Self::H::ONE);
12+
let carry = if carry { Self::H::ONE } else { Self::H::ZERO };
13+
Self::from_lo_hi(lo, self.hi().wrapping_add(carry))
2314
}
2415
fn usub(self, other: Self) -> Self {
2516
let uneg = (!other).uadd_one();
@@ -48,19 +39,9 @@ trait Addo: AddSub
4839
where
4940
<Self as Int>::UnsignedInt: UAddSub,
5041
{
51-
fn addo(self, other: Self, overflow: &mut i32) -> Self {
52-
*overflow = 0;
53-
let result = AddSub::add(self, other);
54-
if other >= Self::ZERO {
55-
if result < self {
56-
*overflow = 1;
57-
}
58-
} else {
59-
if result >= self {
60-
*overflow = 1;
61-
}
62-
}
63-
result
42+
fn addo(self, other: Self) -> (Self, bool) {
43+
let sum = AddSub::add(self, other);
44+
(sum, (other < Self::ZERO) != (sum < self))
6445
}
6546
}
6647

@@ -71,19 +52,9 @@ trait Subo: AddSub
7152
where
7253
<Self as Int>::UnsignedInt: UAddSub,
7354
{
74-
fn subo(self, other: Self, overflow: &mut i32) -> Self {
75-
*overflow = 0;
76-
let result = AddSub::sub(self, other);
77-
if other >= Self::ZERO {
78-
if result > self {
79-
*overflow = 1;
80-
}
81-
} else {
82-
if result <= self {
83-
*overflow = 1;
84-
}
85-
}
86-
result
55+
fn subo(self, other: Self) -> (Self, bool) {
56+
let sum = AddSub::sub(self, other);
57+
(sum, (other < Self::ZERO) != (self < sum))
8758
}
8859
}
8960

@@ -92,43 +63,34 @@ impl Subo for u128 {}
9263

9364
intrinsics! {
9465
pub extern "C" fn __rust_i128_add(a: i128, b: i128) -> i128 {
95-
__rust_u128_add(a as _, b as _) as _
66+
AddSub::add(a,b)
9667
}
9768

9869
pub extern "C" fn __rust_i128_addo(a: i128, b: i128) -> (i128, bool) {
99-
let mut oflow = 0;
100-
let r = a.addo(b, &mut oflow);
101-
(r, oflow != 0)
70+
a.addo(b)
10271
}
10372

10473
pub extern "C" fn __rust_u128_add(a: u128, b: u128) -> u128 {
105-
a.add(b)
74+
AddSub::add(a,b)
10675
}
10776

10877
pub extern "C" fn __rust_u128_addo(a: u128, b: u128) -> (u128, bool) {
109-
let mut oflow = 0;
110-
let r = a.addo(b, &mut oflow);
111-
(r, oflow != 0)
78+
a.addo(b)
11279
}
11380

114-
11581
pub extern "C" fn __rust_i128_sub(a: i128, b: i128) -> i128 {
116-
__rust_u128_sub(a as _, b as _) as _
82+
AddSub::sub(a,b)
11783
}
11884

11985
pub extern "C" fn __rust_i128_subo(a: i128, b: i128) -> (i128, bool) {
120-
let mut oflow = 0;
121-
let r = a.subo(b, &mut oflow);
122-
(r, oflow != 0)
86+
a.subo(b)
12387
}
12488

12589
pub extern "C" fn __rust_u128_sub(a: u128, b: u128) -> u128 {
126-
a.sub(b)
90+
AddSub::sub(a,b)
12791
}
12892

12993
pub extern "C" fn __rust_u128_subo(a: u128, b: u128) -> (u128, bool) {
130-
let mut oflow = 0;
131-
let r = a.subo(b, &mut oflow);
132-
(r, oflow != 0)
94+
a.subo(b)
13395
}
13496
}

src/int/mod.rs

-44
Original file line numberDiff line numberDiff line change
@@ -384,50 +384,6 @@ impl_h_int!(
384384
i64 u64 i128
385385
);
386386

387-
/// Trait to convert an integer to/from smaller parts
388-
pub(crate) trait LargeInt: Int {
389-
type LowHalf: Int;
390-
type HighHalf: Int;
391-
392-
fn low(self) -> Self::LowHalf;
393-
fn low_as_high(low: Self::LowHalf) -> Self::HighHalf;
394-
fn high(self) -> Self::HighHalf;
395-
fn high_as_low(low: Self::HighHalf) -> Self::LowHalf;
396-
fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
397-
}
398-
399-
macro_rules! large_int {
400-
($ty:ty, $tylow:ty, $tyhigh:ty, $halfbits:expr) => {
401-
impl LargeInt for $ty {
402-
type LowHalf = $tylow;
403-
type HighHalf = $tyhigh;
404-
405-
fn low(self) -> $tylow {
406-
self as $tylow
407-
}
408-
fn low_as_high(low: $tylow) -> $tyhigh {
409-
low as $tyhigh
410-
}
411-
fn high(self) -> $tyhigh {
412-
(self >> $halfbits) as $tyhigh
413-
}
414-
fn high_as_low(high: $tyhigh) -> $tylow {
415-
high as $tylow
416-
}
417-
fn from_parts(low: $tylow, high: $tyhigh) -> $ty {
418-
low as $ty | ((high as $ty) << $halfbits)
419-
}
420-
}
421-
};
422-
}
423-
424-
large_int!(u32, u16, u16, 16);
425-
large_int!(i32, u16, i16, 16);
426-
large_int!(u64, u32, u32, 32);
427-
large_int!(i64, u32, i32, 32);
428-
large_int!(u128, u64, u64, 64);
429-
large_int!(i128, u64, i64, 64);
430-
431387
/// Trait to express (possibly lossy) casting of integers
432388
pub(crate) trait CastInto<T: Copy>: Copy {
433389
fn cast(self) -> T;

src/int/mul.rs

+24-21
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
1-
use int::LargeInt;
21
use int::{DInt, HInt, Int};
32

4-
trait Mul: LargeInt {
5-
fn mul(self, other: Self) -> Self {
6-
let half_bits = Self::BITS / 4;
7-
let lower_mask = !<<Self as LargeInt>::LowHalf>::ZERO >> half_bits;
8-
let mut low = (self.low() & lower_mask).wrapping_mul(other.low() & lower_mask);
9-
let mut t = low >> half_bits;
10-
low &= lower_mask;
11-
t += (self.low() >> half_bits).wrapping_mul(other.low() & lower_mask);
12-
low += (t & lower_mask) << half_bits;
13-
let mut high = Self::low_as_high(t >> half_bits);
14-
t = low >> half_bits;
15-
low &= lower_mask;
16-
t += (other.low() >> half_bits).wrapping_mul(self.low() & lower_mask);
17-
low += (t & lower_mask) << half_bits;
18-
high += Self::low_as_high(t >> half_bits);
19-
high += Self::low_as_high((self.low() >> half_bits).wrapping_mul(other.low() >> half_bits));
20-
high = high
21-
.wrapping_add(self.high().wrapping_mul(Self::low_as_high(other.low())))
22-
.wrapping_add(Self::low_as_high(self.low()).wrapping_mul(other.high()));
23-
Self::from_parts(low, high)
3+
trait Mul: DInt
4+
where
5+
Self::H: DInt,
6+
{
7+
fn mul(self, rhs: Self) -> Self {
8+
// In order to prevent infinite recursion, we cannot use the `widen_mul` in this:
9+
//self.lo().widen_mul(rhs.lo())
10+
// .wrapping_add(self.lo().wrapping_mul(rhs.hi()).widen_hi())
11+
// .wrapping_add(self.hi().wrapping_mul(rhs.lo()).widen_hi())
12+
13+
let lhs_lo = self.lo();
14+
let rhs_lo = rhs.lo();
15+
// construct the widening multiplication using only `Self::H` sized multiplications
16+
let tmp_0 = lhs_lo.lo().zero_widen_mul(rhs_lo.lo());
17+
let tmp_1 = lhs_lo.lo().zero_widen_mul(rhs_lo.hi());
18+
let tmp_2 = lhs_lo.hi().zero_widen_mul(rhs_lo.lo());
19+
let tmp_3 = lhs_lo.hi().zero_widen_mul(rhs_lo.hi());
20+
// sum up all widening partials
21+
let mul = Self::from_lo_hi(tmp_0, tmp_3)
22+
.wrapping_add(tmp_1.zero_widen() << (Self::BITS / 4))
23+
.wrapping_add(tmp_2.zero_widen() << (Self::BITS / 4));
24+
// add the higher partials
25+
mul.wrapping_add(lhs_lo.wrapping_mul(rhs.hi()).widen_hi())
26+
.wrapping_add(self.hi().wrapping_mul(rhs_lo).widen_hi())
2427
}
2528
}
2629

src/int/shift.rs

+32-40
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
use int::{Int, LargeInt};
1+
use int::{DInt, HInt, Int};
22

3-
trait Ashl: Int + LargeInt {
3+
trait Ashl: DInt {
44
/// Returns `a << b`, requires `b < Self::BITS`
5-
fn ashl(self, offset: u32) -> Self
6-
where
7-
Self: LargeInt<HighHalf = <Self as LargeInt>::LowHalf>,
8-
{
9-
let half_bits = Self::BITS / 2;
10-
if offset & half_bits != 0 {
11-
Self::from_parts(Int::ZERO, self.low() << (offset - half_bits))
12-
} else if offset == 0 {
5+
fn ashl(self, shl: u32) -> Self {
6+
let n_h = Self::H::BITS;
7+
if shl & n_h != 0 {
8+
// we only need `self.lo()` because `self.hi()` will be shifted out entirely
9+
(self.lo() << (shl - n_h)).widen_hi()
10+
} else if shl == 0 {
1311
self
1412
} else {
15-
Self::from_parts(
16-
self.low() << offset,
17-
(self.high() << offset) | (self.low() >> (half_bits - offset)),
13+
Self::from_lo_hi(
14+
self.lo() << shl,
15+
self.lo().logical_shr(n_h - shl) | (self.hi() << shl),
1816
)
1917
}
2018
}
@@ -24,25 +22,22 @@ impl Ashl for u32 {}
2422
impl Ashl for u64 {}
2523
impl Ashl for u128 {}
2624

27-
trait Ashr: Int + LargeInt {
25+
trait Ashr: DInt {
2826
/// Returns arithmetic `a >> b`, requires `b < Self::BITS`
29-
fn ashr(self, offset: u32) -> Self
30-
where
31-
Self: LargeInt<LowHalf = <<Self as LargeInt>::HighHalf as Int>::UnsignedInt>,
32-
{
33-
let half_bits = Self::BITS / 2;
34-
if offset & half_bits != 0 {
35-
Self::from_parts(
36-
(self.high() >> (offset - half_bits)).unsigned(),
37-
self.high() >> (half_bits - 1),
27+
fn ashr(self, shr: u32) -> Self {
28+
let n_h = Self::H::BITS;
29+
if shr & n_h != 0 {
30+
Self::from_lo_hi(
31+
self.hi() >> (shr - n_h),
32+
// smear the sign bit
33+
self.hi() >> (n_h - 1),
3834
)
39-
} else if offset == 0 {
35+
} else if shr == 0 {
4036
self
4137
} else {
42-
let high_unsigned = self.high().unsigned();
43-
Self::from_parts(
44-
(high_unsigned << (half_bits - offset)) | (self.low() >> offset),
45-
self.high() >> offset,
38+
Self::from_lo_hi(
39+
self.lo().logical_shr(shr) | (self.hi() << (n_h - shr)),
40+
self.hi() >> shr,
4641
)
4742
}
4843
}
@@ -52,21 +47,18 @@ impl Ashr for i32 {}
5247
impl Ashr for i64 {}
5348
impl Ashr for i128 {}
5449

55-
trait Lshr: Int + LargeInt {
50+
trait Lshr: DInt {
5651
/// Returns logical `a >> b`, requires `b < Self::BITS`
57-
fn lshr(self, offset: u32) -> Self
58-
where
59-
Self: LargeInt<HighHalf = <Self as LargeInt>::LowHalf>,
60-
{
61-
let half_bits = Self::BITS / 2;
62-
if offset & half_bits != 0 {
63-
Self::from_parts(self.high() >> (offset - half_bits), Int::ZERO)
64-
} else if offset == 0 {
52+
fn lshr(self, shr: u32) -> Self {
53+
let n_h = Self::H::BITS;
54+
if shr & n_h != 0 {
55+
self.hi().logical_shr(shr - n_h).zero_widen()
56+
} else if shr == 0 {
6557
self
6658
} else {
67-
Self::from_parts(
68-
(self.high() << (half_bits - offset)) | (self.low() >> offset),
69-
self.high() >> offset,
59+
Self::from_lo_hi(
60+
self.lo().logical_shr(shr) | (self.hi() << (n_h - shr)),
61+
self.hi().logical_shr(shr),
7062
)
7163
}
7264
}

src/macros.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -284,16 +284,16 @@ pub mod win64_128bit_abi_hack {
284284

285285
impl From<i128> for U64x2 {
286286
fn from(i: i128) -> U64x2 {
287-
use int::LargeInt;
287+
use int::DInt;
288288
let j = i as u128;
289-
U64x2(j.low(), j.high())
289+
U64x2(j.lo(), j.hi())
290290
}
291291
}
292292

293293
impl From<u128> for U64x2 {
294294
fn from(i: u128) -> U64x2 {
295-
use int::LargeInt;
296-
U64x2(i.low(), i.high())
295+
use int::DInt;
296+
U64x2(i.lo(), i.hi())
297297
}
298298
}
299299
}

0 commit comments

Comments
 (0)