mirror of
https://github.com/Z3Prover/z3
synced 2025-04-06 01:24:08 +00:00
more fpa
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
79162b96f3
commit
08a87b102c
|
@ -4358,3 +4358,95 @@ void fpa2bv_converter_wrapped::mk_rm_const(func_decl* f, expr_ref& result) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
expr* fpa2bv_converter_wrapped::bv2rm_value(expr* b) {
|
||||
app* result = nullptr;
|
||||
unsigned bv_sz;
|
||||
rational val(0);
|
||||
VERIFY(m_bv_util.is_numeral(b, val, bv_sz));
|
||||
SASSERT(bv_sz == 3);
|
||||
|
||||
switch (val.get_uint64()) {
|
||||
case BV_RM_TIES_TO_AWAY: result = m_util.mk_round_nearest_ties_to_away(); break;
|
||||
case BV_RM_TIES_TO_EVEN: result = m_util.mk_round_nearest_ties_to_even(); break;
|
||||
case BV_RM_TO_NEGATIVE: result = m_util.mk_round_toward_negative(); break;
|
||||
case BV_RM_TO_POSITIVE: result = m_util.mk_round_toward_positive(); break;
|
||||
case BV_RM_TO_ZERO:
|
||||
default: result = m_util.mk_round_toward_zero();
|
||||
}
|
||||
|
||||
TRACE("t_fpa", tout << "result: " << mk_ismt2_pp(result, m) << std::endl;);
|
||||
return result;
|
||||
}
|
||||
|
||||
expr* fpa2bv_converter_wrapped::bv2fpa_value(sort* s, expr* a, expr* b, expr* c) {
|
||||
mpf_manager& mpfm = m_util.fm();
|
||||
unsynch_mpz_manager& mpzm = mpfm.mpz_manager();
|
||||
app* result;
|
||||
unsigned ebits = m_util.get_ebits(s);
|
||||
unsigned sbits = m_util.get_sbits(s);
|
||||
|
||||
scoped_mpz bias(mpzm);
|
||||
mpzm.power(mpz(2), ebits - 1, bias);
|
||||
mpzm.dec(bias);
|
||||
|
||||
scoped_mpz sgn_z(mpzm), sig_z(mpzm), exp_z(mpzm);
|
||||
unsigned bv_sz;
|
||||
|
||||
if (b == nullptr) {
|
||||
SASSERT(m_bv_util.is_bv(a));
|
||||
SASSERT(m_bv_util.get_bv_size(a) == (ebits + sbits));
|
||||
|
||||
rational all_r(0);
|
||||
scoped_mpz all_z(mpzm);
|
||||
|
||||
VERIFY(m_bv_util.is_numeral(a, all_r, bv_sz));
|
||||
SASSERT(bv_sz == (ebits + sbits));
|
||||
SASSERT(all_r.is_int());
|
||||
mpzm.set(all_z, all_r.to_mpq().numerator());
|
||||
|
||||
mpzm.machine_div2k(all_z, ebits + sbits - 1, sgn_z);
|
||||
mpzm.mod(all_z, mpfm.m_powers2(ebits + sbits - 1), all_z);
|
||||
|
||||
mpzm.machine_div2k(all_z, sbits - 1, exp_z);
|
||||
mpzm.mod(all_z, mpfm.m_powers2(sbits - 1), all_z);
|
||||
|
||||
mpzm.set(sig_z, all_z);
|
||||
}
|
||||
else {
|
||||
SASSERT(b);
|
||||
SASSERT(c);
|
||||
rational sgn_r(0), exp_r(0), sig_r(0);
|
||||
|
||||
bool r = m_bv_util.is_numeral(a, sgn_r, bv_sz);
|
||||
SASSERT(r && bv_sz == 1);
|
||||
r = m_bv_util.is_numeral(b, exp_r, bv_sz);
|
||||
SASSERT(r && bv_sz == ebits);
|
||||
r = m_bv_util.is_numeral(c, sig_r, bv_sz);
|
||||
SASSERT(r && bv_sz == sbits - 1);
|
||||
(void)r;
|
||||
|
||||
SASSERT(mpzm.is_one(sgn_r.to_mpq().denominator()));
|
||||
SASSERT(mpzm.is_one(exp_r.to_mpq().denominator()));
|
||||
SASSERT(mpzm.is_one(sig_r.to_mpq().denominator()));
|
||||
|
||||
mpzm.set(sgn_z, sgn_r.to_mpq().numerator());
|
||||
mpzm.set(exp_z, exp_r.to_mpq().numerator());
|
||||
mpzm.set(sig_z, sig_r.to_mpq().numerator());
|
||||
}
|
||||
|
||||
scoped_mpz exp_u = exp_z - bias;
|
||||
SASSERT(mpzm.is_int64(exp_u));
|
||||
|
||||
scoped_mpf f(mpfm);
|
||||
mpfm.set(f, ebits, sbits, mpzm.is_one(sgn_z), mpzm.get_int64(exp_u), sig_z);
|
||||
result = m_util.mk_value(f);
|
||||
|
||||
TRACE("t_fpa", tout << "result: [" <<
|
||||
mpzm.to_string(sgn_z) << "," <<
|
||||
mpzm.to_string(exp_z) << "," <<
|
||||
mpzm.to_string(sig_z) << "] --> " <<
|
||||
mk_ismt2_pp(result, m) << std::endl;);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -239,5 +239,8 @@ class fpa2bv_converter_wrapped : public fpa2bv_converter {
|
|||
app_ref wrap(expr * e);
|
||||
app_ref unwrap(expr * e, sort * s);
|
||||
|
||||
expr* bv2rm_value(expr* b);
|
||||
expr* bv2fpa_value(sort* s, expr* a, expr* b = nullptr, expr* c = nullptr);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ Revision History:
|
|||
#include "model/seq_factory.h"
|
||||
#include "model/datatype_factory.h"
|
||||
#include "model/numeral_factory.h"
|
||||
#include "model/fpa_factory.h"
|
||||
|
||||
|
||||
model::model(ast_manager & m):
|
||||
|
@ -99,11 +100,13 @@ bool model::eval_expr(expr * e, expr_ref & result, bool model_completion) {
|
|||
value_factory* model::get_factory(sort* s) {
|
||||
if (m_factories.plugins().empty()) {
|
||||
seq_util su(m);
|
||||
fpa_util fu(m);
|
||||
m_factories.register_plugin(alloc(array_factory, m, *this));
|
||||
m_factories.register_plugin(alloc(datatype_factory, m, *this));
|
||||
m_factories.register_plugin(alloc(bv_factory, m));
|
||||
m_factories.register_plugin(alloc(arith_factory, m));
|
||||
m_factories.register_plugin(alloc(seq_factory, m, su.get_family_id(), *this));
|
||||
m_factories.register_plugin(alloc(fpa_value_factory, m, fu.get_family_id()));
|
||||
}
|
||||
family_id fid = s->get_family_id();
|
||||
return m_factories.get_plugin(fid);
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace sat {
|
|||
virtual std::ostream& display(std::ostream& out) const = 0;
|
||||
virtual std::ostream& display_justification(std::ostream& out, ext_justification_idx idx) const = 0;
|
||||
virtual std::ostream& display_constraint(std::ostream& out, ext_constraint_idx idx) const = 0;
|
||||
virtual void collect_statistics(statistics& st) const = 0;
|
||||
virtual void collect_statistics(statistics& st) const {}
|
||||
virtual extension* copy(solver* s) { UNREACHABLE(); return nullptr; }
|
||||
virtual void find_mutexes(literal_vector& lits, vector<literal_vector> & mutexes) {}
|
||||
virtual void gc() {}
|
||||
|
|
|
@ -29,6 +29,8 @@ namespace euf {
|
|||
deps.topological_sort();
|
||||
dependencies2values(deps, mdl);
|
||||
values2model(deps, mdl);
|
||||
for (auto* mb : m_solvers)
|
||||
mb->finalize_model(*mdl);
|
||||
}
|
||||
|
||||
bool solver::include_func_interp(func_decl* f) {
|
||||
|
|
|
@ -24,6 +24,7 @@ Author:
|
|||
#include "sat/smt/euf_solver.h"
|
||||
#include "sat/smt/array_solver.h"
|
||||
#include "sat/smt/q_solver.h"
|
||||
#include "sat/smt/fpa_solver.h"
|
||||
|
||||
namespace euf {
|
||||
|
||||
|
@ -97,6 +98,7 @@ namespace euf {
|
|||
pb_util pb(m);
|
||||
bv_util bvu(m);
|
||||
array_util au(m);
|
||||
fpa_util fpa(m);
|
||||
if (pb.get_family_id() == fid) {
|
||||
ext = alloc(sat::ba_solver, *this, fid);
|
||||
if (use_drat())
|
||||
|
@ -112,6 +114,11 @@ namespace euf {
|
|||
if (use_drat())
|
||||
s().get_drat().add_theory(fid, symbol("array"));
|
||||
}
|
||||
else if (fpa.get_family_id() == fid) {
|
||||
ext = alloc(fpa::solver, *this);
|
||||
if (use_drat())
|
||||
s().get_drat().add_theory(fid, symbol("fpa"));
|
||||
}
|
||||
if (ext) {
|
||||
ext->set_solver(m_solver);
|
||||
ext->push_scopes(s().num_scopes());
|
||||
|
|
|
@ -133,9 +133,8 @@ namespace fpa {
|
|||
atom.neg();
|
||||
add_unit(atom);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
else {
|
||||
switch (a->get_decl_kind()) {
|
||||
case OP_FPA_TO_FP:
|
||||
case OP_FPA_TO_UBV:
|
||||
|
@ -148,7 +147,9 @@ namespace fpa {
|
|||
add_units(mk_side_conditions());
|
||||
break;
|
||||
}
|
||||
default: /* ignore */;
|
||||
default: /* ignore */
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -166,16 +167,14 @@ namespace fpa {
|
|||
return;
|
||||
attach_new_th_var(n);
|
||||
|
||||
if (m_fpa_util.is_rm(s)) {
|
||||
if (m_fpa_util.is_rm(s) && !m_fpa_util.is_bv2rm(owner)) {
|
||||
// For every RM term, we need to make sure that it's
|
||||
// associated bit-vector is within the valid range.
|
||||
if (!m_fpa_util.is_bv2rm(owner)) {
|
||||
expr_ref valid(m), limit(m);
|
||||
limit = m_bv_util.mk_numeral(4, 3);
|
||||
valid = m_bv_util.mk_ule(m_converter.wrap(owner), limit);
|
||||
add_unit(b_internalize(valid));
|
||||
}
|
||||
}
|
||||
activate(owner);
|
||||
}
|
||||
|
||||
|
@ -307,19 +306,22 @@ namespace fpa {
|
|||
expr* a = values.get(n->get_arg(0)->get_root_id());
|
||||
expr* b = values.get(n->get_arg(1)->get_root_id());
|
||||
expr* c = values.get(n->get_arg(2)->get_root_id());
|
||||
value = bvs2fpa_value(m.get_sort(e), a, b, c);
|
||||
value = m_converter.bv2fpa_value(m.get_sort(e), a, b, c);
|
||||
}
|
||||
else if (m_fpa_util.is_bv2rm(e)) {
|
||||
SASSERT(n->num_args() == 1);
|
||||
value = bv2rm_value(values.get(n->get_arg(0)->get_root_id()));
|
||||
value = m_converter.bv2rm_value(values.get(n->get_arg(0)->get_root_id()));
|
||||
}
|
||||
else if (m_fpa_util.is_rm(e) && is_wrapped())
|
||||
value = bv2rm_value(values.get(expr2enode(wrapped)->get_root_id()));
|
||||
value = m_converter.bv2rm_value(values.get(expr2enode(wrapped)->get_root_id()));
|
||||
else if (m_fpa_util.is_rm(e))
|
||||
value = m_fpa_util.mk_round_toward_zero();
|
||||
else if (m_fpa_util.is_float(e) && is_wrapped()) {
|
||||
expr* a = values.get(expr2enode(wrapped)->get_root_id());
|
||||
value = bvs2fpa_value(m.get_sort(e), a, nullptr, nullptr);
|
||||
value = m_converter.bv2fpa_value(m.get_sort(e), a);
|
||||
}
|
||||
else {
|
||||
SASSERT(m_fpa_util.is_float(e));
|
||||
unsigned ebits = m_fpa_util.get_ebits(m.get_sort(e));
|
||||
unsigned sbits = m_fpa_util.get_sbits(m.get_sort(e));
|
||||
value = m_fpa_util.mk_pzero(ebits, sbits);
|
||||
|
@ -327,99 +329,6 @@ namespace fpa {
|
|||
values.set(n->get_root_id(), value);
|
||||
}
|
||||
|
||||
expr* solver::bv2rm_value(expr* b) {
|
||||
app* result = nullptr;
|
||||
unsigned bv_sz;
|
||||
rational val(0);
|
||||
VERIFY(m_bv_util.is_numeral(b, val, bv_sz));
|
||||
SASSERT(bv_sz == 3);
|
||||
|
||||
switch (val.get_uint64()) {
|
||||
case BV_RM_TIES_TO_AWAY: result = m_fpa_util.mk_round_nearest_ties_to_away(); break;
|
||||
case BV_RM_TIES_TO_EVEN: result = m_fpa_util.mk_round_nearest_ties_to_even(); break;
|
||||
case BV_RM_TO_NEGATIVE: result = m_fpa_util.mk_round_toward_negative(); break;
|
||||
case BV_RM_TO_POSITIVE: result = m_fpa_util.mk_round_toward_positive(); break;
|
||||
case BV_RM_TO_ZERO:
|
||||
default: result = m_fpa_util.mk_round_toward_zero();
|
||||
}
|
||||
|
||||
TRACE("t_fpa", tout << "result: " << mk_ismt2_pp(result, m) << std::endl;);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
expr* solver::bvs2fpa_value(sort* s, expr* a, expr* b, expr* c) {
|
||||
mpf_manager& mpfm = m_fpa_util.fm();
|
||||
unsynch_mpz_manager& mpzm = mpfm.mpz_manager();
|
||||
app* result;
|
||||
unsigned ebits = m_fpa_util.get_ebits(s);
|
||||
unsigned sbits = m_fpa_util.get_sbits(s);
|
||||
|
||||
scoped_mpz bias(mpzm);
|
||||
mpzm.power(mpz(2), ebits - 1, bias);
|
||||
mpzm.dec(bias);
|
||||
|
||||
scoped_mpz sgn_z(mpzm), sig_z(mpzm), exp_z(mpzm);
|
||||
unsigned bv_sz;
|
||||
|
||||
if (b == nullptr) {
|
||||
SASSERT(m_bv_util.is_bv(a));
|
||||
SASSERT(m_bv_util.get_bv_size(a) == (ebits + sbits));
|
||||
|
||||
rational all_r(0);
|
||||
scoped_mpz all_z(mpzm);
|
||||
|
||||
VERIFY(m_bv_util.is_numeral(a, all_r, bv_sz));
|
||||
SASSERT(bv_sz == (ebits + sbits));
|
||||
SASSERT(all_r.is_int());
|
||||
mpzm.set(all_z, all_r.to_mpq().numerator());
|
||||
|
||||
mpzm.machine_div2k(all_z, ebits + sbits - 1, sgn_z);
|
||||
mpzm.mod(all_z, mpfm.m_powers2(ebits + sbits - 1), all_z);
|
||||
|
||||
mpzm.machine_div2k(all_z, sbits - 1, exp_z);
|
||||
mpzm.mod(all_z, mpfm.m_powers2(sbits - 1), all_z);
|
||||
|
||||
mpzm.set(sig_z, all_z);
|
||||
}
|
||||
else {
|
||||
SASSERT(b);
|
||||
SASSERT(c);
|
||||
rational sgn_r(0), exp_r(0), sig_r(0);
|
||||
|
||||
bool r = m_bv_util.is_numeral(a, sgn_r, bv_sz);
|
||||
SASSERT(r && bv_sz == 1);
|
||||
r = m_bv_util.is_numeral(b, exp_r, bv_sz);
|
||||
SASSERT(r && bv_sz == ebits);
|
||||
r = m_bv_util.is_numeral(c, sig_r, bv_sz);
|
||||
SASSERT(r && bv_sz == sbits - 1);
|
||||
(void)r;
|
||||
|
||||
SASSERT(mpzm.is_one(sgn_r.to_mpq().denominator()));
|
||||
SASSERT(mpzm.is_one(exp_r.to_mpq().denominator()));
|
||||
SASSERT(mpzm.is_one(sig_r.to_mpq().denominator()));
|
||||
|
||||
mpzm.set(sgn_z, sgn_r.to_mpq().numerator());
|
||||
mpzm.set(exp_z, exp_r.to_mpq().numerator());
|
||||
mpzm.set(sig_z, sig_r.to_mpq().numerator());
|
||||
}
|
||||
|
||||
scoped_mpz exp_u = exp_z - bias;
|
||||
SASSERT(mpzm.is_int64(exp_u));
|
||||
|
||||
scoped_mpf f(mpfm);
|
||||
mpfm.set(f, ebits, sbits, mpzm.is_one(sgn_z), mpzm.get_int64(exp_u), sig_z);
|
||||
result = m_fpa_util.mk_value(f);
|
||||
|
||||
TRACE("t_fpa", tout << "result: [" <<
|
||||
mpzm.to_string(sgn_z) << "," <<
|
||||
mpzm.to_string(exp_z) << "," <<
|
||||
mpzm.to_string(sig_z) << "] --> " <<
|
||||
mk_ismt2_pp(result, m) << std::endl;);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void solver::add_dep(euf::enode* n, top_sort<euf::enode>& dep) {
|
||||
expr* e = n->get_expr();
|
||||
if (m_fpa_util.is_fp(e)) {
|
||||
|
@ -432,9 +341,9 @@ namespace fpa {
|
|||
dep.add(n, n->get_arg(0));
|
||||
}
|
||||
else if (m_fpa_util.is_rm(e) || m_fpa_util.is_float(e)) {
|
||||
app_ref wrapped = m_converter.wrap(e);
|
||||
if (expr2enode(wrapped))
|
||||
dep.add(n, expr2enode(wrapped));
|
||||
euf::enode* wrapped = expr2enode(m_converter.wrap(e));
|
||||
if (wrapped)
|
||||
dep.add(n, wrapped);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -475,7 +384,6 @@ namespace fpa {
|
|||
return out;
|
||||
}
|
||||
|
||||
|
||||
void solver::finalize_model(model& mdl) {
|
||||
model new_model(m);
|
||||
|
||||
|
|
|
@ -46,11 +46,6 @@ namespace fpa {
|
|||
void attach_new_th_var(enode* n);
|
||||
void activate(expr* e);
|
||||
void ensure_equality_relation(theory_var x, theory_var y);
|
||||
expr* bv2rm_value(expr* b);
|
||||
expr* bvs2fpa_value(sort* s, expr* a, expr* b, expr* c);
|
||||
|
||||
void finalize_model(model& mdl);
|
||||
|
||||
|
||||
public:
|
||||
solver(euf::solver& ctx);
|
||||
|
@ -66,10 +61,20 @@ namespace fpa {
|
|||
void apply_sort_cnstr(euf::enode* n, sort* s) override;
|
||||
|
||||
std::ostream& display(std::ostream& out) const override;
|
||||
|
||||
std::ostream& display_justification(std::ostream& out, sat::ext_justification_idx idx) const override { UNREACHABLE(); return out; }
|
||||
std::ostream& display_constraint(std::ostream& out, sat::ext_constraint_idx idx) const override { UNREACHABLE(); return out; }
|
||||
void add_value(euf::enode* n, model& mdl, expr_ref_vector& values) override;
|
||||
void add_dep(euf::enode* n, top_sort<euf::enode>& dep) override;
|
||||
void finalize_model(model& mdl) override;
|
||||
|
||||
bool unit_propagate() override { return false; }
|
||||
void get_antecedents(sat::literal l, sat::ext_justification_idx idx, sat::literal_vector& r, bool probing) override { UNREACHABLE(); }
|
||||
sat::check_result check() override { return sat::check_result::CR_DONE; }
|
||||
|
||||
euf::th_solver* clone(sat::solver*, euf::solver& ctx) { return alloc(solver, ctx); }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -86,6 +86,11 @@ namespace euf {
|
|||
\brief should function be included in model.
|
||||
*/
|
||||
virtual bool include_func_interp(func_decl* f) const { return false; }
|
||||
|
||||
/**
|
||||
\brief conclude model building
|
||||
*/
|
||||
virtual void finalize_model(model& mdl) {}
|
||||
};
|
||||
|
||||
class th_solver : public sat::extension, public th_model_builder, public th_decompile, public th_internalizer {
|
||||
|
|
Loading…
Reference in a new issue