in checker/src/abstract_value.rs [2463:2511]
fn divide(&self, other: Rc<AbstractValue>) -> Rc<AbstractValue> {
match (&self.expression, &other.expression) {
(_, Expression::CompileTimeConstant(ConstantDomain::U128(c1))) if *c1 == 1 => {
return self.clone();
}
// [(x * y) / x] -> y
// [(x * y) / y] -> x
(Expression::Mul { left: x, right: y }, _) => {
if x.eq(&other) {
return y.clone();
} else if y.eq(&other) {
return x.clone();
}
}
(
Expression::Cast {
operand,
target_type,
},
Expression::CompileTimeConstant(ConstantDomain::U128(c2)),
) => {
if let Expression::Mul { left: x, right: y } = &operand.expression {
if x.eq(&other) {
// [((x * y) as target_type) / x] -> y as target_type
return y.cast(*target_type);
} else if y.eq(&other) {
// [((x * y) as target_type) / y] -> x as target_type
return x.cast(*target_type);
} else {
// [((c1 * y) as t) / c2] -> ((c1 / c2) * y) as t if c1 >= c2 and c1 % c2 == 0
if let Expression::CompileTimeConstant(ConstantDomain::U128(c1)) =
&x.expression
{
if *c1 > *c2 && *c1 % *c2 == 0 {
return x.divide(other).multiply(y.clone()).cast(*target_type);
}
}
}
}
}
_ => (),
}
self.try_to_constant_fold_and_distribute_binary_op(
other,
ConstantDomain::div,
Self::divide,
|l, r| AbstractValue::make_binary(l, r, |left, right| Expression::Div { left, right }),
)
}