From e780f8df417f064ff4e0982e4ea21dbc32d7d4f5 Mon Sep 17 00:00:00 2001 From: Mathieu <60658558+enitrat@users.noreply.github.com> Date: Mon, 14 Aug 2023 11:24:21 +0200 Subject: [PATCH] feat: 0x05 sdiv (#69) * feat: 0x05 - sdiv * chore: remove test double underscore * fix: fmt --- .../stop_and_arithmetic_operations.cairo | 22 +++++++-- .../test_stop_and_arithmetic_operations.cairo | 49 +++++++++++++++++++ .../test_utils/test_u256_signed_math.cairo | 2 +- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/instructions/stop_and_arithmetic_operations.cairo b/src/instructions/stop_and_arithmetic_operations.cairo index 0904b9baa..b7a498755 100644 --- a/src/instructions/stop_and_arithmetic_operations.cairo +++ b/src/instructions/stop_and_arithmetic_operations.cairo @@ -4,6 +4,7 @@ use kakarot::context::ExecutionContext; use kakarot::context::ExecutionContextTrait; use kakarot::stack::StackTrait; +use kakarot::utils::u256_signed_math::u256_signed_div_rem; use integer::{u256_overflowing_add, u256_overflow_sub, u256_overflow_mul, u256_safe_divmod}; #[generate_trait] @@ -13,7 +14,7 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// # Additional informations: /// - Since: Frontier /// - Group: - /// - Gas: + /// - Gas: /// # Arguments /// * `self` - the execution context fn exec_stop(ref self: ExecutionContext) { @@ -130,12 +131,23 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// - Stack consumed elements: 2 /// - Stack produced elements: 1 /// # Arguments - ///TODO + ///TODO /// - Implement me. /// * `self` - the execution context - fn exec_sdiv( - ref self: ExecutionContext - ) { //TODO implement two's complement u256 signed division + fn exec_sdiv(ref self: ExecutionContext) { + // Stack input: + // 0 - a: numerator. + // 1 - b: denominator. + let popped = self.stack.pop_n(2); + let a = *popped[0]; + let b = *popped[1]; + + // Compute the division + let (result, _) = u256_signed_div_rem(a, b); + + // Stack output: + // a / b: signed integer result of the division of a by b + self.stack.push(result); } /// MOD operation. diff --git a/src/tests/test_instructions/test_stop_and_arithmetic_operations.cairo b/src/tests/test_instructions/test_stop_and_arithmetic_operations.cairo index a7d32e592..47e367a64 100644 --- a/src/tests/test_instructions/test_stop_and_arithmetic_operations.cairo +++ b/src/tests/test_instructions/test_stop_and_arithmetic_operations.cairo @@ -198,3 +198,52 @@ fn test__exec_addmod_overflow() { assert(ctx.stack.peek().unwrap() == 100, 'stack top should be 100'); } + +#[test] +#[available_gas(20000000)] +fn test_exec_sdiv_pos() { + // Given + let mut ctx = setup_execution_context(); + ctx.stack.push(5); + ctx.stack.push(10); + + // When + ctx.exec_sdiv(); // 10 / 5 + + // Then + assert(ctx.stack.len() == 1, 'stack len should be 1'); + assert(ctx.stack.peek().unwrap() == 2, 'ctx not stopped'); +} + +#[test] +#[available_gas(20000000)] +fn test__exec_sdiv_neg() { + // Given + let mut ctx = setup_execution_context(); + ctx.stack.push(BoundedInt::max()); + ctx.stack.push(2); + + // When + ctx.exec_sdiv(); // 2 / -1 + + // Then + assert(ctx.stack.len() == 1, 'stack len should be 1'); + assert(ctx.stack.peek().unwrap() == BoundedInt::max() - 1, 'ctx not stopped'); +} + +#[test] +#[available_gas(20000000)] +fn test__exec_sdiv_by_0() { + // Given + let mut ctx = setup_execution_context(); + ctx.stack.push(0); + ctx.stack.push(10); + + // When + ctx.exec_sdiv(); + + // Then + assert(ctx.stack.len() == 1, 'stack len should be 1'); + assert(ctx.stack.peek().unwrap() == 0, 'stack top should be 0'); +} + diff --git a/src/tests/test_utils/test_u256_signed_math.cairo b/src/tests/test_utils/test_u256_signed_math.cairo index 71464f25c..640076ee2 100644 --- a/src/tests/test_utils/test_u256_signed_math.cairo +++ b/src/tests/test_utils/test_u256_signed_math.cairo @@ -91,7 +91,7 @@ fn test_signed_div_rem() { MAX_SIGNED_VALUE, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ) == (MIN_SIGNED_VALUE + 1, 0), 'Div by a neg num failed - 2.' - ); // MAX_VALUE (2**255 -1) / -1 == MIN_VALUE + 1 + ); // MAX_VALUE (2**255 -1) / -1 == MIN_VALUE + 1 assert( u256_signed_div_rem( 0x1, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF