Skip to main content

cairo_vm/hint_processor/builtin_hint_processor/
math_utils.rs

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
40//Implements hint: memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1
41pub 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    //Main logic (assert a is not negative and within the expected range)
49    insert_value_into_ap(vm, Felt252::from(a.as_ref() >= range_check_bound))
50}
51
52//Implements hint: memory[ap] = 0 if 0 <= ((-ids.a - 1) % PRIME) < range_check_builtin.bound else 1
53pub 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    //Main logic (assert a is not negative and within the expected range)
62    insert_value_into_ap(vm, Felt252::from(-(a + 1) >= *range_check_bound))
63}
64/* Implements hint:from starkware.cairo.common.math_utils import assert_integer
65%{
66    import itertools
67
68    from starkware.cairo.common.math_utils import assert_integer
69    assert_integer(ids.a)
70    assert_integer(ids.b)
71    a = ids.a % PRIME
72    b = ids.b % PRIME
73    assert a <= b, f'a = {a} is not less than or equal to b = {b}.'
74
75    # Find an arc less than PRIME / 3, and another less than PRIME / 2.
76    lengths_and_indices = [(a, 0), (b - a, 1), (PRIME - 1 - b, 2)]
77    lengths_and_indices.sort()
78    assert lengths_and_indices[0][0] <= PRIME // 3 and lengths_and_indices[1][0] <= PRIME // 2
79    excluded = lengths_and_indices[2][1]
80
81    memory[ids.range_check_ptr + 1], memory[ids.range_check_ptr + 0] = (
82        divmod(lengths_and_indices[0][0], ids.PRIME_OVER_3_HIGH))
83    memory[ids.range_check_ptr + 3], memory[ids.range_check_ptr + 2] = (
84        divmod(lengths_and_indices[1][0], ids.PRIME_OVER_2_HIGH))
85%}
86*/
87pub 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    // TODO: use UnsignedInteger for this
108    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    // TODO: I believe this check can be removed
123    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
211//Implements hint:from starkware.cairo.common.math_cmp import is_le_felt
212//    memory[ap] = 0 if (ids.a % PRIME) <= (ids.b % PRIME) else 1
213pub 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
228//Implements hint: from starkware.cairo.lang.vm.relocatable import RelocatableValue
229//        both_ints = isinstance(ids.a, int) and isinstance(ids.b, int)
230//        both_relocatable = (
231//            isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and
232//            ids.a.segment_index == ids.b.segment_index)
233//        assert both_ints or both_relocatable, \
234//            f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'
235//        assert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'
236pub 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
269//Implements hint:
270// %{
271//     from starkware.cairo.common.math_utils import assert_integer
272//     assert_integer(ids.a)
273//     assert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'
274// %}
275pub 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    // assert 0 <= ids.a % PRIME < range_check_builtin.bound
283    // as prime > 0, a % prime will always be > 0
284    if a.as_ref() >= range_check_builtin.bound() {
285        Err(HintError::AssertNNValueOutOfRange(Box::new(a)))
286    } else {
287        Ok(())
288    }
289}
290
291//Implements hint:from starkware.cairo.common.math.cairo
292// %{
293// from starkware.cairo.common.math_utils import assert_integer
294// assert_integer(ids.value)
295// assert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'
296// %}
297pub 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
312//Implements hint: assert ids.value == 0, 'split_int(): value is out of range.'
313pub 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    //Main logic (assert value == 0)
320    if !value.is_zero() {
321        return Err(HintError::SplitIntNotZero);
322    }
323    Ok(())
324}
325
326//Implements hint: memory[ids.output] = res = (int(ids.value) % PRIME) % ids.base
327//        assert res < ids.bound, f'split_int(): Limb {res} is out of range.'
328pub 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    //Main Logic
343    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
350//from starkware.cairo.common.math_utils import is_positive
351//ids.is_positive = 1 if is_positive(
352//    value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0
353pub 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    // Avoid using abs so we don't allocate a new BigInt
363    let (sign, abs_value) = value_as_int.into_parts();
364    //Main logic (assert a is positive)
365    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
373//Implements hint:
374// %{
375//     from starkware.cairo.common.math_utils import assert_integer
376//     assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128
377//     assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW
378//     assert_integer(ids.value)
379//     ids.low = ids.value & ((1 << 128) - 1)
380//     ids.high = ids.value >> 128
381// %}
382pub 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    //Main logic
406    //assert_integer(ids.value) (done by match)
407    // ids.low = ids.value & ((1 << 128) - 1)
408    // ids.high = ids.value >> 128
409    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
414//Implements hint: from starkware.python.math_utils import isqrt
415//        value = ids.value % PRIME
416//        assert value < 2 ** 250, f"value={value} is outside of the range [0, 2**250)."
417//        assert 2 ** 250 < PRIME
418//        ids.root = isqrt(value)
419pub 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    //This is equal to mod_value > Felt252::from(2).pow(250)
426    if mod_value > pow2_const(250) {
427        return Err(HintError::ValueOutside250BitRange(Box::new(mod_value)));
428        //This is equal to mod_value > bigint!(2).pow(250)
429    }
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
485/*
486Implements hint:
487
488from starkware.cairo.common.math_utils import assert_integer
489assert_integer(ids.div)
490assert 0 < ids.div <= PRIME // range_check_builtin.bound, \
491    f'div={hex(ids.div)} is out of the valid range.'
492ids.q, ids.r = divmod(ids.value, ids.div)
493*/
494pub 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    // Main logic
504    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
513//Implements hint: from starkware.cairo.common.math_utils import as_int
514//        # Correctness check.
515//        value = as_int(ids.value, PRIME) % PRIME
516//        assert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).'
517//        # Calculation for the assertion.
518//        ids.high, ids.low = divmod(ids.value, ids.SHIFT)
519pub 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    //Declare constant values
528    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    //Main logic
541    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
549// Implements hint:
550// %{ ids.is_250 = 1 if ids.addr < 2**250 else 0 %}
551pub 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    // Main logic: ids.is_250 = 1 if ids.addr < 2**250 else 0
559    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
564/*
565Implements hint:
566%{
567    # Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME.
568    ADDR_BOUND = ids.ADDR_BOUND % PRIME
569    assert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and (
570            ADDR_BOUND * 2 > PRIME), \
571        'normalize_address() cannot be used with the current constants.'
572    ids.is_small = 1 if ids.addr < ADDR_BOUND else 0
573%}
574*/
575pub 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    // assert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and (
592    //      ADDR_BOUND * 2 > PRIME), \
593    //      'normalize_address() cannot be used with the current constants.'
594    // The second check is not needed, as it's true for the CAIRO_PRIME
595    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    // Main logic: ids.is_small = 1 if ids.addr < ADDR_BOUND else 0
607    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
612/*
613Implements hint:
614%{
615    from starkware.cairo.common.math_utils import assert_integer
616    assert_integer(ids.a)
617    assert_integer(ids.b)
618    assert (ids.a % PRIME) < (ids.b % PRIME), \
619        f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'
620%}
621*/
622pub 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    // Main logic
630    // assert_integer(ids.a)
631    // assert_integer(ids.b)
632    // assert (ids.a % PRIME) < (ids.b % PRIME), \
633    //     f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'
634    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 Pow::pow(felt_to_biguint(x), &(&*CAIRO_PRIME >> 1_u32)).is_one() {
650    } 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
678/* Implements hint:
679   %{
680       ids.a_lsb = ids.a & 1
681       ids.b_lsb = ids.b & 1
682   %}
683*/
684pub 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
711/* Implements hint:
712   PRIME = 2**255 - 19
713   II = pow(2, (PRIME - 1) // 4, PRIME)
714
715   xx = ids.xx.low + (ids.xx.high<<128)
716   x = pow(xx, (PRIME + 3) // 8, PRIME)
717   if (x * x - xx) % PRIME != 0:
718       x = (x * II) % PRIME
719   if x % 2 != 0:
720       x = PRIME - x
721   ids.x.low = x & ((1<<128)-1)
722   ids.x.high = x >> 128
723
724   Note: doesnt belong to and is not variation of any hint from common/math
725*/
726pub 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        //Initialize fp
781        vm.run_context.fp = 10;
782        //Insert ids into memory
783        vm.segments = segments![((1, 9), (-1))];
784        add_segments!(vm, 1);
785        //Create ids_data & hint_data
786        let ids_data = ids_data!["a"];
787        //Execute the hint
788        run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
789        //Check that ap now contains false (1)
790        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        //Initialize fp
798        vm.run_context.fp = 5;
799        //Insert ids into memory
800        vm.segments = segments![((1, 4), 1)];
801        add_segments!(vm, 1);
802        //Create ids_data
803        let ids_data = ids_data!["a"];
804        //Execute the hint
805        run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
806        //Check that ap now contains true (0)
807        check_memory![vm.segments.memory, ((1, 0), 0)];
808    }
809
810    #[test]
811    //This test contemplates the case when the number itself is negative, but it is within the range (-prime, -range_check_bound)
812    //Making the comparison return 1 (true)
813    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        //Initialize fp
817        vm.run_context.fp = 5;
818        //Insert ids into memory
819        add_segments!(vm, 2);
820        vm.insert_value(
821            (1, 4).into(),
822            felt_str!(
823                "3618502788666131213697322783095070105623107215331596699973092056135872020480"
824            )
825            .neg(),
826        )
827        .unwrap();
828        //Create ids_data
829        let ids_data = ids_data!["a"];
830        //Execute the hint
831        run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
832        //Check that ap now contains true (0)
833        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        //Initialize fp
841        vm.run_context.fp = 5;
842        //Insert ids into memory
843        vm.segments = segments![((1, 4), 1)];
844        //Create ids_data
845        let ids_data = ids_data!["a"];
846        //Execute the hint
847        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        //Initialize ap
861        //Create ids_data & hint_data
862        let ids_data = ids_data!["b"];
863        //Execute the hint
864        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        //Initialize fp
876        vm.run_context.fp = 5;
877        //Dont insert ids into memory
878        //Create ids_data
879        let ids_data = ids_data!["a"];
880        //Execute the hint
881        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        //Initialize fp
892        vm.run_context.fp = 5;
893        //Insert ids into memory
894        vm.segments = segments![((1, 4), (2, 3))];
895        //Create ids_data
896        let ids_data = ids_data!["a"];
897        //Execute the hint
898        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        //Initialize fp
918        vm.run_context.fp = 3;
919        //Insert ids into memory
920        vm.segments = segments![((1, 0), 1), ((1, 1), 2), ((1, 2), (2, 0))];
921        add_segments!(vm, 1);
922        //Create ids_data & hint_data
923        let ids_data = ids_data!["a", "b", "range_check_ptr"];
924        //Execute the hint
925        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        //Hint would return an error if the assertion fails
936    }
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        //Initialize fp
943        vm.run_context.fp = 10;
944        //Insert ids into memory
945        vm.segments = segments![((1, 8), 1), ((1, 9), 2)];
946        add_segments!(vm, 1);
947        let ids_data = ids_data!["a", "b"];
948        //Execute the hint
949        assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
950        //Check result
951        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        //Initialize fp
959        vm.run_context.fp = 2;
960        vm.segments = segments![((1, 0), 1), ((1, 1), 2)];
961        //Create ids_data & hint_data
962        let ids_data = ids_data!["a", "b"];
963        //Execute the hint
964        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        //Create ids_data & hint_data
981        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        //Initialize fp
993        vm.run_context.fp = 1;
994        //Insert ids into memory
995        vm.segments = segments![((1, 0), 1)];
996        //Create ids_data & hint_data
997        let ids_data = ids_data!["a"];
998        //Execute the hint
999        assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1000        //Hint would return an error if the assertion fails
1001    }
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        //Initialize fp
1008        vm.run_context.fp = 1;
1009        //Insert ids into memory
1010        vm.segments = segments![((1, 0), (-1))];
1011        //Create ids_data & hint_data
1012        let ids_data = ids_data!["a"];
1013        //Execute the hint
1014        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        //Initialize fp
1025        vm.run_context.fp = 4;
1026        //Insert ids into memory
1027        vm.segments = segments![((1, 0), (-1))];
1028        let ids_data = ids_data!["incorrect_id"];
1029        //Execute the hint
1030        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        //Initialize fp
1041        vm.run_context.fp = 1;
1042        //Insert ids into memory
1043        vm.segments = segments![((1, 0), (10, 10))];
1044        let ids_data = ids_data!["a"];
1045        //Execute the hint
1046        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        //Initialize fp
1057        vm.run_context.fp = 1;
1058        //Insert ids into memory
1059        vm.segments = segments![((1, 0), 1)];
1060        let ids_data = ids_data!["a"];
1061        //Execute the hint
1062        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        //Initialize fp
1076        vm.run_context.fp = 4;
1077        let ids_data = ids_data!["a"];
1078        //Execute the hint
1079        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        //Initialize fp
1099        vm.run_context.fp = 3;
1100        //Insert ids into memory
1101        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        //Execute the hint
1105        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        //Initialize fp
1125        vm.run_context.fp = 3;
1126        //Insert ids into memory
1127        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        //Execute the hint
1130        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        //Initialize fp
1150        vm.run_context.fp = 3;
1151        //Insert ids into memory
1152        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        //Execute the hint
1155        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        //Initialize fp
1167        vm.run_context.fp = 5;
1168        //Insert ids into memory
1169        vm.segments = segments![((1, 4), 2)];
1170        add_segments!(vm, 1);
1171        //Create ids_data
1172        let ids_data = ids_data!["a"];
1173        //Execute the hint
1174        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        //Initialize fp
1184        vm.run_context.fp = 5;
1185        //Insert ids into memory
1186        vm.segments = segments![((1, 4), (-1))];
1187        add_segments!(vm, 1);
1188        //Create ids_data
1189        let ids_data = ids_data!["a"];
1190        //Execute the hint
1191        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        //Initialize fp
1199        vm.run_context.fp = 10;
1200        //Insert ids into memory
1201        vm.segments = segments![((1, 8), 1), ((1, 9), 1)];
1202        let ids_data = ids_data!["a", "b"];
1203        //Execute the hint
1204        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        //Initialize fp
1216        vm.run_context.fp = 10;
1217        //Insert ids into memory
1218        vm.segments = segments![((1, 8), 1), ((1, 9), 3)];
1219        let ids_data = ids_data!["a", "b"];
1220        //Execute the hint
1221        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        //Initialize fp
1230        vm.run_context.fp = 10;
1231        //Insert ids into memory
1232        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        //Execute the hint
1244        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        //Initialize fp
1252        vm.run_context.fp = 10;
1253        //Insert ids into memory
1254        vm.segments = segments![((1, 8), (1, 0)), ((1, 9), (1, 0))];
1255        let ids_data = ids_data!["a", "b"];
1256        //Execute the hint
1257        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        //Initialize fp
1269        vm.run_context.fp = 10;
1270        //Insert ids into memory
1271        vm.segments = segments![((1, 8), (0, 1)), ((1, 9), (0, 0))];
1272        let ids_data = ids_data!["a", "b"];
1273        //Execute the hint
1274        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        //Initialize fp
1282        vm.run_context.fp = 10;
1283        //Insert ids into memory
1284        vm.segments = segments![((1, 8), (2, 0)), ((1, 9), (1, 0))];
1285        let ids_data = ids_data!["a", "b"];
1286        //Execute the hint
1287        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        //Initialize fp
1299        vm.run_context.fp = 10;
1300        //Insert ids into memory
1301        vm.segments = segments![((1, 8), (1, 0)), ((1, 9), 1)];
1302        let ids_data = ids_data!["a", "b"];
1303        //Execute the hint
1304        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        // //Initialize fp
1318        vm.run_context.fp = 5;
1319        //Insert ids into memory
1320        vm.segments = segments![((1, 4), 5)];
1321        //Create ids
1322        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        // //Initialize fp
1333        vm.run_context.fp = 5;
1334        //Insert ids into memory
1335        vm.segments = segments![((1, 4), 0)];
1336        //Create ids
1337        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        // //Initialize fp
1350        vm.run_context.fp = 5;
1351        //Insert ids into memory
1352        vm.segments = segments![((1, 4), 0)];
1353        //Create invalid id key
1354        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        // //Initialize fp
1367        vm.run_context.fp = 5;
1368        //Insert ids into memory
1369        vm.segments = segments![((1, 4), (1, 0))];
1370        //Create ids_data & hint_data
1371        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        //Initialize fp
1383        vm.run_context.fp = 5;
1384        //Insert ids into memory
1385        vm.segments = segments![((1, 4), 1)];
1386        let ids_data = ids_data!["value"];
1387        //Execute the hint
1388        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        //Initialize fp
1399        vm.run_context.fp = 5;
1400        //Insert ids into memory
1401        vm.segments = segments![((1, 4), 0)];
1402        let ids_data = ids_data!["value"];
1403        //Execute the hint
1404        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        //Initialize fp
1412        vm.run_context.fp = 4;
1413        //Insert ids into memory
1414        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        //Execute the hint
1418        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        //Initialize fp
1427        vm.run_context.fp = 4;
1428        //Insert ids into memory
1429        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        //Execute the hint
1438        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        //Initialize fp
1450        vm.run_context.fp = 2;
1451        //Insert ids.value into memory
1452        vm.segments = segments![((1, 0), 250)];
1453        //Dont insert ids.is_positive as we need to modify it inside the hint
1454        //Create ids
1455        let ids_data = ids_data!["value", "is_positive"];
1456        //Execute the hint
1457        run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
1458        //Check that is_positive now contains 1 (true)
1459        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        //Initialize fp
1468        vm.run_context.fp = 2;
1469        //Insert ids.value into memory
1470        vm.segments = segments![((1, 0), (-250))];
1471        //Dont insert ids.is_positive as we need to modify it inside the hint
1472        let ids_data = ids_data!["value", "is_positive"];
1473        //Execute the hint
1474        run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
1475        //Check that is_positive now contains 0 (false)
1476        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        //Initialize fp
1485        vm.run_context.fp = 2;
1486        //Insert ids.value into memory
1487        vm.segments = segments![(
1488            (1, 0),
1489            (
1490                "618502761706184546546682988428055018603476541694452277432519575032261771265",
1491                10
1492            )
1493        )];
1494        //Dont insert ids.is_positive as we need to modify it inside the hint
1495        let ids_data = ids_data!["value", "is_positive"];
1496        //Execute the hint
1497        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        //Initialize fp
1511        vm.run_context.fp = 2;
1512        //Insert ids into memory
1513        vm.segments = segments![((1, 0), 2), ((1, 1), 4)];
1514        let ids_data = ids_data!["value", "is_positive"];
1515        //Execute the hint
1516        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        //Initialize fp
1531        vm.run_context.fp = 2;
1532        //Insert ids.value into memory
1533        vm.segments = segments![((1, 0), 81)];
1534        //Create ids
1535        let ids_data = ids_data!["value", "root"];
1536        //Execute the hint
1537        assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1538        //Check that root (0,1) has the square root of 81
1539        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        //Initialize fp
1547        vm.run_context.fp = 2;
1548        //Insert ids.value into memory
1549        vm.segments = segments![((1, 0), (-81))];
1550        //Create ids
1551        let ids_data = ids_data!["value", "root"];
1552        //Execute the hint
1553        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        //Initialize fp
1566        vm.run_context.fp = 2;
1567        //Insert ids.value into memory
1568        vm.segments = segments![((1, 0), 81), ((1, 1), 7)];
1569        //Create ids
1570        let ids_data = ids_data!["value", "root"];
1571        //Execute the hint
1572        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        //Initialize fp
1587        vm.run_context.fp = 4;
1588        //Insert ids into memory
1589        vm.segments = segments![((1, 2), 5), ((1, 3), 7)];
1590        //Create ids
1591        let ids_data = ids_data!["r", "q", "div", "value"];
1592        //Execute the hint
1593        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        //Initialize fp
1602        vm.run_context.fp = 4;
1603        //Insert ids into memory
1604        vm.segments = segments![((1, 2), (-5)), ((1, 3), 7)];
1605        //Create ids
1606        let ids_data = ids_data!["r", "q", "div", "value"];
1607        //Execute the hint
1608        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        //Initialize fp
1620        vm.run_context.fp = 4;
1621        //Insert ids into memory
1622        vm.segments = segments![((1, 2), 5), ((1, 3), 7)];
1623        //Create ids_data
1624        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        //Initialize fp
1638        vm.run_context.fp = 4;
1639        //Insert ids into memory
1640        vm.segments = segments![((1, 0), 5), ((1, 2), 5), ((1, 3), 7)];
1641        //Create ids_data
1642        let ids_data = ids_data!["r", "q", "div", "value"];
1643        //Execute the hint
1644        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        //Initialize fp
1659        vm.run_context.fp = 4;
1660        //Insert ids into memory
1661        vm.segments = segments![((1, 2), 5), ((1, 3), 7)];
1662        //Create ids
1663        let ids_data = ids_data!["a", "b", "iv", "vlue"];
1664        //Execute the hint
1665        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        //Initialize fp
1676        vm.run_context.fp = 6;
1677        //Insert ids into memory
1678        vm.segments = segments![((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1679        //Create ids
1680        let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1681        //Execute the hint
1682        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        //Initialize fp
1691        vm.run_context.fp = 6;
1692        //Insert ids into memory
1693        vm.segments = segments![((1, 3), 7), ((1, 4), (-10)), ((1, 5), 29)];
1694        //Create ids
1695        let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1696        //Execute the hint
1697        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        //Initialize fp
1706        vm.run_context.fp = 6;
1707        //Insert ids into memory
1708        vm.segments = segments![((1, 3), (-5)), ((1, 4), 10), ((1, 5), 29)];
1709        //Create ids
1710        let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1711        //Execute the hint
1712        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        //Initialize fp
1724        vm.run_context.fp = 6;
1725        //Insert ids into memory
1726        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        //Create ids
1730        let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1731        //Execute the hint
1732        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        //Initialize fp
1745        vm.run_context.fp = 6;
1746        //Insert ids into memory
1747        vm.segments = segments![((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1748        //Create ids
1749        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        //Initialize fp
1763        vm.run_context.fp = 6;
1764        //Insert ids into memory
1765        vm.segments = segments![((1, 1), 10), ((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1766        //Create ids
1767        let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1768        //Execute the hint
1769        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        //Initialize fp
1784        vm.run_context.fp = 6;
1785        //Insert ids into memory
1786        vm.segments = segments![((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1787        //Create ids
1788        let ids_data = ids_data!["r", "b", "r", "d", "v", "b"];
1789        //Execute the hint
1790        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        //Initialize fp
1805        vm.run_context.fp = 3;
1806        //Insert ids into memory
1807        vm.segments = segments![((1, 0), 1)];
1808        //Create ids
1809        let ids_data = ids_data!["value", "high", "low"];
1810        //Execute the hint
1811        assert_matches!(
1812            run_hint!(vm, ids_data, hint_code, &mut exec_scopes_ref!(), &constants),
1813            Ok(())
1814        );
1815        //Hint would return an error if the assertion fails
1816        //Check ids.high and ids.low values
1817        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        //Initialize fp
1829        vm.run_context.fp = 3;
1830        //Insert ids into memory
1831        //ids.value
1832        vm.segments = segments![(
1833            (1, 0),
1834            (
1835                "3618502788666131106986593281521497120414687020801267626233049500247285301248",
1836                10
1837            )
1838        )];
1839        //Create ids
1840        let ids_data = ids_data!["value", "high", "low"];
1841        //Execute the hint
1842        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        //Initialize fp
1853        vm.run_context.fp = 2;
1854        //Insert ids into memory
1855        vm.segments = segments![((1, 0), 1152251)];
1856        //Create ids
1857        let ids_data = ids_data!["addr", "is_250"];
1858        //Execute the hint
1859        assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1860        //Check ids.is_low
1861        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        //Initialize fp
1869        vm.run_context.fp = 2;
1870        //Insert ids into memory
1871        //ids.value
1872        vm.segments = segments![(
1873            (1, 0),
1874            (
1875                "3618502788666131106986593281521497120414687020801267626233049500247285301248",
1876                10
1877            )
1878        )];
1879        //Create ids
1880        let ids_data = ids_data!["addr", "is_250"];
1881        //Execute the hint
1882        assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1883        //Check ids.is_low
1884        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        //Initialize fp
1895        vm.run_context.fp = 2;
1896        //Insert ids into memory
1897        vm.segments = segments![(
1898            (1, 0),
1899            (
1900                "1809251394333067160431340899751024102169435851563236335319518532916477952000",
1901                10
1902            )
1903        ),];
1904        //Create ids
1905        let ids_data = ids_data!["addr", "is_small"];
1906        //Execute the hint
1907        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 ids.is_low
1921        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        //Initialize fp
1930        vm.run_context.fp = 2;
1931        //Insert ids into memory
1932        vm.segments = segments![(
1933            (1, 0),
1934            (
1935                "3618502788666131106986593281521497120414687020801267626233049500247285301000",
1936                10
1937            )
1938        ),];
1939        //Create ids
1940        let ids_data = ids_data!["addr", "is_small"];
1941        //Execute the hint
1942        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        //Initialize fp
1960        vm.run_context.fp = 2;
1961        //Insert ids into memory
1962        vm.segments = segments![((1, 0), 0),];
1963        //Create ids
1964        let ids_data = ids_data!["addr", "is_small"];
1965        //Execute the hint
1966        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        //Initialize fp
1983        vm.run_context.fp = 7;
1984        //Create ids
1985        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        //Execute the hint
1997        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 hint memory inserts
2014        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        //Initialize fp
2031        vm.run_context.fp = 7;
2032        //Create incomplete ids
2033        //Create ids_data & hint_data
2034        let ids_data = ids_data!["low"];
2035        //Execute the hint
2036        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        //Initialize fp
2065        vm.run_context.fp = 7;
2066        //Create ids_data & hint_data
2067        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        //Execute the hint
2080        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        //Initialize fp
2114        vm.run_context.fp = 7;
2115        //Create ids_data & hint_data
2116        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        //Execute the hint
2128        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        //Initialize fp
2157        vm.run_context.fp = 7;
2158        //Create ids_data & hint_data
2159        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        //Execute the hint
2171        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        //Initialize fp
2200        vm.run_context.fp = 7;
2201        //Create ids
2202        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        //Execute the hint
2214        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        //Initialize fp
2231        vm.run_context.fp = 7;
2232        //Create ids
2233        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        //Execute the hint
2245        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        //Initialize fp
2274        vm.run_context.fp = 7;
2275        //Create ids
2276        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        //Execute the hint
2288        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        //Initialize fp
2312        vm.run_context.fp = 3;
2313        //Insert ids into memory
2314        vm.segments = segments![((1, 1), 1), ((1, 2), 2)];
2315        //Create ids
2316        let ids_data = ids_data!["a", "b"];
2317        //Execute the hint
2318        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        //Initialize fp
2327        vm.run_context.fp = 3;
2328        vm.segments = segments![((1, 1), 3), ((1, 2), 2)];
2329        let ids_data = ids_data!["a", "b"];
2330        //Execute the hint
2331        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        //Initialize fp
2343        vm.run_context.fp = 3;
2344        vm.segments = segments![((1, 1), 1), ((1, 2), 2)];
2345        //Create Incorrects ids
2346        let ids_data = ids_data!["a"];
2347        //Execute the hint
2348        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        //Initialize fp
2360        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        //Execute the hint
2364        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        //Initialize fp
2376        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        //Execute the hint
2380        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        //Initialize fp
2392        vm.run_context.fp = 3;
2393        //Insert ids.a into memory
2394        vm.segments = segments![((1, 1), 1)];
2395        let ids_data = ids_data!["a", "b"];
2396        //Execute the hint
2397        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        //Initialize ap
2409        //Create ids_data & hint_data
2410        let ids_data = ids_data!["a", "b"];
2411        //Execute the hint
2412        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        //Initialize ap
2424        //Create ids_data & hint_data
2425        let ids_data = ids_data!["a", "b"];
2426        //Execute the hint
2427        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        // Proptest to check is_quad_residue hint function
2436        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}