in checker/src/z3_solver.rs [491:540]
fn general_ne(&self, left: &Rc<AbstractValue>, right: &Rc<AbstractValue>) -> z3_sys::Z3_ast {
let num_bits = if left.expression.is_bit_vector() {
u32::from(left.expression.infer_type().bit_length())
} else if right.expression.is_bit_vector() {
let mut result = u32::from(right.expression.infer_type().bit_length());
if let Expression::BitAnd { left, .. } = &right.expression {
if let Expression::CompileTimeConstant(ConstantDomain::U128(v)) = left.expression {
if v < u128::MAX && (v + 1).is_power_of_two() {
result = 0;
}
}
}
result
} else {
0
};
if num_bits > 0 {
let left_ast = self.get_as_bv_z3_ast(&(**left).expression, num_bits);
let right_ast = self.get_as_bv_z3_ast(&(**right).expression, num_bits);
unsafe {
z3_sys::Z3_mk_not(
self.z3_context,
z3_sys::Z3_mk_eq(self.z3_context, left_ast, right_ast),
)
}
} else {
let (lf, left_ast) = self.get_as_numeric_z3_ast(&(**left).expression);
let (rf, right_ast) = self.get_as_numeric_z3_ast(&(**right).expression);
if lf != rf {
warn!("can't encode {:?} != {:?}", left, right);
return self
.general_variable(&Path::get_as_path(left.clone()), ExpressionType::Bool);
}
unsafe {
if lf {
let l = z3_sys::Z3_mk_fpa_is_nan(self.z3_context, left_ast);
let r = z3_sys::Z3_mk_fpa_is_nan(self.z3_context, right_ast);
let eq = z3_sys::Z3_mk_fpa_eq(self.z3_context, left_ast, right_ast);
let ne = z3_sys::Z3_mk_not(self.z3_context, eq);
let tmp = vec![l, r, ne];
z3_sys::Z3_mk_or(self.z3_context, 3, tmp.as_ptr())
} else {
z3_sys::Z3_mk_not(
self.z3_context,
z3_sys::Z3_mk_eq(self.z3_context, left_ast, right_ast),
)
}
}
}
}