Skip to content

Commit db3fb45

Browse files
committed
Big update
1 parent 4a69a34 commit db3fb45

File tree

3 files changed

+49
-24
lines changed

3 files changed

+49
-24
lines changed

src/int/big.rs

+24-23
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,26 @@ const WORD_FULL_MASK: u64 = 0xffffffffffffffff;
1212
// Stored little endian
1313
#[allow(non_camel_case_types)]
1414
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
15-
pub struct u256([u64; 4]);
15+
pub struct u256(pub [u64; 4]);
1616

1717
impl u256 {
1818
/// Reinterpret as a signed integer
19-
fn as_signed(self) -> i256 {
19+
pub fn signed(self) -> i256 {
2020
i256(self.0)
2121
}
2222
}
2323

24-
impl u256 {
24+
impl i256 {
2525
/// Reinterpret as an unsigned integer
26-
fn as_unsigned(self) -> u256 {
26+
pub fn unsigned(self) -> u256 {
2727
u256(self.0)
2828
}
2929
}
3030

3131
// Stored little endian
3232
#[allow(non_camel_case_types)]
3333
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
34-
pub struct i256([u64; 4]);
34+
pub struct i256(pub [u64; 4]);
3535

3636
impl MinInt for u256 {
3737
type OtherSign = i256;
@@ -194,7 +194,6 @@ macro_rules! impl_common {
194194
impl_common!(i256);
195195
impl_common!(u256);
196196

197-
198197
macro_rules! word {
199198
(1, $val:expr) => {
200199
(($val >> (32 * 3)) & Self::from(WORD_LO_MASK)) as u64
@@ -280,34 +279,36 @@ impl HInt for i128 {
280279
type D = i256;
281280

282281
fn widen(self) -> Self::D {
283-
let w0 = self & i128::from(u64::MAX);
284-
let w1 = (self >> u64::BITS) & i128::from(u64::MAX);
285-
i256([w0 as u64, w1 as u64, u64::MAX, u64::MAX])
282+
let mut ret = self.unsigned().zero_widen().signed();
283+
if self.is_negative() {
284+
ret.0[2] = u64::MAX;
285+
ret.0[3] = u64::MAX;
286+
}
287+
ret
286288
}
287289

288290
fn zero_widen(self) -> Self::D {
289-
self.unsigned().zero_widen().as_signed()
291+
self.unsigned().zero_widen().signed()
290292
}
291293

292294
fn zero_widen_mul(self, rhs: Self) -> Self::D {
293-
self.unsigned().zero_widen_mul(rhs.unsigned()).as_signed()
295+
self.unsigned().zero_widen_mul(rhs.unsigned()).signed()
294296
}
295297

296298
fn widen_mul(self, rhs: Self) -> Self::D {
297-
let sign0 = self & (0b1 << 127);
298-
let sign1 = rhs & (0b1 << 127);
299-
let signed_res = sign0 ^ sign1;
300299
let mut res = self.zero_widen_mul(rhs);
300+
if self.is_negative() ^ rhs.is_negative() {
301+
for word in res.0.iter_mut().rev() {
302+
let zeroes = word.leading_zeros();
303+
let leading = u64::MAX << (64 - zeroes);
304+
*word |= leading;
305+
if zeroes != 64 {
306+
break
307+
}
308+
}
309+
}
301310

302-
// if signed_res > 0 {
303-
// for word in res.0.iter_mut().rev() {
304-
// for shift in (0..=63).rev() {
305-
// if
306-
// todo!()
307-
// }
308-
// }
309-
// }
310-
todo!()
311+
res
311312
}
312313
}
313314

src/int/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ pub mod sdiv;
1010
pub mod shift;
1111
pub mod udiv;
1212

13-
pub use self::leading_zeros::__clzsi2;
13+
pub use leading_zeros::__clzsi2;
14+
pub use big::{i256, u256};
1415

1516
public_test_dep! {
1617
/// Minimal integer implementations needed on all integer types, including wide integers.

testcrate/tests/big.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use compiler_builtins::int::{i256, u256, HInt};
2+
3+
#[test]
4+
fn widen_u128() {
5+
assert_eq!(u128::MAX.widen(), u256([u64::MAX, u64::MAX, 0, 0]));
6+
assert_eq!(
7+
0xaaaaaaaaaaaaaaaaffffffffffffffff_u128.widen(),
8+
u256([u64::MAX, 0xaaaaaaaaaaaaaaaa, 0, 0])
9+
);
10+
}
11+
12+
#[test]
13+
fn widen_i128() {
14+
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(),
20+
i256([u64::MAX, 0xaaaaaaaaaaaaaaaa, u64::MAX, u64::MAX])
21+
);
22+
assert_eq!((-1i128).zero_widen().unsigned(), (u128::MAX).widen());
23+
}

0 commit comments

Comments
 (0)