3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-08 12:11:23 +00:00

fpa2bv slight refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
This commit is contained in:
Christoph M. Wintersteiger 2015-01-02 18:59:27 +00:00
parent f684675a6e
commit 3266e96e80
2 changed files with 181 additions and 174 deletions

View file

@ -1873,7 +1873,7 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args
m_arith_util.is_numeral(args[1]) && m_arith_util.is_numeral(args[1]) &&
m_arith_util.is_numeral(args[2])) m_arith_util.is_numeral(args[2]))
{ {
// Three arguments, some of them are not numerals. // rm + real + int -> float
SASSERT(m_util.is_float(f->get_range())); SASSERT(m_util.is_float(f->get_range()));
unsigned ebits = m_util.get_ebits(f->get_range()); unsigned ebits = m_util.get_ebits(f->get_range());
unsigned sbits = m_util.get_sbits(f->get_range()); unsigned sbits = m_util.get_sbits(f->get_range());
@ -1938,14 +1938,25 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args
result); result);
} }
else if (num == 2 && else if (num == 2 &&
m_util.is_rm(args[0]) &&
is_app(args[1]) && is_app(args[1]) &&
m_util.is_float(m.get_sort(args[1]))) { m_util.is_float(m.get_sort(args[1]))) {
// We also support float to float conversion // float -> float conversion
sort * s = f->get_range(); mk_to_fp_float(f, f->get_range(), args[0], args[1], result);
expr_ref rm(m), x(m); }
rm = args[0]; else if (num == 2 &&
x = args[1]; m_util.is_rm(args[0]),
m_arith_util.is_real(args[1])) {
// rm + real -> float
mk_to_fp_real(f, f->get_range(), args[0], args[1], result);
}
else
UNREACHABLE();
SASSERT(is_well_sorted(m, result));
}
void fpa2bv_converter::mk_to_fp_float(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result) {
unsigned from_sbits = m_util.get_sbits(m.get_sort(x)); unsigned from_sbits = m_util.get_sbits(m.get_sort(x));
unsigned from_ebits = m_util.get_ebits(m.get_sort(x)); unsigned from_ebits = m_util.get_ebits(m.get_sort(x));
unsigned to_sbits = m_util.get_sbits(s); unsigned to_sbits = m_util.get_sbits(s);
@ -2000,13 +2011,11 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args
SASSERT(m_bv_util.get_bv_size(exp) == from_ebits); SASSERT(m_bv_util.get_bv_size(exp) == from_ebits);
SASSERT(m_bv_util.get_bv_size(lz) == from_ebits); SASSERT(m_bv_util.get_bv_size(lz) == from_ebits);
if (from_sbits < (to_sbits + 3)) if (from_sbits < (to_sbits + 3)) {
{
// make sure that sig has at least to_sbits + 3 // make sure that sig has at least to_sbits + 3
res_sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, to_sbits+3-from_sbits)); res_sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, to_sbits + 3 - from_sbits));
} }
else if (from_sbits > (to_sbits + 3)) else if (from_sbits >(to_sbits + 3)) {
{
// collapse the extra bits into a sticky bit. // collapse the extra bits into a sticky bit.
expr_ref sticky(m), low(m), high(m); expr_ref sticky(m), low(m), high(m);
low = m_bv_util.mk_extract(from_sbits - to_sbits - 3, 0, sig); low = m_bv_util.mk_extract(from_sbits - to_sbits - 3, 0, sig);
@ -2019,27 +2028,25 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args
res_sig = m_bv_util.mk_zero_extend(1, res_sig); // extra zero in the front for the rounder. res_sig = m_bv_util.mk_zero_extend(1, res_sig); // extra zero in the front for the rounder.
unsigned sig_sz = m_bv_util.get_bv_size(res_sig); unsigned sig_sz = m_bv_util.get_bv_size(res_sig);
SASSERT(sig_sz == to_sbits+4); SASSERT(sig_sz == to_sbits + 4);
expr_ref exponent_overflow(m); expr_ref exponent_overflow(m);
exponent_overflow = m.mk_false(); exponent_overflow = m.mk_false();
if (from_ebits < (to_ebits + 2)) if (from_ebits < (to_ebits + 2)) {
{ res_exp = m_bv_util.mk_sign_extend(to_ebits - from_ebits + 2, exp);
res_exp = m_bv_util.mk_sign_extend(to_ebits-from_ebits+2, exp);
// subtract lz for subnormal numbers. // subtract lz for subnormal numbers.
expr_ref lz_ext(m); expr_ref lz_ext(m);
lz_ext = m_bv_util.mk_zero_extend(to_ebits-from_ebits+2, lz); lz_ext = m_bv_util.mk_zero_extend(to_ebits - from_ebits + 2, lz);
res_exp = m_bv_util.mk_bv_sub(res_exp, lz_ext); res_exp = m_bv_util.mk_bv_sub(res_exp, lz_ext);
} }
else if (from_ebits > (to_ebits + 2)) else if (from_ebits >(to_ebits + 2)) {
{
expr_ref high(m), low(m), lows(m), high_red_or(m), high_red_and(m), h_or_eq(m), h_and_eq(m); expr_ref high(m), low(m), lows(m), high_red_or(m), high_red_and(m), h_or_eq(m), h_and_eq(m);
expr_ref no_ovf(m), zero1(m), s_is_one(m), s_is_zero(m); expr_ref no_ovf(m), zero1(m), s_is_one(m), s_is_zero(m);
high = m_bv_util.mk_extract(from_ebits - 1, to_ebits + 2, exp); high = m_bv_util.mk_extract(from_ebits - 1, to_ebits + 2, exp);
low = m_bv_util.mk_extract(to_ebits+1, 0, exp); low = m_bv_util.mk_extract(to_ebits + 1, 0, exp);
lows = m_bv_util.mk_extract(to_ebits+1, to_ebits+1, low); lows = m_bv_util.mk_extract(to_ebits + 1, to_ebits + 1, low);
high_red_or = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, high.get()); high_red_or = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, high.get());
high_red_and = m.mk_app(m_bv_util.get_fid(), OP_BREDAND, high.get()); high_red_and = m.mk_app(m_bv_util.get_fid(), OP_BREDAND, high.get());
@ -2058,8 +2065,8 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args
// subtract lz for subnormal numbers. // subtract lz for subnormal numbers.
expr_ref lz_ext(m), lz_rest(m), lz_redor(m), lz_redor_bool(m); expr_ref lz_ext(m), lz_rest(m), lz_redor(m), lz_redor_bool(m);
lz_ext = m_bv_util.mk_extract(to_ebits+1, 0, lz); lz_ext = m_bv_util.mk_extract(to_ebits + 1, 0, lz);
lz_rest = m_bv_util.mk_extract(from_ebits-1, to_ebits+2, lz); lz_rest = m_bv_util.mk_extract(from_ebits - 1, to_ebits + 2, lz);
lz_redor = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, lz_rest.get()); lz_redor = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, lz_rest.get());
m_simp.mk_eq(lz_redor, one1, lz_redor_bool); m_simp.mk_eq(lz_redor, one1, lz_redor_bool);
m_simp.mk_or(exponent_overflow, lz_redor_bool, exponent_overflow); m_simp.mk_or(exponent_overflow, lz_redor_bool, exponent_overflow);
@ -2069,14 +2076,14 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args
else // from_ebits == (to_ebits + 2) else // from_ebits == (to_ebits + 2)
res_exp = m_bv_util.mk_bv_sub(exp, lz); res_exp = m_bv_util.mk_bv_sub(exp, lz);
SASSERT(m_bv_util.get_bv_size(res_exp) == to_ebits+2); SASSERT(m_bv_util.get_bv_size(res_exp) == to_ebits + 2);
SASSERT(is_well_sorted(m, res_exp)); SASSERT(is_well_sorted(m, res_exp));
dbg_decouple("fpa2bv_to_float_res_sig", res_sig); dbg_decouple("fpa2bv_to_float_res_sig", res_sig);
dbg_decouple("fpa2bv_to_float_res_exp", res_exp); dbg_decouple("fpa2bv_to_float_res_exp", res_exp);
expr_ref rounded(m); expr_ref rounded(m);
round(s, rm, res_sgn, res_sig, res_exp, rounded); round(s, expr_ref (rm, m), res_sgn, res_sig, res_exp, rounded);
expr_ref is_neg(m), sig_inf(m); expr_ref is_neg(m), sig_inf(m);
m_simp.mk_eq(sgn, one1, is_neg); m_simp.mk_eq(sgn, one1, is_neg);
@ -2092,25 +2099,24 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args
mk_ite(c2, v2, result, result); mk_ite(c2, v2, result, result);
mk_ite(c1, v1, result, result); mk_ite(c1, v1, result, result);
} }
}
else if (num == 2 &&
m_util.is_rm(args[0]),
m_arith_util.is_real(args[1])) {
// .. other than that, we only support rationals for to_fp
SASSERT(m_util.is_float(f->get_range()));
unsigned ebits = m_util.get_ebits(f->get_range());
unsigned sbits = m_util.get_sbits(f->get_range());
SASSERT(m_bv_util.is_numeral(args[0])); SASSERT(is_well_sorted(m, result));
}
void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result) {
SASSERT(m_util.is_float(s));
unsigned ebits = m_util.get_ebits(s);
unsigned sbits = m_util.get_sbits(s);
if (m_bv_util.is_numeral(rm) && m_util.au().is_numeral(x)) {
rational tmp_rat; unsigned sz; rational tmp_rat; unsigned sz;
m_bv_util.is_numeral(to_expr(args[0]), tmp_rat, sz); m_bv_util.is_numeral(to_expr(rm), tmp_rat, sz);
SASSERT(tmp_rat.is_int32()); SASSERT(tmp_rat.is_int32());
SASSERT(sz == 3); SASSERT(sz == 3);
BV_RM_VAL bv_rm = (BV_RM_VAL)tmp_rat.get_unsigned(); BV_RM_VAL bv_rm = (BV_RM_VAL)tmp_rat.get_unsigned();
mpf_rounding_mode rm; mpf_rounding_mode rm;
switch (bv_rm) switch (bv_rm) {
{
case BV_RM_TIES_TO_AWAY: rm = MPF_ROUND_NEAREST_TAWAY; break; case BV_RM_TIES_TO_AWAY: rm = MPF_ROUND_NEAREST_TAWAY; break;
case BV_RM_TIES_TO_EVEN: rm = MPF_ROUND_NEAREST_TEVEN; break; case BV_RM_TIES_TO_EVEN: rm = MPF_ROUND_NEAREST_TEVEN; break;
case BV_RM_TO_NEGATIVE: rm = MPF_ROUND_TOWARD_NEGATIVE; break; case BV_RM_TO_NEGATIVE: rm = MPF_ROUND_TOWARD_NEGATIVE; break;
@ -2119,10 +2125,8 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args
default: UNREACHABLE(); default: UNREACHABLE();
} }
SASSERT(m_util.au().is_numeral(args[1]));
rational q; rational q;
m_util.au().is_numeral(args[1], q); m_util.au().is_numeral(x, q);
scoped_mpf v(m_mpf_manager); scoped_mpf v(m_mpf_manager);
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq()); m_util.fm().set(v, ebits, sbits, rm, q.to_mpq());
@ -2135,8 +2139,9 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args
mk_triple(sgn, s, e, result); mk_triple(sgn, s, e, result);
} }
else else {
UNREACHABLE(); NOT_IMPLEMENTED_YET();
}
SASSERT(is_well_sorted(m, result)); SASSERT(is_well_sorted(m, result));
} }

View file

@ -130,6 +130,8 @@ public:
void mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_fp_float(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result);
void mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result);
void mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);