diff --git a/src/value.rs b/src/value.rs index c8729e4..1b477cd 100644 --- a/src/value.rs +++ b/src/value.rs @@ -181,8 +181,10 @@ impl Value { CoreTypeConcrete::Sint64(_) => todo!(), CoreTypeConcrete::Nullable(info) => self.is(registry, &info.ty), CoreTypeConcrete::Uninitialized(_) => matches!(self, Self::Uninitialized { .. }), - CoreTypeConcrete::Felt252DictEntry(_) => todo!(), - CoreTypeConcrete::SquashedFelt252Dict(_) => todo!(), + CoreTypeConcrete::Felt252DictEntry(info) => matches!(self, Self::FeltDictEntry { ty, .. } if *ty == info.ty), + CoreTypeConcrete::SquashedFelt252Dict(info) => { + matches!(self, Self::FeltDict { ty, .. } if *ty == info.ty) + }, CoreTypeConcrete::Pedersen(_) => matches!(self, Self::Unit), CoreTypeConcrete::Poseidon(_) => matches!(self, Self::Unit), CoreTypeConcrete::Span(_) => todo!(), diff --git a/src/vm/uint128.rs b/src/vm/uint128.rs index 7dc4c83..fe35766 100644 --- a/src/vm/uint128.rs +++ b/src/vm/uint128.rs @@ -1,5 +1,5 @@ use super::EvalAction; -use crate::Value; +use crate::{debug::debug_signature, Value}; use cairo_lang_sierra::{ extensions::{ core::{CoreLibfunc, CoreType}, @@ -24,7 +24,7 @@ pub fn eval( match selector { Uint128Concrete::Const(info) => eval_const(registry, info, args), Uint128Concrete::Operation(info) => eval_operation(registry, info, args), - Uint128Concrete::SquareRoot(_) => todo!(), + Uint128Concrete::SquareRoot(info) => eval_square_root(registry, info, args), Uint128Concrete::Equal(info) => eval_equal(registry, info, args), Uint128Concrete::ToFelt252(info) => eval_to_felt(registry, info, args), Uint128Concrete::FromFelt252(info) => eval_from_felt(registry, info, args), @@ -54,6 +54,23 @@ pub fn eval_guarantee_mul( EvalAction::NormalBranch(0, smallvec![high, low, Value::Unit]) } +pub fn eval_square_root( + _registry: &ProgramRegistry, + _info: &SignatureOnlyConcreteLibfunc, + args: Vec, +) -> EvalAction { + let [range_check @ Value::Unit, Value::U128(value)]: [Value; 2] = args.try_into().unwrap() + else { + panic!() + }; + + let value_big = BigUint::from(value); + + let result: u64 = value_big.sqrt().try_into().unwrap(); + + EvalAction::NormalBranch(0, smallvec![range_check, Value::U64(result)]) +} + pub fn eval_guarantee_verify( _registry: &ProgramRegistry, _info: &SignatureOnlyConcreteLibfunc, @@ -215,3 +232,27 @@ pub fn eval_byte_reverse( EvalAction::NormalBranch(0, smallvec![bitwise, Value::U128(value)]) } + +#[cfg(test)] +mod test { + use crate::{load_cairo, test_utils::run_test_program, Value}; + + #[test] + fn test_square_root() { + let (_, program) = load_cairo!( + use core::num::traits::Sqrt; + fn main() -> u64 { + 0xffffffffffffffffffffffffffffffff_u128.sqrt() + } + ); + + let result = run_test_program(program); + + let Value::U64(payload) = result.last().unwrap() + else { + panic!("No output"); + }; + + assert_eq!(*payload, 0xffffffffffffffff); + } +}