@@ -7,6 +7,7 @@ use crate::{
77 error:: { Result , SierraAssertError } ,
88 libfuncs:: r#struct:: build_struct_value,
99 metadata:: MetadataStorage ,
10+ native_panic,
1011 types:: { circuit:: build_u384_struct_type, TypeBuilder } ,
1112 utils:: { get_integer_layout, layout_repeat, BlockExt , ProgramRegistryExt } ,
1213} ;
@@ -33,6 +34,7 @@ use melior::{
3334 } ,
3435 Context ,
3536} ;
37+ use num_traits:: Signed ;
3638
3739/// Select and call the correct libfunc builder function from the selector.
3840pub fn build < ' ctx , ' this > (
@@ -66,11 +68,10 @@ pub fn build<'ctx, 'this>(
6668 CircuitConcreteLibfunc :: FailureGuaranteeVerify ( info) => build_failure_guarantee_verify (
6769 context, registry, entry, location, helper, metadata, info,
6870 ) ,
69- CircuitConcreteLibfunc :: IntoU96Guarantee ( SignatureAndTypeConcreteLibfunc {
70- signature,
71- ..
72- } )
73- | CircuitConcreteLibfunc :: U96SingleLimbLessThanGuaranteeVerify (
71+ CircuitConcreteLibfunc :: IntoU96Guarantee ( info) => {
72+ build_into_u96_guarantee ( context, registry, entry, location, helper, metadata, info)
73+ }
74+ CircuitConcreteLibfunc :: U96SingleLimbLessThanGuaranteeVerify (
7475 SignatureOnlyConcreteLibfunc { signature, .. } ,
7576 )
7677 | CircuitConcreteLibfunc :: U96GuaranteeVerify ( SignatureOnlyConcreteLibfunc { signature } ) => {
@@ -1083,6 +1084,52 @@ fn build_array_slice<'ctx>(
10831084 )
10841085}
10851086
1087+ /// Converts input to an U96Guarantee.
1088+ /// Input type must fit inside of an u96.
1089+ ///
1090+ /// # Signature
1091+ /// ```cairo
1092+ /// extern fn into_u96_guarantee<T>(val: T) -> U96Guarantee nopanic;
1093+ /// ```
1094+ fn build_into_u96_guarantee < ' ctx , ' this > (
1095+ context : & ' ctx Context ,
1096+ registry : & ProgramRegistry < CoreType , CoreLibfunc > ,
1097+ entry : & ' this Block < ' ctx > ,
1098+ location : Location < ' ctx > ,
1099+ helper : & LibfuncHelper < ' ctx , ' this > ,
1100+ _metadata : & mut MetadataStorage ,
1101+ info : & SignatureAndTypeConcreteLibfunc ,
1102+ ) -> Result < ( ) > {
1103+ let src = entry. argument ( 0 ) ?. into ( ) ;
1104+
1105+ let src_ty = registry. get_type ( & info. param_signatures ( ) [ 0 ] . ty ) ?;
1106+
1107+ let src_range = src_ty. integer_range ( registry) ?;
1108+
1109+ // We expect the input value to be unsigned, but we check it just in case.
1110+ if src_range. lower . is_negative ( ) {
1111+ native_panic ! ( "into_u96_guarantee expects an unsigned integer" )
1112+ }
1113+
1114+ // Extend the input value to an u96
1115+ let mut dst = entry. extui ( src, IntegerType :: new ( context, 96 ) . into ( ) , location) ?;
1116+
1117+ // If the lower bound is positive, we offset the value by the lower bound
1118+ // to obtain the actual value.
1119+ if src_range. lower . is_positive ( ) {
1120+ let klower = entry. const_int_from_type (
1121+ context,
1122+ location,
1123+ src_range. lower ,
1124+ IntegerType :: new ( context, 96 ) . into ( ) ,
1125+ ) ?;
1126+ dst = entry. addi ( dst, klower, location) ?
1127+ }
1128+
1129+ entry. append_operation ( helper. br ( 0 , & [ dst] , location) ) ;
1130+ Ok ( ( ) )
1131+ }
1132+
10861133#[ cfg( test) ]
10871134mod test {
10881135
@@ -1094,8 +1141,8 @@ mod test {
10941141 values:: Value ,
10951142 } ;
10961143 use cairo_lang_sierra:: extensions:: utils:: Range ;
1097- use num_bigint:: BigUint ;
1098- use num_traits:: Num ;
1144+ use num_bigint:: { BigInt , BigUint } ;
1145+ use num_traits:: { Num , One } ;
10991146 use starknet_types_core:: felt:: Felt ;
11001147
11011148 fn u384 ( limbs : [ & str ; 4 ] ) -> Value {
@@ -1404,4 +1451,45 @@ mod test {
14041451 ) ,
14051452 ) ;
14061453 }
1454+
1455+ #[ test]
1456+ fn run_into_u96_guarantee ( ) {
1457+ let program = load_cairo ! (
1458+ use core:: circuit:: { into_u96_guarantee, U96Guarantee } ;
1459+ use core:: internal:: bounded_int:: BoundedInt ;
1460+
1461+ fn main( ) -> ( U96Guarantee , U96Guarantee , U96Guarantee ) {
1462+ (
1463+ into_u96_guarantee:: <BoundedInt <0 , 79228162514264337593543950335 >>( 123 ) ,
1464+ into_u96_guarantee:: <BoundedInt <100 , 1000 >>( 123 ) ,
1465+ into_u96_guarantee:: <u8 >( 123 ) ,
1466+ )
1467+ }
1468+ ) ;
1469+
1470+ let range = Range {
1471+ lower : BigInt :: ZERO ,
1472+ upper : BigInt :: one ( ) << 96 ,
1473+ } ;
1474+
1475+ run_program_assert_output (
1476+ & program,
1477+ "main" ,
1478+ & [ ] ,
1479+ jit_struct ! (
1480+ Value :: BoundedInt {
1481+ value: 123 . into( ) ,
1482+ range: range. clone( )
1483+ } ,
1484+ Value :: BoundedInt {
1485+ value: 123 . into( ) ,
1486+ range: range. clone( )
1487+ } ,
1488+ Value :: BoundedInt {
1489+ value: 123 . into( ) ,
1490+ range: range. clone( )
1491+ }
1492+ ) ,
1493+ ) ;
1494+ }
14071495}
0 commit comments