mirror of
https://github.com/Z3Prover/z3
synced 2025-04-27 02:45:51 +00:00
Corrected unspecified behavior of corner cases in fp.min/fp.max.
Partially addresses #68.
This commit is contained in:
parent
6e852762ba
commit
8a026c355f
10 changed files with 211 additions and 55 deletions
|
@ -1088,16 +1088,55 @@ void fpa2bv_converter::mk_min(func_decl * f, unsigned num, expr * const * args,
|
|||
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;);
|
||||
|
||||
result = y;
|
||||
mk_ite(lt, x, result, result);
|
||||
mk_ite(both_zero, y, result, result);
|
||||
mk_ite(m.mk_and(both_zero, sgn_diff), pzero, result, result); // min(-0.0, +0.0) = min(+0.0, -0.0) = +0.0
|
||||
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);
|
||||
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
expr_ref fpa2bv_converter::mk_min_unspecified(func_decl * f, expr * x, expr * y) {
|
||||
unsigned ebits = m_util.get_ebits(f->get_range());
|
||||
unsigned sbits = m_util.get_sbits(f->get_range());
|
||||
expr_ref res(m);
|
||||
|
||||
// The only cases in which min is unspecified for is when the arguments are +0.0 and -0.0.
|
||||
|
||||
if (m_hi_fp_unspecified)
|
||||
// The hardware interpretation is -0.0.
|
||||
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());
|
||||
|
||||
expr_ref pn(m), np(m);
|
||||
mk_fp(pn_nondet,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
pn);
|
||||
mk_fp(np_nondet,
|
||||
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);
|
||||
mk_ite(m.mk_and(x_is_pzero, x_is_nzero), pn, np, res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
|
||||
|
@ -1121,17 +1160,55 @@ 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), pzero, result, result); // max(-0.0, +0.0) = max(+0.0, -0.0) = +0.0
|
||||
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);
|
||||
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
expr_ref fpa2bv_converter::mk_max_unspecified(func_decl * f, expr * x, expr * y) {
|
||||
unsigned ebits = m_util.get_ebits(f->get_range());
|
||||
unsigned sbits = m_util.get_sbits(f->get_range());
|
||||
expr_ref res(m);
|
||||
|
||||
// The only cases in which max is unspecified for is when the arguments are +0.0 and -0.0.
|
||||
|
||||
if (m_hi_fp_unspecified)
|
||||
// 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());
|
||||
|
||||
expr_ref pn(m), np(m);
|
||||
mk_fp(pn_nondet,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
pn);
|
||||
mk_fp(np_nondet,
|
||||
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);
|
||||
mk_ite(m.mk_and(x_is_pzero, x_is_nzero), pn, np, res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 4);
|
||||
|
||||
|
|
|
@ -55,7 +55,8 @@ protected:
|
|||
|
||||
obj_map<func_decl, expr*> m_const2bv;
|
||||
obj_map<func_decl, expr*> m_rm_const2bv;
|
||||
obj_map<func_decl, func_decl*> m_uf2bvuf;
|
||||
obj_map<func_decl, func_decl*> m_uf2bvuf;
|
||||
obj_hashtable<func_decl> m_decls_to_hide;
|
||||
|
||||
public:
|
||||
fpa2bv_converter(ast_manager & m);
|
||||
|
@ -136,13 +137,16 @@ public:
|
|||
void mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
|
||||
void set_unspecified_fp_hi(bool v) { m_hi_fp_unspecified = v; }
|
||||
expr_ref mk_min_unspecified(func_decl * f, expr * x, expr * y);
|
||||
expr_ref mk_max_unspecified(func_decl * f, expr * x, expr * y);
|
||||
expr_ref mk_to_ubv_unspecified(unsigned width);
|
||||
expr_ref mk_to_sbv_unspecified(unsigned width);
|
||||
expr_ref mk_to_real_unspecified();
|
||||
|
||||
obj_map<func_decl, expr*> const & const2bv() const { return m_const2bv; }
|
||||
obj_map<func_decl, expr*> const & rm_const2bv() const { return m_rm_const2bv; }
|
||||
obj_map<func_decl, func_decl*> const & uf2bvuf() const { return m_uf2bvuf; }
|
||||
obj_map<func_decl, func_decl*> const & uf2bvuf() const { return m_uf2bvuf; }
|
||||
obj_hashtable<func_decl> const & decls_to_hide() const { return m_decls_to_hide; }
|
||||
|
||||
void reset(void);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
def_module_params(module_name='rewriter',
|
||||
class_name='fpa2bv_rewriter_params',
|
||||
export=True,
|
||||
params=(("hi_fp_unspecified", BOOL, True, "use the 'hardware interpretation' for unspecified values in fp.to_ubv, fp.to_sbv, and fp.to_real"),
|
||||
params=(("hi_fp_unspecified", BOOL, False, "use the 'hardware interpretation' for unspecified values in fp.min, fp.max, fp.to_ubv, fp.to_sbv, and fp.to_real"),
|
||||
))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue