Skip to content

Commit b88e870

Browse files
committed
Fix widen mul
1 parent 1124a6a commit b88e870

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed

src/int/big.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@ use core::ops;
88
const WORD_LO_MASK: u64 = 0x00000000ffffffff;
99
const WORD_HI_MASK: u64 = 0xffffffff00000000;
1010
const WORD_FULL_MASK: u64 = 0xffffffffffffffff;
11+
const U128_LO_MASK: u128 = u64::MAX as u128;
12+
const U128_HI_MASK: u128 = (u64::MAX as u128) << 64;
1113

1214
// Stored little endian
1315
#[allow(non_camel_case_types)]
1416
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
1517
pub struct u256(pub [u64; 4]);
1618

1719
impl u256 {
20+
pub const MAX: Self = Self([u64::MAX, u64::MAX, u64::MAX, u64::MAX]);
21+
1822
/// Reinterpret as a signed integer
1923
pub fn signed(self) -> i256 {
2024
i256(self.0)
@@ -256,7 +260,7 @@ impl HInt for u128 {
256260
let r1: u128 = (sum0 >> 64)
257261
+ ((sum1 >> 32) & u128::from(WORD_FULL_MASK))
258262
+ (sum2 & u128::from(WORD_FULL_MASK))
259-
+ ((sum3 << 32) & u128::from(WORD_FULL_MASK));
263+
+ ((sum3 << 32) & u128::from(WORD_HI_MASK));
260264

261265
let lo = r0 + (r1 << 64);
262266
let hi = (r1 >> 64)
@@ -267,7 +271,12 @@ impl HInt for u128 {
267271
+ (sum5 << 32)
268272
+ (sum6 << 64);
269273

270-
u256([word!(1, lo), word!(2, lo), word!(1, hi), word!(2, hi)])
274+
u256([
275+
(lo & U128_LO_MASK) as u64,
276+
((lo >> 64) & U128_LO_MASK) as u64,
277+
(hi & U128_LO_MASK) as u64,
278+
((hi >> 64) & U128_LO_MASK) as u64,
279+
])
271280
}
272281

273282
fn widen_mul(self, rhs: Self) -> Self::D {
@@ -302,8 +311,8 @@ impl HInt for i128 {
302311
let zeroes = word.leading_zeros();
303312
let leading = u64::MAX << (64 - zeroes);
304313
*word |= leading;
305-
if zeroes != 64 {
306-
break
314+
if zeroes != 64 {
315+
break;
307316
}
308317
}
309318
}

testcrate/tests/big.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,49 @@
11
use compiler_builtins::int::{i256, u256, HInt};
22

3+
const LOHI_SPLIT: u128 = 0xaaaaaaaaaaaaaaaaffffffffffffffff;
4+
35
#[test]
46
fn widen_u128() {
57
assert_eq!(u128::MAX.widen(), u256([u64::MAX, u64::MAX, 0, 0]));
68
assert_eq!(
7-
0xaaaaaaaaaaaaaaaaffffffffffffffff_u128.widen(),
9+
LOHI_SPLIT.widen(),
810
u256([u64::MAX, 0xaaaaaaaaaaaaaaaa, 0, 0])
911
);
1012
}
1113

1214
#[test]
1315
fn widen_i128() {
16+
assert_eq!((-1i128).widen(), u256::MAX.signed());
1417
assert_eq!(
15-
(-1i128).widen(),
16-
i256([u64::MAX, u64::MAX, u64::MAX, u64::MAX])
17-
);
18-
assert_eq!(
19-
(0xaaaaaaaaaaaaaaaaffffffffffffffff_u128 as i128).widen(),
18+
(LOHI_SPLIT as i128).widen(),
2019
i256([u64::MAX, 0xaaaaaaaaaaaaaaaa, u64::MAX, u64::MAX])
2120
);
2221
assert_eq!((-1i128).zero_widen().unsigned(), (u128::MAX).widen());
2322
}
23+
24+
const WORD_LO_MASK: u64 = 0x00000000ffffffff;
25+
const WORD_HI_MASK: u64 = 0xffffffff00000000;
26+
const WORD_FULL_MASK: u64 = 0xffffffffffffffff;
27+
macro_rules! word {
28+
(1, $val:expr) => {
29+
(($val >> (32 * 3)) & u128::from(WORD_LO_MASK)) as u64
30+
};
31+
(2, $val:expr) => {
32+
(($val >> (32 * 2)) & u128::from(WORD_LO_MASK)) as u64
33+
};
34+
(3, $val:expr) => {
35+
(($val >> (32 * 1)) & u128::from(WORD_LO_MASK)) as u64
36+
};
37+
(4, $val:expr) => {
38+
(($val >> (32 * 0)) & u128::from(WORD_LO_MASK)) as u64
39+
};
40+
}
41+
42+
#[test]
43+
fn widen_mul_u128() {
44+
let a = u128::MAX;
45+
let b = 2_u128;
46+
let res = a.zero_widen_mul(b);
47+
48+
assert_eq!(res, u256([u64::MAX - 1, u64::MAX, 1, 0]));
49+
}

0 commit comments

Comments
 (0)