in amzn-smt-eager-arithmetic/src/stats.rs [65:119]
fn determine_special_case(&self) -> SpecialCase {
use ArithOp::*;
use Op::*;
let (mut k, mut equality_logic) = (0, self.mu_b.is_zero());
let bad = || {
unreachable!(
"only terms of the form `({<=,<,=,>=,>} (+ ...) ...)` are added to constraints"
)
};
for t in self.constraints.iter() {
if !matches!(t, Term::CoreOp(op) if matches!(op.as_ref(), CoreOp::Eq(..))) {
equality_logic = false;
}
let args = match t {
Term::CoreOp(op) => match op.as_ref() {
CoreOp::Eq(args) => args,
_ => bad(),
},
Term::OtherOp(op) => match op.as_ref() {
Arith(Gte(args) | Gt(args) | Lte(args) | Lt(args)) => args,
_ => bad(),
},
_ => bad(),
};
let lhs = match args.first() {
Some(Term::OtherOp(op)) => match op.as_ref() {
Arith(Plus(args)) => args.as_slice(),
_ => bad(),
},
_ => bad(),
};
// Check if this is the LHS of a separation constraint (SC)
match lhs {
// x >= c (SC)
[Term::Variable(_)] => {}
// -x >= c === x <= -c (SC)
[Term::OtherOp(op)]
// x - y >= c (SC)
| [Term::Variable(_), Term::OtherOp(op)]
// y - x >= c (SC)
| [Term::OtherOp(op), Term::Variable(_)]
if matches!(op.as_ref(), Arith(Neg(Term::Variable(_)))) => {}
// Not a separation constraint
_ => {
k += 1;
}
}
}
match NonZeroU32::new(k) {
Some(k) => SpecialCase::None { k },
None if equality_logic => SpecialCase::EqualityLogic,
None => SpecialCase::SeparationLogic,
}
}