Skip to content

Commit

Permalink
Added implementation for i128 mul. (#3625)
Browse files Browse the repository at this point in the history
  • Loading branch information
orizi authored Sep 18, 2023
1 parent f3de13f commit 8f0397b
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
26 changes: 26 additions & 0 deletions corelib/src/integer.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2359,6 +2359,32 @@ impl I128Neg of Neg<i128> {
}
}

impl I128Mul of Mul<i128> {
fn mul(lhs: i128, rhs: i128) -> i128 {
let (lhs_u127, lhs_neg) = match i128_diff(lhs, 0) {
Result::Ok(v) => (v, false),
Result::Err(v) => (~v + 1, true),
};
let (rhs_u127, res_neg) = match i128_diff(rhs, 0) {
Result::Ok(v) => (v, lhs_neg),
Result::Err(v) => (~v + 1, !lhs_neg),
};
let res_as_u128 = lhs_u127 * rhs_u127;
let res_as_felt252: felt252 = if res_neg {
-res_as_u128.into()
} else {
res_as_u128.into()
};
res_as_felt252.try_into().expect('i128_mul Overflow')
}
}
impl I128MulEq of MulEq<i128> {
#[inline(always)]
fn mul_eq(ref self: i128, other: i128) {
self = Mul::mul(self, other);
}
}

/// If `lhs` >= `rhs` returns `Ok(lhs - rhs)` else returns `Err(2**128 + lhs - rhs)`.
extern fn i128_diff(lhs: i128, rhs: i128) -> Result<u128, u128> implicits(RangeCheck) nopanic;
impl I128PartialOrd of PartialOrd<i128> {
Expand Down
32 changes: 32 additions & 0 deletions corelib/src/test/integer_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -1563,6 +1563,20 @@ fn test_i128_operators() {
assert_eq(@(-3_i128 + -6_i128), @-9_i128, '-3 + -6 == -9');
assert_eq(@(-3_i128 - -1_i128), @-2_i128, '-3 - -1 == -2');
assert_eq(@(-231_i128 - -131_i128), @-100_i128, '-231--131=-100');
assert_eq(@(1_i128 * 3_i128), @3_i128, '1 * 3 == 3');
assert_eq(@(7_i128 * 0_i128), @0_i128, '7 * 0 == 0');
assert_eq(@(2_i128 * 4_i128), @8_i128, '2 * 4 == 8');
assert_eq(@(-1_i128 * 3_i128), @-3_i128, '-1 * 3 == -3');
assert_eq(@(-2_i128 * 4_i128), @-8_i128, '-2 * 4 == -8');
assert_eq(@(1_i128 * -3_i128), @-3_i128, '1 * -3 == -3');
assert_eq(@(2_i128 * -4_i128), @-8_i128, '2 * -4 == -8');
assert_eq(@(-1_i128 * -3_i128), @3_i128, '-1 * -3 == 3');
assert_eq(@(-2_i128 * -4_i128), @8_i128, '-2 * -4 == 8');
assert_eq(
@(0x800000000000000_i128 * -0x100000000000000000_i128),
@-0x80000000000000000000000000000000_i128,
'failed MIN_I128 as mul result'
);
assert_lt(1_i128, 4_i128, '1 < 4');
assert_le(1_i128, 4_i128, '1 <= 4');
assert(!(4_i128 < 4_i128), '!(4 < 4)');
Expand Down Expand Up @@ -1622,6 +1636,24 @@ fn test_i128_add_underflow() {
-0x64000000000000000000000000000000_i128 + -0x1e000000000000000000000000000000_i128;
}

#[test]
#[should_panic]
fn test_i128_mul_overflow_1() {
0x10000000000000000000000000000000_i128 * 0x10000000000000000000000000000000_i128;
}

#[test]
#[should_panic]
fn test_i128_mul_overflow_2() {
0x11000000000000000000000000000000_i128 * 0x10000000000000000000000000000000_i128;
}

#[test]
#[should_panic]
fn test_i128_mul_overflow_3() {
2_i128 * 0x40000000000000000000000000000000_i128;
}

#[test]
fn test_signed_int_diff() {
assert_eq(@integer::i8_diff(3, 3).unwrap(), @0, 'i8: 3 - 3 == 0');
Expand Down

0 comments on commit 8f0397b

Please sign in to comment.