/*++ Copyright (c) 2021 Microsoft Corporation Module Name: polysat multiplication overflow constraint Author: Jakob Rath, Nikolaj Bjorner (nbjorner) 2021-12-09 --*/ #include "math/polysat/smul_fl_constraint.h" #include "math/polysat/solver.h" namespace polysat { smul_fl_constraint::smul_fl_constraint(constraint_manager& m, pdd const& p, pdd const& q, bool is_overflow): constraint(m, ckind_t::smul_fl_t), m_is_overflow(is_overflow), m_p(p), m_q(q) { simplify(); m_vars.append(m_p.free_vars()); for (auto v : m_q.free_vars()) if (!m_vars.contains(v)) m_vars.push_back(v); } void smul_fl_constraint::simplify() { if (m_p.is_zero() || m_q.is_zero() || m_p.is_one() || m_q.is_one()) { m_q = 0; m_p = 0; return; } if (m_p.index() > m_q.index()) std::swap(m_p, m_q); } std::ostream& smul_fl_constraint::display(std::ostream& out, lbool status) const { switch (status) { case l_true: return display(out); case l_false: return display(out << "~"); case l_undef: return display(out << "?"); } return out; } std::ostream& smul_fl_constraint::display(std::ostream& out) const { if (m_is_overflow) return out << "sovfl*(" << m_p << ", " << m_q << ")"; else return out << "sudfl*(" << m_p << ", " << m_q << ")"; } /** * TODO - verify the rules for small bit-widths. * * sovfl(p,q) => p >= 2, q >= 2 * sovfl(p,q) => p >s 0 <=> q >s 0 * sovfl(p,q) & p >s 0 => p*q < 0 or ovfl(p,q) * sovfl(p,q) & p p*q < 0 or ovfl(-p,-q) * ~sovfl(p,q) & p >s 0 = q >s 0 => q > 0 => ~ovfl(p,q) & p*q >=s 0 * smul_noovfl(p,q) => sign(p) != sign(q) or p'*q' < 2^{K-1} * sudfl(p, q) => p >= 2, q >= 2 * sudfl(p, q) => p >s 0 xor q >s 0 * sudfl(p, q) & p >s 0 => p*q > 0 or ovfl(p, -q) * sudfl(p, q) & q >s 0 => p*q > 0 or ovfl(-p, q) * * ~sudfl(p, q) & p >s 0 & q ~ovfl(p, -q) & p*q s 0 => ~ovfl(-p, q) & p*q