fix -SmallInt::from(i128::MIN)

This commit is contained in:
Solomon Ucko 2022-08-10 00:16:26 -04:00
parent 3cd8536296
commit 586a0f427e
2 changed files with 15 additions and 3 deletions

View File

@ -9,7 +9,15 @@ impl Neg for SmallInt {
fn neg(self) -> Self::Output { fn neg(self) -> Self::Output {
match self.0 { match self.0 {
SmallIntType::Inline(i) => SmallInt(SmallIntType::Inline(-i)), SmallIntType::Inline(i) => {
if let Some(n) = i.checked_neg() {
SmallInt(SmallIntType::Inline(n))
} else {
// -i128::MIN = i128::MAX + 1 = 0x8000...
let mut val = ManuallyDrop::new(Box::new([0, 0, 0, 0x80_00_00_00]));
SmallInt(SmallIntType::Heap((val.as_mut_ptr(), 4)))
}
},
SmallIntType::Heap((r, s)) => { SmallIntType::Heap((r, s)) => {
let size = usize::try_from(s.abs()).unwrap(); let size = usize::try_from(s.abs()).unwrap();
let slice = unsafe { core::slice::from_raw_parts(r, size) }; let slice = unsafe { core::slice::from_raw_parts(r, size) };

View File

@ -320,9 +320,13 @@ fn test_op_neg() {
let q = -i; let q = -i;
assert_eq!(BigInt::from(&q), -BigInt::from(u128::MAX)); assert_eq!(BigInt::from(&q), -BigInt::from(u128::MAX));
let i = SmallInt::from(i64::MIN); let i = SmallInt::from(i128::MAX);
let q = -i; let q = -i;
assert_eq!(BigInt::from(&q), -BigInt::from(i64::MIN)); assert_eq!(BigInt::from(&q), -BigInt::from(i128::MAX));
let i = SmallInt::from(i128::MIN);
let q = -i;
assert_eq!(BigInt::from(&q), -BigInt::from(i128::MIN));
} }
#[test] #[test]