Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Uint512DivMod Hint #1171

Merged
merged 8 commits into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#### Upcoming Changes


* fix: Fix felt sqrt and Signed impl [#1150](https://github.com/lambdaclass/cairo-rs/pull/1150)

* BREAKING: Fix `Felt252` methods `abs`, `signum`, `is_positive`, `is_negative` and `sqrt`
Expand All @@ -21,7 +22,8 @@

* Fix implementation of `InitSquashData` and `ShouldSkipSquashLoop`

* Add more hints to `Cairo1HintProcessor` [#1143](https://github.com/lambdaclass/cairo-rs/pull/1143)
* Add more hints to `Cairo1HintProcessor` [#1171](https://github.com/lambdaclass/cairo-rs/pull/1171)
[#1143](https://github.com/lambdaclass/cairo-rs/pull/1143)

* `Cairo1HintProcessor` can now run the following hints:
* Felt252DictEntryInit
Expand All @@ -32,6 +34,7 @@
* GetCurrentAccessIndex
* ShouldContinueSquashLoop
* FieldSqrt
* Uint512DivMod

* Add some small considerations regarding Cairo 1 programs [#1144](https://github.com/lambdaclass/cairo-rs/pull/1144):

Expand Down
47 changes: 23 additions & 24 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ felt = { package = "cairo-felt", path = "./felt", version = "0.4.0", default-fea
bitvec = { version = "1", default-features = false, features = ["alloc"] }

# Dependencies for cairo-1-hints feature
cairo-lang-starknet = { git = "https://github.com/starkware-libs/cairo.git", rev = "44fdeb26231f5022f2441bf89018272460c4e326", optional = true}
cairo-lang-casm = { git = "https://github.com/starkware-libs/cairo.git", rev = "44fdeb26231f5022f2441bf89018272460c4e326", optional = true }
cairo-lang-starknet = { git = "https://github.com/starkware-libs/cairo.git", rev = "4afacfd574de1121d61dea28f8c73e1516c7e07d", optional = true}
cairo-lang-casm = { git = "https://github.com/starkware-libs/cairo.git", rev = "4afacfd574de1121d61dea28f8c73e1516c7e07d", optional = true }

# TODO: check these dependencies for wasm compatibility
ark-ff = {version = "0.4.0-alpha.7", default-features = false, optional = true}
Expand Down
26 changes: 26 additions & 0 deletions cairo_programs/cairo-1-contracts/uint512_div_mod.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#[contract]
mod UintDivMod {

use integer::{u512, u512_safe_div_rem_by_u256};

#[external]
fn div_mod() -> () {
let zero = u512 { limb0: 0, limb1: 0, limb2: 0, limb3: 0 };
let one = u512 { limb0: 1, limb1: 0, limb2: 0, limb3: 0 };

let (q, r) = u512_safe_div_rem_by_u256(zero, integer::u256_as_non_zero(1));
assert(q == zero, '0 / 1 != 0');
assert(r == 0, '0 % 1 != 0');

let (q, r) = u512_safe_div_rem_by_u256(one, integer::u256_as_non_zero(1));
assert(q == one, '1 / 1 != 1');
assert(r == 0, '1 % 1 != 0');

let two = u512 {limb0: 0, limb1: 0, limb2: 0, limb3: 2};
let (q, r) = u512_safe_div_rem_by_u256(two, integer::u256_as_non_zero(1));
assert(q == two, '2/1 != 2');
assert(r == 0, '2/1 != 0');

return ();
}
}
87 changes: 85 additions & 2 deletions src/hint_processor/cairo_1_hint_processor/hint_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ use crate::any_box;
use crate::felt::{felt_str, Felt252};
use crate::hint_processor::cairo_1_hint_processor::dict_manager::DictSquashExecScope;
use crate::hint_processor::hint_processor_definition::HintReference;
use crate::types::relocatable::Relocatable;

use crate::stdlib::collections::HashMap;
use crate::stdlib::prelude::*;
use crate::types::relocatable::Relocatable;
use crate::{
hint_processor::hint_processor_definition::HintProcessor,
types::exec_scope::ExecutionScopes,
Expand All @@ -27,6 +26,7 @@ use core::ops::Mul;
use num_bigint::BigUint;
use num_integer::Integer;
use num_traits::{cast::ToPrimitive, Zero};
use std::ops::Shl;

/// Execution scope for constant memory allocation.
struct MemoryExecScope {
Expand Down Expand Up @@ -232,6 +232,25 @@ impl Cairo1HintProcessor {
high,
low,
})) => self.wide_mul_128(vm, lhs, rhs, high, low),

Hint::Core(CoreHintBase::Core(CoreHint::Uint512DivModByUint256 {
dividend0,
dividend1,
dividend2,
dividend3,
divisor0,
divisor1,
quotient0,
quotient1,
quotient2,
quotient3,
remainder0,
remainder1,
})) => self.uint512_div_mod(
vm, dividend0, dividend1, dividend2, dividend3, divisor0, divisor1, quotient0,
quotient1, quotient2, quotient3, remainder0, remainder1,
),

hint => Err(HintError::UnknownHint(hint.to_string())),
}
}
Expand Down Expand Up @@ -600,6 +619,70 @@ impl Cairo1HintProcessor {
Ok(())
}

#[allow(clippy::too_many_arguments)]
fn uint512_div_mod(
&self,
vm: &mut VirtualMachine,
dividend0: &ResOperand,
dividend1: &ResOperand,
dividend2: &ResOperand,
dividend3: &ResOperand,
divisor0: &ResOperand,
divisor1: &ResOperand,
quotient0: &CellRef,
quotient1: &CellRef,
quotient2: &CellRef,
quotient3: &CellRef,
remainder0: &CellRef,
remainder1: &CellRef,
) -> Result<(), HintError> {
let pow_2_128 = BigUint::from(u128::MAX) + 1u32;
let dividend0 = res_operand_get_val(vm, dividend0)?.to_biguint();
let dividend1 = res_operand_get_val(vm, dividend1)?.to_biguint();
let dividend2 = res_operand_get_val(vm, dividend2)?.to_biguint();
let dividend3 = res_operand_get_val(vm, dividend3)?.to_biguint();
let divisor0 = res_operand_get_val(vm, divisor0)?.to_biguint();
let divisor1 = res_operand_get_val(vm, divisor1)?.to_biguint();
let dividend: BigUint =
dividend0 + dividend1.shl(128) + dividend2.shl(256) + dividend3.shl(384);
let divisor = divisor0 + divisor1.shl(128);
let (quotient, remainder) = dividend.div_rem(&divisor);
let (quotient, limb0) = quotient.div_rem(&pow_2_128);

vm.insert_value(
cell_ref_to_relocatable(quotient0, vm)?,
Felt252::from(limb0),
)?;

let (quotient, limb1) = quotient.div_rem(&pow_2_128);
vm.insert_value(
cell_ref_to_relocatable(quotient1, vm)?,
Felt252::from(limb1),
)?;
let (limb3, limb2) = quotient.div_rem(&pow_2_128);

vm.insert_value(
cell_ref_to_relocatable(quotient2, vm)?,
Felt252::from(limb2),
)?;
vm.insert_value(
cell_ref_to_relocatable(quotient3, vm)?,
Felt252::from(limb3),
)?;
let (limb1, limb0) = remainder.div_rem(&pow_2_128);

vm.insert_value(
cell_ref_to_relocatable(remainder0, vm)?,
Felt252::from(limb0),
)?;
vm.insert_value(
cell_ref_to_relocatable(remainder1, vm)?,
Felt252::from(limb1),
)?;

Ok(())
}

#[allow(clippy::too_many_arguments)]
fn uint256_square_root(
&self,
Expand Down
Loading