mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 17:45:32 +00:00
Use parity helper functions
This commit is contained in:
parent
bf03886a87
commit
a0f5386bdd
5 changed files with 33 additions and 40 deletions
|
@ -169,15 +169,8 @@ namespace dd {
|
|||
if (m_semantics != mod2N_e)
|
||||
return 0;
|
||||
|
||||
if (is_val(p)) {
|
||||
rational v = val(p);
|
||||
if (v.is_zero())
|
||||
return m_power_of_2 + 1;
|
||||
unsigned r = 0;
|
||||
while (v.is_even() && v > 0)
|
||||
r++, v /= 2;
|
||||
return r;
|
||||
}
|
||||
if (is_val(p))
|
||||
return val(p).parity(m_power_of_2);
|
||||
init_mark();
|
||||
PDD q = p;
|
||||
m_todo.push_back(hi(q));
|
||||
|
@ -185,9 +178,9 @@ namespace dd {
|
|||
q = lo(q);
|
||||
m_todo.push_back(hi(q));
|
||||
}
|
||||
unsigned p2 = val(q).trailing_zeros();
|
||||
unsigned parity = val(q).parity(m_power_of_2);
|
||||
init_mark();
|
||||
while (p2 != 0 && !m_todo.empty()) {
|
||||
while (parity != 0 && !m_todo.empty()) {
|
||||
PDD r = m_todo.back();
|
||||
m_todo.pop_back();
|
||||
if (is_marked(r))
|
||||
|
@ -199,11 +192,11 @@ namespace dd {
|
|||
}
|
||||
else if (val(r).is_zero())
|
||||
continue;
|
||||
else if (val(r).trailing_zeros() < p2)
|
||||
p2 = val(r).trailing_zeros();
|
||||
else
|
||||
parity = std::min(parity, val(r).trailing_zeros());
|
||||
}
|
||||
m_todo.reset();
|
||||
return p2;
|
||||
return parity;
|
||||
}
|
||||
|
||||
pdd pdd_manager::subst_val(pdd const& p, pdd const& s) {
|
||||
|
@ -1812,11 +1805,10 @@ namespace dd {
|
|||
return p.val();
|
||||
}
|
||||
|
||||
rational const& pdd::offset() const {
|
||||
pdd p = *this;
|
||||
while (!p.is_val())
|
||||
p = p.lo();
|
||||
return p.val();
|
||||
rational const& pdd_manager::offset(PDD p) const {
|
||||
while (!is_val(p))
|
||||
p = lo(p);
|
||||
return val(p);
|
||||
}
|
||||
|
||||
pdd pdd::shl(unsigned n) const {
|
||||
|
|
|
@ -367,6 +367,8 @@ namespace dd {
|
|||
bool is_univariate_in(PDD p, unsigned v);
|
||||
void get_univariate_coefficients(PDD p, vector<rational>& coeff);
|
||||
|
||||
rational const& offset(PDD p) const;
|
||||
|
||||
// create an spoly r if leading monomials of a and b overlap
|
||||
bool try_spoly(pdd const& a, pdd const& b, pdd& r);
|
||||
|
||||
|
@ -416,7 +418,7 @@ namespace dd {
|
|||
unsigned var() const { return m.var(root); }
|
||||
rational const& val() const { SASSERT(is_val()); return m.val(root); }
|
||||
rational const& leading_coefficient() const;
|
||||
rational const& offset() const;
|
||||
rational const& offset() const { return m.offset(root); }
|
||||
bool is_val() const { return m.is_val(root); }
|
||||
bool is_one() const { return m.is_one(root); }
|
||||
bool is_zero() const { return m.is_zero(root); }
|
||||
|
|
|
@ -426,17 +426,6 @@ namespace polysat {
|
|||
return -p - 1;
|
||||
}
|
||||
|
||||
static unsigned common_coefficient_power_of_2(const pdd& p) {
|
||||
#if 0
|
||||
if (p.is_zero())
|
||||
return 0; // TODO: Or something different? ==> if p == 0, we can divide by any 2^k, so just return UINT_MAX. (but the case p.is_val() is handled separately, anyway.)
|
||||
#endif
|
||||
unsigned min_power = UINT32_MAX;
|
||||
for (auto& m : p) // TODO: add coefficient iterator? we don't need the variable vectors here.
|
||||
min_power = std::min(min_power, m.coeff.trailing_zeros());
|
||||
return min_power;
|
||||
}
|
||||
|
||||
pdd constraint_manager::mk_op_term(op_constraint::code op, pdd const& p, pdd const& q) {
|
||||
auto& m = p.manager();
|
||||
unsigned sz = m.power_of_2();
|
||||
|
@ -467,9 +456,9 @@ namespace polysat {
|
|||
if (p.is_val())
|
||||
return m.mk_val(machine_div2k(p.val(), q.val().get_unsigned()));
|
||||
// 2^i * p' >> q ==> 2^(i-q) * p' if i >= q
|
||||
unsigned common = common_coefficient_power_of_2(p);
|
||||
if (common >= q.val())
|
||||
return p.div(rational::power_of_two(common));
|
||||
unsigned parity = p.min_parity();
|
||||
if (parity >= q.val())
|
||||
return p.div(rational::power_of_two(parity));
|
||||
}
|
||||
return mk_op_term(op_constraint::code::lshr_op, p, q);
|
||||
}
|
||||
|
@ -524,8 +513,9 @@ namespace polysat {
|
|||
}
|
||||
|
||||
pdd constraint_manager::pseudo_inv(pdd const& p) {
|
||||
auto& m = p.manager();
|
||||
if (p.is_val())
|
||||
return p.manager().mk_val(p.val().pseudo_inverse(p.power_of_2()));
|
||||
return mk_op_term(op_constraint::code::inv_op, p, p.manager().zero());
|
||||
return m.mk_val(p.val().pseudo_inverse(m.power_of_2()));
|
||||
return mk_op_term(op_constraint::code::inv_op, p, m.zero());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -872,10 +872,10 @@ namespace polysat {
|
|||
auto& m = p.manager();
|
||||
unsigned N = m.power_of_2();
|
||||
if (p.is_val())
|
||||
return p.val() == 0 ? N : p.val().trailing_zeros();
|
||||
return p.val().parity(N);
|
||||
|
||||
if (s.try_eval(p, val)) {
|
||||
unsigned k = val == 0 ? N : val.trailing_zeros();
|
||||
unsigned k = val.parity(N);
|
||||
if (k > 0)
|
||||
explain.push_back(s.parity_at_least(p, k));
|
||||
return k;
|
||||
|
@ -910,10 +910,10 @@ namespace polysat {
|
|||
unsigned N = m.power_of_2();
|
||||
rational val;
|
||||
if (p.is_val())
|
||||
return p.val() == 0 ? N : p.val().trailing_zeros();
|
||||
return p.val().parity(N);
|
||||
|
||||
if (s.try_eval(p, val)) {
|
||||
unsigned k = val == 0 ? N : val.trailing_zeros();
|
||||
unsigned k = val.parity(N);
|
||||
if (k != N)
|
||||
explain.push_back(s.parity_at_most(p, k));
|
||||
return k;
|
||||
|
|
|
@ -501,6 +501,15 @@ public:
|
|||
return k;
|
||||
}
|
||||
|
||||
/** Number of trailing zeros in an N-bit representation */
|
||||
unsigned parity(unsigned num_bits) const {
|
||||
SASSERT(!is_neg());
|
||||
SASSERT(*this < rational::power_of_two(num_bits));
|
||||
if (is_zero())
|
||||
return num_bits;
|
||||
return trailing_zeros();
|
||||
}
|
||||
|
||||
static bool limit_denominator(rational &num, rational const& limit);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue