Skip to content

Commit 9d57bdd

Browse files
Assorted fixes for floats (#6968)
* Improve 4be26eb * Add-on to 0f4f32c * Fix mk_numeral * Fix corner-case in fp.div * Fixes for corner-cases in mk_to_fp_(un)signed * Fix out-of-range results in mpf_manager::fma * Further adjustments for fp.to_fp_(un)signed * fp.to_fp from real can't be NaN * fp.to_fp from reals: add bounds * Fix NaN encodings in theory_fpa. * Fix fp.fma rounding with tiny floats * Fix literal creation order in theory_fpa
1 parent bd8e5ee commit 9d57bdd

File tree

6 files changed

+161
-89
lines changed

6 files changed

+161
-89
lines changed

src/ast/fpa/bv2fpa_converter.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ func_interp * bv2fpa_converter::convert_func_interp(model_core * mc, func_decl *
324324
expr_ref else_value(m.mk_app(to_bv_i, dom.size(), dom.data()), m);
325325
result->set_else(else_value);
326326
}
327-
else if (m_fpa_util.is_to_real(f)) {
327+
else if (m_fpa_util.is_to_real(f)) {
328328
SASSERT(dom.size() == 1);
329329
func_decl_ref to_real_i(m.mk_func_decl(fid, OP_FPA_TO_REAL_I, 0, nullptr, dom.size(), dom.data()), m);
330330
expr_ref else_value(m.mk_app(to_real_i, dom.size(), dom.data()), m);
@@ -508,7 +508,7 @@ void bv2fpa_converter::convert_uf2bvuf(model_core * mc, model_core * target_mode
508508
}
509509
}
510510

511-
TRACE("bv2fpa", tout << "Target model: " << *target_model; );
511+
TRACE("bv2fpa", tout << "Target model: " << *target_model << std::endl; );
512512
}
513513

514514
void bv2fpa_converter::display(std::ostream & out) {

src/ast/fpa/fpa2bv_converter.cpp

+100-62
Original file line numberDiff line numberDiff line change
@@ -147,36 +147,11 @@ void fpa2bv_converter::mk_distinct(func_decl * f, unsigned num, expr * const * a
147147

148148
void fpa2bv_converter::mk_numeral(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
149149
SASSERT(num == 0);
150-
sort* s = f->get_range();
151-
if (f->get_num_parameters() == 1) {
152-
SASSERT(f->get_parameter(0).is_external());
153-
unsigned p_id = f->get_parameter(0).get_ext_id();
154-
mpf const& v = m_plugin->get_value(p_id);
155-
mk_numeral(s, v, result);
156-
return;
157-
}
158-
scoped_mpf v(m_mpf_manager);
159-
unsigned ebits = m_util.get_ebits(s), sbits = m_util.get_sbits(s);
160-
switch (f->get_decl_kind()) {
161-
case OP_FPA_PLUS_INF:
162-
m_util.fm().mk_pinf(ebits, sbits, v);
163-
break;
164-
case OP_FPA_MINUS_INF:
165-
m_util.fm().mk_ninf(ebits, sbits, v);
166-
break;
167-
case OP_FPA_NAN:
168-
m_util.fm().mk_nan(ebits, sbits, v);
169-
break;
170-
case OP_FPA_PLUS_ZERO:
171-
m_util.fm().mk_pzero(ebits, sbits, v);
172-
break;
173-
case OP_FPA_MINUS_ZERO:
174-
m_util.fm().mk_nzero(ebits, sbits, v);
175-
break;
176-
default:
177-
UNREACHABLE();
178-
}
179-
mk_numeral(s, v, result);
150+
scoped_mpf v(m_mpf_manager);
151+
expr_ref a(m);
152+
a = m.mk_app(f, num, args);
153+
m_util.is_numeral(a, v);
154+
mk_numeral(f->get_range(), v, result);
180155
}
181156

182157
void fpa2bv_converter::mk_numeral(sort * s, mpf const & v, expr_ref & result) {
@@ -941,8 +916,8 @@ void fpa2bv_converter::mk_div(sort * s, expr_ref & rm, expr_ref & x, expr_ref &
941916
dbg_decouple("fpa2bv_div_y_is_pos", y_is_pos);
942917
dbg_decouple("fpa2bv_div_y_is_inf", y_is_inf);
943918

944-
expr_ref c1(m), c2(m), c3(m), c4(m), c5(m), c6(m), c7(m);
945-
expr_ref v1(m), v2(m), v3(m), v4(m), v5(m), v6(m), v7(m), v8(m);
919+
expr_ref c1(m), c2(m), c3(m), c4(m), c5(m), c6(m), c7(m), c8(m);
920+
expr_ref v1(m), v2(m), v3(m), v4(m), v5(m), v6(m), v7(m), v8(m), v9(m);
946921

947922
// (x is NaN) || (y is NaN) -> NaN
948923
m_simp.mk_or(x_is_nan, y_is_nan, c1);
@@ -998,6 +973,9 @@ void fpa2bv_converter::mk_div(sort * s, expr_ref & rm, expr_ref & x, expr_ref &
998973
a_sig_ext = m_bv_util.mk_concat(a_sig, m_bv_util.mk_numeral(0, sbits + extra_bits));
999974
b_sig_ext = m_bv_util.mk_zero_extend(sbits + extra_bits, b_sig);
1000975

976+
dbg_decouple("fpa2bv_div_a_sig_ext", a_sig_ext);
977+
dbg_decouple("fpa2bv_div_b_sig_ext", b_sig_ext);
978+
1001979
expr_ref a_exp_ext(m), b_exp_ext(m);
1002980
a_exp_ext = m_bv_util.mk_sign_extend(2, a_exp);
1003981
b_exp_ext = m_bv_util.mk_sign_extend(2, b_exp);
@@ -1017,14 +995,21 @@ void fpa2bv_converter::mk_div(sort * s, expr_ref & rm, expr_ref & x, expr_ref &
1017995
expr_ref quotient(m);
1018996
// b_sig_ext can't be 0 here, so it's safe to use OP_BUDIV_I
1019997
quotient = m.mk_app(m_bv_util.get_fid(), OP_BUDIV_I, a_sig_ext, b_sig_ext);
1020-
1021998
dbg_decouple("fpa2bv_div_quotient", quotient);
1022999

10231000
SASSERT(m_bv_util.get_bv_size(quotient) == (sbits + sbits + extra_bits));
10241001

1025-
expr_ref sticky(m);
1002+
expr_ref sticky(m), upper(m), upper_reduced(m), too_large(m);
10261003
sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, m_bv_util.mk_extract(extra_bits-2, 0, quotient));
10271004
res_sig = m_bv_util.mk_concat(m_bv_util.mk_extract(extra_bits+sbits+1, extra_bits-1, quotient), sticky);
1005+
upper = m_bv_util.mk_extract(sbits + sbits + extra_bits-1, extra_bits+sbits+2, quotient);
1006+
upper_reduced = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, upper.get());
1007+
too_large = m.mk_eq(upper_reduced, m_bv_util.mk_numeral(1, 1));
1008+
c8 = too_large;
1009+
mk_ite(signs_xor, ninf, pinf, v8);
1010+
dbg_decouple("fpa2bv_div_res_sig_p4", res_sig);
1011+
dbg_decouple("fpa2bv_div_upper", upper);
1012+
dbg_decouple("fpa2bv_div_too_large", too_large);
10281013

10291014
SASSERT(m_bv_util.get_bv_size(res_sig) == (sbits + 4));
10301015

@@ -1042,10 +1027,14 @@ void fpa2bv_converter::mk_div(sort * s, expr_ref & rm, expr_ref & x, expr_ref &
10421027
m_simp.mk_ite(shift_cond, res_sig, res_sig_shifted, res_sig);
10431028
m_simp.mk_ite(shift_cond, res_exp, res_exp_shifted, res_exp);
10441029

1045-
round(s, rm, res_sgn, res_sig, res_exp, v8);
1030+
dbg_decouple("fpa2bv_div_res_sig", res_sig);
1031+
dbg_decouple("fpa2bv_div_res_exp", res_exp);
1032+
1033+
round(s, rm, res_sgn, res_sig, res_exp, v9);
10461034

10471035
// And finally, we tie them together.
1048-
mk_ite(c7, v7, v8, result);
1036+
mk_ite(c8, v8, v9, result);
1037+
mk_ite(c7, v7, result, result);
10491038
mk_ite(c6, v6, result, result);
10501039
mk_ite(c5, v5, result, result);
10511040
mk_ite(c4, v4, result, result);
@@ -2809,8 +2798,46 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr *
28092798

28102799
expr * e = m.mk_eq(m_util.mk_to_real(result), x);
28112800
m_extra_assertions.push_back(e);
2812-
// x = 0 -> result = 0+
2813-
m_extra_assertions.push_back(m.mk_implies(m.mk_eq(x, zero), m.mk_eq(result, m_util.mk_pzero(result->get_sort()))));
2801+
2802+
expr_ref r_is_nan(m);
2803+
mk_is_nan(result, r_is_nan);
2804+
m_extra_assertions.push_back(m.mk_not(r_is_nan));
2805+
2806+
rational min_real, max_real;
2807+
const mpz& max_exp_z = m_mpf_manager.m_powers2.m1(ebits-1);
2808+
SASSERT(m_mpz_manager.is_uint(max_exp_z));
2809+
unsigned max_exp = m_mpz_manager.get_uint(max_exp_z);
2810+
rational max_sig = m_mpf_manager.m_powers2.m1(sbits) / m_mpf_manager.m_powers2(sbits-1);
2811+
max_real = max_sig * rational(m_mpf_manager.m_powers2(max_exp));
2812+
TRACE("fpa2bv_to_real", tout << "max exp: " << max_exp << " max real: " << max_real << std::endl;);
2813+
2814+
expr_ref r_is_pinf(m), r_is_ninf(m);
2815+
mk_is_pinf(result, r_is_pinf);
2816+
mk_is_ninf(result, r_is_ninf);
2817+
2818+
expr_ref e_max_real(m), e_max_real_neg(m);
2819+
e_max_real = m_arith_util.mk_numeral(max_real, false);
2820+
e_max_real_neg = m_arith_util.mk_numeral(-max_real, false);
2821+
2822+
expr_ref rm_nta(m), rm_nte(m), rm_tp(m), rm_tn(m), rm_tz(m);
2823+
mk_is_rm(bv_rm, BV_RM_TIES_TO_AWAY, rm_nta);
2824+
mk_is_rm(bv_rm, BV_RM_TIES_TO_EVEN, rm_nte);
2825+
mk_is_rm(bv_rm, BV_RM_TO_POSITIVE, rm_tp);
2826+
mk_is_rm(bv_rm, BV_RM_TO_NEGATIVE, rm_tn);
2827+
mk_is_rm(bv_rm, BV_RM_TO_ZERO, rm_tz);
2828+
2829+
expr_ref implies_gt_max_real(m), implies_lt_min_real(m);
2830+
implies_gt_max_real = m.mk_implies(r_is_pinf, m.mk_and(rm_tp, m_arith_util.mk_gt(x, e_max_real)));
2831+
implies_lt_min_real = m.mk_implies(r_is_ninf, m.mk_and(rm_tn, m_arith_util.mk_lt(x, e_max_real_neg)));
2832+
2833+
m_extra_assertions.push_back(implies_gt_max_real);
2834+
m_extra_assertions.push_back(implies_lt_min_real);
2835+
2836+
// x = 0 -> result = +0/-0
2837+
expr_ref pzero(m), nzero(m);
2838+
mk_pzero(result->get_sort(), pzero);
2839+
mk_nzero(result->get_sort(), nzero);
2840+
m_extra_assertions.push_back(m.mk_implies(m.mk_eq(x, zero), m.mk_or(m.mk_eq(result, pzero), m.mk_eq(result, nzero))));
28142841
}
28152842

28162843
SASSERT(is_well_sorted(m, result));
@@ -2854,19 +2881,13 @@ void fpa2bv_converter::mk_to_fp_real_int(func_decl * f, unsigned num, expr * con
28542881
m_mpf_manager.set(tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, e.to_mpq().numerator(), q.to_mpq());
28552882
m_mpf_manager.set(tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, e.to_mpq().numerator(), q.to_mpq());
28562883

2857-
app_ref a_nte(m), a_nta(m), a_tp(m), a_tn(m), a_tz(m);
2858-
a_nte = m_plugin->mk_numeral(nte);
2859-
a_nta = m_plugin->mk_numeral(nta);
2860-
a_tp = m_plugin->mk_numeral(tp);
2861-
a_tn = m_plugin->mk_numeral(tn);
2862-
a_tz = m_plugin->mk_numeral(tz);
2863-
28642884
expr_ref bv_nte(m), bv_nta(m), bv_tp(m), bv_tn(m), bv_tz(m);
2865-
mk_numeral(a_nte->get_decl(), 0, nullptr, bv_nte);
2866-
mk_numeral(a_nta->get_decl(), 0, nullptr, bv_nta);
2867-
mk_numeral(a_tp->get_decl(), 0, nullptr, bv_tp);
2868-
mk_numeral(a_tn->get_decl(), 0, nullptr, bv_tn);
2869-
mk_numeral(a_tz->get_decl(), 0, nullptr, bv_tz);
2885+
sort *s = f->get_range();
2886+
mk_numeral(s, nte, bv_nte);
2887+
mk_numeral(s, nta, bv_nta);
2888+
mk_numeral(s, tp, bv_tp);
2889+
mk_numeral(s, tn, bv_tn);
2890+
mk_numeral(s, tz, bv_tz);
28702891

28712892
expr_ref c1(m), c2(m), c3(m), c4(m);
28722893
c1 = m.mk_eq(bv_rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3));
@@ -3003,30 +3024,42 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const
30033024
unsigned bv_sz = m_bv_util.get_bv_size(x);
30043025
SASSERT(m_bv_util.get_bv_size(rm) == 3);
30053026

3027+
expr_ref rm_is_to_neg(m);
3028+
mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_is_to_neg);
3029+
30063030
expr_ref bv1_1(m), bv0_sz(m);
30073031
bv1_1 = m_bv_util.mk_numeral(1, 1);
30083032
bv0_sz = m_bv_util.mk_numeral(0, bv_sz);
30093033

3010-
expr_ref is_zero(m), pzero(m);
3034+
expr_ref is_zero(m), pzero(m), nzero(m);
30113035
is_zero = m.mk_eq(x, bv0_sz);
30123036
mk_pzero(f, pzero);
3037+
mk_nzero(f, nzero);
30133038

3014-
// Special case: x == 0 -> p/n zero
3039+
// Special case: x == 0 -> +zero
30153040
expr_ref c1(m), v1(m);
30163041
c1 = is_zero;
3017-
v1 = pzero;
3042+
v1 = pzero; // No -zero? zeros_consistent_4.smt2 requires +zero.
30183043

30193044
// Special case: x != 0
3020-
expr_ref is_neg_bit(m), exp_too_large(m), sig_4(m), exp_2(m);
3045+
expr_ref sign_bit(m), exp_too_large(m), sig_4(m), exp_2(m), rest(m);
30213046
expr_ref is_neg(m), x_abs(m), neg_x(m);
3022-
is_neg_bit = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, x);
3023-
is_neg = m.mk_eq(is_neg_bit, bv1_1);
3024-
neg_x = m_bv_util.mk_bv_neg(x); // overflow problem?
3047+
sign_bit = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, x);
3048+
rest = m_bv_util.mk_extract(bv_sz - 2, 0, x);
3049+
dbg_decouple("fpa2bv_to_fp_signed_rest", rest);
3050+
is_neg = m.mk_eq(sign_bit, bv1_1);
3051+
neg_x = m_bv_util.mk_bv_neg(x);
30253052
x_abs = m.mk_ite(is_neg, neg_x, x);
30263053
dbg_decouple("fpa2bv_to_fp_signed_is_neg", is_neg);
30273054
// x_abs has an extra bit in the front.
30283055
// x_abs is [bv_sz-1, bv_sz-2] . [bv_sz-3 ... 0] * 2^(bv_sz-2)
30293056
// bv_sz-2 is the "1.0" bit for the rounder.
3057+
expr_ref is_max_neg(m);
3058+
is_max_neg = m.mk_and(is_neg, m.mk_eq(rest, m_bv_util.mk_numeral(0, bv_sz-1)));
3059+
dbg_decouple("fpa2bv_to_fp_signed_is_max_neg", is_max_neg);
3060+
3061+
x_abs = m.mk_ite(is_max_neg, m_bv_util.mk_concat(bv1_1, m_bv_util.mk_numeral(0, bv_sz-1)), x_abs);
3062+
dbg_decouple("fpa2bv_to_fp_signed_x_abs", x_abs);
30303063

30313064
expr_ref lz(m);
30323065
mk_leading_zeros(x_abs, bv_sz, lz);
@@ -3061,6 +3094,7 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const
30613094
expr_ref s_exp(m), exp_rest(m);
30623095
s_exp = m_bv_util.mk_bv_sub(m_bv_util.mk_numeral(bv_sz - 2, bv_sz), lz);
30633096
// s_exp = (bv_sz-2) + (-lz) signed
3097+
s_exp = m.mk_ite(is_max_neg, m_bv_util.mk_bv_sub(s_exp, m_bv_util.mk_numeral(1, bv_sz)), s_exp);
30643098
SASSERT(m_bv_util.get_bv_size(s_exp) == bv_sz);
30653099
dbg_decouple("fpa2bv_to_fp_signed_s_exp", s_exp);
30663100

@@ -3093,7 +3127,7 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const
30933127
dbg_decouple("fpa2bv_to_fp_signed_exp_too_large", exp_too_large);
30943128

30953129
expr_ref sgn(m), sig(m), exp(m);
3096-
sgn = is_neg_bit;
3130+
sgn = sign_bit;
30973131
sig = sig_4;
30983132
exp = exp_2;
30993133

@@ -3132,6 +3166,9 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con
31323166
rm = to_app(args[0])->get_arg(0);
31333167
x = args[1];
31343168

3169+
expr_ref rm_is_to_neg(m);
3170+
mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_is_to_neg);
3171+
31353172
dbg_decouple("fpa2bv_to_fp_unsigned_x", x);
31363173

31373174
unsigned ebits = m_util.get_ebits(f->get_range());
@@ -3143,14 +3180,15 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con
31433180
bv0_1 = m_bv_util.mk_numeral(0, 1);
31443181
bv0_sz = m_bv_util.mk_numeral(0, bv_sz);
31453182

3146-
expr_ref is_zero(m), pzero(m);
3183+
expr_ref is_zero(m), pzero(m), nzero(m);
31473184
is_zero = m.mk_eq(x, bv0_sz);
31483185
mk_pzero(f, pzero);
3186+
mk_nzero(f, nzero);
31493187

3150-
// Special case: x == 0 -> p/n zero
3188+
// Special case: x == 0 -> +zero
31513189
expr_ref c1(m), v1(m);
31523190
c1 = is_zero;
3153-
v1 = pzero;
3191+
v1 = pzero; // No nzero?
31543192

31553193
// Special case: x != 0
31563194
expr_ref exp_too_large(m), sig_4(m), exp_2(m);
@@ -3194,7 +3232,7 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con
31943232
unsigned exp_sz = ebits + 2; // (+2 for rounder)
31953233
exp_2 = m_bv_util.mk_extract(exp_sz - 1, 0, s_exp);
31963234
// the remaining bits are 0 if ebits is large enough.
3197-
exp_too_large = m.mk_false(); // This is always in range.
3235+
exp_too_large = m.mk_false();
31983236

31993237
// The exponent is at most bv_sz, i.e., we need ld(bv_sz)+1 ebits.
32003238
// exp < bv_sz (+sign bit which is [0])

src/ast/fpa/fpa2bv_converter.h

+1
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ class fpa2bv_converter {
208208

209209
private:
210210
void mk_nan(sort * s, expr_ref & result);
211+
211212
void mk_nzero(sort * s, expr_ref & result);
212213
void mk_pzero(sort * s, expr_ref & result);
213214
void mk_zero(sort * s, expr_ref & sgn, expr_ref & result);

src/smt/theory_fpa.cpp

+31-3
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ namespace smt {
220220
TRACE("t_fpa_detail", tout << "asserting " << mk_ismt2_pp(e, m) << "\n";);
221221
if (m.has_trace_stream()) log_axiom_instantiation(e);
222222
ctx.internalize(e, false);
223-
if (m.has_trace_stream()) m.trace_stream() << "[end-of-instance]\n";
223+
if (m.has_trace_stream()) m.trace_stream() << "[end-of-instance]\n";
224224
literal lit(ctx.get_literal(e));
225225
ctx.mark_as_relevant(lit);
226226
ctx.mk_th_axiom(get_id(), 1, &lit);
@@ -239,11 +239,11 @@ namespace smt {
239239
if (ctx.b_internalized(atom))
240240
return true;
241241

242-
ctx.internalize(atom->get_args(), atom->get_num_args(), false);
243-
244242
literal l(ctx.mk_bool_var(atom));
245243
ctx.set_var_theory(l.var(), get_id());
246244

245+
ctx.internalize(atom->get_args(), atom->get_num_args(), false);
246+
247247
expr_ref bv_atom(m_rw.convert_atom(m_th_rw, atom));
248248
expr_ref bv_atom_w_side_c(m), atom_eq(m);
249249
bv_atom_w_side_c = m.mk_and(bv_atom, mk_side_conditions());
@@ -253,6 +253,18 @@ namespace smt {
253253
return true;
254254
}
255255

256+
void theory_fpa::mk_bv_nan(sort * s, expr_ref & result) {
257+
SASSERT(m_fpa_util.is_float(s));
258+
unsigned sbits = m_fpa_util.get_sbits(s);
259+
unsigned ebits = m_fpa_util.get_ebits(s);
260+
expr_ref exp(m), sgn(m), sig(m);
261+
exp = m_bv_util.mk_numeral(m_fpa_util.fm().m_powers2.m1(ebits), ebits);
262+
sgn = m_bv_util.mk_numeral(0, 1);
263+
sig = m_bv_util.mk_numeral(1, sbits - 1);
264+
expr * args[3] = {sgn, exp, sig};
265+
result = m_bv_util.mk_concat(3, args);
266+
}
267+
256268
bool theory_fpa::internalize_term(app * term) {
257269
TRACE("t_fpa_internalize", tout << "internalizing term: " << mk_ismt2_pp(term, m) << "\n";);
258270
SASSERT(term->get_family_id() == get_family_id());
@@ -286,6 +298,22 @@ namespace smt {
286298
default: /* ignore */;
287299
}
288300

301+
expr * owner = e->get_expr();
302+
sort * s = owner->get_sort();
303+
if (m_fpa_util.is_float(s))
304+
{
305+
TRACE("t_fpa", tout << "extra nan constraint for: " << mk_ismt2_pp(owner, m) << "\n";);
306+
expr_ref wrapped(m), is_nan(m), bv_nan(m);
307+
app_ref impl(m);
308+
wrapped = m_converter.wrap(owner);
309+
is_nan = m_fpa_util.mk_is_nan(owner);
310+
mk_bv_nan(s, bv_nan);
311+
impl = m.mk_or(m.mk_and(is_nan, m.mk_eq(wrapped, bv_nan)),
312+
m.mk_and(m.mk_not(is_nan), m.mk_not(m.mk_eq(wrapped, bv_nan))));
313+
assert_cnstr(impl);
314+
assert_cnstr(mk_side_conditions());
315+
}
316+
289317
if (!ctx.relevancy())
290318
relevant_eh(term);
291319
}

src/smt/theory_fpa.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,11 @@ namespace smt {
121121
void attach_new_th_var(enode * n);
122122
void assert_cnstr(expr * e);
123123

124-
125124
enode* ensure_enode(expr* e);
126125
enode* get_root(expr* a) { return ensure_enode(a)->get_root(); }
127126
app* get_ite_value(expr* e);
127+
128+
void mk_bv_nan(sort * s, expr_ref & result);
128129
};
129130

130131
};

0 commit comments

Comments
 (0)