Skip to content
Open
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
109 changes: 44 additions & 65 deletions vm/src/hint_processor/builtin_hint_processor/uint256_utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::secp::bigint_utils::Uint512;
use crate::Felt252;
use crate::{
hint_processor::builtin_hint_processor::hint_utils::{
Expand Down Expand Up @@ -43,6 +44,23 @@ impl<'a> Uint256<'a> {
})
}

pub(crate) fn from_base_addr_with_offsets(
addr: Relocatable,
name: &str,
vm: &'a VirtualMachine,
offset_low: usize,
offset_high: usize,
) -> Result<Self, HintError> {
Ok(Self {
low: vm.get_integer((addr + offset_low)?).map_err(|_| {
HintError::IdentifierHasNoMember(Box::new((name.to_string(), "low".to_string())))
})?,
high: vm.get_integer((addr + offset_high)?).map_err(|_| {
HintError::IdentifierHasNoMember(Box::new((name.to_string(), "high".to_string())))
})?,
})
}

pub(crate) fn from_var_name(
name: &str,
vm: &'a VirtualMachine,
Expand Down Expand Up @@ -311,12 +329,12 @@ pub fn uint256_signed_nn(
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
let a_addr = get_relocatable_from_var_name("a", vm, ids_data, ap_tracking)?;
let a_high = vm.get_integer((a_addr + 1_usize)?)?;
let a = Uint256::from_var_name("a", vm, ids_data, ap_tracking)?;
let a_high = a.high;
//Main logic
//memory[ap] = 1 if 0 <= (ids.a.high % PRIME) < 2 ** 127 else 0
let result: Felt252 =
if *a_high >= Felt252::ZERO && a_high.as_ref() <= &Felt252::from(i128::MAX) {
if *a_high.as_ref() >= Felt252::ZERO && a_high.as_ref() <= &Felt252::from(i128::MAX) {
Comment on lines +332 to +337
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would imply fetching a.low, but not using it, right?

Felt252::ONE
} else {
Felt252::ZERO
Expand Down Expand Up @@ -377,11 +395,15 @@ pub fn uint256_offseted_unsigned_div_rem(
let a_low = a.low.as_ref();
let a_high = a.high.as_ref();

let div_addr = get_relocatable_from_var_name("div", vm, ids_data, ap_tracking)?;
let div_low = vm.get_integer((div_addr + div_offset_low)?)?;
let div_high = vm.get_integer((div_addr + div_offset_high)?)?;
let div_low = div_low.as_ref();
let div_high = div_high.as_ref();
let div = if div_offset_low == 0 && div_offset_high == 1 {
// Standard Uint256 layout
Uint256::from_var_name("div", vm, ids_data, ap_tracking)?
} else {
let div_addr = get_relocatable_from_var_name("div", vm, ids_data, ap_tracking)?;
Uint256::from_base_addr_with_offsets(div_addr, "div", vm, div_offset_low, div_offset_high)?
};
let div_low = div.low.as_ref();
let div_high = div.high.as_ref();
Comment on lines +398 to +406
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here could we call from_base_addr_with_offsets directly and avoid the conditional? It would make the function easier to read.

Also, in this function we are packing the U256 into a bigint manually. Could you modify it to call pack? Given that this PR is for unifying U256 usage in general, we can include it.


//Main logic
//a = (ids.a.high << 128) + ids.a.low
Expand Down Expand Up @@ -428,68 +450,25 @@ pub fn uint256_mul_div_mod(
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
// Extract variables
let a_addr = get_relocatable_from_var_name("a", vm, ids_data, ap_tracking)?;
let b_addr = get_relocatable_from_var_name("b", vm, ids_data, ap_tracking)?;
let div_addr = get_relocatable_from_var_name("div", vm, ids_data, ap_tracking)?;
let quotient_low_addr =
get_relocatable_from_var_name("quotient_low", vm, ids_data, ap_tracking)?;
let quotient_high_addr =
get_relocatable_from_var_name("quotient_high", vm, ids_data, ap_tracking)?;
let remainder_addr = get_relocatable_from_var_name("remainder", vm, ids_data, ap_tracking)?;

let a_low = vm.get_integer(a_addr)?;
let a_high = vm.get_integer((a_addr + 1_usize)?)?;
let b_low = vm.get_integer(b_addr)?;
let b_high = vm.get_integer((b_addr + 1_usize)?)?;
let div_low = vm.get_integer(div_addr)?;
let div_high = vm.get_integer((div_addr + 1_usize)?)?;
let a_low = a_low.as_ref();
let a_high = a_high.as_ref();
let b_low = b_low.as_ref();
let b_high = b_high.as_ref();
let div_low = div_low.as_ref();
let div_high = div_high.as_ref();

// Main Logic
let a = a_high.to_biguint().shl(128_usize) + a_low.to_biguint();
let b = b_high.to_biguint().shl(128_usize) + b_low.to_biguint();
let div = div_high.to_biguint().shl(128_usize) + div_low.to_biguint();
// Read inputs via Uint256 helper
let a = Uint256::from_var_name("a", vm, ids_data, ap_tracking)?.pack();
let b = Uint256::from_var_name("b", vm, ids_data, ap_tracking)?.pack();
let div = Uint256::from_var_name("div", vm, ids_data, ap_tracking)?.pack();
if div.is_zero() {
return Err(MathError::DividedByZero.into());
}
let (quotient, remainder) = (a * b).div_mod_floor(&div);

// ids.quotient_low.low
vm.insert_value(
quotient_low_addr,
Felt252::from(&(&quotient & &BigUint::from(u128::MAX))),
)?;
// ids.quotient_low.high
vm.insert_value(
(quotient_low_addr + 1)?,
Felt252::from(&((&quotient).shr(128_u32) & &BigUint::from(u128::MAX))),
)?;
// ids.quotient_high.low
vm.insert_value(
quotient_high_addr,
Felt252::from(&((&quotient).shr(256_u32) & &BigUint::from(u128::MAX))),
)?;
// ids.quotient_high.high
vm.insert_value(
(quotient_high_addr + 1)?,
Felt252::from(&((&quotient).shr(384_u32))),
)?;
//ids.remainder.low
vm.insert_value(
remainder_addr,
Felt252::from(&(&remainder & &BigUint::from(u128::MAX))),
)?;
//ids.remainder.high
vm.insert_value(
(remainder_addr + 1)?,
Felt252::from(&remainder.shr(128_u32)),
)?;
// Write quotient using Uint512 split into two Uint256 values
let q512 = Uint512::split(&quotient);
let q_low = Uint256::from_values(*q512.limbs[0].as_ref(), *q512.limbs[1].as_ref());
let q_high = Uint256::from_values(*q512.limbs[2].as_ref(), *q512.limbs[3].as_ref());
q_low.insert_from_var_name("quotient_low", vm, ids_data, ap_tracking)?;
q_high.insert_from_var_name("quotient_high", vm, ids_data, ap_tracking)?;

// Write remainder as Uint256
let r_u256 = Uint256::from(&remainder);
r_u256.insert_from_var_name("remainder", vm, ids_data, ap_tracking)?;

Ok(())
}
Expand Down
Loading