Skip to content

Commit b2b4a96

Browse files
[0.6.x] Fix BoundedInt Constrain libfunc (#1466)
* Add fix for constrain and tests * Add negative bounds test * Add test --------- Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com>
1 parent 9c5a17d commit b2b4a96

File tree

1 file changed

+311
-4
lines changed

1 file changed

+311
-4
lines changed

src/libfuncs/bounded_int.rs

Lines changed: 311 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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)]
853862
mod 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

Comments
 (0)