1use crate::{
2 hint_processor::builtin_hint_processor::hint_utils::get_constant_from_var_name,
3 math_utils::signed_felt, types::errors::math_errors::MathError,
4};
5use lazy_static::lazy_static;
6use num_traits::{Signed, Zero};
7use std::collections::HashMap;
8
9use crate::utils::CAIRO_PRIME;
10
11use crate::Felt252;
12use crate::{
13 any_box,
14 hint_processor::{
15 builtin_hint_processor::hint_utils::{
16 get_integer_from_var_name, get_ptr_from_var_name, insert_value_from_var_name,
17 insert_value_into_ap,
18 },
19 hint_processor_definition::HintReference,
20 },
21 math_utils::{isqrt, pow2_const},
22 serde::deserialize_program::ApTracking,
23 types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable},
24 vm::{
25 errors::{hint_errors::HintError, vm_errors::VirtualMachineError},
26 vm_core::VirtualMachine,
27 },
28};
29use num_bigint::{BigUint, Sign};
30use num_integer::Integer;
31use num_traits::One;
32
33use super::{
34 hint_utils::{get_maybe_relocatable_from_var_name, get_relocatable_from_var_name},
35 uint256_utils::Uint256,
36};
37
38const ADDR_BOUND: &str = "starkware.starknet.common.storage.ADDR_BOUND";
39
40pub fn is_nn(
42 vm: &mut VirtualMachine,
43 ids_data: &HashMap<String, HintReference>,
44 ap_tracking: &ApTracking,
45) -> Result<(), HintError> {
46 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
47 let range_check_bound = vm.get_range_check_builtin()?.bound();
48 insert_value_into_ap(vm, Felt252::from(a.as_ref() >= range_check_bound))
50}
51
52pub fn is_nn_out_of_range(
54 vm: &mut VirtualMachine,
55 ids_data: &HashMap<String, HintReference>,
56 ap_tracking: &ApTracking,
57) -> Result<(), HintError> {
58 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
59 let a = a.as_ref();
60 let range_check_bound = vm.get_range_check_builtin()?.bound();
61 insert_value_into_ap(vm, Felt252::from(-(a + 1) >= *range_check_bound))
63}
64pub fn assert_le_felt(
88 vm: &mut VirtualMachine,
89 exec_scopes: &mut ExecutionScopes,
90 ids_data: &HashMap<String, HintReference>,
91 ap_tracking: &ApTracking,
92 constants: &HashMap<String, Felt252>,
93) -> Result<(), HintError> {
94 const PRIME_OVER_3_HIGH: &str = "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH";
95 const PRIME_OVER_2_HIGH: &str = "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH";
96
97 let prime_over_3_high = constants
98 .get(PRIME_OVER_3_HIGH)
99 .ok_or_else(|| HintError::MissingConstant(Box::new(PRIME_OVER_3_HIGH)))?;
100 let prime_over_2_high = constants
101 .get(PRIME_OVER_2_HIGH)
102 .ok_or_else(|| HintError::MissingConstant(Box::new(PRIME_OVER_2_HIGH)))?;
103 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?.to_biguint();
104 let b = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?.to_biguint();
105 let range_check_ptr = get_ptr_from_var_name("range_check_ptr", vm, ids_data, ap_tracking)?;
106
107 let prime_div2 = prime_div_constant(2)?;
109 let prime_div3 = prime_div_constant(3)?;
110
111 if a > b {
112 return Err(HintError::NonLeFelt252(Box::new((
113 Felt252::from(&a),
114 Felt252::from(&b),
115 ))));
116 }
117
118 let arc1 = &b - &a;
119 let arc2 = &*CAIRO_PRIME - 1_u32 - &b;
120 let mut lengths_and_indices = [(&a, 0_i32), (&arc1, 1_i32), (&arc2, 2_i32)];
121 lengths_and_indices.sort();
122 if lengths_and_indices[0].0 > &prime_div3 || lengths_and_indices[1].0 > &prime_div2 {
124 return Err(HintError::ArcTooBig(Box::new((
125 Felt252::from(&lengths_and_indices[0].0.clone()),
126 Felt252::from(&prime_div3),
127 Felt252::from(&lengths_and_indices[1].0.clone()),
128 Felt252::from(&prime_div2),
129 ))));
130 }
131
132 let excluded = lengths_and_indices[2].1;
133 exec_scopes.assign_or_update_variable("excluded", any_box!(Felt252::from(excluded)));
134
135 let (q_0, r_0) = (lengths_and_indices[0].0).div_mod_floor(&prime_over_3_high.to_biguint());
136 let (q_1, r_1) = (lengths_and_indices[1].0).div_mod_floor(&prime_over_2_high.to_biguint());
137
138 vm.insert_value(range_check_ptr, Felt252::from(&r_0))?;
139 vm.insert_value((range_check_ptr + 1_i32)?, Felt252::from(&q_0))?;
140 vm.insert_value((range_check_ptr + 2_i32)?, Felt252::from(&r_1))?;
141 vm.insert_value((range_check_ptr + 3_i32)?, Felt252::from(&q_1))?;
142 Ok(())
143}
144
145pub fn assert_le_felt_v_0_6(
146 vm: &mut VirtualMachine,
147 ids_data: &HashMap<String, HintReference>,
148 ap_tracking: &ApTracking,
149) -> Result<(), HintError> {
150 let a = &get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
151 let b = &get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;
152
153 if a > b {
154 return Err(HintError::NonLeFelt252(Box::new((*a, *b))));
155 }
156 Ok(())
157}
158
159pub fn assert_le_felt_v_0_8(
160 vm: &mut VirtualMachine,
161 ids_data: &HashMap<String, HintReference>,
162 ap_tracking: &ApTracking,
163) -> Result<(), HintError> {
164 let a = &get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
165 let b = &get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;
166
167 if a > b {
168 return Err(HintError::NonLeFelt252(Box::new((*a, *b))));
169 }
170 let bound = vm.get_range_check_builtin()?.bound();
171 let small_inputs = Felt252::from((a < bound && b - a < *bound) as u8);
172 insert_value_from_var_name("small_inputs", small_inputs, vm, ids_data, ap_tracking)
173}
174
175pub fn assert_le_felt_excluded_2(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> {
176 let excluded: Felt252 = exec_scopes.get("excluded")?;
177
178 if excluded != Felt252::from(2_i32) {
179 Err(HintError::ExcludedNot2(Box::new(excluded)))
180 } else {
181 Ok(())
182 }
183}
184
185pub fn assert_le_felt_excluded_1(
186 vm: &mut VirtualMachine,
187 exec_scopes: &mut ExecutionScopes,
188) -> Result<(), HintError> {
189 let excluded: Felt252 = exec_scopes.get("excluded")?;
190
191 if excluded != Felt252::ONE {
192 insert_value_into_ap(vm, Felt252::ONE)
193 } else {
194 insert_value_into_ap(vm, Felt252::ZERO)
195 }
196}
197
198pub fn assert_le_felt_excluded_0(
199 vm: &mut VirtualMachine,
200 exec_scopes: &mut ExecutionScopes,
201) -> Result<(), HintError> {
202 let excluded: Felt252 = exec_scopes.get("excluded")?;
203
204 if !excluded.is_zero() {
205 insert_value_into_ap(vm, Felt252::ONE)
206 } else {
207 insert_value_into_ap(vm, Felt252::ZERO)
208 }
209}
210
211pub fn is_le_felt(
214 vm: &mut VirtualMachine,
215 ids_data: &HashMap<String, HintReference>,
216 ap_tracking: &ApTracking,
217) -> Result<(), HintError> {
218 let a_mod = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
219 let b_mod = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;
220 let value = if a_mod > b_mod {
221 Felt252::ONE
222 } else {
223 Felt252::ZERO
224 };
225 insert_value_into_ap(vm, value)
226}
227
228pub fn assert_not_equal(
237 vm: &mut VirtualMachine,
238 ids_data: &HashMap<String, HintReference>,
239 ap_tracking: &ApTracking,
240) -> Result<(), HintError> {
241 let maybe_rel_a = get_maybe_relocatable_from_var_name("a", vm, ids_data, ap_tracking)?;
242 let maybe_rel_b = get_maybe_relocatable_from_var_name("b", vm, ids_data, ap_tracking)?;
243 match (maybe_rel_a, maybe_rel_b) {
244 (MaybeRelocatable::Int(a), MaybeRelocatable::Int(b)) => {
245 if (a - b).is_zero() {
246 return Err(HintError::AssertNotEqualFail(Box::new((
247 MaybeRelocatable::Int(a),
248 MaybeRelocatable::Int(b),
249 ))));
250 };
251 Ok(())
252 }
253 (MaybeRelocatable::RelocatableValue(a), MaybeRelocatable::RelocatableValue(b)) => {
254 if a.segment_index != b.segment_index {
255 Err(VirtualMachineError::DiffIndexComp(Box::new((a, b))))?;
256 };
257 if a.offset == b.offset {
258 return Err(HintError::AssertNotEqualFail(Box::new((
259 MaybeRelocatable::RelocatableValue(a),
260 MaybeRelocatable::RelocatableValue(b),
261 ))));
262 };
263 Ok(())
264 }
265 (a, b) => Err(VirtualMachineError::DiffTypeComparison(Box::new((a, b))))?,
266 }
267}
268
269pub fn assert_nn(
276 vm: &mut VirtualMachine,
277 ids_data: &HashMap<String, HintReference>,
278 ap_tracking: &ApTracking,
279) -> Result<(), HintError> {
280 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
281 let range_check_builtin = vm.get_range_check_builtin()?;
282 if a.as_ref() >= range_check_builtin.bound() {
285 Err(HintError::AssertNNValueOutOfRange(Box::new(a)))
286 } else {
287 Ok(())
288 }
289}
290
291pub fn assert_not_zero(
298 vm: &mut VirtualMachine,
299 ids_data: &HashMap<String, HintReference>,
300 ap_tracking: &ApTracking,
301) -> Result<(), HintError> {
302 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
303 if value.is_zero() {
304 return Err(HintError::AssertNotZero(Box::new((
305 value,
306 crate::utils::PRIME_STR.to_string(),
307 ))));
308 };
309 Ok(())
310}
311
312pub fn split_int_assert_range(
314 vm: &mut VirtualMachine,
315 ids_data: &HashMap<String, HintReference>,
316 ap_tracking: &ApTracking,
317) -> Result<(), HintError> {
318 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
319 if !value.is_zero() {
321 return Err(HintError::SplitIntNotZero);
322 }
323 Ok(())
324}
325
326pub fn split_int(
329 vm: &mut VirtualMachine,
330 ids_data: &HashMap<String, HintReference>,
331 ap_tracking: &ApTracking,
332) -> Result<(), HintError> {
333 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
334 let base = get_integer_from_var_name("base", vm, ids_data, ap_tracking)?;
335 let bound = get_integer_from_var_name("bound", vm, ids_data, ap_tracking)?;
336 let base = &base
337 .as_ref()
338 .try_into()
339 .map_err(|_| MathError::DividedByZero)?;
340 let bound = bound.as_ref();
341 let output = get_ptr_from_var_name("output", vm, ids_data, ap_tracking)?;
342 let res = value.mod_floor(base);
344 if &res > bound {
345 return Err(HintError::SplitIntLimbOutOfRange(Box::new(res)));
346 }
347 vm.insert_value(output, res).map_err(HintError::Memory)
348}
349
350pub fn is_positive(
354 vm: &mut VirtualMachine,
355 ids_data: &HashMap<String, HintReference>,
356 ap_tracking: &ApTracking,
357) -> Result<(), HintError> {
358 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
359 let value_as_int = signed_felt(value);
360 let range_check_builtin = vm.get_range_check_builtin()?;
361
362 let (sign, abs_value) = value_as_int.into_parts();
364 if abs_value >= range_check_builtin.bound().to_biguint() {
366 return Err(HintError::ValueOutsideValidRange(Box::new(value)));
367 }
368
369 let result = Felt252::from((sign == Sign::Plus) as u8);
370 insert_value_from_var_name("is_positive", result, vm, ids_data, ap_tracking)
371}
372
373pub fn split_felt(
383 vm: &mut VirtualMachine,
384 ids_data: &HashMap<String, HintReference>,
385 ap_tracking: &ApTracking,
386 constants: &HashMap<String, Felt252>,
387) -> Result<(), HintError> {
388 let assert = |b: bool, msg: &str| {
389 b.then_some(())
390 .ok_or_else(|| HintError::AssertionFailed(msg.to_string().into_boxed_str()))
391 };
392 let bound = pow2_const(128);
393 let max_high = get_constant_from_var_name("MAX_HIGH", constants)?;
394 let max_low = get_constant_from_var_name("MAX_LOW", constants)?;
395 assert(
396 max_high < &bound && max_low < &bound,
397 "assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128",
398 )?;
399 assert(
400 Felt252::MAX == max_high * bound + max_low,
401 "assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW",
402 )?;
403 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
404 let value = value.as_ref();
405 let (high, low) = value.div_rem(&bound.try_into().unwrap());
410 insert_value_from_var_name("high", high, vm, ids_data, ap_tracking)?;
411 insert_value_from_var_name("low", low, vm, ids_data, ap_tracking)
412}
413
414pub fn sqrt(
420 vm: &mut VirtualMachine,
421 ids_data: &HashMap<String, HintReference>,
422 ap_tracking: &ApTracking,
423) -> Result<(), HintError> {
424 let mod_value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
425 if mod_value > pow2_const(250) {
427 return Err(HintError::ValueOutside250BitRange(Box::new(mod_value)));
428 }
430 insert_value_from_var_name(
431 "root",
432 Felt252::from(&isqrt(&mod_value.to_biguint())?),
433 vm,
434 ids_data,
435 ap_tracking,
436 )
437}
438
439pub fn signed_div_rem(
440 vm: &mut VirtualMachine,
441 ids_data: &HashMap<String, HintReference>,
442 ap_tracking: &ApTracking,
443) -> Result<(), HintError> {
444 let div = get_integer_from_var_name("div", vm, ids_data, ap_tracking)?;
445 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
446 let value = value.as_ref();
447 let bound = get_integer_from_var_name("bound", vm, ids_data, ap_tracking)?;
448 let builtin = vm.get_range_check_builtin()?;
449
450 let builtin_bound = builtin.bound();
451 if div.is_zero() || div.as_ref() > &div_prime_by_bound(*builtin_bound)? {
452 return Err(HintError::OutOfValidRange(Box::new((div, *builtin_bound))));
453 }
454 let builtin_bound_div_2 = builtin_bound.field_div(&Felt252::TWO.try_into().unwrap());
455 if bound > builtin_bound_div_2 {
456 return Err(HintError::OutOfValidRange(Box::new((
457 bound,
458 builtin_bound_div_2,
459 ))));
460 }
461
462 let int_value = signed_felt(*value);
463 let int_div = div.to_bigint();
464 let int_bound = bound.to_bigint();
465 let (q, r) = int_value.div_mod_floor(&int_div);
466
467 if int_bound.abs() < q.abs() {
468 return Err(HintError::OutOfValidRange(Box::new((
469 Felt252::from(&q),
470 bound,
471 ))));
472 }
473
474 let biased_q = q + int_bound;
475 insert_value_from_var_name("r", Felt252::from(&r), vm, ids_data, ap_tracking)?;
476 insert_value_from_var_name(
477 "biased_q",
478 Felt252::from(&biased_q),
479 vm,
480 ids_data,
481 ap_tracking,
482 )
483}
484
485pub fn unsigned_div_rem(
495 vm: &mut VirtualMachine,
496 ids_data: &HashMap<String, HintReference>,
497 ap_tracking: &ApTracking,
498) -> Result<(), HintError> {
499 let div = get_integer_from_var_name("div", vm, ids_data, ap_tracking)?;
500 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
501 let builtin_bound = vm.get_range_check_builtin()?.bound();
502
503 if div.is_zero() || div.as_ref() > &div_prime_by_bound(*builtin_bound)? {
505 return Err(HintError::OutOfValidRange(Box::new((div, *builtin_bound))));
506 }
507
508 let (q, r) = value.div_rem(&(div).try_into().map_err(|_| MathError::DividedByZero)?);
509 insert_value_from_var_name("r", r, vm, ids_data, ap_tracking)?;
510 insert_value_from_var_name("q", q, vm, ids_data, ap_tracking)
511}
512
513pub fn assert_250_bit(
520 vm: &mut VirtualMachine,
521 ids_data: &HashMap<String, HintReference>,
522 ap_tracking: &ApTracking,
523 constants: &HashMap<String, Felt252>,
524) -> Result<(), HintError> {
525 const UPPER_BOUND: &str = "starkware.cairo.common.math.assert_250_bit.UPPER_BOUND";
526 const SHIFT: &str = "starkware.cairo.common.math.assert_250_bit.SHIFT";
527 let upper_bound = constants
529 .get(UPPER_BOUND)
530 .map_or_else(|| get_constant_from_var_name("UPPER_BOUND", constants), Ok)?;
531 let shift = constants
532 .get(SHIFT)
533 .map_or_else(|| get_constant_from_var_name("SHIFT", constants), Ok)?;
534 let value = Felt252::from(&signed_felt(get_integer_from_var_name(
535 "value",
536 vm,
537 ids_data,
538 ap_tracking,
539 )?));
540 if &value > upper_bound {
542 return Err(HintError::ValueOutside250BitRange(Box::new(value)));
543 }
544 let (high, low) = value.div_rem(&shift.try_into().map_err(|_| MathError::DividedByZero)?);
545 insert_value_from_var_name("high", high, vm, ids_data, ap_tracking)?;
546 insert_value_from_var_name("low", low, vm, ids_data, ap_tracking)
547}
548
549pub fn is_250_bits(
552 vm: &mut VirtualMachine,
553 ids_data: &HashMap<String, HintReference>,
554 ap_tracking: &ApTracking,
555) -> Result<(), HintError> {
556 let addr = get_integer_from_var_name("addr", vm, ids_data, ap_tracking)?;
557
558 let is_250 = Felt252::from((addr.as_ref().bits() <= 250) as u8);
560
561 insert_value_from_var_name("is_250", is_250, vm, ids_data, ap_tracking)
562}
563
564pub fn is_addr_bounded(
576 vm: &mut VirtualMachine,
577 ids_data: &HashMap<String, HintReference>,
578 ap_tracking: &ApTracking,
579 constants: &HashMap<String, Felt252>,
580) -> Result<(), HintError> {
581 let addr = get_integer_from_var_name("addr", vm, ids_data, ap_tracking)?;
582
583 let addr_bound = constants
584 .get(ADDR_BOUND)
585 .ok_or_else(|| HintError::MissingConstant(Box::new(ADDR_BOUND)))?
586 .to_biguint();
587
588 let lower_bound = BigUint::one() << 250_usize;
589 let upper_bound = BigUint::one() << 251_usize;
590
591 if !(lower_bound < addr_bound
596 && addr_bound <= upper_bound
597 && (&addr_bound << 1_usize) > *CAIRO_PRIME)
598 {
599 return Err(HintError::AssertionFailed(
600 "normalize_address() cannot be used with the current constants."
601 .to_string()
602 .into_boxed_str(),
603 ));
604 }
605
606 let is_small = Felt252::from((addr.as_ref() < &Felt252::from(&addr_bound)) as u8);
608
609 insert_value_from_var_name("is_small", is_small, vm, ids_data, ap_tracking)
610}
611
612pub fn assert_lt_felt(
623 vm: &mut VirtualMachine,
624 ids_data: &HashMap<String, HintReference>,
625 ap_tracking: &ApTracking,
626) -> Result<(), HintError> {
627 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
628 let b = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;
629 if a >= b {
635 return Err(HintError::AssertLtFelt252(Box::new((a, b))));
636 };
637 Ok(())
638}
639
640pub fn is_quad_residue(
641 vm: &mut VirtualMachine,
642 ids_data: &HashMap<String, HintReference>,
643 ap_tracking: &ApTracking,
644) -> Result<(), HintError> {
645 let x = get_integer_from_var_name("x", vm, ids_data, ap_tracking)?;
646
647 if x.is_zero() || x == Felt252::ONE {
648 insert_value_from_var_name("y", *x.as_ref(), vm, ids_data, ap_tracking)
649 } else if x.pow_felt(&Felt252::MAX.div_rem(&Felt252::TWO.try_into().unwrap()).0) == Felt252::ONE
651 {
652 insert_value_from_var_name("y", x.sqrt().unwrap_or_default(), vm, ids_data, ap_tracking)
653 } else {
654 insert_value_from_var_name(
655 "y",
656 (x.field_div(&Felt252::THREE.try_into().unwrap()))
657 .sqrt()
658 .unwrap_or_default(),
659 vm,
660 ids_data,
661 ap_tracking,
662 )
663 }
664}
665
666fn div_prime_by_bound(bound: Felt252) -> Result<Felt252, VirtualMachineError> {
667 let prime: &BigUint = &CAIRO_PRIME;
668 let limit = prime / bound.to_biguint();
669 Ok(Felt252::from(&limit))
670}
671
672fn prime_div_constant(bound: u32) -> Result<BigUint, VirtualMachineError> {
673 let prime: &BigUint = &CAIRO_PRIME;
674 let limit = prime / bound;
675 Ok(limit)
676}
677
678pub fn a_b_bitand_1(
685 vm: &mut VirtualMachine,
686 ids_data: &HashMap<String, HintReference>,
687 ap_tracking: &ApTracking,
688) -> Result<(), HintError> {
689 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
690 let b = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;
691 let two = Felt252::TWO.try_into().unwrap();
692 let a_lsb = a.mod_floor(&two);
693 let b_lsb = b.mod_floor(&two);
694 insert_value_from_var_name("a_lsb", a_lsb, vm, ids_data, ap_tracking)?;
695 insert_value_from_var_name("b_lsb", b_lsb, vm, ids_data, ap_tracking)
696}
697
698lazy_static! {
699 static ref SPLIT_XX_PRIME: BigUint = BigUint::parse_bytes(
700 b"57896044618658097711785492504343953926634992332820282019728792003956564819949",
701 10
702 )
703 .unwrap();
704 static ref II: BigUint = BigUint::parse_bytes(
705 b"19681161376707505956807079304988542015446066515923890162744021073123829784752",
706 10
707 )
708 .unwrap();
709}
710
711pub fn split_xx(
727 vm: &mut VirtualMachine,
728 ids_data: &HashMap<String, HintReference>,
729 ap_tracking: &ApTracking,
730) -> Result<(), HintError> {
731 let xx = Uint256::from_var_name("xx", vm, ids_data, ap_tracking)?;
732 let x_addr = get_relocatable_from_var_name("x", vm, ids_data, ap_tracking)?;
733 let xx: BigUint = xx.low.to_biguint() + (*xx.high * pow2_const(128)).to_biguint();
734 let mut x = xx.modpow(
735 &(&*SPLIT_XX_PRIME + 3_u32).div_floor(&BigUint::from(8_u32)),
736 &SPLIT_XX_PRIME,
737 );
738 if !(&x * &x - xx).mod_floor(&SPLIT_XX_PRIME).is_zero() {
739 x = (&x * &*II).mod_floor(&SPLIT_XX_PRIME)
740 };
741 if !x.mod_floor(&2_u32.into()).is_zero() {
742 x = &*SPLIT_XX_PRIME - x;
743 }
744
745 vm.insert_value(x_addr, Felt252::from(&(&x & &BigUint::from(u128::MAX))))?;
746 vm.insert_value((x_addr + 1)?, Felt252::from(&(x >> 128_u32)))?;
747
748 Ok(())
749}
750
751#[cfg(test)]
752mod tests {
753 use super::*;
754 use crate::{felt_hex, felt_str};
755 use core::ops::Neg;
756
757 use crate::{
758 any_box,
759 hint_processor::{
760 builtin_hint_processor::{
761 builtin_hint_processor_definition::{BuiltinHintProcessor, HintProcessorData},
762 hint_code,
763 },
764 hint_processor_definition::HintProcessorLogic,
765 },
766 relocatable,
767 types::exec_scope::ExecutionScopes,
768 types::relocatable::Relocatable,
769 utils::test_utils::*,
770 vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine},
771 };
772 use assert_matches::assert_matches;
773
774 use proptest::prelude::*;
775
776 #[test]
777 fn run_is_nn_hint_false() {
778 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
779 let mut vm = vm_with_range_check!();
780 vm.run_context.fp = 10;
782 vm.segments = segments![((1, 9), (-1))];
784 add_segments!(vm, 1);
785 let ids_data = ids_data!["a"];
787 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
789 check_memory![vm.segments.memory, ((1, 0), 1)];
791 }
792
793 #[test]
794 fn run_is_nn_hint_true() {
795 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
796 let mut vm = vm_with_range_check!();
797 vm.run_context.fp = 5;
799 vm.segments = segments![((1, 4), 1)];
801 add_segments!(vm, 1);
802 let ids_data = ids_data!["a"];
804 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
806 check_memory![vm.segments.memory, ((1, 0), 0)];
808 }
809
810 #[test]
811 fn run_is_nn_hint_true_border_case() {
814 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
815 let mut vm = vm_with_range_check!();
816 vm.run_context.fp = 5;
818 add_segments!(vm, 2);
820 vm.insert_value(
821 (1, 4).into(),
822 felt_str!(
823 "3618502788666131213697322783095070105623107215331596699973092056135872020480"
824 )
825 .neg(),
826 )
827 .unwrap();
828 let ids_data = ids_data!["a"];
830 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
832 check_memory![vm.segments.memory, ((1, 0), 0)];
834 }
835
836 #[test]
837 fn run_is_nn_hint_no_range_check_builtin() {
838 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
839 let mut vm = vm!();
840 vm.run_context.fp = 5;
842 vm.segments = segments![((1, 4), 1)];
844 let ids_data = ids_data!["a"];
846 assert_matches!(
848 run_hint!(vm, ids_data, hint_code),
849 Err(HintError::Internal(
850 VirtualMachineError::NoRangeCheckBuiltin
851 ))
852 );
853 }
854
855 #[test]
856 fn run_is_nn_hint_incorrect_ids() {
857 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
858 let mut vm = vm_with_range_check!();
859 add_segments!(vm, 2);
860 let ids_data = ids_data!["b"];
863 assert_matches!(
865 run_hint!(vm, ids_data, hint_code),
866 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "a"
867 );
868 }
869
870 #[test]
871 fn run_is_nn_hint_cant_get_ids_from_memory() {
872 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
873 let mut vm = vm_with_range_check!();
874 add_segments!(vm, 2);
875 vm.run_context.fp = 5;
877 let ids_data = ids_data!["a"];
880 assert_matches!(
882 run_hint!(vm, ids_data, hint_code),
883 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "a"
884 );
885 }
886
887 #[test]
888 fn run_is_nn_hint_ids_are_relocatable_values() {
889 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
890 let mut vm = vm_with_range_check!();
891 vm.run_context.fp = 5;
893 vm.segments = segments![((1, 4), (2, 3))];
895 let ids_data = ids_data!["a"];
897 assert_matches!(
899 run_hint!(vm, ids_data, hint_code),
900 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "a"
901 );
902 }
903
904 #[test]
905 fn run_assert_le_felt_valid() {
906 let mut constants = HashMap::new();
907 constants.insert(
908 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(),
909 felt_hex!("4000000000000088000000000000001"),
910 );
911 constants.insert(
912 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(),
913 felt_hex!("2AAAAAAAAAAAAB05555555555555556"),
914 );
915 let mut vm = vm_with_range_check!();
916 let mut exec_scopes = scope![("excluded", 1)];
917 vm.run_context.fp = 3;
919 vm.segments = segments![((1, 0), 1), ((1, 1), 2), ((1, 2), (2, 0))];
921 add_segments!(vm, 1);
922 let ids_data = ids_data!["a", "b", "range_check_ptr"];
924 assert_matches!(
926 run_hint!(
927 vm,
928 ids_data,
929 hint_code::ASSERT_LE_FELT,
930 &mut exec_scopes,
931 &constants
932 ),
933 Ok(())
934 );
935 }
937
938 #[test]
939 fn is_le_felt_hint_true() {
940 let hint_code = "memory[ap] = 0 if (ids.a % PRIME) <= (ids.b % PRIME) else 1";
941 let mut vm = vm_with_range_check!();
942 vm.run_context.fp = 10;
944 vm.segments = segments![((1, 8), 1), ((1, 9), 2)];
946 add_segments!(vm, 1);
947 let ids_data = ids_data!["a", "b"];
948 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
950 check_memory![vm.segments.memory, ((1, 0), 0)];
952 }
953
954 #[test]
955 fn run_is_le_felt_hint_inconsistent_memory() {
956 let hint_code = "memory[ap] = 0 if (ids.a % PRIME) <= (ids.b % PRIME) else 1";
957 let mut vm = vm_with_range_check!();
958 vm.run_context.fp = 2;
960 vm.segments = segments![((1, 0), 1), ((1, 1), 2)];
961 let ids_data = ids_data!["a", "b"];
963 assert_matches!(
965 run_hint!(vm, ids_data, hint_code),
966 Err(HintError::Memory(
967 MemoryError::InconsistentMemory(bx)
968 )) if *bx == (Relocatable::from((1, 0)),
969 MaybeRelocatable::Int(Felt252::ONE),
970 MaybeRelocatable::Int(Felt252::ZERO))
971 );
972 }
973
974 #[test]
975 fn run_is_le_felt_hint_incorrect_ids() {
976 let hint_code = "memory[ap] = 0 if (ids.a % PRIME) <= (ids.b % PRIME) else 1";
977 let mut vm = vm!();
978 vm.run_context.fp = 10;
979 vm.segments = segments![((1, 8), 1), ((1, 9), 2)];
980 let ids_data = ids_data!["a", "c"];
982 assert_matches!(
983 run_hint!(vm, ids_data, hint_code),
984 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "b"
985 );
986 }
987
988 #[test]
989 fn run_assert_nn_valid() {
990 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
991 let mut vm = vm_with_range_check!();
992 vm.run_context.fp = 1;
994 vm.segments = segments![((1, 0), 1)];
996 let ids_data = ids_data!["a"];
998 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1000 }
1002
1003 #[test]
1004 fn run_assert_nn_invalid() {
1005 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
1006 let mut vm = vm_with_range_check!();
1007 vm.run_context.fp = 1;
1009 vm.segments = segments![((1, 0), (-1))];
1011 let ids_data = ids_data!["a"];
1013 assert_matches!(
1015 run_hint!(vm, ids_data, hint_code),
1016 Err(HintError::AssertNNValueOutOfRange(bx)) if *bx == Felt252::from(-1)
1017 );
1018 }
1019
1020 #[test]
1021 fn run_assert_nn_incorrect_ids() {
1022 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
1023 let mut vm = vm_with_range_check!();
1024 vm.run_context.fp = 4;
1026 vm.segments = segments![((1, 0), (-1))];
1028 let ids_data = ids_data!["incorrect_id"];
1029 assert_matches!(
1031 run_hint!(vm, ids_data, hint_code),
1032 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "a"
1033 );
1034 }
1035
1036 #[test]
1037 fn run_assert_nn_a_is_not_integer() {
1038 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
1039 let mut vm = vm_with_range_check!();
1040 vm.run_context.fp = 1;
1042 vm.segments = segments![((1, 0), (10, 10))];
1044 let ids_data = ids_data!["a"];
1045 assert_matches!(
1047 run_hint!(vm, ids_data, hint_code),
1048 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "a"
1049 );
1050 }
1051
1052 #[test]
1053 fn run_assert_nn_no_range_check_builtin() {
1054 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
1055 let mut vm = vm!();
1056 vm.run_context.fp = 1;
1058 vm.segments = segments![((1, 0), 1)];
1060 let ids_data = ids_data!["a"];
1061 assert_matches!(
1063 run_hint!(vm, ids_data, hint_code),
1064 Err(HintError::Internal(
1065 VirtualMachineError::NoRangeCheckBuiltin
1066 ))
1067 );
1068 }
1069
1070 #[test]
1071 fn run_assert_nn_reference_is_not_in_memory() {
1072 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
1073 let mut vm = vm_with_range_check!();
1074 add_segments!(vm, 1);
1075 vm.run_context.fp = 4;
1077 let ids_data = ids_data!["a"];
1078 assert_matches!(
1080 run_hint!(vm, ids_data, hint_code),
1081 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "a"
1082 );
1083 }
1084
1085 #[test]
1086 fn run_is_assert_le_felt_invalid() {
1087 let mut vm = vm_with_range_check!();
1088 let mut constants = HashMap::new();
1089 constants.insert(
1090 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(),
1091 felt_hex!("4000000000000088000000000000001"),
1092 );
1093 constants.insert(
1094 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(),
1095 felt_hex!("2AAAAAAAAAAAAB05555555555555556"),
1096 );
1097 let mut exec_scopes = scope![("excluded", Felt252::ONE)];
1098 vm.run_context.fp = 3;
1100 vm.segments = segments![((1, 0), 2), ((1, 1), 1), ((1, 2), (2, 0))];
1102 let ids_data = ids_data!["a", "b", "range_check_ptr"];
1103 add_segments!(vm, 1);
1104 assert_matches!(
1106 run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, &constants),
1107 Err(HintError::NonLeFelt252(bx)) if *bx == (Felt252::from(2), Felt252::ONE)
1108 );
1109 }
1110
1111 #[test]
1112 fn run_is_assert_le_felt_a_is_not_integer() {
1113 let mut vm = vm_with_range_check!();
1114 let mut constants = HashMap::new();
1115 constants.insert(
1116 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(),
1117 felt_hex!("4000000000000088000000000000001"),
1118 );
1119 constants.insert(
1120 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(),
1121 felt_hex!("2AAAAAAAAAAAAB05555555555555556"),
1122 );
1123 let mut exec_scopes = scope![("excluded", 1)];
1124 vm.run_context.fp = 3;
1126 vm.segments = segments![((1, 0), (1, 0)), ((1, 1), 1), ((1, 2), (2, 0))];
1128 let ids_data = ids_data!["a", "b", "range_check_ptr"];
1129 assert_matches!(
1131 run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, &constants),
1132 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "a"
1133 );
1134 }
1135
1136 #[test]
1137 fn run_is_assert_le_felt_b_is_not_integer() {
1138 let mut vm = vm_with_range_check!();
1139 let mut constants = HashMap::new();
1140 constants.insert(
1141 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(),
1142 felt_hex!("4000000000000088000000000000001"),
1143 );
1144 constants.insert(
1145 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(),
1146 felt_hex!("2AAAAAAAAAAAAB05555555555555556"),
1147 );
1148 let mut exec_scopes = scope![("excluded", 1)];
1149 vm.run_context.fp = 3;
1151 vm.segments = segments![((1, 0), 1), ((1, 1), (1, 0)), ((1, 2), (2, 0))];
1153 let ids_data = ids_data!["a", "b", "range_check_builtin"];
1154 assert_matches!(
1156 run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, &constants),
1157 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "b"
1158 );
1159 }
1160
1161 #[test]
1162 fn run_is_nn_hint_out_of_range_false() {
1163 let hint_code =
1164 "memory[ap] = 0 if 0 <= ((-ids.a - 1) % PRIME) < range_check_builtin.bound else 1";
1165 let mut vm = vm_with_range_check!();
1166 vm.run_context.fp = 5;
1168 vm.segments = segments![((1, 4), 2)];
1170 add_segments!(vm, 1);
1171 let ids_data = ids_data!["a"];
1173 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
1175 check_memory![vm.segments.memory, ((1, 0), 1)];
1176 }
1177
1178 #[test]
1179 fn run_is_nn_hint_out_of_range_true() {
1180 let hint_code =
1181 "memory[ap] = 0 if 0 <= ((-ids.a - 1) % PRIME) < range_check_builtin.bound else 1";
1182 let mut vm = vm_with_range_check!();
1183 vm.run_context.fp = 5;
1185 vm.segments = segments![((1, 4), (-1))];
1187 add_segments!(vm, 1);
1188 let ids_data = ids_data!["a"];
1190 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
1192 check_memory![vm.segments.memory, ((1, 0), 0)];
1193 }
1194 #[test]
1195 fn run_assert_not_equal_int_false() {
1196 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1197 let mut vm = vm!();
1198 vm.run_context.fp = 10;
1200 vm.segments = segments![((1, 8), 1), ((1, 9), 1)];
1202 let ids_data = ids_data!["a", "b"];
1203 assert_matches!(
1205 run_hint!(vm, ids_data, hint_code),
1206 Err(HintError::AssertNotEqualFail(bx))
1207 if *bx == (MaybeRelocatable::from(Felt252::ONE), MaybeRelocatable::from(Felt252::ONE))
1208 );
1209 }
1210
1211 #[test]
1212 fn run_assert_not_equal_int_true() {
1213 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1214 let mut vm = vm!();
1215 vm.run_context.fp = 10;
1217 vm.segments = segments![((1, 8), 1), ((1, 9), 3)];
1219 let ids_data = ids_data!["a", "b"];
1220 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1222 }
1223
1224 #[test]
1225 fn run_assert_not_equal_int_bignum_true() {
1226 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1227 let mut vm = vm!();
1228 add_segments!(vm, 2);
1229 vm.run_context.fp = 10;
1231 vm.segments = segments![
1233 ((1, 8), (-1)),
1234 (
1235 (1, 9),
1236 (
1237 "618502788666131213697322783095070105623107215331596699973092056135872020480",
1238 10
1239 )
1240 )
1241 ];
1242 let ids_data = ids_data!["a", "b"];
1243 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1245 }
1246
1247 #[test]
1248 fn run_assert_not_equal_relocatable_false() {
1249 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1250 let mut vm = vm!();
1251 vm.run_context.fp = 10;
1253 vm.segments = segments![((1, 8), (1, 0)), ((1, 9), (1, 0))];
1255 let ids_data = ids_data!["a", "b"];
1256 assert_matches!(
1258 run_hint!(vm, ids_data, hint_code),
1259 Err(HintError::AssertNotEqualFail(bx))
1260 if *bx == (MaybeRelocatable::from((1, 0)), MaybeRelocatable::from((1, 0)))
1261 );
1262 }
1263
1264 #[test]
1265 fn run_assert_not_equal_relocatable_true() {
1266 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1267 let mut vm = vm!();
1268 vm.run_context.fp = 10;
1270 vm.segments = segments![((1, 8), (0, 1)), ((1, 9), (0, 0))];
1272 let ids_data = ids_data!["a", "b"];
1273 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1275 }
1276
1277 #[test]
1278 fn run_assert_non_equal_relocatable_diff_index() {
1279 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1280 let mut vm = vm!();
1281 vm.run_context.fp = 10;
1283 vm.segments = segments![((1, 8), (2, 0)), ((1, 9), (1, 0))];
1285 let ids_data = ids_data!["a", "b"];
1286 assert_matches!(
1288 run_hint!(vm, ids_data, hint_code),
1289 Err(HintError::Internal(VirtualMachineError::DiffIndexComp(bx)))
1290 if *bx == (relocatable!(2, 0), relocatable!(1, 0))
1291 );
1292 }
1293
1294 #[test]
1295 fn run_assert_not_equal_relocatable_and_integer() {
1296 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1297 let mut vm = vm!();
1298 vm.run_context.fp = 10;
1300 vm.segments = segments![((1, 8), (1, 0)), ((1, 9), 1)];
1302 let ids_data = ids_data!["a", "b"];
1303 assert_matches!(
1305 run_hint!(vm, ids_data, hint_code),
1306 Err(HintError::Internal(
1307 VirtualMachineError::DiffTypeComparison(bx)
1308 )) if *bx == (MaybeRelocatable::from((1, 0)), MaybeRelocatable::from(Felt252::ONE))
1309 );
1310 }
1311
1312 #[test]
1313 fn run_assert_not_zero_true() {
1314 let hint_code =
1315 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'";
1316 let mut vm = vm!();
1317 vm.run_context.fp = 5;
1319 vm.segments = segments![((1, 4), 5)];
1321 let ids_data = ids_data!["value"];
1323
1324 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1325 }
1326
1327 #[test]
1328 fn run_assert_not_zero_false() {
1329 let hint_code =
1330 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'";
1331 let mut vm = vm!();
1332 vm.run_context.fp = 5;
1334 vm.segments = segments![((1, 4), 0)];
1336 let ids_data = ids_data!["value"];
1338 assert_matches!(
1339 run_hint!(vm, ids_data, hint_code),
1340 Err(HintError::AssertNotZero(bx)) if *bx == (Felt252::ZERO, crate::utils::PRIME_STR.to_string())
1341 );
1342 }
1343
1344 #[test]
1345 fn run_assert_not_zero_incorrect_id() {
1346 let hint_code =
1347 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'";
1348 let mut vm = vm!();
1349 vm.run_context.fp = 5;
1351 vm.segments = segments![((1, 4), 0)];
1353 let ids_data = ids_data!["incorrect_id"];
1355 assert_matches!(
1356 run_hint!(vm, ids_data, hint_code),
1357 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "value"
1358 );
1359 }
1360
1361 #[test]
1362 fn run_assert_not_zero_expected_integer_error() {
1363 let hint_code =
1364 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'";
1365 let mut vm = vm!();
1366 vm.run_context.fp = 5;
1368 vm.segments = segments![((1, 4), (1, 0))];
1370 let ids_data = ids_data!["value"];
1372 assert_matches!(
1373 run_hint!(vm, ids_data, hint_code),
1374 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "value"
1375 );
1376 }
1377
1378 #[test]
1379 fn run_split_int_assertion_invalid() {
1380 let hint_code = "assert ids.value == 0, 'split_int(): value is out of range.'";
1381 let mut vm = vm!();
1382 vm.run_context.fp = 5;
1384 vm.segments = segments![((1, 4), 1)];
1386 let ids_data = ids_data!["value"];
1387 assert_matches!(
1389 run_hint!(vm, ids_data, hint_code),
1390 Err(HintError::SplitIntNotZero)
1391 );
1392 }
1393
1394 #[test]
1395 fn run_split_int_assertion_valid() {
1396 let hint_code = "assert ids.value == 0, 'split_int(): value is out of range.'";
1397 let mut vm = vm!();
1398 vm.run_context.fp = 5;
1400 vm.segments = segments![((1, 4), 0)];
1402 let ids_data = ids_data!["value"];
1403 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1405 }
1406
1407 #[test]
1408 fn run_split_int_valid() {
1409 let hint_code = "memory[ids.output] = res = (int(ids.value) % PRIME) % ids.base\nassert res < ids.bound, f'split_int(): Limb {res} is out of range.'";
1410 let mut vm = vm!();
1411 vm.run_context.fp = 4;
1413 vm.segments = segments![((1, 0), (2, 0)), ((1, 1), 2), ((1, 2), 10), ((1, 3), 100)];
1415 add_segments!(vm, 2);
1416 let ids_data = ids_data!["output", "value", "base", "bound"];
1417 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1419 check_memory![vm.segments.memory, ((2, 0), 2)];
1420 }
1421
1422 #[test]
1423 fn run_split_int_invalid() {
1424 let hint_code = "memory[ids.output] = res = (int(ids.value) % PRIME) % ids.base\nassert res < ids.bound, f'split_int(): Limb {res} is out of range.'";
1425 let mut vm = vm!();
1426 vm.run_context.fp = 4;
1428 vm.segments = segments![
1430 ((1, 0), (2, 0)),
1431 ((1, 1), 100),
1432 ((1, 2), 10000),
1433 ((1, 3), 10)
1434 ];
1435 add_segments!(vm, 2);
1436 let ids_data = ids_data!["output", "value", "base", "bound"];
1437 assert_matches!(
1439 run_hint!(vm, ids_data, hint_code),
1440 Err(HintError::SplitIntLimbOutOfRange(bx)) if *bx == Felt252::from(100)
1441 );
1442 }
1443
1444 #[test]
1445 fn run_is_positive_hint_true() {
1446 let hint_code =
1447 "from starkware.cairo.common.math_utils import is_positive\nids.is_positive = 1 if is_positive(\n value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0";
1448 let mut vm = vm_with_range_check!();
1449 vm.run_context.fp = 2;
1451 vm.segments = segments![((1, 0), 250)];
1453 let ids_data = ids_data!["value", "is_positive"];
1456 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
1458 check_memory![vm.segments.memory, ((1, 1), 1)];
1460 }
1461
1462 #[test]
1463 fn run_is_positive_hint_false() {
1464 let hint_code =
1465 "from starkware.cairo.common.math_utils import is_positive\nids.is_positive = 1 if is_positive(\n value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0";
1466 let mut vm = vm_with_range_check!();
1467 vm.run_context.fp = 2;
1469 vm.segments = segments![((1, 0), (-250))];
1471 let ids_data = ids_data!["value", "is_positive"];
1473 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
1475 check_memory![vm.segments.memory, ((1, 1), 0)];
1477 }
1478
1479 #[test]
1480 fn run_is_positive_hint_outside_valid_range() {
1481 let hint_code =
1482 "from starkware.cairo.common.math_utils import is_positive\nids.is_positive = 1 if is_positive(\n value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0";
1483 let mut vm = vm_with_range_check!();
1484 vm.run_context.fp = 2;
1486 vm.segments = segments![(
1488 (1, 0),
1489 (
1490 "618502761706184546546682988428055018603476541694452277432519575032261771265",
1491 10
1492 )
1493 )];
1494 let ids_data = ids_data!["value", "is_positive"];
1496 assert_matches!(
1498 run_hint!(vm, ids_data, hint_code),
1499 Err(HintError::ValueOutsideValidRange(bx)) if *bx == felt_str!(
1500 "618502761706184546546682988428055018603476541694452277432519575032261771265"
1501 )
1502 );
1503 }
1504
1505 #[test]
1506 fn run_is_positive_hint_is_positive_not_empty() {
1507 let hint_code ="from starkware.cairo.common.math_utils import is_positive\nids.is_positive = 1 if is_positive(\n value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0";
1508 let mut vm = vm_with_range_check!();
1509 add_segments!(vm, 2);
1510 vm.run_context.fp = 2;
1512 vm.segments = segments![((1, 0), 2), ((1, 1), 4)];
1514 let ids_data = ids_data!["value", "is_positive"];
1515 assert_matches!(
1517 run_hint!(vm, ids_data, hint_code),
1518 Err(HintError::Memory(
1519 MemoryError::InconsistentMemory(bx)
1520 )) if *bx == (Relocatable::from((1, 1)),
1521 MaybeRelocatable::from(Felt252::from(4)),
1522 MaybeRelocatable::from(Felt252::ONE))
1523 );
1524 }
1525
1526 #[test]
1527 fn run_sqrt_valid() {
1528 let hint_code = "from starkware.python.math_utils import isqrt\nvalue = ids.value % PRIME\nassert value < 2 ** 250, f\"value={value} is outside of the range [0, 2**250).\"\nassert 2 ** 250 < PRIME\nids.root = isqrt(value)";
1529 let mut vm = vm!();
1530 vm.run_context.fp = 2;
1532 vm.segments = segments![((1, 0), 81)];
1534 let ids_data = ids_data!["value", "root"];
1536 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1538 check_memory![vm.segments.memory, ((1, 1), 9)];
1540 }
1541
1542 #[test]
1543 fn run_sqrt_invalid_negative_number() {
1544 let hint_code = "from starkware.python.math_utils import isqrt\nvalue = ids.value % PRIME\nassert value < 2 ** 250, f\"value={value} is outside of the range [0, 2**250).\"\nassert 2 ** 250 < PRIME\nids.root = isqrt(value)";
1545 let mut vm = vm!();
1546 vm.run_context.fp = 2;
1548 vm.segments = segments![((1, 0), (-81))];
1550 let ids_data = ids_data!["value", "root"];
1552 assert_matches!(
1554 run_hint!(vm, ids_data, hint_code),
1555 Err(HintError::ValueOutside250BitRange(bx)) if *bx == felt_str!(
1556 "3618502788666131213697322783095070105623107215331596699973092056135872020400"
1557 )
1558 );
1559 }
1560
1561 #[test]
1562 fn run_sqrt_invalid_mismatched_root() {
1563 let hint_code = "from starkware.python.math_utils import isqrt\nvalue = ids.value % PRIME\nassert value < 2 ** 250, f\"value={value} is outside of the range [0, 2**250).\"\nassert 2 ** 250 < PRIME\nids.root = isqrt(value)";
1564 let mut vm = vm!();
1565 vm.run_context.fp = 2;
1567 vm.segments = segments![((1, 0), 81), ((1, 1), 7)];
1569 let ids_data = ids_data!["value", "root"];
1571 assert_matches!(
1573 run_hint!(vm, ids_data, hint_code),
1574 Err(HintError::Memory(
1575 MemoryError::InconsistentMemory(bx)
1576 )) if *bx == (Relocatable::from((1, 1)),
1577 MaybeRelocatable::from(Felt252::from(7)),
1578 MaybeRelocatable::from(Felt252::from(9)))
1579 );
1580 }
1581
1582 #[test]
1583 fn unsigned_div_rem_success() {
1584 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\nids.q, ids.r = divmod(ids.value, ids.div)";
1585 let mut vm = vm_with_range_check!();
1586 vm.run_context.fp = 4;
1588 vm.segments = segments![((1, 2), 5), ((1, 3), 7)];
1590 let ids_data = ids_data!["r", "q", "div", "value"];
1592 assert!(run_hint!(vm, ids_data, hint_code).is_ok());
1594 check_memory![vm.segments.memory, ((1, 0), 2), ((1, 1), 1)];
1595 }
1596
1597 #[test]
1598 fn unsigned_div_rem_out_of_range() {
1599 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\nids.q, ids.r = divmod(ids.value, ids.div)";
1600 let mut vm = vm_with_range_check!();
1601 vm.run_context.fp = 4;
1603 vm.segments = segments![((1, 2), (-5)), ((1, 3), 7)];
1605 let ids_data = ids_data!["r", "q", "div", "value"];
1607 assert_matches!(
1609 run_hint!(vm, ids_data, hint_code),
1610 Err(HintError::OutOfValidRange(bx))
1611 if *bx == (Felt252::from(-5), felt_str!("340282366920938463463374607431768211456"))
1612 )
1613 }
1614
1615 #[test]
1616 fn unsigned_div_rem_no_range_check_builtin() {
1617 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\nids.q, ids.r = divmod(ids.value, ids.div)";
1618 let mut vm = vm!();
1619 vm.run_context.fp = 4;
1621 vm.segments = segments![((1, 2), 5), ((1, 3), 7)];
1623 let ids_data = ids_data!["r", "q", "div", "value"];
1625 assert_matches!(
1626 run_hint!(vm, ids_data, hint_code),
1627 Err(HintError::Internal(
1628 VirtualMachineError::NoRangeCheckBuiltin
1629 ))
1630 );
1631 }
1632
1633 #[test]
1634 fn unsigned_div_rem_inconsitent_memory() {
1635 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\nids.q, ids.r = divmod(ids.value, ids.div)";
1636 let mut vm = vm_with_range_check!();
1637 vm.run_context.fp = 4;
1639 vm.segments = segments![((1, 0), 5), ((1, 2), 5), ((1, 3), 7)];
1641 let ids_data = ids_data!["r", "q", "div", "value"];
1643 assert_matches!(
1645 run_hint!(vm, ids_data, hint_code),
1646 Err(HintError::Memory(
1647 MemoryError::InconsistentMemory(bx)
1648 )) if *bx == (Relocatable::from((1, 0)),
1649 MaybeRelocatable::Int(Felt252::from(5)),
1650 MaybeRelocatable::Int(Felt252::from(2)))
1651 );
1652 }
1653
1654 #[test]
1655 fn unsigned_div_rem_incorrect_ids() {
1656 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\nids.q, ids.r = divmod(ids.value, ids.div)";
1657 let mut vm = vm_with_range_check!();
1658 vm.run_context.fp = 4;
1660 vm.segments = segments![((1, 2), 5), ((1, 3), 7)];
1662 let ids_data = ids_data!["a", "b", "iv", "vlue"];
1664 assert_matches!(
1666 run_hint!(vm, ids_data, hint_code),
1667 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "div"
1668 )
1669 }
1670
1671 #[test]
1672 fn signed_div_rem_success() {
1673 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1674 let mut vm = vm_with_range_check!();
1675 vm.run_context.fp = 6;
1677 vm.segments = segments![((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1679 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1681 assert!(run_hint!(vm, ids_data, hint_code).is_ok());
1683 check_memory![vm.segments.memory, ((1, 0), 0), ((1, 1), 31)];
1684 }
1685
1686 #[test]
1687 fn signed_div_rem_negative_quotient() {
1688 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1689 let mut vm = vm_with_range_check!();
1690 vm.run_context.fp = 6;
1692 vm.segments = segments![((1, 3), 7), ((1, 4), (-10)), ((1, 5), 29)];
1694 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1696 assert!(run_hint!(vm, ids_data, hint_code).is_ok());
1698 check_memory![vm.segments.memory, ((1, 0), 4), ((1, 1), 27)];
1699 }
1700
1701 #[test]
1702 fn signed_div_rem_out_of_range() {
1703 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1704 let mut vm = vm_with_range_check!();
1705 vm.run_context.fp = 6;
1707 vm.segments = segments![((1, 3), (-5)), ((1, 4), 10), ((1, 5), 29)];
1709 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1711 assert_matches!(
1713 run_hint!(vm, ids_data, hint_code),
1714 Err(HintError::OutOfValidRange(bx))
1715 if *bx == (Felt252::from(-5), felt_str!("340282366920938463463374607431768211456"))
1716 )
1717 }
1718
1719 #[test]
1720 fn signed_div_rem_out_of_range_bound() {
1721 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1722 let mut vm = vm_with_range_check!();
1723 vm.run_context.fp = 6;
1725 let bound = vm.get_range_check_builtin().unwrap().bound();
1727 vm.segments = segments![((1, 3), (5)), ((1, 4), 10)];
1728 vm.insert_value((1, 5).into(), bound).unwrap();
1729 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1731 let builtin_bound = felt_str!("340282366920938463463374607431768211456");
1733 assert_matches!(
1734 run_hint!(vm, ids_data, hint_code),
1735 Err(HintError::OutOfValidRange(bx))
1736 if *bx == (*bound, builtin_bound.field_div(&Felt252::TWO.try_into().unwrap()))
1737 )
1738 }
1739
1740 #[test]
1741 fn signed_div_rem_no_range_check_builtin() {
1742 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1743 let mut vm = vm!();
1744 vm.run_context.fp = 6;
1746 vm.segments = segments![((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1748 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1750 assert_matches!(
1751 run_hint!(vm, ids_data, hint_code),
1752 Err(HintError::Internal(
1753 VirtualMachineError::NoRangeCheckBuiltin
1754 ))
1755 );
1756 }
1757
1758 #[test]
1759 fn signed_div_rem_inconsitent_memory() {
1760 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1761 let mut vm = vm_with_range_check!();
1762 vm.run_context.fp = 6;
1764 vm.segments = segments![((1, 1), 10), ((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1766 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1768 assert_matches!(
1770 run_hint!(vm, ids_data, hint_code),
1771 Err(HintError::Memory(
1772 MemoryError::InconsistentMemory(bx)
1773 )) if *bx == (Relocatable::from((1, 1)),
1774 MaybeRelocatable::Int(Felt252::from(10)),
1775 MaybeRelocatable::Int(Felt252::from(31)))
1776 );
1777 }
1778
1779 #[test]
1780 fn signed_div_rem_incorrect_ids() {
1781 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1782 let mut vm = vm_with_range_check!();
1783 vm.run_context.fp = 6;
1785 vm.segments = segments![((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1787 let ids_data = ids_data!["r", "b", "r", "d", "v", "b"];
1789 assert_matches!(
1791 run_hint!(vm, ids_data, hint_code),
1792 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "div"
1793 )
1794 }
1795
1796 #[test]
1797 fn run_assert_250_bit_valid() {
1798 let hint_code = hint_code::ASSERT_250_BITS;
1799 let constants = HashMap::from([
1800 ("UPPER_BOUND".to_string(), Felt252::from(15)),
1801 ("SHIFT".to_string(), Felt252::from(5)),
1802 ]);
1803 let mut vm = vm!();
1804 vm.run_context.fp = 3;
1806 vm.segments = segments![((1, 0), 1)];
1808 let ids_data = ids_data!["value", "high", "low"];
1810 assert_matches!(
1812 run_hint!(vm, ids_data, hint_code, &mut exec_scopes_ref!(), &constants),
1813 Ok(())
1814 );
1815 check_memory![vm.segments.memory, ((1, 1), 0), ((1, 2), 1)];
1818 }
1819
1820 #[test]
1821 fn run_assert_250_bit_invalid() {
1822 let hint_code = hint_code::ASSERT_250_BITS;
1823 let constants = HashMap::from([
1824 ("UPPER_BOUND".to_string(), Felt252::from(15)),
1825 ("SHIFT".to_string(), Felt252::from(5)),
1826 ]);
1827 let mut vm = vm!();
1828 vm.run_context.fp = 3;
1830 vm.segments = segments![(
1833 (1, 0),
1834 (
1835 "3618502788666131106986593281521497120414687020801267626233049500247285301248",
1836 10
1837 )
1838 )];
1839 let ids_data = ids_data!["value", "high", "low"];
1841 assert_matches!(
1843 run_hint!(vm, ids_data, hint_code, &mut exec_scopes_ref!(), &constants),
1844 Err(HintError::ValueOutside250BitRange(bx)) if *bx == pow2_const(251)
1845 );
1846 }
1847
1848 #[test]
1849 fn run_is_250_bits_valid() {
1850 let hint_code = "ids.is_250 = 1 if ids.addr < 2**250 else 0";
1851 let mut vm = vm!();
1852 vm.run_context.fp = 2;
1854 vm.segments = segments![((1, 0), 1152251)];
1856 let ids_data = ids_data!["addr", "is_250"];
1858 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1860 check_memory![vm.segments.memory, ((1, 1), 1)];
1862 }
1863
1864 #[test]
1865 fn run_is_250_bits_invalid() {
1866 let hint_code = "ids.is_250 = 1 if ids.addr < 2**250 else 0";
1867 let mut vm = vm!();
1868 vm.run_context.fp = 2;
1870 vm.segments = segments![(
1873 (1, 0),
1874 (
1875 "3618502788666131106986593281521497120414687020801267626233049500247285301248",
1876 10
1877 )
1878 )];
1879 let ids_data = ids_data!["addr", "is_250"];
1881 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1883 check_memory![vm.segments.memory, ((1, 1), 0)];
1885 }
1886
1887 #[test]
1888 fn run_is_addr_bounded_ok() {
1889 let hint_code = hint_code::IS_ADDR_BOUNDED;
1890 let mut vm = vm!();
1891 let addr_bound = felt_str!(
1892 "3618502788666131106986593281521497120414687020801267626233049500247285301000"
1893 );
1894 vm.run_context.fp = 2;
1896 vm.segments = segments![(
1898 (1, 0),
1899 (
1900 "1809251394333067160431340899751024102169435851563236335319518532916477952000",
1901 10
1902 )
1903 ),];
1904 let ids_data = ids_data!["addr", "is_small"];
1906 assert_matches!(
1908 run_hint!(
1909 vm,
1910 ids_data,
1911 hint_code,
1912 exec_scopes_ref!(),
1913 &[(ADDR_BOUND, addr_bound)]
1914 .into_iter()
1915 .map(|(k, v)| (k.to_string(), v))
1916 .collect()
1917 ),
1918 Ok(())
1919 );
1920 check_memory![vm.segments.memory, ((1, 1), 1)];
1922 }
1923
1924 #[test]
1925 fn run_is_addr_bounded_assert_fail() {
1926 let hint_code = hint_code::IS_ADDR_BOUNDED;
1927 let mut vm = vm!();
1928 let addr_bound = Felt252::ONE;
1929 vm.run_context.fp = 2;
1931 vm.segments = segments![(
1933 (1, 0),
1934 (
1935 "3618502788666131106986593281521497120414687020801267626233049500247285301000",
1936 10
1937 )
1938 ),];
1939 let ids_data = ids_data!["addr", "is_small"];
1941 assert_matches!(
1943 run_hint!(
1944 vm,
1945 ids_data,
1946 hint_code,
1947 exec_scopes_ref!(),
1948 &HashMap::from([(ADDR_BOUND.to_string(), addr_bound)])
1949 ),
1950 Err(HintError::AssertionFailed(bx))
1951 if bx.as_ref() == "normalize_address() cannot be used with the current constants."
1952 );
1953 }
1954
1955 #[test]
1956 fn run_is_addr_bounded_missing_const() {
1957 let hint_code = hint_code::IS_ADDR_BOUNDED;
1958 let mut vm = vm!();
1959 vm.run_context.fp = 2;
1961 vm.segments = segments![((1, 0), 0),];
1963 let ids_data = ids_data!["addr", "is_small"];
1965 assert_matches!(
1967 run_hint!(vm, ids_data, hint_code),
1968 Err(HintError::MissingConstant(bx)) if *bx == ADDR_BOUND
1969 );
1970 }
1971
1972 #[test]
1973 fn run_split_felt_ok() {
1974 let hint_code =
1975 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
1976 let mut vm = vm_with_range_check!();
1977 vm.segments = segments![
1978 ((1, 3), ("335438970432432812899076431678123043273", 10)),
1979 ((1, 4), (2, 0))
1980 ];
1981 add_segments!(vm, 1);
1982 vm.run_context.fp = 7;
1984 let ids_data = HashMap::from([
1986 ("value".to_string(), HintReference::new_simple(-4)),
1987 (
1988 "low".to_string(),
1989 HintReference::new(-3, 0, true, true, true),
1990 ),
1991 (
1992 "high".to_string(),
1993 HintReference::new(-3, 1, true, true, true),
1994 ),
1995 ]);
1996 assert_matches!(
1998 run_hint!(
1999 vm,
2000 ids_data,
2001 hint_code,
2002 exec_scopes_ref!(),
2003 &HashMap::from([
2004 ("MAX_LOW".to_string(), Felt252::ZERO),
2005 (
2006 "MAX_HIGH".to_string(),
2007 felt_str!("10633823966279327296825105735305134080")
2008 )
2009 ])
2010 ),
2011 Ok(())
2012 );
2013 check_memory![
2015 vm.segments.memory,
2016 ((2, 0), ("335438970432432812899076431678123043273", 10)),
2017 ((2, 1), 0)
2018 ];
2019 }
2020
2021 #[test]
2022 fn run_split_felt_incorrect_ids() {
2023 let hint_code =
2024 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2025 let mut vm = vm_with_range_check!();
2026 vm.segments = segments![
2027 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2028 ((1, 4), (2, 0))
2029 ];
2030 vm.run_context.fp = 7;
2032 let ids_data = ids_data!["low"];
2035 assert_matches!(
2037 run_hint!(
2038 vm,
2039 ids_data,
2040 hint_code,
2041 exec_scopes_ref!(),
2042 &HashMap::from([
2043 ("MAX_LOW".to_string(), Felt252::ZERO),
2044 (
2045 "MAX_HIGH".to_string(),
2046 felt_str!("10633823966279327296825105735305134080")
2047 )
2048 ])
2049 ),
2050 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "value"
2051 );
2052 }
2053
2054 #[test]
2055 fn run_split_felt_fails_first_insert() {
2056 let hint_code =
2057 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2058 let mut vm = vm_with_range_check!();
2059 vm.segments = segments![
2060 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2061 ((1, 4), (2, 0)),
2062 ((2, 0), 99)
2063 ];
2064 vm.run_context.fp = 7;
2066 let ids_data = HashMap::from([
2068 ("value".to_string(), HintReference::new_simple(-4)),
2069 (
2070 "low".to_string(),
2071 HintReference::new(-3, 0, true, true, true),
2072 ),
2073 (
2074 "high".to_string(),
2075 HintReference::new(-3, 1, true, true, true),
2076 ),
2077 ]);
2078
2079 assert_matches!(
2081 run_hint!(
2082 vm,
2083 ids_data,
2084 hint_code,
2085 exec_scopes_ref!(),
2086 &HashMap::from([
2087 ("MAX_LOW".to_string(), Felt252::ZERO),
2088 (
2089 "MAX_HIGH".to_string(),
2090 felt_str!("10633823966279327296825105735305134080")
2091 )
2092 ])
2093 ),
2094 Err(HintError::Memory(
2095 MemoryError::InconsistentMemory(bx)
2096 )) if *bx == (Relocatable::from((2, 0)),
2097 MaybeRelocatable::from(Felt252::from(99)),
2098 MaybeRelocatable::from(felt_str!("335438970432432812899076431678123043273")))
2099 );
2100 }
2101
2102 #[test]
2103 fn run_split_felt_fails_second_insert() {
2104 let hint_code =
2105 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2106 let mut vm = vm_with_range_check!();
2107 vm.segments = segments![
2108 ((1, 4), (2, 0)),
2109 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2110 ((2, 1), 99)
2111 ];
2112 add_segments!(vm, 1);
2113 vm.run_context.fp = 7;
2115 let ids_data = HashMap::from([
2117 ("value".to_string(), HintReference::new_simple(-4)),
2118 (
2119 "low".to_string(),
2120 HintReference::new(-3, 0, true, true, true),
2121 ),
2122 (
2123 "high".to_string(),
2124 HintReference::new(-3, 1, true, true, true),
2125 ),
2126 ]);
2127 assert_matches!(
2129 run_hint!(
2130 vm,
2131 ids_data,
2132 hint_code,
2133 exec_scopes_ref!(),
2134 &HashMap::from([
2135 ("MAX_LOW".to_string(), Felt252::ZERO),
2136 (
2137 "MAX_HIGH".to_string(),
2138 felt_str!("10633823966279327296825105735305134080")
2139 )
2140 ])
2141 ),
2142 Err(HintError::Memory(
2143 MemoryError::InconsistentMemory(bx)
2144 )) if *bx == (Relocatable::from((2, 1)),
2145 MaybeRelocatable::from(Felt252::from(99)),
2146 MaybeRelocatable::from(Felt252::from(0)))
2147 );
2148 }
2149
2150 #[test]
2151 fn run_split_felt_value_is_not_integer() {
2152 let hint_code =
2153 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2154 let mut vm = vm_with_range_check!();
2155 vm.segments = segments![((1, 3), (1, 0)), ((1, 4), (2, 0))];
2156 vm.run_context.fp = 7;
2158 let ids_data = HashMap::from([
2160 ("value".to_string(), HintReference::new_simple(-4)),
2161 (
2162 "low".to_string(),
2163 HintReference::new(-3, 0, true, true, true),
2164 ),
2165 (
2166 "high".to_string(),
2167 HintReference::new(-3, 1, true, true, true),
2168 ),
2169 ]);
2170 assert_matches!(
2172 run_hint!(
2173 vm,
2174 ids_data,
2175 hint_code,
2176 exec_scopes_ref!(),
2177 &HashMap::from([
2178 ("MAX_LOW".to_string(), Felt252::ZERO),
2179 (
2180 "MAX_HIGH".to_string(),
2181 felt_str!("10633823966279327296825105735305134080")
2182 )
2183 ])
2184 ),
2185 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "value"
2186 );
2187 }
2188
2189 #[test]
2190 fn run_split_felt_no_constants() {
2191 let hint_code =
2192 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2193 let mut vm = vm_with_range_check!();
2194 vm.segments = segments![
2195 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2196 ((1, 4), (2, 0))
2197 ];
2198 add_segments!(vm, 1);
2199 vm.run_context.fp = 7;
2201 let ids_data = HashMap::from([
2203 ("value".to_string(), HintReference::new_simple(-4)),
2204 (
2205 "low".to_string(),
2206 HintReference::new(-3, 0, true, true, true),
2207 ),
2208 (
2209 "high".to_string(),
2210 HintReference::new(-3, 1, true, true, true),
2211 ),
2212 ]);
2213 assert_matches!(
2215 run_hint!(vm, ids_data, hint_code),
2216 Err(HintError::MissingConstant(x)) if (*x) == "MAX_HIGH"
2217 );
2218 }
2219
2220 #[test]
2221 fn run_split_felt_constants_over_128_bits() {
2222 let hint_code =
2223 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2224 let mut vm = vm_with_range_check!();
2225 vm.segments = segments![
2226 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2227 ((1, 4), (2, 0))
2228 ];
2229 add_segments!(vm, 1);
2230 vm.run_context.fp = 7;
2232 let ids_data = HashMap::from([
2234 ("value".to_string(), HintReference::new_simple(-4)),
2235 (
2236 "low".to_string(),
2237 HintReference::new(-3, 0, true, true, true),
2238 ),
2239 (
2240 "high".to_string(),
2241 HintReference::new(-3, 1, true, true, true),
2242 ),
2243 ]);
2244 assert_matches!(
2246 run_hint!(
2247 vm,
2248 ids_data,
2249 hint_code,
2250 exec_scopes_ref!(),
2251 &HashMap::from([
2252 ("MAX_LOW".to_string(), Felt252::from(-1)),
2253 (
2254 "MAX_HIGH".to_string(),
2255 Felt252::from(-1),
2256 )
2257 ])
2258 ),
2259 Err(HintError::AssertionFailed(x)) if &(*x) == "assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128"
2260 );
2261 }
2262
2263 #[test]
2264 fn run_split_felt_wrong_constants() {
2265 let hint_code =
2266 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2267 let mut vm = vm_with_range_check!();
2268 vm.segments = segments![
2269 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2270 ((1, 4), (2, 0))
2271 ];
2272 add_segments!(vm, 1);
2273 vm.run_context.fp = 7;
2275 let ids_data = HashMap::from([
2277 ("value".to_string(), HintReference::new_simple(-4)),
2278 (
2279 "low".to_string(),
2280 HintReference::new(-3, 0, true, true, true),
2281 ),
2282 (
2283 "high".to_string(),
2284 HintReference::new(-3, 1, true, true, true),
2285 ),
2286 ]);
2287 assert_matches!(
2289 run_hint!(
2290 vm,
2291 ids_data,
2292 hint_code,
2293 exec_scopes_ref!(),
2294 &HashMap::from([
2295 ("MAX_LOW".to_string(), Felt252::ZERO),
2296 (
2297 "MAX_HIGH".to_string(),
2298 Felt252::ZERO,
2299 )
2300 ])
2301 ),
2302 Err(HintError::AssertionFailed(x)) if &(*x) == "assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW"
2303 );
2304 }
2305
2306 #[test]
2307 fn run_assert_lt_felt_ok() {
2308 let hint_code =
2309 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2310 let mut vm = vm_with_range_check!();
2311 vm.run_context.fp = 3;
2313 vm.segments = segments![((1, 1), 1), ((1, 2), 2)];
2315 let ids_data = ids_data!["a", "b"];
2317 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
2319 }
2320
2321 #[test]
2322 fn run_assert_lt_felt_assert_fails() {
2323 let hint_code =
2324 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2325 let mut vm = vm_with_range_check!();
2326 vm.run_context.fp = 3;
2328 vm.segments = segments![((1, 1), 3), ((1, 2), 2)];
2329 let ids_data = ids_data!["a", "b"];
2330 assert_matches!(
2332 run_hint!(vm, ids_data, hint_code),
2333 Err(HintError::AssertLtFelt252(bx)) if *bx == (Felt252::from(3), Felt252::from(2))
2334 );
2335 }
2336
2337 #[test]
2338 fn run_assert_lt_felt_incorrect_ids() {
2339 let hint_code =
2340 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2341 let mut vm = vm_with_range_check!();
2342 vm.run_context.fp = 3;
2344 vm.segments = segments![((1, 1), 1), ((1, 2), 2)];
2345 let ids_data = ids_data!["a"];
2347 assert_matches!(
2349 run_hint!(vm, ids_data, hint_code),
2350 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "b"
2351 );
2352 }
2353
2354 #[test]
2355 fn run_assert_lt_felt_a_is_not_integer() {
2356 let hint_code =
2357 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2358 let mut vm = vm_with_range_check!();
2359 vm.run_context.fp = 3;
2361 vm.segments = segments![((1, 1), (1, 0)), ((1, 2), 2)];
2362 let ids_data = ids_data!["a", "b"];
2363 assert_matches!(
2365 run_hint!(vm, ids_data, hint_code),
2366 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "a"
2367 );
2368 }
2369
2370 #[test]
2371 fn run_assert_lt_felt_b_is_not_integer() {
2372 let hint_code =
2373 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2374 let mut vm = vm_with_range_check!();
2375 vm.run_context.fp = 3;
2377 vm.segments = segments![((1, 1), 1), ((1, 2), (1, 0))];
2378 let ids_data = ids_data!["a", "b"];
2379 assert_matches!(
2381 run_hint!(vm, ids_data, hint_code),
2382 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "b"
2383 );
2384 }
2385
2386 #[test]
2387 fn run_assert_lt_felt_ok_failed_to_get_ids() {
2388 let hint_code =
2389 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2390 let mut vm = vm_with_range_check!();
2391 vm.run_context.fp = 3;
2393 vm.segments = segments![((1, 1), 1)];
2395 let ids_data = ids_data!["a", "b"];
2396 assert_matches!(
2398 run_hint!(vm, ids_data, hint_code),
2399 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "b"
2400 );
2401 }
2402
2403 #[test]
2404 fn run_is_assert_le_felt_v_0_6_assertion_fail() {
2405 let mut vm = vm_with_range_check!();
2406 vm.set_fp(2);
2407 vm.segments = segments![((1, 0), 17), ((1, 1), 7)];
2408 let ids_data = ids_data!["a", "b"];
2411 assert_matches!(
2413 run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT_V_0_6),
2414 Err(HintError::NonLeFelt252(bx)) if *bx == (17_u32.into(), 7_u32.into())
2415 );
2416 }
2417
2418 #[test]
2419 fn run_is_assert_le_felt_v_0_8_assertion_fail() {
2420 let mut vm = vm_with_range_check!();
2421 vm.set_fp(2);
2422 vm.segments = segments![((1, 0), 17), ((1, 1), 7)];
2423 let ids_data = ids_data!["a", "b"];
2426 assert_matches!(
2428 run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT_V_0_8),
2429 Err(HintError::NonLeFelt252(bx)) if *bx == (17_u32.into(), 7_u32.into())
2430 );
2431 }
2432
2433 proptest! {
2434 #[test]
2435 fn run_is_quad_residue(ref x in "([1-9][0-9]*)") {
2437 let mut vm = vm!();
2438 vm.run_context.fp = 2;
2439 vm.segments = segments![((1, 1), (&x[..], 10))];
2440 let ids_data = ids_data!["y", "x"];
2441
2442 assert_matches!(run_hint!(vm, ids_data, hint_code::IS_QUAD_RESIDUE), Ok(()));
2443
2444 let x = felt_str!(x);
2445
2446 if x.is_zero() || x == Felt252::ONE {
2447 assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().as_ref(), &x);
2448 } else if x.pow_felt(&Felt252::MAX.field_div(&Felt252::TWO.try_into().unwrap())) == Felt252::ONE {
2449 assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().into_owned(), x.sqrt().unwrap());
2450 } else {
2451 assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().into_owned(), (x.field_div(&(Felt252::from(3).try_into().unwrap())).sqrt().unwrap()));
2452 }
2453 }
2454 }
2455}