mirror of
https://github.com/Z3Prover/z3
synced 2025-04-27 02:45:51 +00:00
Partial fix for fp,min/fp.max models
This commit is contained in:
parent
e3ed0159a8
commit
099775947e
9 changed files with 115 additions and 148 deletions
|
@ -35,7 +35,11 @@ fpa2bv_converter::fpa2bv_converter(ast_manager & m) :
|
|||
m_arith_util(m),
|
||||
m_mpf_manager(m_util.fm()),
|
||||
m_mpz_manager(m_mpf_manager.mpz_manager()),
|
||||
m_hi_fp_unspecified(true),
|
||||
m_hi_fp_unspecified(true),
|
||||
m_min_pn_zeros(0, m),
|
||||
m_min_np_zeros(0, m),
|
||||
m_max_pn_zeros(0, m),
|
||||
m_max_np_zeros(0, m),
|
||||
m_extra_assertions(m) {
|
||||
m_plugin = static_cast<fpa_decl_plugin*>(m.get_plugin(m.mk_family_id("fpa")));
|
||||
}
|
||||
|
@ -1064,7 +1068,7 @@ void fpa2bv_converter::mk_abs(func_decl * f, unsigned num, expr * const * args,
|
|||
mk_fp(m_bv_util.mk_numeral(0, 1), e, s, result);
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_min(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
void fpa2bv_converter::mk_min_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
|
||||
expr * x = args[0], * y = args[1];
|
||||
|
@ -1086,16 +1090,11 @@ void fpa2bv_converter::mk_min(func_decl * f, unsigned num, expr * const * args,
|
|||
sgn_diff = m.mk_not(m.mk_eq(x_sgn, y_sgn));
|
||||
|
||||
expr_ref lt(m);
|
||||
mk_float_lt(f, num, args, lt);
|
||||
|
||||
expr_ref zz(m);
|
||||
zz = mk_min_unspecified(f, x, y);
|
||||
TRACE("fpa2bv", tout << "min = " << mk_ismt2_pp(zz, m) << std::endl;);
|
||||
mk_float_lt(f, num, args, lt);
|
||||
|
||||
result = y;
|
||||
mk_ite(lt, x, result, result);
|
||||
mk_ite(both_zero, y, result, result);
|
||||
mk_ite(m.mk_and(both_zero, sgn_diff), zz, result, result);
|
||||
mk_ite(y_is_nan, x, result, result);
|
||||
mk_ite(x_is_nan, y, result, result);
|
||||
|
||||
|
@ -1111,33 +1110,40 @@ expr_ref fpa2bv_converter::mk_min_unspecified(func_decl * f, expr * x, expr * y)
|
|||
|
||||
if (m_hi_fp_unspecified)
|
||||
// The hardware interpretation is -0.0.
|
||||
mk_nzero(f, res);
|
||||
mk_nzero(f, res);
|
||||
else {
|
||||
app_ref pn_nondet(m), np_nondet(m);
|
||||
pn_nondet = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
np_nondet = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
m_decls_to_hide.insert(pn_nondet->get_decl());
|
||||
m_decls_to_hide.insert(np_nondet->get_decl());
|
||||
if (m_min_pn_zeros.get() == 0) m_min_pn_zeros = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
if (m_min_np_zeros.get() == 0) m_min_np_zeros = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
|
||||
expr_ref pn(m), np(m);
|
||||
mk_fp(pn_nondet,
|
||||
mk_fp(m_min_pn_zeros,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
pn);
|
||||
mk_fp(np_nondet,
|
||||
mk_fp(m_min_np_zeros,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
np);
|
||||
expr_ref x_is_pzero(m), x_is_nzero(m);
|
||||
|
||||
expr_ref x_is_pzero(m), x_is_nzero(m), ite(m);
|
||||
mk_is_pzero(x, x_is_pzero);
|
||||
mk_is_nzero(y, x_is_nzero);
|
||||
mk_ite(m.mk_and(x_is_pzero, x_is_nzero), pn, np, res);
|
||||
mk_ite(m.mk_and(x_is_pzero, x_is_nzero), pn, np, ite);
|
||||
|
||||
expr * args[] = { x, y };
|
||||
mk_uninterpreted_function(f, 2, args, res);
|
||||
|
||||
expr_ref pzero(m), nzero(m), extra(m);
|
||||
mk_pzero(f, pzero);
|
||||
mk_nzero(f, nzero);
|
||||
extra = m.mk_or(m.mk_eq(ite, pzero), m.mk_eq(ite, nzero));
|
||||
m_extra_assertions.push_back(extra);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
void fpa2bv_converter::mk_max_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
|
||||
expr * x = args[0], *y = args[1];
|
||||
|
@ -1160,14 +1166,10 @@ void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args,
|
|||
|
||||
expr_ref gt(m);
|
||||
mk_float_gt(f, num, args, gt);
|
||||
|
||||
expr_ref zz(m);
|
||||
zz = mk_max_unspecified(f, x, y);
|
||||
|
||||
|
||||
result = y;
|
||||
mk_ite(gt, x, result, result);
|
||||
mk_ite(both_zero, y, result, result);
|
||||
mk_ite(m.mk_and(both_zero, sgn_diff), zz, result, result);
|
||||
mk_ite(both_zero, y, result, result);
|
||||
mk_ite(y_is_nan, x, result, result);
|
||||
mk_ite(x_is_nan, y, result, result);
|
||||
|
||||
|
@ -1185,21 +1187,19 @@ expr_ref fpa2bv_converter::mk_max_unspecified(func_decl * f, expr * x, expr * y)
|
|||
// The hardware interpretation is +0.0.
|
||||
mk_pzero(f, res);
|
||||
else {
|
||||
app_ref pn_nondet(m), np_nondet(m);
|
||||
pn_nondet = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
np_nondet = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
m_decls_to_hide.insert(pn_nondet->get_decl());
|
||||
m_decls_to_hide.insert(np_nondet->get_decl());
|
||||
if (m_max_pn_zeros.get() == 0) m_max_pn_zeros = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
if (m_max_np_zeros.get() == 0) m_max_np_zeros = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
|
||||
expr_ref pn(m), np(m);
|
||||
mk_fp(pn_nondet,
|
||||
mk_fp(m_max_pn_zeros,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
pn);
|
||||
mk_fp(np_nondet,
|
||||
mk_fp(m_max_np_zeros,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
np);
|
||||
|
||||
expr_ref x_is_pzero(m), x_is_nzero(m);
|
||||
mk_is_pzero(x, x_is_pzero);
|
||||
mk_is_nzero(y, x_is_nzero);
|
||||
|
|
|
@ -57,6 +57,11 @@ protected:
|
|||
obj_map<func_decl, expr*> m_rm_const2bv;
|
||||
obj_map<func_decl, func_decl*> m_uf2bvuf;
|
||||
obj_hashtable<func_decl> m_decls_to_hide;
|
||||
|
||||
app_ref m_min_pn_zeros;
|
||||
app_ref m_min_np_zeros;
|
||||
app_ref m_max_pn_zeros;
|
||||
app_ref m_max_np_zeros;
|
||||
|
||||
public:
|
||||
fpa2bv_converter(ast_manager & m);
|
||||
|
@ -102,8 +107,8 @@ public:
|
|||
void mk_div(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_rem(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_abs(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_min(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_min_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_max_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_fma(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_sqrt(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_round_to_integral(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
|
|
|
@ -141,9 +141,7 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
|
|||
case OP_FPA_MUL: m_conv.mk_mul(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE;
|
||||
|
@ -166,8 +164,16 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
|
|||
case OP_FPA_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
|
||||
|
||||
case OP_FPA_MIN:
|
||||
case OP_FPA_MAX:
|
||||
throw rewriter_exception("operator is not supported, you must simplify the goal before applying fpa2bv");
|
||||
|
||||
case OP_FPA_INTERNAL_MIN_UNSPECIFIED: result = m_conv.mk_min_unspecified(f, args[0], args[1]); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_MAX_UNSPECIFIED: result = m_conv.mk_max_unspecified(f, args[0], args[1]); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_MIN_I: m_conv.mk_min_i(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_MAX_I: m_conv.mk_max_i(f, num, args, result); return BR_DONE;
|
||||
|
||||
case OP_FPA_INTERNAL_BVWRAP:
|
||||
case OP_FPA_INTERNAL_BVUNWRAP:
|
||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue