From 1581e78feb5ff935fa7b47111c665e7d5b16faed Mon Sep 17 00:00:00 2001 From: Ori Ziv Date: Wed, 28 Jun 2023 14:32:58 +0300 Subject: [PATCH] Added implementation for i128 mul. commit-id:e5ea59f5 --- corelib/src/integer.cairo | 26 +++++++++++++++++++++++ corelib/src/test/integer_test.cairo | 32 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/corelib/src/integer.cairo b/corelib/src/integer.cairo index 57eaf9a3aeb..60dab9d727b 100644 --- a/corelib/src/integer.cairo +++ b/corelib/src/integer.cairo @@ -2359,6 +2359,32 @@ impl I128Neg of Neg { } } +impl I128Mul of Mul { + 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 { + #[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 implicits(RangeCheck) nopanic; impl I128PartialOrd of PartialOrd { diff --git a/corelib/src/test/integer_test.cairo b/corelib/src/test/integer_test.cairo index e2744b8ca8e..bba6c5273f5 100644 --- a/corelib/src/test/integer_test.cairo +++ b/corelib/src/test/integer_test.cairo @@ -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)'); @@ -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');