Skip to content

Commit 892aa12

Browse files
author
Christoph M. Wintersteiger
committed
Fix for fp.rem. Fixes #2381.
1 parent 0edd587 commit 892aa12

File tree

1 file changed

+36
-45
lines changed

1 file changed

+36
-45
lines changed

src/ast/fpa/fpa2bv_converter.cpp

Lines changed: 36 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,78 +1122,69 @@ void fpa2bv_converter::mk_rem(sort * s, expr_ref & x, expr_ref & y, expr_ref & r
11221122
a_lz_ext = m_bv_util.mk_zero_extend(2, a_lz);
11231123
b_lz_ext = m_bv_util.mk_zero_extend(2, b_lz);
11241124

1125-
expr_ref exp_diff(m), neg_exp_diff(m), exp_diff_is_neg(m), exp_diff_ge_zero(m);
1125+
expr_ref exp_diff(m), neg_exp_diff(m), exp_diff_is_neg(m), exp_diff_ge_zero(m), exp_diff_is_zero(m);
11261126
exp_diff = m_bv_util.mk_bv_sub(
11271127
m_bv_util.mk_bv_sub(a_exp_ext, a_lz_ext),
11281128
m_bv_util.mk_bv_sub(b_exp_ext, b_lz_ext));
11291129
neg_exp_diff = m_bv_util.mk_bv_neg(exp_diff);
11301130
exp_diff_is_neg = m_bv_util.mk_sle(exp_diff, m_bv_util.mk_numeral(0, ebits+2));
1131+
exp_diff_is_zero = m.mk_eq(exp_diff, m_bv_util.mk_numeral(0, ebits+2));
11311132
exp_diff_ge_zero = m_bv_util.mk_sle(m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(exp_diff)), exp_diff);
11321133
dbg_decouple("fpa2bv_rem_exp_diff", exp_diff);
11331134

11341135
// CMW: This creates _huge_ bit-vectors, which is potentially sub-optimal,
11351136
// but calculating this via rem = x - y * nearest(x/y) creates huge
11361137
// circuits, too. Lazy instantiation seems the way to go in the long run
11371138
// (using the lazy bit-blaster helps on simple instances).
1138-
expr_ref a_sig_ext(m), b_sig_ext(m), lshift(m), rshift(m), shifted(m), huge_rem(m);
1139+
expr_ref a_sig_ext(m), b_sig_ext(m), lshift(m), rshift(m), shifted(m), huge_rem(m), huge_div(m), huge_div_is_even(m);
11391140
a_sig_ext = m_bv_util.mk_concat(m_bv_util.mk_zero_extend(max_exp_diff_ui, a_sig), m_bv_util.mk_numeral(0, 3));
11401141
b_sig_ext = m_bv_util.mk_concat(m_bv_util.mk_zero_extend(max_exp_diff_ui, b_sig), m_bv_util.mk_numeral(0, 3));
11411142
lshift = m_bv_util.mk_zero_extend(max_exp_diff_ui + sbits - (ebits+2) + 3, exp_diff);
11421143
rshift = m_bv_util.mk_zero_extend(max_exp_diff_ui + sbits - (ebits+2) + 3, neg_exp_diff);
11431144
shifted = m.mk_ite(exp_diff_is_neg, m_bv_util.mk_bv_ashr(a_sig_ext, rshift),
11441145
m_bv_util.mk_bv_shl(a_sig_ext, lshift));
11451146
huge_rem = m_bv_util.mk_bv_urem(shifted, b_sig_ext);
1147+
huge_div = m.mk_app(m_bv_util.get_fid(), OP_BUDIV_I, shifted, b_sig_ext);
1148+
huge_div_is_even = m.mk_eq(m_bv_util.mk_extract(0, 0, huge_div), m_bv_util.mk_numeral(0, 1));
1149+
dbg_decouple("fpa2bv_rem_exp_diff_is_neg", exp_diff_is_neg);
1150+
dbg_decouple("fpa2bv_rem_lshift", lshift);
1151+
dbg_decouple("fpa2bv_rem_rshift", rshift);
11461152
dbg_decouple("fpa2bv_rem_huge_rem", huge_rem);
1153+
dbg_decouple("fpa2bv_rem_huge_div", huge_div);
11471154

