diff --git a/cairo_programs/signed_div_rem.cairo b/cairo_programs/signed_div_rem.cairo index 70586943..18c255cc 100644 --- a/cairo_programs/signed_div_rem.cairo +++ b/cairo_programs/signed_div_rem.cairo @@ -5,6 +5,7 @@ from starkware.cairo.common.serialize import serialize_word func signed_div_rem_man{range_check_ptr}(value, div, bound) -> (q: felt, r: felt) { let r = [range_check_ptr]; let biased_q = [range_check_ptr + 1]; // == q + bound. + let range_check_ptr = range_check_ptr + 2; %{ from starkware.cairo.common.math_utils import as_int, assert_integer diff --git a/pkg/hints/hint_processor.go b/pkg/hints/hint_processor.go index 76df26a9..32e09d15 100644 --- a/pkg/hints/hint_processor.go +++ b/pkg/hints/hint_processor.go @@ -71,6 +71,8 @@ func (p *CairoVmHintProcessor) ExecuteHint(vm *vm.VirtualMachine, hintData *any, return vm_enter_scope(execScopes) case UNSIGNED_DIV_REM: return unsignedDivRem(data.Ids, vm) + case SIGNED_DIV_REM: + return signedDivRem(data.Ids, vm) default: return errors.Errorf("Unknown Hint: %s", data.Code) } diff --git a/pkg/hints/math_hints.go b/pkg/hints/math_hints.go index 5283e46a..5b9b2073 100644 --- a/pkg/hints/math_hints.go +++ b/pkg/hints/math_hints.go @@ -1,7 +1,6 @@ package hints import ( - "fmt" "math/big" "github.com/lambdaclass/cairo-vm.go/pkg/builtins" @@ -253,77 +252,26 @@ func signedDivRem(ids IdsManager, vm *VirtualMachine) error { if div.IsZero() || divGreater { return errors.Errorf("div=%d is out of the valid range", div) } - if bound.Cmp(rcBound.Shr(1)) == 1 { return errors.Errorf("bound=%d is out of the valid range", bound) } sgnValue := value.ToSigned() - sgnBound := bound.ToBigInt() + intBound := bound.ToBigInt() intDiv := div.ToBigInt() - q := new(big.Int).Div(sgnValue, intDiv) - r := new(big.Int).Rem(sgnValue, intDiv) + q, r := new(big.Int).DivMod(sgnValue, intDiv, new(big.Int)) + + if new(big.Int).Abs(intBound).Cmp(new(big.Int).Abs(q)) == -1 { + return errors.Errorf("%d / %d = %d is out of the range [-%d, %d]", sgnValue, div, q, bound, bound) + } - fmt.Println(sgnBound, q, r) + biasedQ := new(big.Int).Add(q, intBound) + biasedQFelt := lambdaworks.FeltFromBigInt(biasedQ) + rFelt := lambdaworks.FeltFromBigInt(r) + + ids.Insert("r", NewMaybeRelocatableFelt(rFelt), vm) + ids.Insert("biased_q", NewMaybeRelocatableFelt(biasedQFelt), vm) return nil } - -// pub fn signed_div_rem( -// vm: &mut VirtualMachine, -// ids_data: &HashMap, -// ap_tracking: &ApTracking, -// ) -> Result<(), HintError> { -// let div = get_integer_from_var_name("div", vm, ids_data, ap_tracking)?; -// let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; -// let value = value.as_ref(); -// let bound = get_integer_from_var_name("bound", vm, ids_data, ap_tracking)?; -// let builtin = vm.get_range_check_builtin()?; - -// match &builtin._bound { -// Some(builtin_bound) -// if div.is_zero() || div.as_ref() > &div_prime_by_bound(builtin_bound.clone())? => -// { -// return Err(HintError::OutOfValidRange(Box::new(( -// div.into_owned(), -// builtin_bound.clone(), -// )))); -// } -// Some(builtin_bound) if bound.as_ref() > &(builtin_bound >> 1_u32) => { -// return Err(HintError::OutOfValidRange(Box::new(( -// bound.into_owned(), -// builtin_bound >> 1_u32, -// )))); -// } -// None if div.is_zero() => { -// return Err(HintError::OutOfValidRange(Box::new(( -// div.into_owned(), -// Felt252::zero() - Felt252::one(), -// )))); -// } -// _ => {} -// } - -// let int_value = value.to_signed_felt(); -// let int_div = div.to_bigint(); -// let int_bound = bound.to_bigint(); -// let (q, r) = int_value.div_mod_floor(&int_div); - -// if int_bound.abs() < q.abs() { -// return Err(HintError::OutOfValidRange(Box::new(( -// Felt252::new(q), -// bound.into_owned(), -// )))); -// } - -// let biased_q = q + int_bound; -// insert_value_from_var_name("r", Felt252::new(r), vm, ids_data, ap_tracking)?; -// insert_value_from_var_name( -// "biased_q", -// Felt252::new(biased_q), -// vm, -// ids_data, -// ap_tracking, -// ) -// } diff --git a/pkg/lambdaworks/lambdaworks.go b/pkg/lambdaworks/lambdaworks.go index d77f3a85..56c3a649 100644 --- a/pkg/lambdaworks/lambdaworks.go +++ b/pkg/lambdaworks/lambdaworks.go @@ -58,7 +58,7 @@ func FeltFromUint64(value uint64) Felt { return fromC(result) } -func FeltFromBigInt(value big.Int) Felt { +func FeltFromBigInt(value *big.Int) Felt { buff := make([]byte, 32) bytes := value.FillBytes(buff) return FeltFromBeBytes((*[32]byte)(bytes)) diff --git a/pkg/lambdaworks/lambdaworks_test.go b/pkg/lambdaworks/lambdaworks_test.go index 7418aea7..28209dd6 100644 --- a/pkg/lambdaworks/lambdaworks_test.go +++ b/pkg/lambdaworks/lambdaworks_test.go @@ -184,7 +184,7 @@ func TestFromBigInt(t *testing.T) { big := big.NewInt(15) expectedFelt := lambdaworks.FeltFromDecString("15") - resFelt := lambdaworks.FeltFromBigInt(*big) + resFelt := lambdaworks.FeltFromBigInt(big) if resFelt.Cmp(expectedFelt) != 0 { t.Errorf("TestFromBigInt failed. Expected 15, got: %v", resFelt) diff --git a/pkg/vm/cairo_run/cairo_run_test.go b/pkg/vm/cairo_run/cairo_run_test.go index 30b63411..09530e8d 100644 --- a/pkg/vm/cairo_run/cairo_run_test.go +++ b/pkg/vm/cairo_run/cairo_run_test.go @@ -210,3 +210,11 @@ func TestUnsignedDivRemHint(t *testing.T) { t.Errorf("Program execution failed with error: %s", err) } } + +func TestSignedDivRemHint(t *testing.T) { + cairoRunConfig := cairo_run.CairoRunConfig{DisableTracePadding: false, Layout: "all_cairo", ProofMode: false} + _, err := cairo_run.CairoRun("../../../cairo_programs/signed_div_rem.json", cairoRunConfig) + if err != nil { + t.Errorf("Program execution failed with error: %s", err) + } +}