3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-03 09:50:23 +00:00

Add get_sort(expr * n) function that does not depend on ast_manager. Move power_of_two to rational class. Add arith_recognizers and bv_recognizers classes. The two new classes contain the 'read-only' methods from arith_util and bv_util.

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2012-12-18 14:44:51 -08:00
parent 4f0d5a5756
commit cec328cfdc
17 changed files with 314 additions and 282 deletions

View file

@ -41,26 +41,6 @@ bv_decl_plugin::bv_decl_plugin():
m_int_sort(0) {
}
void bv_decl_plugin::mk_table_upto(unsigned n) {
if (m_powers.empty()) {
m_powers.push_back(rational(1));
}
unsigned sz = m_powers.size();
rational curr = m_powers[sz - 1];
rational two(2);
for (unsigned i = sz; i <= n; i++) {
curr *= two;
m_powers.push_back(curr);
}
}
rational bv_decl_plugin::power_of_two(unsigned n) const {
if (n >= m_powers.size()) {
const_cast<bv_decl_plugin*>(this)->mk_table_upto(n + 1);
}
return m_powers[n];
}
void bv_decl_plugin::set_manager(ast_manager * m, family_id id) {
decl_plugin::set_manager(m, id);
@ -169,7 +149,7 @@ void bv_decl_plugin::mk_bv_sort(unsigned bv_size) {
sz = sort_size::mk_very_big();
}
else {
sz = sort_size(power_of_two(bv_size));
sz = sort_size(rational::power_of_two(bv_size));
}
m_bv_sorts[bv_size] = m_manager->mk_sort(symbol("bv"), sort_info(m_family_id, BV_SORT, sz, 1, &p));
m_manager->inc_ref(m_bv_sorts[bv_size]);
@ -436,7 +416,7 @@ func_decl * bv_decl_plugin::mk_num_decl(unsigned num_parameters, parameter const
// This cannot be enforced now, since some Z3 modules try to generate these invalid numerals.
// After SMT-COMP, I should find all offending modules.
// For now, I will just simplify the numeral here.
parameter p0(mod(parameters[0].get_rational(), power_of_two(bv_size)));
parameter p0(mod(parameters[0].get_rational(), rational::power_of_two(bv_size)));
parameter ps[2] = { p0, parameters[1] };
sort * bv = get_bv_sort(bv_size);
return m_manager->mk_const_decl(m_bv_sym, bv, func_decl_info(m_family_id, OP_BV_NUM, num_parameters, ps));
@ -621,7 +601,7 @@ void bv_decl_plugin::get_offset_term(app * a, expr * & t, rational & offset) con
offset = decl->get_parameter(0).get_rational();
sz = decl->get_parameter(1).get_int();
t = a->get_arg(1);
offset = mod(offset, power_of_two(sz));
offset = mod(offset, rational::power_of_two(sz));
}
else {
t = a;
@ -729,37 +709,104 @@ expr * bv_decl_plugin::get_some_value(sort * s) {
return m_manager->mk_app(m_family_id, OP_BV_NUM, 2, p, 0, 0);
}
bv_util::bv_util(ast_manager & m):
m_manager(m) {
SASSERT(m.has_plugin(symbol("bv")));
m_plugin = static_cast<bv_decl_plugin*>(m.get_plugin(m.get_family_id("bv")));
}
rational bv_util::norm(rational const & val, unsigned bv_size, bool is_signed) const {
rational r = mod(val, power_of_two(bv_size));
rational bv_recognizers::norm(rational const & val, unsigned bv_size, bool is_signed) const {
rational r = mod(val, rational::power_of_two(bv_size));
SASSERT(!r.is_neg());
if (is_signed) {
if (r >= power_of_two(bv_size - 1)) {
r -= power_of_two(bv_size);
if (r >= rational::power_of_two(bv_size - 1)) {
r -= rational::power_of_two(bv_size);
}
if (r < -power_of_two(bv_size - 1)) {
r += power_of_two(bv_size);
if (r < -rational::power_of_two(bv_size - 1)) {
r += rational::power_of_two(bv_size);
}
}
return r;
}
bool bv_util::has_sign_bit(rational const & n, unsigned bv_size) const {
bool bv_recognizers::has_sign_bit(rational const & n, unsigned bv_size) const {
SASSERT(bv_size > 0);
rational m = norm(n, bv_size, false);
rational p = power_of_two(bv_size - 1);
rational p = rational::power_of_two(bv_size - 1);
return m >= p;
}
bool bv_util::is_bv_sort(sort const * s) const {
bool bv_recognizers::is_bv_sort(sort const * s) const {
return (s->get_family_id() == get_fid() && s->get_decl_kind() == BV_SORT && s->get_num_parameters() == 1);
}
bool bv_recognizers::is_numeral(expr const * n, rational & val, unsigned & bv_size) const {
if (!is_app_of(n, get_fid(), OP_BV_NUM)) {
return false;
}
func_decl * decl = to_app(n)->get_decl();
val = decl->get_parameter(0).get_rational();
bv_size = decl->get_parameter(1).get_int();
return true;
}
bool bv_recognizers::is_allone(expr const * e) const {
rational r;
unsigned bv_size;
if (!is_numeral(e, r, bv_size)) {
return false;
}
bool result = (r == rational::power_of_two(bv_size) - rational(1));
TRACE("is_allone", tout << r << " " << result << "\n";);
return result;
}
bool bv_recognizers::is_zero(expr const * n) const {
if (!is_app_of(n, get_fid(), OP_BV_NUM)) {
return false;
}
func_decl * decl = to_app(n)->get_decl();
return decl->get_parameter(0).get_rational().is_zero();
}
bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, expr*& b) {
if (!is_extract(e)) return false;
low = get_extract_low(e);
high = get_extract_high(e);
b = to_app(e)->get_arg(0);
return true;
}
bool bv_recognizers::is_bv2int(expr const* e, expr*& r) {
if (!is_bv2int(e)) return false;
r = to_app(e)->get_arg(0);
return true;
}
bool bv_recognizers::mult_inverse(rational const & n, unsigned bv_size, rational & result) {
if (n.is_one()) {
result = n;
return true;
}
if (!mod(n, rational(2)).is_one()) {
return false;
}
rational g;
rational x;
rational y;
g = gcd(n, rational::power_of_two(bv_size), x, y);
if (x.is_neg()) {
x = mod(x, rational::power_of_two(bv_size));
}
SASSERT(x.is_pos());
SASSERT(mod(x * n, rational::power_of_two(bv_size)).is_one());
result = x;
return true;
}
bv_util::bv_util(ast_manager & m):
bv_recognizers(m.get_family_id(symbol("bv"))),
m_manager(m) {
SASSERT(m.has_plugin(symbol("bv")));
m_plugin = static_cast<bv_decl_plugin*>(m.get_plugin(m.get_family_id("bv")));
}
app * bv_util::mk_numeral(rational const & val, sort* s) {
if (!is_bv_sort(s)) {
return 0;
@ -774,65 +821,11 @@ app * bv_util::mk_numeral(rational const & val, unsigned bv_size) {
return m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, 0);
}
bool bv_util::is_numeral(expr const * n, rational & val, unsigned & bv_size) const {
if (!is_app_of(n, get_fid(), OP_BV_NUM)) {
return false;
}
func_decl * decl = to_app(n)->get_decl();
val = decl->get_parameter(0).get_rational();
bv_size = decl->get_parameter(1).get_int();
return true;
}
bool bv_util::is_allone(expr const * e) const {
rational r;
unsigned bv_size;
if (!is_numeral(e, r, bv_size)) {
return false;
}
bool result = (r == power_of_two(bv_size) - rational(1));
TRACE("is_allone", tout << r << " " << result << "\n";);
return result;
}
bool bv_util::is_zero(expr const * n) const {
if (!is_app_of(n, get_fid(), OP_BV_NUM)) {
return false;
}
func_decl * decl = to_app(n)->get_decl();
return decl->get_parameter(0).get_rational().is_zero();
}
sort * bv_util::mk_sort(unsigned bv_size) {
parameter p[1] = { parameter(bv_size) };
return m_manager.mk_sort(get_fid(), BV_SORT, 1, p);
}
bool bv_util::mult_inverse(rational const & n, unsigned bv_size, rational & result) {
if (n.is_one()) {
result = n;
return true;
}
if (!mod(n, rational(2)).is_one()) {
return false;
}
rational g;
rational x;
rational y;
g = gcd(n, power_of_two(bv_size), x, y);
if (x.is_neg()) {
x = mod(x, power_of_two(bv_size));
}
SASSERT(x.is_pos());
SASSERT(mod(x * n, power_of_two(bv_size)).is_one());
result = x;
return true;
}
app * bv_util::mk_bv2int(expr* e) {
sort* s = m_manager.mk_sort(m_manager.get_family_id("arith"), INT_SORT);
parameter p(s);