use crate::{
hint_processor::builtin_hint_processor::uint256_utils::Uint256,
hint_processor::{
builtin_hint_processor::secp::bigint_utils::Uint512,
hint_processor_definition::HintReference,
},
math_utils::div_mod,
serde::deserialize_program::ApTracking,
stdlib::{collections::HashMap, prelude::*},
types::errors::math_errors::MathError,
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
};
use num_bigint::{BigInt, ToBigInt};
use num_integer::div_rem;
use num_traits::{One, Zero};
pub fn uint512_unsigned_div_rem(
vm: &mut VirtualMachine,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
let x = Uint512::from_var_name("x", 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) = div_rem(x, div);
Uint512::from("ient).insert_from_var_name("quotient", vm, ids_data, ap_tracking)?;
Uint256::from(&remainder).insert_from_var_name("remainder", vm, ids_data, ap_tracking)
}
pub fn inv_mod_p_uint256(
vm: &mut VirtualMachine,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
let b = Uint256::from_var_name("b", vm, ids_data, ap_tracking)?
.pack()
.to_bigint()
.unwrap_or_default();
let p = Uint256::from_var_name("p", vm, ids_data, ap_tracking)?
.pack()
.to_bigint()
.unwrap_or_default();
let b_inverse_mod_p = div_mod(&BigInt::one(), &b, &p)?;
let res = Uint256::from(&b_inverse_mod_p.to_biguint().unwrap_or_default());
res.insert_from_var_name("b_inverse_mod_p", vm, ids_data, ap_tracking)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::any_box;
use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor;
use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData;
use crate::hint_processor::builtin_hint_processor::hint_code;
use crate::hint_processor::hint_processor_definition::HintProcessorLogic;
use crate::types::errors::math_errors::MathError;
use crate::utils::test_utils::*;
use assert_matches::assert_matches;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::*;
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_uint512_unsigned_div_rem_ok() {
let hint_code = hint_code::UINT512_UNSIGNED_DIV_REM;
let mut vm = vm_with_range_check!();
vm.segments = segments![
((1, 0), 2363463),
((1, 1), 566795),
((1, 2), 8760799),
((1, 3), 62362634),
((1, 4), 8340843),
((1, 5), 124152)
];
let ids_data =
non_continuous_ids_data![("x", 0), ("div", 4), ("quotient", 6), ("remainder", 10)];
assert_matches!(
run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
Ok(())
);
check_memory![
vm.segments.memory,
((1, 6), 158847186690949537631480225217589612243),
((1, 7), 105056890940778813909974456334651647691),
((1, 8), 502),
((1, 9), 0),
((1, 10), ("235556430256711128858231095164527378198", 10)),
((1, 11), 83573),
];
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_uint512_unsigned_div_rem_div_is_zero() {
let hint_code = hint_code::UINT512_UNSIGNED_DIV_REM;
let mut vm = vm_with_range_check!();
vm.segments = segments![
((1, 0), 2363463),
((1, 1), 566795),
((1, 2), 8760799),
((1, 3), 62362634),
((1, 4), 0),
((1, 5), 0)
];
let ids_data =
non_continuous_ids_data![("x", 0), ("div", 4), ("quotient", 6), ("remainder", 10)];
assert_matches!(
run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
Err(HintError::Math(MathError::DividedByZero))
);
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_inv_mod_p_uint256_ok() {
let hint_code = hint_code::INV_MOD_P_UINT256;
let mut vm = vm_with_range_check!();
vm.segments = segments![
((1, 0), 2363463),
((1, 1), 566795),
((1, 2), 8760799),
((1, 3), 62362634),
((1, 4), 8340842),
((1, 5), 124152)
];
let ids_data =
non_continuous_ids_data![("a", 0), ("b", 2), ("p", 4), ("b_inverse_mod_p", 6)];
assert_matches!(
run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
Ok(())
);
check_memory![
vm.segments.memory,
((1, 6), ("320134454404400884259649806286603992559", 10)),
((1, 7), 106713),
];
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_inv_mod_p_uint256_igcdex_not_1() {
let hint_code = hint_code::INV_MOD_P_UINT256;
let mut vm = vm_with_range_check!();
vm.segments = segments![
((1, 0), 2363463),
((1, 1), 566795),
((1, 2), 1),
((1, 3), 1),
((1, 4), 1),
((1, 5), 1)
];
let ids_data =
non_continuous_ids_data![("a", 0), ("b", 2), ("p", 4), ("b_inverse_mod_p", 6)];
assert_matches!(
run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
Err(HintError::Math(MathError::DivModIgcdexNotZero(_)))
);
}
}