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,
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::{BigInt, ToBigInt};
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)?
102 .pack()
103 .to_bigint()
104 .unwrap_or_default();
105 let p = Uint256::from_var_name("p", vm, ids_data, ap_tracking)?
106 .pack()
107 .to_bigint()
108 .unwrap_or_default();
109
110 let b_inverse_mod_p = div_mod(&BigInt::one(), &b, &p)?;
112
113 let res = Uint256::from(&b_inverse_mod_p.to_biguint().unwrap_or_default());
114 res.insert_from_var_name("b_inverse_mod_p", vm, ids_data, ap_tracking)
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use crate::any_box;
121 use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor;
122 use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData;
123 use crate::hint_processor::builtin_hint_processor::hint_code;
124 use crate::hint_processor::hint_processor_definition::HintProcessorLogic;
125 use crate::types::errors::math_errors::MathError;
126 use crate::utils::test_utils::*;
127 use assert_matches::assert_matches;
128
129 #[cfg(target_arch = "wasm32")]
130 use wasm_bindgen_test::*;
131
132 #[test]
133 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
134 fn test_uint512_unsigned_div_rem_ok() {
135 let hint_code = hint_code::UINT512_UNSIGNED_DIV_REM;
136 let mut vm = vm_with_range_check!();
137
138 vm.segments = segments![
139 ((1, 0), 2363463),
140 ((1, 1), 566795),
141 ((1, 2), 8760799),
142 ((1, 3), 62362634),
143 ((1, 4), 8340843),
144 ((1, 5), 124152)
145 ];
146 let ids_data =
148 non_continuous_ids_data![("x", 0), ("div", 4), ("quotient", 6), ("remainder", 10)];
149 assert_matches!(
150 run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
151 Ok(())
152 );
153 check_memory![
155 vm.segments.memory,
156 ((1, 6), 158847186690949537631480225217589612243),
158 ((1, 7), 105056890940778813909974456334651647691),
159 ((1, 8), 502),
160 ((1, 9), 0),
161 ((1, 10), ("235556430256711128858231095164527378198", 10)),
163 ((1, 11), 83573),
164 ];
165 }
166
167 #[test]
168 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
169 fn test_uint512_unsigned_div_rem_div_is_zero() {
170 let hint_code = hint_code::UINT512_UNSIGNED_DIV_REM;
171 let mut vm = vm_with_range_check!();
172
173 vm.segments = segments![
174 ((1, 0), 2363463),
175 ((1, 1), 566795),
176 ((1, 2), 8760799),
177 ((1, 3), 62362634),
178 ((1, 4), 0),
179 ((1, 5), 0)
180 ];
181 let ids_data =
183 non_continuous_ids_data![("x", 0), ("div", 4), ("quotient", 6), ("remainder", 10)];
184 assert_matches!(
185 run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
186 Err(HintError::Math(MathError::DividedByZero))
187 );
188 }
189
190 #[test]
191 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
192 fn test_inv_mod_p_uint256_ok() {
193 let hint_code = hint_code::INV_MOD_P_UINT256;
194 let mut vm = vm_with_range_check!();
195
196 vm.segments = segments![
197 ((1, 0), 2363463),
198 ((1, 1), 566795),
199 ((1, 2), 8760799),
200 ((1, 3), 62362634),
201 ((1, 4), 8340842),
202 ((1, 5), 124152)
203 ];
204 let ids_data =
206 non_continuous_ids_data![("a", 0), ("b", 2), ("p", 4), ("b_inverse_mod_p", 6)];
207 assert_matches!(
208 run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
209 Ok(())
210 );
211 check_memory![
213 vm.segments.memory,
214 ((1, 6), ("320134454404400884259649806286603992559", 10)),
216 ((1, 7), 106713),
217 ];
218 }
219
220 #[test]
221 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
222 fn test_inv_mod_p_uint256_igcdex_not_1() {
223 let hint_code = hint_code::INV_MOD_P_UINT256;
224 let mut vm = vm_with_range_check!();
225
226 vm.segments = segments![
227 ((1, 0), 2363463),
228 ((1, 1), 566795),
229 ((1, 2), 1),
230 ((1, 3), 1),
231 ((1, 4), 1),
232 ((1, 5), 1)
233 ];
234 let ids_data =
236 non_continuous_ids_data![("a", 0), ("b", 2), ("p", 4), ("b_inverse_mod_p", 6)];
237 assert_matches!(
238 run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
239 Err(HintError::Math(MathError::DivModIgcdexNotZero(_)))
240 );
241 }
242}