1148-
expr_ref rndd_sgn(m), rndd_exp(m), rndd_sig(m), rne_bv(m), rndd(m);
1155+
expr_ref rndd_sgn(m), rndd_exp(m), rndd_sig(m), rne_bv(m), rndd_sig_lz(m);
11491156
rndd_sgn = a_sgn;
11501157
rndd_exp = m_bv_util.mk_bv_sub(b_exp_ext, b_lz_ext);
11511158
rndd_sig = m_bv_util.mk_extract(sbits+3, 0, huge_rem);
11521159
rne_bv = m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3);
1153-
round(s, rne_bv, rndd_sgn, rndd_sig, rndd_exp, rndd);
1154-
1155-
expr_ref y_half(m), ny_half(m), zero_e(m), two_e(m);
1156-
expr_ref y_half_is_zero(m), y_half_is_nz(m);
1157-
expr_ref r_ge_y_half(m), r_gt_ny_half(m), r_le_y_half(m), r_lt_ny_half(m);
1158-
expr_ref r_ge_zero(m), r_le_zero(m);
1159-
expr_ref rounded_sub_y(m), rounded_add_y(m);
1160-
mpf zero, two;
1161-
m_mpf_manager.set(two, ebits, sbits, 2);
1162-
m_mpf_manager.set(zero, ebits, sbits, 0);
1163-
mk_numeral(s, two, two_e);
1164-
mk_numeral(s, zero, zero_e);
1165-
mk_div(s, rne_bv, y, two_e, y_half);
1166-
mk_neg(s, y_half, ny_half);
1167-
mk_is_zero(y_half, y_half_is_zero);
1168-
y_half_is_nz = m.mk_not(y_half_is_zero);
1169-
1170-
mk_float_ge(s, rndd, y_half, r_ge_y_half);
1171-
mk_float_gt(s, rndd, ny_half, r_gt_ny_half);
1172-
mk_float_le(s, rndd, y_half, r_le_y_half);
1173-
mk_float_lt(s, rndd, ny_half, r_lt_ny_half);
1174-
1175-
mk_sub(s, rne_bv, rndd, y, rounded_sub_y);
1176-
mk_add(s, rne_bv, rndd, y, rounded_add_y);
1177-
1178-
expr_ref sub_cnd(m), add_cnd(m);
1179-
sub_cnd = m.mk_and(exp_diff_ge_zero,
1180-
m.mk_and(y_half_is_nz,
1181-
m.mk_or(m.mk_and(y_is_pos, r_ge_y_half),
1182-
m.mk_and(y_is_neg, r_le_y_half))));
1183-
add_cnd = m.mk_and(exp_diff_ge_zero,
1184-
m.mk_and(y_half_is_nz,
1185-
m.mk_or(m.mk_and(y_is_pos, r_lt_ny_half),
1186-
m.mk_and(y_is_neg, r_gt_ny_half))));
1187-
1188-
dbg_decouple("fpa2bv_rem_y_half", y_half);
1160+
mk_leading_zeros(rndd_sig, ebits+2, rndd_sig_lz);
1161+
dbg_decouple("fpa2bv_rem_rndd_sig", rndd_sig);
1162+
dbg_decouple("fpa2bv_rem_rndd_sig_lz", rndd_sig_lz);
1163+
1164+
SASSERT(m_bv_util.get_bv_size(rndd_exp) == ebits+2);
1165+
SASSERT(m_bv_util.get_bv_size(y_exp_m1) == ebits);
1166+
1167+
expr_ref rndd_exp_eq_y_exp_m1(m), y_sig_le_rndd_sig(m);
1168+
rndd_exp_eq_y_exp_m1 = m.mk_eq(rndd_sig_lz, m_bv_util.mk_numeral(2, ebits+2));
1169+
dbg_decouple("fpa2bv_rem_rndd_exp_eq_y_exp_m1", rndd_exp_eq_y_exp_m1);
1170+
1171+
expr_ref y_sig_ext(m), y_sig_eq_rndd_sig(m);
1172+
y_sig_ext = m_bv_util.mk_concat(m_bv_util.mk_zero_extend(2, b_sig), m_bv_util.mk_numeral(0, 2));
1173+
y_sig_le_rndd_sig = m_bv_util.mk_sle(y_sig_ext, rndd_sig);
1174+
y_sig_eq_rndd_sig = m.mk_eq(y_sig_ext, rndd_sig);
1175+
dbg_decouple("fpa2bv_rem_y_sig_ext", y_sig_ext);
1176+
dbg_decouple("fpa2bv_rem_y_sig_le_rndd_sig", y_sig_le_rndd_sig);
1177+
dbg_decouple("fpa2bv_rem_y_sig_eq_rndd_sig", y_sig_eq_rndd_sig);
1178+
1179+
expr_ref sub_cnd(m);
1180+
sub_cnd = m.mk_or(m.mk_and(rndd_exp_eq_y_exp_m1, y_sig_le_rndd_sig, m.mk_not(y_sig_eq_rndd_sig)),
1181+
m.mk_and(rndd_exp_eq_y_exp_m1, y_sig_eq_rndd_sig, m.mk_not(huge_div_is_even)));
11891182
dbg_decouple("fpa2bv_rem_sub_cnd", sub_cnd);
1190-
dbg_decouple("fpa2bv_rem_add_cnd", add_cnd);
1191-
dbg_decouple("fpa2bv_rem_rounded_add_y", rounded_add_y);
1192-
dbg_decouple("fpa2bv_rem_rounded_sub_y", rounded_sub_y);
1193-
dbg_decouple("fpa2bv_rem_rndd", rndd);
11941183

1195-
mk_ite(add_cnd, rounded_add_y, rndd, v7);
1196-
mk_ite(sub_cnd, rounded_sub_y, v7, v7);
1184+
expr_ref rndd(m), rounded_sub_y(m), rounded_add_y(m);
1185+
round(s, rne_bv, rndd_sgn, rndd_sig, rndd_exp, rndd);
1186+
mk_sub(s, rne_bv, rndd, y, rounded_sub_y);
1187+
mk_ite(sub_cnd, rounded_sub_y, rndd, v7);
11971188

11981189
// And finally, we tie them together.
11991190
mk_ite(c6, v6, v7, result);

0 commit comments

Comments
 (0)