@@ -648,8 +648,17 @@ fn build_constrain<'ctx, 'this>(
648648 . get_type ( & info. branch_signatures ( ) [ 1 ] . vars [ 1 ] . ty ) ?
649649 . integer_range ( registry) ?;
650650
651- let boundary =
652- entry. const_int_from_type ( context, location, info. boundary . clone ( ) , src_value. r#type ( ) ) ?;
651+ let boundary = if src_ty. is_bounded_int ( registry) ? {
652+ entry. const_int_from_type (
653+ context,
654+ location,
655+ info. boundary . clone ( ) - src_range. lower . clone ( ) ,
656+ src_value. r#type ( ) ,
657+ ) ?
658+ } else {
659+ entry. const_int_from_type ( context, location, info. boundary . clone ( ) , src_value. r#type ( ) ) ?
660+ } ;
661+
653662 let is_lower = entry. cmpi (
654663 context,
655664 if src_range. lower . sign ( ) == Sign :: Minus {
@@ -851,11 +860,16 @@ fn build_wrap_non_zero<'ctx, 'this>(
851860
852861#[ cfg( test) ]
853862mod test {
863+ use cairo_lang_sierra:: extensions:: utils:: Range ;
854864 use cairo_vm:: Felt252 ;
865+ use num_bigint:: BigInt ;
855866
856867 use crate :: {
857- context:: NativeContext , execution_result:: ExecutionResult , executor:: JitNativeExecutor ,
858- utils:: test:: load_cairo, OptLevel , Value ,
868+ context:: NativeContext ,
869+ execution_result:: ExecutionResult ,
870+ executor:: JitNativeExecutor ,
871+ utils:: test:: { load_cairo, run_program} ,
872+ OptLevel , Value ,
859873 } ;
860874
861875 #[ test]
@@ -989,4 +1003,297 @@ mod test {
9891003 } ;
9901004 assert_eq ! ( value, Felt252 :: from( 0 ) ) ;
9911005 }
1006+
1007+ fn assert_constrain_output ( result : Value , expected_bi : Value ) {
1008+ if let Value :: Enum { tag, value, .. } = result {
1009+ assert_eq ! ( tag, 0 ) ;
1010+ if let Value :: Struct { fields, .. } = * value {
1011+ assert_eq ! ( expected_bi, fields[ 0 ] ) ;
1012+ }
1013+ }
1014+ }
1015+
1016+ #[ test]
1017+ fn test_constrain ( ) {
1018+ let program = load_cairo ! {
1019+ #[ feature( "bounded-int-utils" ) ]
1020+ use core:: internal:: bounded_int:: { self , BoundedInt , ConstrainHelper , constrain} ;
1021+
1022+ fn run_test_1( a: i8 ) -> BoundedInt <-128 , -1 > {
1023+ match constrain:: <i8 , 0 >( a) {
1024+ Ok ( lt0) => lt0,
1025+ Err ( _gt0) => panic!( ) ,
1026+ }
1027+ }
1028+
1029+ fn run_test_2( a: i8 ) -> BoundedInt <0 , 127 > {
1030+ match constrain:: <i8 , 0 >( a) {
1031+ Ok ( _lt0) => panic!( ) ,
1032+ Err ( gt0) => gt0,
1033+ }
1034+ }
1035+
1036+ impl ConstrainTest1 of ConstrainHelper <BoundedInt <0 , 15 >, 5 > {
1037+ type LowT = BoundedInt <0 , 4 >;
1038+ type HighT = BoundedInt <5 , 15 >;
1039+ }
1040+
1041+ fn run_test_3( a: felt252) -> BoundedInt <0 , 4 > {
1042+ let a_bi: BoundedInt <0 , 15 > = a. try_into( ) . unwrap( ) ;
1043+ match constrain:: <_, 5 >( a_bi) {
1044+ Ok ( lt0) => lt0,
1045+ Err ( _gt0) => panic!( ) ,
1046+ }
1047+ }
1048+
1049+ fn run_test_4( a: felt252) -> BoundedInt <5 , 15 > {
1050+ let a_bi: BoundedInt <0 , 15 > = a. try_into( ) . unwrap( ) ;
1051+ match constrain:: <_, 5 >( a_bi) {
1052+ Ok ( _lt0) => panic!( ) ,
1053+ Err ( gt0) => gt0,
1054+ }
1055+ }
1056+
1057+ impl ConstrainTest2 of ConstrainHelper <BoundedInt <-10 , 10 >, 0 > {
1058+ type LowT = BoundedInt <-10 , -1 >;
1059+ type HighT = BoundedInt <0 , 10 >;
1060+ }
1061+
1062+ fn run_test_5( a: felt252) -> BoundedInt <-10 , -1 > {
1063+ let a_bi: BoundedInt <-10 , 10 > = a. try_into( ) . unwrap( ) ;
1064+ match constrain:: <_, 0 >( a_bi) {
1065+ Ok ( lt0) => lt0,
1066+ Err ( _gt0) => panic!( ) ,
1067+ }
1068+ }
1069+
1070+ fn run_test_6( a: felt252) -> BoundedInt <0 , 10 > {
1071+ let a_bi: BoundedInt <-10 , 10 > = a. try_into( ) . unwrap( ) ;
1072+ match constrain:: <_, 0 >( a_bi) {
1073+ Ok ( _lt0) => panic!( ) ,
1074+ Err ( gt0) => gt0,
1075+ }
1076+ }
1077+
1078+ impl ConstrainTest3 of ConstrainHelper <BoundedInt <1 , 61 >, 31 > {
1079+ type LowT = BoundedInt <1 , 30 >;
1080+ type HighT = BoundedInt <31 , 61 >;
1081+ }
1082+
1083+ fn run_test_7( a: felt252) -> BoundedInt <1 , 30 > {
1084+ let a_bi: BoundedInt <1 , 61 > = a. try_into( ) . unwrap( ) ;
1085+ match constrain:: <_, 31 >( a_bi) {
1086+ Ok ( lt0) => lt0,
1087+ Err ( _gt0) => panic!( ) ,
1088+ }
1089+ }
1090+
1091+ fn run_test_8( a: felt252) -> BoundedInt <31 , 61 > {
1092+ let a_bi: BoundedInt <1 , 61 > = a. try_into( ) . unwrap( ) ;
1093+ match constrain:: <_, 31 >( a_bi) {
1094+ Ok ( _lt0) => panic!( ) ,
1095+ Err ( gt0) => gt0,
1096+ }
1097+ }
1098+
1099+ impl ConstrainTest4 of ConstrainHelper <BoundedInt <-200 , -100 >, -150 > {
1100+ type LowT = BoundedInt <-200 , -151 >;
1101+ type HighT = BoundedInt <-150 , -100 >;
1102+ }
1103+
1104+ fn run_test_9( a: felt252) -> BoundedInt <-200 , -151 > {
1105+ let a_bi: BoundedInt <-200 , -100 > = a. try_into( ) . unwrap( ) ;
1106+ match constrain:: <_, -150 >( a_bi) {
1107+ Ok ( lt0) => lt0,
1108+ Err ( _gt0) => panic!( ) ,
1109+ }
1110+ }
1111+
1112+ fn run_test_10( a: felt252) -> BoundedInt <-150 , -100 > {
1113+ let a_bi: BoundedInt <-200 , -100 > = a. try_into( ) . unwrap( ) ;
1114+ match constrain:: <_, -150 >( a_bi) {
1115+ Ok ( _lt0) => panic!( ) ,
1116+ Err ( gt0) => gt0,
1117+ }
1118+ }
1119+
1120+ impl ConstrainTest5 of ConstrainHelper <BoundedInt <30 , 100 >, 100 > {
1121+ type LowT = BoundedInt <30 , 99 >;
1122+ type HighT = BoundedInt <100 , 100 >;
1123+ }
1124+
1125+ fn run_test_11( a: felt252) -> BoundedInt <100 , 100 > {
1126+ let a_bi: BoundedInt <30 , 100 > = a. try_into( ) . unwrap( ) ;
1127+ match constrain:: <_, 100 >( a_bi) {
1128+ Ok ( _lt0) => panic!( ) ,
1129+ Err ( gt0) => gt0,
1130+ }
1131+ }
1132+ } ;
1133+
1134+ let result = run_program ( & program, "run_test_1" , & [ Value :: Sint8 ( -1 ) ] ) . return_value ;
1135+ assert_constrain_output (
1136+ result,
1137+ Value :: BoundedInt {
1138+ value : Felt252 :: from ( -1 ) ,
1139+ range : Range {
1140+ lower : BigInt :: from ( -128 ) ,
1141+ upper : BigInt :: from ( 0 ) ,
1142+ } ,
1143+ } ,
1144+ ) ;
1145+
1146+ let result = run_program ( & program, "run_test_2" , & [ Value :: Sint8 ( 1 ) ] ) . return_value ;
1147+ assert_constrain_output (
1148+ result,
1149+ Value :: BoundedInt {
1150+ value : Felt252 :: from ( 1 ) ,
1151+ range : Range {
1152+ lower : BigInt :: from ( 0 ) ,
1153+ upper : BigInt :: from ( 128 ) ,
1154+ } ,
1155+ } ,
1156+ ) ;
1157+
1158+ let result = run_program ( & program, "run_test_2" , & [ Value :: Sint8 ( 0 ) ] ) . return_value ;
1159+ assert_constrain_output (
1160+ result,
1161+ Value :: BoundedInt {
1162+ value : Felt252 :: from ( 0 ) ,
1163+ range : Range {
1164+ lower : BigInt :: from ( 0 ) ,
1165+ upper : BigInt :: from ( 128 ) ,
1166+ } ,
1167+ } ,
1168+ ) ;
1169+
1170+ let result =
1171+ run_program ( & program, "run_test_3" , & [ Value :: Felt252 ( Felt252 :: from ( 0 ) ) ] ) . return_value ;
1172+ assert_constrain_output (
1173+ result,
1174+ Value :: BoundedInt {
1175+ value : Felt252 :: from ( 0 ) ,
1176+ range : Range {
1177+ lower : BigInt :: from ( 0 ) ,
1178+ upper : BigInt :: from ( 5 ) ,
1179+ } ,
1180+ } ,
1181+ ) ;
1182+
1183+ let result =
1184+ run_program ( & program, "run_test_4" , & [ Value :: Felt252 ( Felt252 :: from ( 15 ) ) ] ) . return_value ;
1185+ assert_constrain_output (
1186+ result,
1187+ Value :: BoundedInt {
1188+ value : Felt252 :: from ( 15 ) ,
1189+ range : Range {
1190+ lower : BigInt :: from ( 5 ) ,
1191+ upper : BigInt :: from ( 16 ) ,
1192+ } ,
1193+ } ,
1194+ ) ;
1195+
1196+ let result =
1197+ run_program ( & program, "run_test_5" , & [ Value :: Felt252 ( Felt252 :: from ( -5 ) ) ] ) . return_value ;
1198+ assert_constrain_output (
1199+ result,
1200+ Value :: BoundedInt {
1201+ value : Felt252 :: from ( -5 ) ,
1202+ range : Range {
1203+ lower : BigInt :: from ( -10 ) ,
1204+ upper : BigInt :: from ( 0 ) ,
1205+ } ,
1206+ } ,
1207+ ) ;
1208+
1209+ let result =
1210+ run_program ( & program, "run_test_6" , & [ Value :: Felt252 ( Felt252 :: from ( 5 ) ) ] ) . return_value ;
1211+ assert_constrain_output (
1212+ result,
1213+ Value :: BoundedInt {
1214+ value : Felt252 :: from ( 5 ) ,
1215+ range : Range {
1216+ lower : BigInt :: from ( 0 ) ,
1217+ upper : BigInt :: from ( 11 ) ,
1218+ } ,
1219+ } ,
1220+ ) ;
1221+
1222+ let result =
1223+ run_program ( & program, "run_test_7" , & [ Value :: Felt252 ( Felt252 :: from ( 30 ) ) ] ) . return_value ;
1224+ assert_constrain_output (
1225+ result,
1226+ Value :: BoundedInt {
1227+ value : Felt252 :: from ( 30 ) ,
1228+ range : Range {
1229+ lower : BigInt :: from ( 1 ) ,
1230+ upper : BigInt :: from ( 31 ) ,
1231+ } ,
1232+ } ,
1233+ ) ;
1234+
1235+ let result =
1236+ run_program ( & program, "run_test_8" , & [ Value :: Felt252 ( Felt252 :: from ( 31 ) ) ] ) . return_value ;
1237+ assert_constrain_output (
1238+ result,
1239+ Value :: BoundedInt {
1240+ value : Felt252 :: from ( 31 ) ,
1241+ range : Range {
1242+ lower : BigInt :: from ( 31 ) ,
1243+ upper : BigInt :: from ( 62 ) ,
1244+ } ,
1245+ } ,
1246+ ) ;
1247+
1248+ let result = run_program (
1249+ & program,
1250+ "run_test_9" ,
1251+ & [ Value :: Felt252 ( Felt252 :: from ( -200 ) ) ] ,
1252+ )
1253+ . return_value ;
1254+ assert_constrain_output (
1255+ result,
1256+ Value :: BoundedInt {
1257+ value : Felt252 :: from ( -200 ) ,
1258+ range : Range {
1259+ lower : BigInt :: from ( -200 ) ,
1260+ upper : BigInt :: from ( -150 ) ,
1261+ } ,
1262+ } ,
1263+ ) ;
1264+
1265+ let result = run_program (
1266+ & program,
1267+ "run_test_10" ,
1268+ & [ Value :: Felt252 ( Felt252 :: from ( -150 ) ) ] ,
1269+ )
1270+ . return_value ;
1271+ assert_constrain_output (
1272+ result,
1273+ Value :: BoundedInt {
1274+ value : Felt252 :: from ( -150 ) ,
1275+ range : Range {
1276+ lower : BigInt :: from ( -150 ) ,
1277+ upper : BigInt :: from ( -99 ) ,
1278+ } ,
1279+ } ,
1280+ ) ;
1281+
1282+ let result = run_program (
1283+ & program,
1284+ "run_test_11" ,
1285+ & [ Value :: Felt252 ( Felt252 :: from ( 100 ) ) ] ,
1286+ )
1287+ . return_value ;
1288+ assert_constrain_output (
1289+ result,
1290+ Value :: BoundedInt {
1291+ value : Felt252 :: from ( 100 ) ,
1292+ range : Range {
1293+ lower : BigInt :: from ( 100 ) ,
1294+ upper : BigInt :: from ( 101 ) ,
1295+ } ,
1296+ } ,
1297+ ) ;
1298+ }
9921299}
0 commit comments