Skip to content

Commit 9a2bfad

Browse files
mmsc2pefontana
authored andcommitted
Add Uint512DivMod Hint (lambdaclass#1171)
* Add Uint512DivMod Hint * Update changelog * Implement test for hint * Fix test for hint * Fix changelog * Fix changelog --------- Co-authored-by: Pedro Fontana <[email protected]>
1 parent 702b3a9 commit 9a2bfad

File tree

6 files changed

+155
-29
lines changed

6 files changed

+155
-29
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#### Upcoming Changes
44

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

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

2223
* Fix implementation of `InitSquashData` and `ShouldSkipSquashLoop`
2324

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

2628
* `Cairo1HintProcessor` can now run the following hints:
2729
* Felt252DictEntryInit
@@ -32,6 +34,7 @@
3234
* GetCurrentAccessIndex
3335
* ShouldContinueSquashLoop
3436
* FieldSqrt
37+
* Uint512DivMod
3538

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

Cargo.lock

Lines changed: 23 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ felt = { package = "cairo-felt", path = "./felt", version = "0.4.0", default-fea
8383
bitvec = { version = "1", default-features = false, features = ["alloc"] }
8484

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

8989
# TODO: check these dependencies for wasm compatibility
9090
ark-ff = {version = "0.4.0-alpha.7", default-features = false, optional = true}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#[contract]
2+
mod UintDivMod {
3+
4+
use integer::{u512, u512_safe_div_rem_by_u256};
5+
6+
#[external]
7+
fn div_mod() -> () {
8+
let zero = u512 { limb0: 0, limb1: 0, limb2: 0, limb3: 0 };
9+
let one = u512 { limb0: 1, limb1: 0, limb2: 0, limb3: 0 };
10+
11+
let (q, r) = u512_safe_div_rem_by_u256(zero, integer::u256_as_non_zero(1));
12+
assert(q == zero, '0 / 1 != 0');
13+
assert(r == 0, '0 % 1 != 0');
14+
15+
let (q, r) = u512_safe_div_rem_by_u256(one, integer::u256_as_non_zero(1));
16+
assert(q == one, '1 / 1 != 1');
17+
assert(r == 0, '1 % 1 != 0');
18+
19+
let two = u512 {limb0: 0, limb1: 0, limb2: 0, limb3: 2};
20+
let (q, r) = u512_safe_div_rem_by_u256(two, integer::u256_as_non_zero(1));
21+
assert(q == two, '2/1 != 2');
22+
assert(r == 0, '2/1 != 0');
23+
24+
return ();
25+
}
26+
}

src/hint_processor/cairo_1_hint_processor/hint_processor.rs

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ use crate::any_box;
44
use crate::felt::{felt_str, Felt252};
55
use crate::hint_processor::cairo_1_hint_processor::dict_manager::DictSquashExecScope;
66
use crate::hint_processor::hint_processor_definition::HintReference;
7-
use crate::types::relocatable::Relocatable;
8-
97
use crate::stdlib::collections::HashMap;
108
use crate::stdlib::prelude::*;
9+
use crate::types::relocatable::Relocatable;
1110
use crate::{
1211
hint_processor::hint_processor_definition::HintProcessor,
1312
types::exec_scope::ExecutionScopes,
@@ -27,6 +26,7 @@ use core::ops::Mul;
2726
use num_bigint::BigUint;
2827
use num_integer::Integer;
2928
use num_traits::{cast::ToPrimitive, Zero};
29+
use std::ops::Shl;
3030

3131
/// Execution scope for constant memory allocation.
3232
struct MemoryExecScope {
@@ -232,6 +232,25 @@ impl Cairo1HintProcessor {
232232
high,
233233
low,
234234
})) => self.wide_mul_128(vm, lhs, rhs, high, low),
235+
236+
Hint::Core(CoreHintBase::Core(CoreHint::Uint512DivModByUint256 {
237+
dividend0,
238+
dividend1,
239+
dividend2,
240+
dividend3,
241+
divisor0,
242+
divisor1,
243+
quotient0,
244+
quotient1,
245+
quotient2,
246+
quotient3,
247+
remainder0,
248+
remainder1,
249+
})) => self.uint512_div_mod(
250+
vm, dividend0, dividend1, dividend2, dividend3, divisor0, divisor1, quotient0,
251+
quotient1, quotient2, quotient3, remainder0, remainder1,
252+
),
253+
235254
hint => Err(HintError::UnknownHint(hint.to_string())),
236255
}
237256
}
@@ -600,6 +619,70 @@ impl Cairo1HintProcessor {
600619
Ok(())
601620
}
602621

622+
#[allow(clippy::too_many_arguments)]
623+
fn uint512_div_mod(
624+
&self,
625+
vm: &mut VirtualMachine,
626+
dividend0: &ResOperand,
627+
dividend1: &ResOperand,
628+
dividend2: &ResOperand,
629+
dividend3: &ResOperand,
630+
divisor0: &ResOperand,
631+
divisor1: &ResOperand,
632+
quotient0: &CellRef,
633+
quotient1: &CellRef,
634+
quotient2: &CellRef,
635+
quotient3: &CellRef,
636+
remainder0: &CellRef,
637+
remainder1: &CellRef,
638+
) -> Result<(), HintError> {
639+
let pow_2_128 = BigUint::from(u128::MAX) + 1u32;
640+
let dividend0 = res_operand_get_val(vm, dividend0)?.to_biguint();
641+
let dividend1 = res_operand_get_val(vm, dividend1)?.to_biguint();
642+
let dividend2 = res_operand_get_val(vm, dividend2)?.to_biguint();
643+
let dividend3 = res_operand_get_val(vm, dividend3)?.to_biguint();
644+
let divisor0 = res_operand_get_val(vm, divisor0)?.to_biguint();
645+
let divisor1 = res_operand_get_val(vm, divisor1)?.to_biguint();
646+
let dividend: BigUint =
647+
dividend0 + dividend1.shl(128) + dividend2.shl(256) + dividend3.shl(384);
648+
let divisor = divisor0 + divisor1.shl(128);
649+
let (quotient, remainder) = dividend.div_rem(&divisor);
650+
let (quotient, limb0) = quotient.div_rem(&pow_2_128);
651+
652+
vm.insert_value(
653+
cell_ref_to_relocatable(quotient0, vm)?,
654+
Felt252::from(limb0),
655+
)?;
656+
657+
let (quotient, limb1) = quotient.div_rem(&pow_2_128);
658+
vm.insert_value(
659+
cell_ref_to_relocatable(quotient1, vm)?,
660+
Felt252::from(limb1),
661+
)?;
662+
let (limb3, limb2) = quotient.div_rem(&pow_2_128);
663+
664+
vm.insert_value(
665+
cell_ref_to_relocatable(quotient2, vm)?,
666+
Felt252::from(limb2),
667+
)?;
668+
vm.insert_value(
669+
cell_ref_to_relocatable(quotient3, vm)?,
670+
Felt252::from(limb3),
671+
)?;
672+
let (limb1, limb0) = remainder.div_rem(&pow_2_128);
673+
674+
vm.insert_value(
675+
cell_ref_to_relocatable(remainder0, vm)?,
676+
Felt252::from(limb0),
677+
)?;
678+
vm.insert_value(
679+
cell_ref_to_relocatable(remainder1, vm)?,
680+
Felt252::from(limb1),
681+
)?;
682+
683+
Ok(())
684+
}
685+
603686
#[allow(clippy::too_many_arguments)]
604687
fn uint256_square_root(
605688
&self,

0 commit comments

Comments
 (0)