1use crate::{
4 hint_processor::builtin_hint_processor::uint256_utils::Uint256,
5 hint_processor::{
6 builtin_hint_processor::secp::bigint_utils::Uint512,
7 hint_processor_definition::HintReference,
8 },
9 math_utils::div_mod_unsigned,
10 serde::deserialize_program::ApTracking,
11 stdlib::{collections::HashMap, prelude::*},
12 types::errors::math_errors::MathError,
13 vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
14};
15use num_bigint::BigUint;
16use num_integer::div_rem;
17use num_traits::{One, Zero};
18
19pub fn uint512_unsigned_div_rem(
53 vm: &mut VirtualMachine,
54 ids_data: &HashMap<String, HintReference>,
55 ap_tracking: &ApTracking,
56) -> Result<(), HintError> {
57 let x = Uint512::from_var_name("x", vm, ids_data, ap_tracking)?.pack();
58 let div = Uint256::from_var_name("div", vm, ids_data, ap_tracking)?.pack();
59
60 if div.is_zero() {
63 return Err(MathError::DividedByZero.into());
64 }
65 let (quotient, remainder) = div_rem(x, div);
66
67 Uint512::from("ient).insert_from_var_name("quotient", vm, ids_data, ap_tracking)?;
68 Uint256::from(&remainder).insert_from_var_name("remainder", vm, ids_data, ap_tracking)
69}
70
71pub fn inv_mod_p_uint256(
96 vm: &mut VirtualMachine,
97 ids_data: &HashMap<String, HintReference>,
98 ap_tracking: &ApTracking,
99) -> Result<(), HintError> {
100 let b = Uint256::from_var_name("b", vm, ids_data, ap_tracking)?.pack();
102 let p = Uint256::from_var_name("p", vm, ids_data, ap_tracking)?.pack();
103
104 let b_inverse_mod_p = div_mod_unsigned(&BigUint::one(), &b, &p)?;
106
107 let res = Uint256::from(&b_inverse_mod_p);
108 res.insert_from_var_name("b_inverse_mod_p", vm, ids_data, ap_tracking)
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use crate::any_box;
115 use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor;
116 use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData;
117 use crate::hint_processor::builtin_hint_processor::hint_code;
118 use crate::hint_processor::hint_processor_definition::HintProcessorLogic;
119 use crate::types::errors::math_errors::MathError;
120 use crate::utils::test_utils::*;
121 use assert_matches::assert_matches;
122
123 #[cfg(target_arch = "wasm32")]
124 use wasm_bindgen_test::*;
125
126 #[test]
127 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
128 fn test_uint512_unsigned_div_rem_ok() {
129 let hint_code = hint_code::UINT512_UNSIGNED_DIV_REM;
130 let mut vm = vm_with_range_check!();
131
132 vm.segments = segments![
133 ((1, 0), 2363463),
134 ((1, 1), 566795),
135 ((1, 2), 8760799),
136 ((1, 3), 62362634),
137 ((1, 4), 8340843),
138 ((1, 5), 124152)
139 ];
140 let ids_data =
142 non_continuous_ids_data![("x", 0), ("div", 4), ("quotient", 6), ("remainder", 10)];
143 assert_matches!(
144 run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
145 Ok(())
146 );
147 check_memory![
149 vm.segments.memory,
150 ((1, 6), 158847186690949537631480225217589612243),
152 ((1, 7), 105056890940778813909974456334651647691),
153 ((1, 8), 502),
154 ((1, 9), 0),
155 ((1, 10), ("235556430256711128858231095164527378198", 10)),
157 ((1, 11), 83573),
158 ];
159 }
160
161 #[test]
162 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
163 fn test_uint512_unsigned_div_rem_div_is_zero() {
164 let hint_code = hint_code::UINT512_UNSIGNED_DIV_REM;
165 let mut vm = vm_with_range_check!();
166
167 vm.segments = segments![
168 ((1, 0), 2363463),
169 ((1, 1), 566795),
170 ((1, 2), 8760799),
171 ((1, 3), 62362634),
172 ((1, 4), 0),
173 ((1, 5), 0)
174 ];
175 let ids_data =
177 non_continuous_ids_data![("x", 0), ("div", 4), ("quotient", 6), ("remainder", 10)];
178 assert_matches!(
179 run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
180 Err(HintError::Math(MathError::DividedByZero))
181 );
182 }
183
184 #[test]
185 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
186 fn test_inv_mod_p_uint256_ok() {
187 let hint_code = hint_code::INV_MOD_P_UINT256;
188 let mut vm = vm_with_range_check!();
189
190 vm.segments = segments![
191 ((1, 0), 2363463),
192 ((1, 1), 566795),
193 ((1, 2), 8760799),
194 ((1, 3), 62362634),
195 ((1, 4), 8340842),
196 ((1, 5), 124152)
197 ];
198 let ids_data =
200 non_continuous_ids_data![("a", 0), ("b", 2), ("p", 4), ("b_inverse_mod_p", 6)];
201 assert_matches!(
202 run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
203 Ok(())
204 );
205 check_memory![
207 vm.segments.memory,
208 ((1, 6), ("320134454404400884259649806286603992559", 10)),
210 ((1, 7), 106713),
211 ];
212 }
213
214 #[test]
215 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
216 fn test_inv_mod_p_uint256_igcdex_not_1() {
217 let hint_code = hint_code::INV_MOD_P_UINT256;
218 let mut vm = vm_with_range_check!();
219
220 vm.segments = segments![
221 ((1, 0), 2363463),
222 ((1, 1), 566795),
223 ((1, 2), 1),
224 ((1, 3), 1),
225 ((1, 4), 1),
226 ((1, 5), 1)
227 ];
228 let ids_data =
230 non_continuous_ids_data![("a", 0), ("b", 2), ("p", 4), ("b_inverse_mod_p", 6)];
231 assert_matches!(
232 run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
233 Err(HintError::Math(MathError::DivModIgcdexNotZero(_)))
234 );
235 }
236}