mirror of
https://github.com/Z3Prover/z3
synced 2025-04-07 09:55:19 +00:00
n/a
This commit is contained in:
parent
ddf2d28350
commit
388b2f5eec
|
@ -942,3 +942,13 @@ app* bv_util::mk_int2bv(unsigned sz, expr* e) {
|
||||||
parameter p(sz);
|
parameter p(sz);
|
||||||
return m_manager.mk_app(get_fid(), OP_INT2BV, 1, &p, 1, &e);
|
return m_manager.mk_app(get_fid(), OP_INT2BV, 1, &p, 1, &e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app* bv_util::mk_bv_rotate_left(expr* arg, unsigned n) {
|
||||||
|
parameter p(n);
|
||||||
|
return m_manager.mk_app(get_fid(), OP_ROTATE_LEFT, 1, &p, 1, &arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
app* bv_util::mk_bv_rotate_right(expr* arg, unsigned n) {
|
||||||
|
parameter p(n);
|
||||||
|
return m_manager.mk_app(get_fid(), OP_ROTATE_RIGHT, 1, &p, 1, &arg);
|
||||||
|
}
|
|
@ -546,6 +546,11 @@ public:
|
||||||
app * mk_bv2int(expr* e);
|
app * mk_bv2int(expr* e);
|
||||||
app * mk_int2bv(unsigned sz, expr* e);
|
app * mk_int2bv(unsigned sz, expr* e);
|
||||||
|
|
||||||
|
app* mk_bv_rotate_left(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_EXT_ROTATE_LEFT, arg1, arg2); }
|
||||||
|
app* mk_bv_rotate_right(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_EXT_ROTATE_RIGHT, arg1, arg2); }
|
||||||
|
app* mk_bv_rotate_left(expr* arg, unsigned n);
|
||||||
|
app* mk_bv_rotate_right(expr* arg, unsigned n);
|
||||||
|
|
||||||
// TODO: all these binary ops commute (right?) but it'd be more logical to swap `n` & `m` in the `return`
|
// TODO: all these binary ops commute (right?) but it'd be more logical to swap `n` & `m` in the `return`
|
||||||
app * mk_bvsmul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_OVFL, n, m); }
|
app * mk_bvsmul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_OVFL, n, m); }
|
||||||
app * mk_bvsmul_no_udfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_UDFL, n, m); }
|
app * mk_bvsmul_no_udfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_UDFL, n, m); }
|
||||||
|
|
|
@ -46,46 +46,53 @@ namespace bv {
|
||||||
m_eval.init_fixed(m_terms.assertions());
|
m_eval.init_fixed(m_terms.assertions());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<bool, app*> sls::next_to_repair() {
|
||||||
|
app* e = nullptr;
|
||||||
|
if (!m_repair_down.empty()) {
|
||||||
|
unsigned index = m_rand(m_repair_down.size());
|
||||||
|
e = m_terms.term(m_repair_down.elem_at(index));
|
||||||
|
}
|
||||||
|
else if (m_repair_up.empty()) {
|
||||||
|
unsigned index = m_rand(m_repair_up.size());
|
||||||
|
e = m_terms.term(m_repair_up.elem_at(index));
|
||||||
|
}
|
||||||
|
return { !m_repair_down.empty(), e };
|
||||||
|
}
|
||||||
|
|
||||||
lbool sls::operator()() {
|
lbool sls::operator()() {
|
||||||
// init and init_eval were invoked.
|
// init and init_eval were invoked.
|
||||||
unsigned& n = m_stats.m_moves;
|
unsigned& n = m_stats.m_moves;
|
||||||
n = 0;
|
n = 0;
|
||||||
for (; n < m_config.m_max_repairs && m.inc(); ++n) {
|
for (; n < m_config.m_max_repairs && m.inc(); ++n) {
|
||||||
if (!m_repair_down.empty()) {
|
auto [down, e] = next_to_repair();
|
||||||
unsigned index = m_rand(m_repair_down.size());
|
if (!e)
|
||||||
unsigned expr_id = m_repair_down.elem_at(index);
|
|
||||||
auto e = m_terms.term(expr_id);
|
|
||||||
IF_VERBOSE(20, verbose_stream() << "d " << mk_bounded_pp(e, m, 1) << "\n");
|
|
||||||
if (eval_is_correct(e))
|
|
||||||
m_repair_down.remove(expr_id);
|
|
||||||
else
|
|
||||||
try_repair_down(e);
|
|
||||||
}
|
|
||||||
else if (!m_repair_up.empty()) {
|
|
||||||
unsigned index = m_rand(m_repair_up.size());
|
|
||||||
unsigned expr_id = m_repair_up.elem_at(index);
|
|
||||||
auto e = m_terms.term(expr_id);
|
|
||||||
IF_VERBOSE(20, verbose_stream() << "u " << mk_bounded_pp(e, m, 1) << "\n");
|
|
||||||
if (eval_is_correct(e))
|
|
||||||
m_repair_up.remove(expr_id);
|
|
||||||
else
|
|
||||||
try_repair_up(e);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return l_true;
|
return l_true;
|
||||||
|
IF_VERBOSE(20, verbose_stream() << (down?"d ":"u ") << mk_bounded_pp(e, m, 1) << "\n");
|
||||||
|
if (eval_is_correct(e)) {
|
||||||
|
if (down)
|
||||||
|
m_repair_down.remove(e->get_id());
|
||||||
|
else
|
||||||
|
m_repair_up.remove(e->get_id());
|
||||||
|
}
|
||||||
|
else if (down) {
|
||||||
|
try_repair_down(e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
try_repair_up(e);
|
||||||
}
|
}
|
||||||
return l_undef;
|
return l_undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls::try_repair_down(app* e) {
|
void sls::try_repair_down(app* e) {
|
||||||
unsigned n = e->get_num_args();
|
unsigned n = e->get_num_args();
|
||||||
if (n == 0)
|
if (n > 0) {
|
||||||
return false;
|
unsigned s = m_rand(n);
|
||||||
unsigned s = m_rand(n);
|
for (unsigned i = 0; i < n; ++i)
|
||||||
for (unsigned i = 0; i < n; ++i)
|
if (try_repair_down(e, (i + s) % n))
|
||||||
if (try_repair_down(e, (i + s) % n))
|
return;
|
||||||
return true;
|
}
|
||||||
return false;
|
m_repair_down.remove(e->get_id());
|
||||||
|
m_repair_up.insert(e->get_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls::try_repair_down(app* e, unsigned i) {
|
bool sls::try_repair_down(app* e, unsigned i) {
|
||||||
|
@ -99,17 +106,16 @@ namespace bv {
|
||||||
return was_repaired;
|
return was_repaired;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls::try_repair_up(app* e) {
|
void sls::try_repair_up(app* e) {
|
||||||
m_repair_up.remove(e->get_id());
|
m_repair_up.remove(e->get_id());
|
||||||
if (m_terms.is_assertion(e)) {
|
if (m_terms.is_assertion(e)) {
|
||||||
m_repair_down.insert(e->get_id());
|
m_repair_down.insert(e->get_id());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
m_eval.repair_up(e);
|
else {
|
||||||
for (auto p : m_terms.parents(e))
|
m_eval.repair_up(e);
|
||||||
m_repair_up.insert(p->get_id());
|
for (auto p : m_terms.parents(e))
|
||||||
|
m_repair_up.insert(p->get_id());
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls::eval_is_correct(app* e) {
|
bool sls::eval_is_correct(app* e) {
|
||||||
|
|
|
@ -49,10 +49,11 @@ namespace bv {
|
||||||
random_gen m_rand;
|
random_gen m_rand;
|
||||||
config m_config;
|
config m_config;
|
||||||
|
|
||||||
|
std::pair<bool, app*> next_to_repair();
|
||||||
|
|
||||||
bool eval_is_correct(app* e);
|
bool eval_is_correct(app* e);
|
||||||
bool try_repair_down(app* e);
|
void try_repair_down(app* e);
|
||||||
bool try_repair_up(app* e);
|
void try_repair_up(app* e);
|
||||||
|
|
||||||
bool try_repair_down(app* e, unsigned i);
|
bool try_repair_down(app* e, unsigned i);
|
||||||
|
|
||||||
|
|
|
@ -343,16 +343,9 @@ namespace bv {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto mk_rotate_left = [&](unsigned n) {
|
auto mk_rotate_left = [&](unsigned n) {
|
||||||
auto& a = wval0(e->get_arg(0));
|
auto& a = wval0(e->get_arg(0));
|
||||||
if (n == 0 || a.bw == 1)
|
VERIFY(try_repair_rotate_left(a, val, a.bw - n));
|
||||||
val.set(a.bits);
|
|
||||||
else {
|
|
||||||
for (unsigned i = a.bw - n; i < a.bw; ++i)
|
|
||||||
val.set(val.bits, i + n - a.bw, a.get(a.bits, i));
|
|
||||||
for (unsigned i = 0; i < a.bw - n; ++i)
|
|
||||||
val.set(val.bits, i + a.bw - n, a.get(a.bits, i));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SASSERT(e->get_family_id() == bv.get_fid());
|
SASSERT(e->get_family_id() == bv.get_fid());
|
||||||
|
@ -853,6 +846,7 @@ namespace bv {
|
||||||
auto child = e->get_arg(i);
|
auto child = e->get_arg(i);
|
||||||
auto ev = bval0(e);
|
auto ev = bval0(e);
|
||||||
if (m.is_bool(child)) {
|
if (m.is_bool(child)) {
|
||||||
|
SASSERT(!is_fixed0(child));
|
||||||
auto bv = bval0(e->get_arg(1 - i));
|
auto bv = bval0(e->get_arg(1 - i));
|
||||||
m_eval[child->get_id()] = ev == bv;
|
m_eval[child->get_id()] = ev == bv;
|
||||||
return true;
|
return true;
|
||||||
|
@ -863,12 +857,21 @@ namespace bv {
|
||||||
if (ev)
|
if (ev)
|
||||||
return a.try_set(b.bits);
|
return a.try_set(b.bits);
|
||||||
else {
|
else {
|
||||||
// pick random bit to differ
|
// pick random bit to differ
|
||||||
for (unsigned i = 0; i < a.nw; ++i)
|
a.get(m_tmp);
|
||||||
m_tmp[i] = a.bits[i];
|
unsigned start = m_rand(a.bw);
|
||||||
unsigned idx = m_rand(a.bw);
|
for (unsigned idx = 0; idx < a.bw; ++idx) {
|
||||||
a.set(m_tmp, idx, !b.get(b.bits, idx));
|
unsigned j = (idx + start) % a.bw;
|
||||||
return a.try_set(m_tmp);
|
if (!a.get(a.fixed, j)) {
|
||||||
|
a.set(m_tmp, idx, !b.get(b.bits, j));
|
||||||
|
bool r = a.try_set(m_tmp);
|
||||||
|
if (r)
|
||||||
|
return true;
|
||||||
|
a.set(m_tmp, j, b.get(b.bits, j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// could be due to bounds?
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1107,9 +1110,9 @@ namespace bv {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls_eval::try_repair_rotate_left(bvval const& e, bvval& a, unsigned n) {
|
bool sls_eval::try_repair_rotate_left(bvval const& e, bvval& a, unsigned n) const {
|
||||||
// a := rotate_right(e, n)
|
// a := rotate_right(e, n)
|
||||||
n = (n % a.bw) - n;
|
n = (a.bw - n) % a.bw;
|
||||||
for (unsigned i = a.bw - n; i < a.bw; ++i)
|
for (unsigned i = a.bw - n; i < a.bw; ++i)
|
||||||
a.set(m_tmp, i + n - a.bw, e.get(e.bits, i));
|
a.set(m_tmp, i + n - a.bw, e.get(e.bits, i));
|
||||||
for (unsigned i = 0; i < a.bw - n; ++i)
|
for (unsigned i = 0; i < a.bw - n; ++i)
|
||||||
|
|
|
@ -88,10 +88,9 @@ namespace bv {
|
||||||
bool try_repair_smod(bvval const& e, bvval& a, bvval& b, unsigned i);
|
bool try_repair_smod(bvval const& e, bvval& a, bvval& b, unsigned i);
|
||||||
bool try_repair_urem(bvval const& e, bvval& a, bvval& b, unsigned i);
|
bool try_repair_urem(bvval const& e, bvval& a, bvval& b, unsigned i);
|
||||||
bool try_repair_srem(bvval const& e, bvval& a, bvval& b, unsigned i);
|
bool try_repair_srem(bvval const& e, bvval& a, bvval& b, unsigned i);
|
||||||
bool try_repair_rotate_left(bvval const& e, bvval& a, unsigned n);
|
bool try_repair_rotate_left(bvval const& e, bvval& a, unsigned n) const;
|
||||||
bool try_repair_rotate_left(bvval const& e, bvval& a, bvval& b, unsigned i);
|
bool try_repair_rotate_left(bvval const& e, bvval& a, bvval& b, unsigned i);
|
||||||
|
|
||||||
|
|
||||||
sls_valuation& wval0(app* e, unsigned i) { return wval0(e->get_arg(i)); }
|
sls_valuation& wval0(app* e, unsigned i) { return wval0(e->get_arg(i)); }
|
||||||
|
|
||||||
void wval1(app* e, sls_valuation& val) const;
|
void wval1(app* e, sls_valuation& val) const;
|
||||||
|
|
|
@ -33,26 +33,27 @@ namespace bv {
|
||||||
for (unsigned i = 0; i < nw; ++i)
|
for (unsigned i = 0; i < nw; ++i)
|
||||||
lo[i] = 0, hi[i] = 0, bits[i] = 0, fixed[i] = 0;
|
lo[i] = 0, hi[i] = 0, bits[i] = 0, fixed[i] = 0;
|
||||||
for (unsigned i = bw; i < 8 * sizeof(digit_t) * nw; ++i)
|
for (unsigned i = bw; i < 8 * sizeof(digit_t) * nw; ++i)
|
||||||
set(fixed, i, true);
|
set(fixed, i, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
sls_valuation::~sls_valuation() {
|
sls_valuation::~sls_valuation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls_valuation::is_feasible() const {
|
bool sls_valuation::in_range(svector<digit_t> const& bits) const {
|
||||||
return true;
|
mpn_manager m;
|
||||||
mpn_manager m;
|
auto c = m.compare(lo.data(), nw, hi.data(), nw);
|
||||||
unsigned nb = (bw + 7) / 8;
|
// full range
|
||||||
auto c = m.compare(lo.data(), nb, hi.data(), nb);
|
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
return true;
|
return true;
|
||||||
|
// lo < hi: then lo <= bits & bits < hi
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
return
|
return
|
||||||
m.compare(lo.data(), nb, bits.data(), nb) <= 0 &&
|
m.compare(lo.data(), nw, bits.data(), nw) <= 0 &&
|
||||||
m.compare(bits.data(), nb, hi.data(), nb) < 0;
|
m.compare(bits.data(), nw, hi.data(), nw) < 0;
|
||||||
return
|
// hi < lo: bits < hi or lo <= bits
|
||||||
m.compare(lo.data(), nb, bits.data(), nb) <= 0 ||
|
return
|
||||||
m.compare(bits.data(), nb, hi.data(), nb) < 0;
|
m.compare(lo.data(), nw, bits.data(), nw) <= 0 ||
|
||||||
|
m.compare(bits.data(), nw, hi.data(), nw) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls_valuation::eq(svector<digit_t> const& other) const {
|
bool sls_valuation::eq(svector<digit_t> const& other) const {
|
||||||
|
@ -65,11 +66,34 @@ namespace bv {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sls_valuation::gt(svector<digit_t> const& a, svector<digit_t> const& b) const {
|
||||||
|
mpn_manager m;
|
||||||
|
return m.compare(a.data(), nw, b.data(), nw) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
void sls_valuation::clear_overflow_bits(svector<digit_t>& bits) const {
|
void sls_valuation::clear_overflow_bits(svector<digit_t>& bits) const {
|
||||||
for (unsigned i = bw; i < nw * sizeof(digit_t) * 8; ++i)
|
for (unsigned i = bw; i < nw * sizeof(digit_t) * 8; ++i)
|
||||||
set(bits, i, false);
|
set(bits, i, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sls_valuation::get_below(svector<digit_t> const& src, svector<digit_t>& dst) {
|
||||||
|
for (unsigned i = 0; i < nw; ++i)
|
||||||
|
dst[i] = (src[i] & ~fixed[i]) | (fixed[i] & bits[i]);
|
||||||
|
for (unsigned i = 0; i < nw; ++i)
|
||||||
|
dst[i] = fixed[i] & bits[i];
|
||||||
|
if (gt(dst, src))
|
||||||
|
return false;
|
||||||
|
if (!in_range(dst)) {
|
||||||
|
// lo < hi:
|
||||||
|
// set dst to lo, except for fixed bits
|
||||||
|
//
|
||||||
|
if (gt(hi, lo)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void sls_valuation::set_value(svector<digit_t>& bits, rational const& n) {
|
void sls_valuation::set_value(svector<digit_t>& bits, rational const& n) {
|
||||||
for (unsigned i = 0; i < bw; ++i)
|
for (unsigned i = 0; i < bw; ++i)
|
||||||
set(bits, i, n.get_bit(i));
|
set(bits, i, n.get_bit(i));
|
||||||
|
@ -94,11 +118,16 @@ namespace bv {
|
||||||
set(bits, i, true);
|
set(bits, i, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sls_valuation::can_set(svector<digit_t> const& new_bits) const {
|
//
|
||||||
|
// new_bits != bits => ~fixed
|
||||||
|
// 0 = (new_bits ^ bits) & fixed
|
||||||
|
// also check that new_bits are in range
|
||||||
|
//
|
||||||
|
bool sls_valuation::can_set(svector<digit_t> const& new_bits) const {
|
||||||
for (unsigned i = 0; i < nw; ++i)
|
for (unsigned i = 0; i < nw; ++i)
|
||||||
if (bits[i] != ((new_bits[i] & ~fixed[i]) | (bits[i] & fixed[i])))
|
if (0 != ((new_bits[i] ^ bits[i]) & fixed[i]))
|
||||||
return true;
|
return false;
|
||||||
return false;
|
return in_range(new_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned sls_valuation::to_nat(svector<digit_t> const& d, unsigned max_n) {
|
unsigned sls_valuation::to_nat(svector<digit_t> const& d, unsigned max_n) {
|
||||||
|
@ -124,10 +153,15 @@ namespace bv {
|
||||||
h = mod(h, rational::power_of_two(bw));
|
h = mod(h, rational::power_of_two(bw));
|
||||||
if (h == l)
|
if (h == l)
|
||||||
return;
|
return;
|
||||||
set_value(this->lo, l);
|
if (eq(lo, hi)) {
|
||||||
set_value(this->hi, h);
|
set_value(lo, l);
|
||||||
|
set_value(hi, h);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: intersect with previous range, if any
|
// TODO: intersect with previous range, if any
|
||||||
|
set_value(lo, l);
|
||||||
|
set_value(hi, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,10 @@ Author:
|
||||||
namespace bv {
|
namespace bv {
|
||||||
|
|
||||||
struct sls_valuation {
|
struct sls_valuation {
|
||||||
unsigned bw; // bit-width
|
unsigned bw; // bit-width
|
||||||
unsigned nw; // num words
|
unsigned nw; // num words
|
||||||
svector<digit_t> lo, hi; // range assignment to bit-vector, as wrap-around interval
|
svector<digit_t> lo, hi; // range assignment to bit-vector, as wrap-around interval
|
||||||
svector<digit_t> bits, fixed; // bit assignment and don't care bit
|
svector<digit_t> bits, fixed; // bit assignment and don't care bit
|
||||||
bool is_feasible() const; // the current bit-evaluation is between lo and hi.
|
|
||||||
sls_valuation(unsigned bw);
|
sls_valuation(unsigned bw);
|
||||||
~sls_valuation();
|
~sls_valuation();
|
||||||
|
|
||||||
|
@ -44,17 +43,15 @@ namespace bv {
|
||||||
void add_range(rational lo, rational hi);
|
void add_range(rational lo, rational hi);
|
||||||
void set1(svector<digit_t>& bits);
|
void set1(svector<digit_t>& bits);
|
||||||
|
|
||||||
|
|
||||||
void clear_overflow_bits(svector<digit_t>& bits) const;
|
void clear_overflow_bits(svector<digit_t>& bits) const;
|
||||||
|
bool in_range(svector<digit_t> const& bits) const;
|
||||||
bool can_set(svector<digit_t> const& bits) const;
|
bool can_set(svector<digit_t> const& bits) const;
|
||||||
|
|
||||||
bool eq(sls_valuation const& other) const { return eq(other.bits); }
|
bool eq(sls_valuation const& other) const { return eq(other.bits); }
|
||||||
|
|
||||||
bool eq(svector<digit_t> const& other) const;
|
bool eq(svector<digit_t> const& other) const { return eq(other, bits); }
|
||||||
|
bool eq(svector<digit_t> const& a, svector<digit_t> const& b) const;
|
||||||
bool gt(svector<digit_t> const& a, svector<digit_t> const& b) const {
|
bool gt(svector<digit_t> const& a, svector<digit_t> const& b) const;
|
||||||
return 0 > memcmp(a.data(), b.data(), num_bytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_zero() const { return is_zero(bits); }
|
bool is_zero() const { return is_zero(bits); }
|
||||||
bool is_zero(svector<digit_t> const& a) const {
|
bool is_zero(svector<digit_t> const& a) const {
|
||||||
|
@ -79,6 +76,10 @@ namespace bv {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// retrieve number at or below src which is feasible
|
||||||
|
// with respect to fixed, lo, hi.
|
||||||
|
bool get_below(svector<digit_t> const& src, svector<digit_t>& dst);
|
||||||
|
|
||||||
bool try_set(svector<digit_t> const& src) {
|
bool try_set(svector<digit_t> const& src) {
|
||||||
if (!can_set(src))
|
if (!can_set(src))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -15,6 +15,12 @@ namespace bv {
|
||||||
bv(m)
|
bv(m)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
void check_eval(expr* a, expr* b, unsigned j) {
|
||||||
|
auto es = create_exprs(a, b, j);
|
||||||
|
for (expr* e : es)
|
||||||
|
check_eval(e);
|
||||||
|
}
|
||||||
|
|
||||||
void check_eval(expr* e) {
|
void check_eval(expr* e) {
|
||||||
std::function<bool(expr*, unsigned)> value = [](expr*, unsigned) {
|
std::function<bool(expr*, unsigned)> value = [](expr*, unsigned) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -44,7 +50,7 @@ namespace bv {
|
||||||
}
|
}
|
||||||
else if (m.is_bool(e)) {
|
else if (m.is_bool(e)) {
|
||||||
auto val1 = ev.bval0(e);
|
auto val1 = ev.bval0(e);
|
||||||
auto val2 = m.is_true(r) ? true : false;
|
auto val2 = m.is_true(r);
|
||||||
if (val1 != val2) {
|
if (val1 != val2) {
|
||||||
verbose_stream() << mk_pp(e, m) << " computed value " << val1 << " at odds with definition\n";
|
verbose_stream() << mk_pp(e, m) << " computed value " << val1 << " at odds with definition\n";
|
||||||
}
|
}
|
||||||
|
@ -53,121 +59,109 @@ namespace bv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check(expr* a, expr* b) {
|
expr_ref_vector create_exprs(expr* a, expr* b, unsigned j) {
|
||||||
expr_ref e(m);
|
expr_ref_vector result(m);
|
||||||
auto& validator = *this;
|
result.push_back(bv.mk_bv_add(a, b))
|
||||||
e = bv.mk_bv_add(a, b);
|
.push_back(bv.mk_bv_mul(a, b))
|
||||||
validator.check_eval(e);
|
.push_back(bv.mk_bv_sub(a, b))
|
||||||
|
.push_back(bv.mk_bv_udiv(a, b))
|
||||||
e = bv.mk_bv_mul(a, b);
|
.push_back(bv.mk_bv_sdiv(a, b))
|
||||||
validator.check_eval(e);
|
.push_back(bv.mk_bv_srem(a, b))
|
||||||
|
.push_back(bv.mk_bv_urem(a, b))
|
||||||
e = bv.mk_bv_sub(a, b);
|
.push_back(bv.mk_bv_smod(a, b))
|
||||||
validator.check_eval(e);
|
.push_back(bv.mk_bv_shl(a, b))
|
||||||
|
.push_back(bv.mk_bv_ashr(a, b))
|
||||||
e = bv.mk_bv_udiv(a, b);
|
.push_back(bv.mk_bv_lshr(a, b))
|
||||||
validator.check_eval(e);
|
.push_back(bv.mk_bv_and(a, b))
|
||||||
|
.push_back(bv.mk_bv_or(a, b))
|
||||||
e = bv.mk_bv_sdiv(a, b);
|
.push_back(bv.mk_bv_xor(a, b))
|
||||||
validator.check_eval(e);
|
.push_back(bv.mk_bv_neg(a))
|
||||||
|
.push_back(bv.mk_bv_not(a))
|
||||||
e = bv.mk_bv_srem(a, b);
|
.push_back(bv.mk_bvumul_ovfl(a, b))
|
||||||
validator.check_eval(e);
|
.push_back(bv.mk_bvumul_no_ovfl(a, b))
|
||||||
|
.push_back(bv.mk_zero_extend(3, a))
|
||||||
e = bv.mk_bv_urem(a, b);
|
.push_back(bv.mk_sign_extend(3, a))
|
||||||
validator.check_eval(e);
|
.push_back(bv.mk_ule(a, b))
|
||||||
|
.push_back(bv.mk_sle(a, b))
|
||||||
e = bv.mk_bv_smod(a, b);
|
.push_back(bv.mk_concat(a, b))
|
||||||
validator.check_eval(e);
|
.push_back(bv.mk_extract(6, 3, a))
|
||||||
|
.push_back(bv.mk_bvuadd_ovfl(a, b))
|
||||||
e = bv.mk_bv_shl(a, b);
|
.push_back(bv.mk_bv_rotate_left(a, j))
|
||||||
validator.check_eval(e);
|
.push_back(bv.mk_bv_rotate_right(a, j))
|
||||||
|
.push_back(bv.mk_bv_rotate_left(a, b))
|
||||||
e = bv.mk_bv_ashr(a, b);
|
.push_back(bv.mk_bv_rotate_right(a, b))
|
||||||
validator.check_eval(e);
|
// .push_back(bv.mk_bvsadd_ovfl(a, b))
|
||||||
|
// .push_back(bv.mk_bvneg_ovfl(a))
|
||||||
e = bv.mk_bv_lshr(a, b);
|
// .push_back(bv.mk_bvsmul_no_ovfl(a, b))
|
||||||
validator.check_eval(e);
|
// .push_back(bv.mk_bvsmul_no_udfl(a, b))
|
||||||
|
// .push_back(bv.mk_bvsmul_ovfl(a, b))
|
||||||
e = bv.mk_bv_and(a, b);
|
// .push_back(bv.mk_bvsdiv_ovfl(a, b))
|
||||||
validator.check_eval(e);
|
;
|
||||||
|
}
|
||||||
e = bv.mk_bv_or(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_bv_xor(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_bv_neg(a);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_bv_not(a);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_bvumul_ovfl(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_bvumul_no_ovfl(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_zero_extend(3, a);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_sign_extend(3, a);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_ule(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_sle(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_concat(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_extract(6, 3, a);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_bvuadd_ovfl(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
// e = op(a, b),
|
||||||
|
// update value of a to "random"
|
||||||
|
// repair a based on computed values.
|
||||||
|
void check_repair(expr* a, expr* b, unsigned j) {
|
||||||
|
expr_ref x(m.mk_const("x", bv.mk_sort(bv.get_bv_size(a))), m);
|
||||||
|
expr_ref y(m.mk_const("y", bv.mk_sort(bv.get_bv_size(b))), m);
|
||||||
|
auto es1 = create_exprs(a, b, j);
|
||||||
|
auto es2 = create_exprs(x, b, j);
|
||||||
|
auto es3 = create_exprs(a, y, j);
|
||||||
|
for (unsigned i = 0; i < es1.size(); ++i) {
|
||||||
|
auto e1 = es1.get(i);
|
||||||
|
auto e2 = es2.get(i);
|
||||||
|
auto e3 = es3.get(i);
|
||||||
|
check_repair_idx(e1, e2, 0, x);
|
||||||
|
if (is_app(e1) && to_app(e1)->get_num_args() == 2)
|
||||||
|
check_repair_idx(e1, e3, 1, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
e = bv.mk_bvsadd_ovfl(a, b);
|
random_gen rand;
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_bvneg_ovfl(a);
|
void check_repair_idx(expr* e1, expr* e2, unsigned idx, expr* x) {
|
||||||
validator.check_eval(e);
|
std::function<bool(expr*, unsigned)> value = [&](expr*, unsigned) {
|
||||||
|
return rand() % 2 == 0;
|
||||||
|
};
|
||||||
|
expr_ref_vector es(m);
|
||||||
|
bv_util bv(m);
|
||||||
|
es.push_back(e1);
|
||||||
|
es.push_back(e2);
|
||||||
|
sls_eval ev(m);
|
||||||
|
ev.init_eval(es, value);
|
||||||
|
th_rewriter rw(m);
|
||||||
|
expr_ref r(e1, m);
|
||||||
|
if (m.is_bool(e1)) {
|
||||||
|
auto val = m.is_true(r);
|
||||||
|
auto val2 = ev.bval0(e2);
|
||||||
|
if (val != val2) {
|
||||||
|
ev.set(e2, val);
|
||||||
|
auto rep1 = ev.try_repair(to_app(e2), idx);
|
||||||
|
if (!rep1) {
|
||||||
|
verbose_stream() << "Not repaired " << mk_pp(e2, m) << "\n";
|
||||||
|
}
|
||||||
|
SASSERT(rep1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bv.is_bv(e1)) {
|
||||||
|
auto& val1 = ev.wval0(e1);
|
||||||
|
auto& val2 = ev.wval0(e2);
|
||||||
|
if (!val1.eq(val2)) {
|
||||||
|
val2.set(val1.bits);
|
||||||
|
auto rep2 = ev.try_repair(to_app(e2), idx);
|
||||||
|
if (!rep2) {
|
||||||
|
verbose_stream() << "Not repaired " << mk_pp(e2, m) << "\n";
|
||||||
|
}
|
||||||
|
SASSERT(rep2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
e = bv.mk_bvsmul_no_ovfl(a, b);
|
// todo:
|
||||||
validator.check_eval(e);
|
void test_fixed() {
|
||||||
|
|
||||||
e = bv.mk_bvsmul_no_udfl(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_bvsmul_ovfl(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_bvsdiv_ovfl(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
e = bv.mk_rotate_left(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_rotate_right(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_rotate_left_ext(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
e = bv.mk_rotate_right_ext(a, b);
|
|
||||||
validator.check_eval(e);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -183,17 +177,36 @@ static void test_eval1() {
|
||||||
bv::sls_test validator(m);
|
bv::sls_test validator(m);
|
||||||
|
|
||||||
unsigned k = 0;
|
unsigned k = 0;
|
||||||
for (unsigned i = 0; i < 256; ++i) {
|
unsigned bw = 6;
|
||||||
expr_ref a(bv.mk_numeral(rational(i), 8), m);
|
for (unsigned i = 0; i < 1ul << bw; ++i) {
|
||||||
for (unsigned j = 0; j < 256; ++j) {
|
expr_ref a(bv.mk_numeral(rational(i), bw), m);
|
||||||
expr_ref b(bv.mk_numeral(rational(j), 8), m);
|
for (unsigned j = 0; j < 1ul << bw; ++j) {
|
||||||
|
expr_ref b(bv.mk_numeral(rational(j), bw), m);
|
||||||
++k;
|
++k;
|
||||||
if (k % 1000 == 0)
|
if (k % 1000 == 0)
|
||||||
verbose_stream() << "tests " << k << "\n";
|
verbose_stream() << "tests " << k << "\n";
|
||||||
|
validator.check_eval(a, b, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
validator.check(a, b);
|
static void test_repair1() {
|
||||||
|
ast_manager m;
|
||||||
|
reg_decl_plugins(m);
|
||||||
|
bv_util bv(m);
|
||||||
|
expr_ref e(m);
|
||||||
|
bv::sls_test validator(m);
|
||||||
|
|
||||||
|
unsigned k = 0;
|
||||||
|
unsigned bw = 6;
|
||||||
|
for (unsigned i = 0; i < 1ul << bw; ++i) {
|
||||||
|
expr_ref a(bv.mk_numeral(rational(i), bw), m);
|
||||||
|
for (unsigned j = 0; j < 1ul << bw; ++j) {
|
||||||
|
expr_ref b(bv.mk_numeral(rational(j), bw), m);
|
||||||
|
++k;
|
||||||
|
if (k % 1000 == 0)
|
||||||
|
verbose_stream() << "tests " << k << "\n";
|
||||||
|
validator.check_repair(a, b, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue