mirror of
https://github.com/Z3Prover/z3
synced 2025-11-04 13:29:11 +00:00
fixup bv operators
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
919ac515bc
commit
88269edd4b
3 changed files with 43 additions and 10 deletions
|
|
@ -636,6 +636,10 @@ void arith_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol con
|
||||||
op_names.push_back(builtin_name("/0",OP_DIV0));
|
op_names.push_back(builtin_name("/0",OP_DIV0));
|
||||||
op_names.push_back(builtin_name("div0",OP_IDIV0));
|
op_names.push_back(builtin_name("div0",OP_IDIV0));
|
||||||
op_names.push_back(builtin_name("mod0",OP_MOD0));
|
op_names.push_back(builtin_name("mod0",OP_MOD0));
|
||||||
|
op_names.push_back(builtin_name(bv_symbol(OP_ARITH_BAND).bare_str(), OP_ARITH_BAND));
|
||||||
|
op_names.push_back(builtin_name(bv_symbol(OP_ARITH_SHL).bare_str(), OP_ARITH_SHL));
|
||||||
|
op_names.push_back(builtin_name(bv_symbol(OP_ARITH_LSHR).bare_str(), OP_ARITH_LSHR));
|
||||||
|
op_names.push_back(builtin_name(bv_symbol(OP_ARITH_ASHR).bare_str(), OP_ARITH_ASHR));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -643,7 +647,7 @@ bool arith_decl_plugin::is_value(app * e) const {
|
||||||
return
|
return
|
||||||
is_app_of(e, m_family_id, OP_NUM) ||
|
is_app_of(e, m_family_id, OP_NUM) ||
|
||||||
is_app_of(e, m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM) ||
|
is_app_of(e, m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM) ||
|
||||||
is_app_of(e, m_family_id, OP_PI) ||
|
is_app_of(e, m_family_id, OP_PI) ||
|
||||||
is_app_of(e, m_family_id, OP_E);
|
is_app_of(e, m_family_id, OP_E);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1600,8 +1600,13 @@ br_status arith_rewriter::mk_lshr_core(unsigned sz, expr* arg1, expr* arg2, expr
|
||||||
N = rational::power_of_two(sz);
|
N = rational::power_of_two(sz);
|
||||||
if (is_num_x)
|
if (is_num_x)
|
||||||
x = mod(x, N);
|
x = mod(x, N);
|
||||||
|
if (is_num_y && y >= sz) {
|
||||||
|
result = m_util.mk_int(0);
|
||||||
|
return BR_DONE;
|
||||||
|
}
|
||||||
if (is_num_y)
|
if (is_num_y)
|
||||||
y = mod(y, N);
|
y = mod(y, N);
|
||||||
|
|
||||||
if (is_num_x && x == 0) {
|
if (is_num_x && x == 0) {
|
||||||
result = m_util.mk_int(0);
|
result = m_util.mk_int(0);
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
|
|
@ -1619,6 +1624,13 @@ br_status arith_rewriter::mk_lshr_core(unsigned sz, expr* arg1, expr* arg2, expr
|
||||||
}
|
}
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_num_y) {
|
||||||
|
result = m_util.mk_mod(arg1, m_util.mk_int(N));
|
||||||
|
//result = arg1; // unsound
|
||||||
|
result = m_util.mk_idiv(result, m_util.mk_int(rational::power_of_two(y.get_unsigned())));
|
||||||
|
return BR_DONE;
|
||||||
|
}
|
||||||
return BR_FAILED;
|
return BR_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2522,11 +2522,15 @@ public:
|
||||||
found_unsupported(n);
|
found_unsupported(n);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
rational N = rational::power_of_two(sz);
|
rational N = rational::power_of_two(sz), r;
|
||||||
valx = mod(valx, N);
|
valx = mod(valx, N);
|
||||||
valy = mod(valy, N);
|
valy = mod(valy, N);
|
||||||
expr_ref x(a.mk_mod(_x, a.mk_int(N)), m);
|
expr_ref x(a.mk_mod(_x, a.mk_int(N)), m);
|
||||||
expr_ref y(a.mk_mod(_y, a.mk_int(N)), m);
|
expr_ref y(a.mk_mod(_y, a.mk_int(N)), m);
|
||||||
|
if (a.is_numeral(_x, r))
|
||||||
|
x = a.mk_int(mod(r, N));
|
||||||
|
if (a.is_numeral(_y, r))
|
||||||
|
y = a.mk_int(mod(r, N));
|
||||||
SASSERT(0 <= valn && valn < N);
|
SASSERT(0 <= valn && valn < N);
|
||||||
|
|
||||||
// x mod 2^{i + 1} >= 2^i means the i'th bit is 1.
|
// x mod 2^{i + 1} >= 2^i means the i'th bit is 1.
|
||||||
|
|
@ -2559,9 +2563,12 @@ public:
|
||||||
return true;
|
return true;
|
||||||
unsigned k = valy.get_unsigned();
|
unsigned k = valy.get_unsigned();
|
||||||
sat::literal eq = th.mk_eq(n, a.mk_mod(a.mk_mul(_x, a.mk_int(rational::power_of_two(k))), a.mk_int(N)), false);
|
sat::literal eq = th.mk_eq(n, a.mk_mod(a.mk_mul(_x, a.mk_int(rational::power_of_two(k))), a.mk_int(N)), false);
|
||||||
|
ctx().mark_as_relevant(eq);
|
||||||
if (ctx().get_assignment(eq) == l_true)
|
if (ctx().get_assignment(eq) == l_true)
|
||||||
return true;
|
return true;
|
||||||
ctx().mk_th_axiom(get_id(), ~th.mk_eq(y, a.mk_int(k), false), eq);
|
sat::literal y_eq_k = th.mk_eq(y, a.mk_int(k), false);
|
||||||
|
ctx().mark_as_relevant(y_eq_k);
|
||||||
|
ctx().mk_th_axiom(get_id(), ~y_eq_k, eq);
|
||||||
IF_VERBOSE(2, verbose_stream() << "shl: " << mk_bounded_pp(n, m) << " " << valn << " := " << valx << " << " << valy << "\n");
|
IF_VERBOSE(2, verbose_stream() << "shl: " << mk_bounded_pp(n, m) << " " << valn << " := " << valx << " << " << valy << "\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -2571,10 +2578,12 @@ public:
|
||||||
return true;
|
return true;
|
||||||
unsigned k = valy.get_unsigned();
|
unsigned k = valy.get_unsigned();
|
||||||
sat::literal eq = th.mk_eq(n, a.mk_idiv(x, a.mk_int(rational::power_of_two(k))), false);
|
sat::literal eq = th.mk_eq(n, a.mk_idiv(x, a.mk_int(rational::power_of_two(k))), false);
|
||||||
|
ctx().mark_as_relevant(eq);
|
||||||
if (ctx().get_assignment(eq) == l_true)
|
if (ctx().get_assignment(eq) == l_true)
|
||||||
return true;
|
return true;
|
||||||
ctx().mk_th_axiom(get_id(), ~th.mk_eq(y, a.mk_int(k), false), eq);
|
sat::literal y_eq_k = th.mk_eq(y, a.mk_int(k), false);
|
||||||
IF_VERBOSE(2, verbose_stream() << "lshr: " << mk_bounded_pp(n, m) << " " << valn << " := " << valx << " >>l " << valy << "\n");
|
ctx().mark_as_relevant(y_eq_k);
|
||||||
|
ctx().mk_th_axiom(get_id(), ~y_eq_k, eq);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (a.is_ashr(n)) {
|
if (a.is_ashr(n)) {
|
||||||
|
|
@ -2590,6 +2599,7 @@ public:
|
||||||
// x < 0 & y = k -> n = (x div 2^k - 2^{N-k}) mod 2^N
|
// x < 0 & y = k -> n = (x div 2^k - 2^{N-k}) mod 2^N
|
||||||
xdiv2k = a.mk_idiv(x, a.mk_int(rational::power_of_two(k)));
|
xdiv2k = a.mk_idiv(x, a.mk_int(rational::power_of_two(k)));
|
||||||
eq = th.mk_eq(n, a.mk_mod(a.mk_add(xdiv2k, a.mk_int(-rational::power_of_two(sz - k))), a.mk_int(N)), false);
|
eq = th.mk_eq(n, a.mk_mod(a.mk_add(xdiv2k, a.mk_int(-rational::power_of_two(sz - k))), a.mk_int(N)), false);
|
||||||
|
ctx().mark_as_relevant(eq);
|
||||||
if (ctx().get_assignment(eq) == l_true)
|
if (ctx().get_assignment(eq) == l_true)
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -2597,6 +2607,7 @@ public:
|
||||||
// x >= 0 & y = k -> n = x div 2^k
|
// x >= 0 & y = k -> n = x div 2^k
|
||||||
xdiv2k = a.mk_idiv(x, a.mk_int(rational::power_of_two(k)));
|
xdiv2k = a.mk_idiv(x, a.mk_int(rational::power_of_two(k)));
|
||||||
eq = th.mk_eq(n, xdiv2k, false);
|
eq = th.mk_eq(n, xdiv2k, false);
|
||||||
|
ctx().mark_as_relevant(eq);
|
||||||
if (ctx().get_assignment(eq) == l_true)
|
if (ctx().get_assignment(eq) == l_true)
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -2604,7 +2615,9 @@ public:
|
||||||
ctx().mark_as_relevant(signx);
|
ctx().mark_as_relevant(signx);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ctx().mk_th_axiom(get_id(), ~th.mk_eq(y, a.mk_int(k), false), ~signx, eq);
|
sat::literal y_eq_k = th.mk_eq(y, a.mk_int(k), false);
|
||||||
|
ctx().mark_as_relevant(y_eq_k);
|
||||||
|
ctx().mk_th_axiom(get_id(), ~y_eq_k, ~signx, eq);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -2622,9 +2635,13 @@ public:
|
||||||
unsigned sz = 0;
|
unsigned sz = 0;
|
||||||
expr* _x = nullptr, * _y = nullptr;
|
expr* _x = nullptr, * _y = nullptr;
|
||||||
VERIFY(a.is_band(n, sz, _x, _y) || a.is_shl(n, sz, _x, _y) || a.is_ashr(n, sz, _x, _y) || a.is_lshr(n, sz, _x, _y));
|
VERIFY(a.is_band(n, sz, _x, _y) || a.is_shl(n, sz, _x, _y) || a.is_ashr(n, sz, _x, _y) || a.is_lshr(n, sz, _x, _y));
|
||||||
rational N = rational::power_of_two(sz);
|
rational N = rational::power_of_two(sz), r;
|
||||||
expr_ref x(a.mk_mod(_x, a.mk_int(N)), m);
|
expr_ref x(a.mk_mod(_x, a.mk_int(N)), m);
|
||||||
expr_ref y(a.mk_mod(_y, a.mk_int(N)), m);
|
expr_ref y(a.mk_mod(_y, a.mk_int(N)), m);
|
||||||
|
if (a.is_numeral(_x, r))
|
||||||
|
x = a.mk_int(mod(r, N));
|
||||||
|
if (a.is_numeral(_y, r))
|
||||||
|
y = a.mk_int(mod(r, N));
|
||||||
|
|
||||||
// 0 <= n < 2^sz
|
// 0 <= n < 2^sz
|
||||||
|
|
||||||
|
|
@ -2657,9 +2674,9 @@ public:
|
||||||
// y >= sz & x >= 2^{sz-1} => n = -1
|
// y >= sz & x >= 2^{sz-1} => n = -1
|
||||||
// y = 0 => n = x
|
// y = 0 => n = x
|
||||||
auto signx = mk_literal(a.mk_ge(x, a.mk_int(N/2)));
|
auto signx = mk_literal(a.mk_ge(x, a.mk_int(N/2)));
|
||||||
ctx().mk_th_axiom(get_id(), ~mk_literal(a.mk_ge(a.mk_mod(y, a.mk_int(N)), a.mk_int(sz))), signx, mk_literal(m.mk_eq(n, a.mk_int(0))));
|
ctx().mk_th_axiom(get_id(), ~mk_literal(a.mk_ge(y, a.mk_int(sz))), signx, mk_literal(m.mk_eq(n, a.mk_int(0))));
|
||||||
ctx().mk_th_axiom(get_id(), ~mk_literal(a.mk_ge(a.mk_mod(y, a.mk_int(N)), a.mk_int(sz))), ~signx, mk_literal(m.mk_eq(n, a.mk_int(N-1))));
|
ctx().mk_th_axiom(get_id(), ~mk_literal(a.mk_ge(y, a.mk_int(sz))), ~signx, mk_literal(m.mk_eq(n, a.mk_int(N-1))));
|
||||||
ctx().mk_th_axiom(get_id(), ~mk_literal(a.mk_eq(a.mk_mod(y, a.mk_int(N)), a.mk_int(0))), mk_literal(m.mk_eq(n, x)));
|
ctx().mk_th_axiom(get_id(), ~mk_literal(a.mk_eq(y, a.mk_int(0))), mk_literal(m.mk_eq(n, x)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue