mirror of
https://github.com/Z3Prover/z3
synced 2025-08-05 10:50:24 +00:00
Fixed renormalization in fp.mul. Relates to #872.
This commit is contained in:
parent
175f042db8
commit
a59907170d
2 changed files with 7 additions and 3 deletions
|
@ -1598,7 +1598,7 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
|
||||||
alignment_sticky_raw = m_bv_util.mk_extract(sbits-1, 0, shifted_big);
|
alignment_sticky_raw = m_bv_util.mk_extract(sbits-1, 0, shifted_big);
|
||||||
alignment_sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, alignment_sticky_raw.get());
|
alignment_sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, alignment_sticky_raw.get());
|
||||||
dbg_decouple("fpa2bv_fma_shifted_f_sig", shifted_f_sig);
|
dbg_decouple("fpa2bv_fma_shifted_f_sig", shifted_f_sig);
|
||||||
dbg_decouple("fpa2bv_fma_f_sig_alignment_stickyw", alignment_sticky);
|
dbg_decouple("fpa2bv_fma_f_sig_alignment_sticky", alignment_sticky);
|
||||||
SASSERT(is_well_sorted(m, alignment_sticky));
|
SASSERT(is_well_sorted(m, alignment_sticky));
|
||||||
SASSERT(m_bv_util.get_bv_size(shifted_f_sig) == 2 * sbits);
|
SASSERT(m_bv_util.get_bv_size(shifted_f_sig) == 2 * sbits);
|
||||||
SASSERT(is_well_sorted(m, shifted_f_sig));
|
SASSERT(is_well_sorted(m, shifted_f_sig));
|
||||||
|
@ -1677,7 +1677,8 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
|
||||||
// Renormalize
|
// Renormalize
|
||||||
expr_ref zero_e2(m), min_exp(m), sig_lz(m), max_exp_delta(m), sig_lz_capped(m), renorm_delta(m);
|
expr_ref zero_e2(m), min_exp(m), sig_lz(m), max_exp_delta(m), sig_lz_capped(m), renorm_delta(m);
|
||||||
zero_e2 = m_bv_util.mk_numeral(0, ebits + 2);
|
zero_e2 = m_bv_util.mk_numeral(0, ebits + 2);
|
||||||
mk_min_exp(ebits+2, min_exp);
|
mk_min_exp(ebits, min_exp);
|
||||||
|
min_exp = m_bv_util.mk_sign_extend(2, min_exp);
|
||||||
mk_leading_zeros(sig_abs, ebits+2, sig_lz);
|
mk_leading_zeros(sig_abs, ebits+2, sig_lz);
|
||||||
sig_lz = m_bv_util.mk_bv_sub(sig_lz, m_bv_util.mk_numeral(2, ebits+2));
|
sig_lz = m_bv_util.mk_bv_sub(sig_lz, m_bv_util.mk_numeral(2, ebits+2));
|
||||||
max_exp_delta = m_bv_util.mk_bv_sub(res_exp, min_exp);
|
max_exp_delta = m_bv_util.mk_bv_sub(res_exp, min_exp);
|
||||||
|
@ -1685,7 +1686,10 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
|
||||||
renorm_delta = m.mk_ite(m_bv_util.mk_sle(zero_e2, sig_lz_capped), sig_lz_capped, zero_e2);
|
renorm_delta = m.mk_ite(m_bv_util.mk_sle(zero_e2, sig_lz_capped), sig_lz_capped, zero_e2);
|
||||||
res_exp = m_bv_util.mk_bv_sub(res_exp, renorm_delta);
|
res_exp = m_bv_util.mk_bv_sub(res_exp, renorm_delta);
|
||||||
sig_abs = m_bv_util.mk_bv_shl(sig_abs, m_bv_util.mk_zero_extend(2*sbits-ebits, renorm_delta));
|
sig_abs = m_bv_util.mk_bv_shl(sig_abs, m_bv_util.mk_zero_extend(2*sbits-ebits, renorm_delta));
|
||||||
|
dbg_decouple("fpa2bv_fma_min_exp", min_exp);
|
||||||
|
dbg_decouple("fpa2bv_fma_max_exp_delta", max_exp_delta);
|
||||||
dbg_decouple("fpa2bv_fma_sig_lz", sig_lz);
|
dbg_decouple("fpa2bv_fma_sig_lz", sig_lz);
|
||||||
|
dbg_decouple("fpa2bv_fma_sig_lz_capped", sig_lz_capped);
|
||||||
dbg_decouple("fpa2bv_fma_renorm_delta", renorm_delta);
|
dbg_decouple("fpa2bv_fma_renorm_delta", renorm_delta);
|
||||||
|
|
||||||
unsigned too_short = 0;
|
unsigned too_short = 0;
|
||||||
|
|
|
@ -919,7 +919,7 @@ void mpf_manager::fma(mpf_rounding_mode rm, mpf const & x, mpf const & y, mpf co
|
||||||
|
|
||||||
mpf_exp_t min_exp = mk_min_exp(x.ebits);
|
mpf_exp_t min_exp = mk_min_exp(x.ebits);
|
||||||
unsigned sig_width = m_mpz_manager.prev_power_of_two(res.get().significand) + 1;
|
unsigned sig_width = m_mpz_manager.prev_power_of_two(res.get().significand) + 1;
|
||||||
mpf_exp_t sig_lz = 2 * x.sbits - sig_width; // want << lz
|
mpf_exp_t sig_lz = 2 * x.sbits - sig_width;
|
||||||
mpf_exp_t max_exp_delta = res.exponent() - min_exp;
|
mpf_exp_t max_exp_delta = res.exponent() - min_exp;
|
||||||
unsigned renorm_delta = (unsigned) std::max((mpf_exp_t)0, std::min(sig_lz, max_exp_delta));
|
unsigned renorm_delta = (unsigned) std::max((mpf_exp_t)0, std::min(sig_lz, max_exp_delta));
|
||||||
res.get().exponent -= renorm_delta;
|
res.get().exponent -= renorm_delta;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue