1 /*++
2 Copyright (c) 2012 Microsoft Corporation
3 
4 Module Name:
5 
6     fpa_decl_plugin.cpp
7 
8 Abstract:
9 
10     Floating point decl plugin
11 
12 Author:
13 
14     Leonardo de Moura (leonardo) 2012-01-15.
15 
16 Revision History:
17 
18 --*/
19 #include "ast/fpa_decl_plugin.h"
20 #include "ast/arith_decl_plugin.h"
21 #include "ast/bv_decl_plugin.h"
22 #include "ast/ast_smt2_pp.h"
23 
fpa_decl_plugin()24 fpa_decl_plugin::fpa_decl_plugin():
25     m_values(m_fm),
26     m_value_table(mpf_hash_proc(m_values), mpf_eq_proc(m_values)) {
27     m_real_sort = nullptr;
28     m_int_sort  = nullptr;
29     m_bv_plugin = nullptr;
30 }
31 
set_manager(ast_manager * m,family_id id)32 void fpa_decl_plugin::set_manager(ast_manager * m, family_id id) {
33     decl_plugin::set_manager(m, id);
34 
35     m_arith_fid = m_manager->mk_family_id("arith");
36     m_real_sort = m_manager->mk_sort(m_arith_fid, REAL_SORT);
37     SASSERT(m_real_sort != 0); // arith_decl_plugin must be installed before fpa_decl_plugin.
38     m_manager->inc_ref(m_real_sort);
39 
40     m_int_sort = m_manager->mk_sort(m_arith_fid, INT_SORT);
41     SASSERT(m_int_sort != 0); // arith_decl_plugin must be installed before fpa_decl_plugin.
42     m_manager->inc_ref(m_int_sort);
43 
44     // BV is not optional anymore.
45     SASSERT(m_manager->has_plugin(symbol("bv")));
46     m_bv_fid = m_manager->mk_family_id("bv");
47     m_bv_plugin = static_cast<bv_decl_plugin*>(m_manager->get_plugin(m_bv_fid));
48 }
49 
~fpa_decl_plugin()50 fpa_decl_plugin::~fpa_decl_plugin() {
51 }
52 
mk_id(mpf const & v)53 unsigned fpa_decl_plugin::mk_id(mpf const & v) {
54     unsigned new_id = m_id_gen.mk();
55     m_values.reserve(new_id+1);
56     m_fm.set(m_values[new_id], v);
57     unsigned old_id = m_value_table.insert_if_not_there(new_id);
58     if (old_id != new_id) {
59         m_id_gen.recycle(new_id);
60         m_fm.del(m_values[new_id]);
61     }
62     return old_id;
63 }
64 
recycled_id(unsigned id)65 void fpa_decl_plugin::recycled_id(unsigned id) {
66     SASSERT(m_value_table.contains(id));
67     m_value_table.erase(id);
68     m_id_gen.recycle(id);
69     m_fm.del(m_values[id]);
70 }
71 
is_considered_uninterpreted(func_decl * f)72 bool fpa_decl_plugin::is_considered_uninterpreted(func_decl * f) {
73     return false;
74 }
75 
mk_numeral_decl(mpf const & v)76 func_decl * fpa_decl_plugin::mk_numeral_decl(mpf const & v) {
77     sort * s = mk_float_sort(v.get_ebits(), v.get_sbits());
78     func_decl * r = nullptr;
79     if (m_fm.is_nan(v))
80         r = m_manager->mk_const_decl(symbol("NaN"), s, func_decl_info(m_family_id, OP_FPA_NAN));
81     else if (m_fm.is_pinf(v))
82         r = m_manager->mk_const_decl(symbol("+oo"), s, func_decl_info(m_family_id, OP_FPA_PLUS_INF));
83     else if (m_fm.is_ninf(v))
84         r = m_manager->mk_const_decl(symbol("-oo"), s, func_decl_info(m_family_id, OP_FPA_MINUS_INF));
85     else if (m_fm.is_pzero(v))
86         r = m_manager->mk_const_decl(symbol("+zero"), s, func_decl_info(m_family_id, OP_FPA_PLUS_ZERO));
87     else if (m_fm.is_nzero(v))
88         r = m_manager->mk_const_decl(symbol("-zero"), s, func_decl_info(m_family_id, OP_FPA_MINUS_ZERO));
89     else {
90         SASSERT(m_fm.is_regular(v));
91         parameter p(mk_id(v), true);
92         SASSERT(p.is_external());
93         sort * s = mk_float_sort(v.get_ebits(), v.get_sbits());
94         r = m_manager->mk_const_decl(symbol("fp.numeral"), s, func_decl_info(m_family_id, OP_FPA_NUM, 1, &p));
95     }
96     return r;
97 }
98 
mk_numeral(mpf const & v)99 app * fpa_decl_plugin::mk_numeral(mpf const & v) {
100     app * r = m_manager->mk_const(mk_numeral_decl(v));
101 
102     if (log_constant_meaning_prelude(r)) {
103         m_fm.display_smt2(m_manager->trace_stream(), v, false);
104         m_manager->trace_stream() << "\n";
105     }
106 
107     return r;
108 }
109 
is_numeral(expr * n,mpf & val)110 bool fpa_decl_plugin::is_numeral(expr * n, mpf & val) {
111     if (is_app_of(n, m_family_id, OP_FPA_NUM)) {
112         m_fm.set(val, m_values[to_app(n)->get_decl()->get_parameter(0).get_ext_id()]);
113         return true;
114     }
115     else if (is_app_of(n, m_family_id, OP_FPA_MINUS_INF)) {
116         unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
117         unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
118         m_fm.mk_ninf(ebits, sbits, val);
119         return true;
120     }
121     else if (is_app_of(n, m_family_id, OP_FPA_PLUS_INF)) {
122         unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
123         unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
124         m_fm.mk_pinf(ebits, sbits, val);
125         return true;
126     }
127     else if (is_app_of(n, m_family_id, OP_FPA_NAN)) {
128         unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
129         unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
130         m_fm.mk_nan(ebits, sbits, val);
131         return true;
132     }
133     else if (is_app_of(n, m_family_id, OP_FPA_PLUS_ZERO)) {
134         unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
135         unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
136         m_fm.mk_pzero(ebits, sbits, val);
137         return true;
138     }
139     else if (is_app_of(n, m_family_id, OP_FPA_MINUS_ZERO)) {
140         unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
141         unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
142         m_fm.mk_nzero(ebits, sbits, val);
143         return true;
144     }
145     return false;
146 }
147 
is_numeral(expr * n)148 bool fpa_decl_plugin::is_numeral(expr * n) {
149     scoped_mpf v(m_fm);
150     return is_numeral(n, v);
151 }
152 
is_rm_numeral(expr * n,mpf_rounding_mode & val)153 bool fpa_decl_plugin::is_rm_numeral(expr * n, mpf_rounding_mode & val) {
154     if (is_app_of(n, m_family_id, OP_FPA_RM_NEAREST_TIES_TO_AWAY)) {
155         val = MPF_ROUND_NEAREST_TAWAY;
156         return true;
157     }
158     else if (is_app_of(n, m_family_id, OP_FPA_RM_NEAREST_TIES_TO_EVEN)) {
159         val = MPF_ROUND_NEAREST_TEVEN;
160         return true;
161     }
162     else if (is_app_of(n, m_family_id, OP_FPA_RM_TOWARD_NEGATIVE)) {
163         val = MPF_ROUND_TOWARD_NEGATIVE;
164         return true;
165     }
166     else if (is_app_of(n, m_family_id, OP_FPA_RM_TOWARD_POSITIVE)) {
167         val = MPF_ROUND_TOWARD_POSITIVE;
168         return true;
169     }
170     else if (is_app_of(n, m_family_id, OP_FPA_RM_TOWARD_ZERO)) {
171         val = MPF_ROUND_TOWARD_ZERO;
172         return true;
173     }
174 
175     return false;
176 }
177 
is_rm_numeral(expr * n)178 bool fpa_decl_plugin::is_rm_numeral(expr * n) {
179     mpf_rounding_mode t;
180     return is_rm_numeral(n, t);
181 }
182 
del(parameter const & p)183 void fpa_decl_plugin::del(parameter const & p) {
184     SASSERT(p.is_external());
185     recycled_id(p.get_ext_id());
186 }
187 
translate(parameter const & p,decl_plugin & target)188 parameter fpa_decl_plugin::translate(parameter const & p, decl_plugin & target) {
189     SASSERT(p.is_external());
190     fpa_decl_plugin & _target = static_cast<fpa_decl_plugin&>(target);
191     return parameter(_target.mk_id(m_values[p.get_ext_id()]), true);
192 }
193 
finalize()194 void fpa_decl_plugin::finalize() {
195     if (m_real_sort) { m_manager->dec_ref(m_real_sort); }
196     if (m_int_sort)  { m_manager->dec_ref(m_int_sort); }
197 }
198 
mk_fresh()199 decl_plugin * fpa_decl_plugin::mk_fresh() {
200     return alloc(fpa_decl_plugin);
201 }
202 
mk_float_sort(unsigned ebits,unsigned sbits)203 sort * fpa_decl_plugin::mk_float_sort(unsigned ebits, unsigned sbits) {
204     if (sbits < 2)
205         m_manager->raise_exception("minimum number of significand bits is 1");
206     if (ebits < 2)
207         m_manager->raise_exception("minimum number of exponent bits is 2");
208     if (ebits > 63)
209         m_manager->raise_exception("maximum number of exponent bits is 63");
210 
211     parameter p1(ebits), p2(sbits);
212     parameter ps[2] = { p1, p2 };
213     sort_size sz;
214     sz = sort_size::mk_very_big(); // TODO: refine
215     return m_manager->mk_sort(symbol("FloatingPoint"), sort_info(m_family_id, FLOATING_POINT_SORT, sz, 2, ps));
216 }
217 
mk_rm_sort()218 sort * fpa_decl_plugin::mk_rm_sort() {
219     return m_manager->mk_sort(symbol("RoundingMode"), sort_info(m_family_id, ROUNDING_MODE_SORT));
220 }
221 
mk_sort(decl_kind k,unsigned num_parameters,parameter const * parameters)222 sort * fpa_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) {
223     switch (k) {
224     case FLOATING_POINT_SORT:
225         if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
226             m_manager->raise_exception("expecting two integer parameters to floating point sort (ebits, sbits)");
227         return mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
228     case ROUNDING_MODE_SORT:
229         return mk_rm_sort();
230     case FLOAT16_SORT:
231         return mk_float_sort(5, 11);
232     case FLOAT32_SORT:
233         return mk_float_sort(8, 24);
234     case FLOAT64_SORT:
235         return mk_float_sort(11, 53);
236     case FLOAT128_SORT:
237         return mk_float_sort(15, 113);
238     default:
239         m_manager->raise_exception("unknown floating point theory sort");
240         return nullptr;
241     }
242 }
243 
mk_rm_const_decl(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)244 func_decl * fpa_decl_plugin::mk_rm_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
245                                                 unsigned arity, sort * const * domain, sort * range) {
246     if (num_parameters != 0)
247         m_manager->raise_exception("rounding mode constant does not have parameters");
248     if (arity != 0)
249         m_manager->raise_exception("rounding mode is a constant");
250     sort * s = mk_rm_sort();
251     func_decl_info finfo(m_family_id, k);
252     switch (k) {
253     case OP_FPA_RM_NEAREST_TIES_TO_EVEN:
254         return m_manager->mk_const_decl(symbol("roundNearestTiesToEven"), s, finfo);
255     case OP_FPA_RM_NEAREST_TIES_TO_AWAY:
256         return m_manager->mk_const_decl(symbol("roundNearestTiesToAway"), s, finfo);
257     case OP_FPA_RM_TOWARD_POSITIVE:
258         return m_manager->mk_const_decl(symbol("roundTowardPositive"), s, finfo);
259     case OP_FPA_RM_TOWARD_NEGATIVE:
260         return m_manager->mk_const_decl(symbol("roundTowardNegative"), s, finfo);
261     case OP_FPA_RM_TOWARD_ZERO:
262         return m_manager->mk_const_decl(symbol("roundTowardZero"), s, finfo);
263     default:
264         UNREACHABLE();
265         return nullptr;
266     }
267 }
268 
mk_float_const_decl(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)269 func_decl * fpa_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
270                                                    unsigned arity, sort * const * domain, sort * range) {
271     sort * s = nullptr;
272     if (num_parameters == 1 && parameters[0].is_ast() && is_sort(parameters[0].get_ast()) && is_float_sort(to_sort(parameters[0].get_ast()))) {
273         s = to_sort(parameters[0].get_ast());
274     }
275     else if (num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()) {
276         s = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
277     }
278     else if (range != nullptr && is_float_sort(range)) {
279         s = range;
280     }
281     else {
282         m_manager->raise_exception("sort of floating point constant was not specified");
283         UNREACHABLE();
284     }
285 
286     SASSERT(is_sort_of(s, m_family_id, FLOATING_POINT_SORT));
287 
288     unsigned ebits = s->get_parameter(0).get_int();
289     unsigned sbits = s->get_parameter(1).get_int();
290     scoped_mpf val(m_fm);
291 
292     switch (k)
293     {
294     case OP_FPA_NAN: m_fm.mk_nan(ebits, sbits, val);
295         SASSERT(m_fm.is_nan(val));
296         break;
297     case OP_FPA_MINUS_INF: m_fm.mk_ninf(ebits, sbits, val); break;
298     case OP_FPA_PLUS_INF: m_fm.mk_pinf(ebits, sbits, val); break;
299     case OP_FPA_MINUS_ZERO: m_fm.mk_nzero(ebits, sbits, val); break;
300     case OP_FPA_PLUS_ZERO: m_fm.mk_pzero(ebits, sbits, val); break;
301     }
302 
303     return mk_numeral_decl(val);
304 }
305 
mk_bin_rel_decl(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)306 func_decl * fpa_decl_plugin::mk_bin_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
307                                                unsigned arity, sort * const * domain, sort * range) {
308     if (arity < 2)
309         m_manager->raise_exception("invalid number of arguments to floating point relation");
310     if (domain[0] != domain[1] || !is_float_sort(domain[0]))
311         m_manager->raise_exception("sort mismatch, expected equal FloatingPoint sorts as arguments");
312     symbol name;
313     switch (k) {
314     case OP_FPA_EQ: name = "fp.eq";  break;
315     case OP_FPA_LT: name = "fp.lt";   break;
316     case OP_FPA_GT: name = "fp.gt";   break;
317     case OP_FPA_LE: name = "fp.leq";  break;
318     case OP_FPA_GE: name = "fp.geq";  break;
319     default:
320         UNREACHABLE();
321         break;
322     }
323     func_decl_info finfo(m_family_id, k);
324     finfo.set_chainable(true);
325     return m_manager->mk_func_decl(name, domain[0], domain[1], m_manager->mk_bool_sort(), finfo);
326 }
327 
mk_unary_rel_decl(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)328 func_decl * fpa_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
329                                                  unsigned arity, sort * const * domain, sort * range) {
330     if (arity != 1)
331         m_manager->raise_exception("invalid number of arguments to floating point relation");
332     if (!is_float_sort(domain[0]))
333         m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort");
334     symbol name;
335     switch (k) {
336     case OP_FPA_IS_ZERO: name = "fp.isZero";  break;
337     case OP_FPA_IS_NEGATIVE: name = "fp.isNegative";  break;
338     case OP_FPA_IS_POSITIVE: name = "fp.isPositive";  break;
339     case OP_FPA_IS_NAN: name = "fp.isNaN";  break;
340     case OP_FPA_IS_INF: name = "fp.isInfinite";  break;
341     case OP_FPA_IS_NORMAL: name = "fp.isNormal";  break;
342     case OP_FPA_IS_SUBNORMAL: name = "fp.isSubnormal";  break;
343     default:
344         UNREACHABLE();
345         break;
346     }
347     return m_manager->mk_func_decl(name, arity, domain, m_manager->mk_bool_sort(), func_decl_info(m_family_id, k));
348 }
349 
mk_unary_decl(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)350 func_decl * fpa_decl_plugin::mk_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
351                                              unsigned arity, sort * const * domain, sort * range) {
352     if (arity != 1)
353         m_manager->raise_exception("invalid number of arguments to floating point operator");
354     if (!is_float_sort(domain[0]))
355         m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort");
356     symbol name;
357     switch (k) {
358     case OP_FPA_ABS: name = "fp.abs"; break;
359     case OP_FPA_NEG: name = "fp.neg"; break;
360     default:
361         UNREACHABLE();
362         break;
363     }
364     return m_manager->mk_func_decl(name, arity, domain, domain[0], func_decl_info(m_family_id, k));
365 }
366 
mk_binary_decl(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)367 func_decl * fpa_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
368                                               unsigned arity, sort * const * domain, sort * range) {
369     if (arity != 2)
370         m_manager->raise_exception("invalid number of arguments to floating point operator");
371     if (domain[0] != domain[1] || !is_float_sort(domain[0]))
372         m_manager->raise_exception("sort mismatch, expected arguments of equal FloatingPoint sorts");
373     symbol name;
374     switch (k) {
375     case OP_FPA_REM: name = "fp.rem"; break;
376     case OP_FPA_MIN: name = "fp.min"; break;
377     case OP_FPA_MAX: name = "fp.max"; break;
378     case OP_FPA_MIN_I: name = "fp.min_i"; break;
379     case OP_FPA_MAX_I: name = "fp.max_i"; break;
380     default:
381         UNREACHABLE();
382         break;
383     }
384     return m_manager->mk_func_decl(name, arity, domain, domain[0], func_decl_info(m_family_id, k));
385 }
386 
mk_rm_binary_decl(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)387 func_decl * fpa_decl_plugin::mk_rm_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
388                                                  unsigned arity, sort * const * domain, sort * range) {
389     if (arity != 3)
390         m_manager->raise_exception("invalid number of arguments to floating point operator");
391     if (!is_rm_sort(domain[0]))
392         m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort");
393     if (domain[1] != domain[2] || !is_float_sort(domain[1]))
394         m_manager->raise_exception("sort mismatch, expected arguments 1 and 2 of equal FloatingPoint sorts");
395     symbol name;
396     switch (k) {
397     case OP_FPA_ADD: name = "fp.add";   break;
398     case OP_FPA_SUB: name = "fp.sub";   break;
399     case OP_FPA_MUL: name = "fp.mul";   break;
400     case OP_FPA_DIV: name = "fp.div";   break;
401     default:
402         UNREACHABLE();
403         break;
404     }
405     return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k));
406 }
407 
mk_rm_unary_decl(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)408 func_decl * fpa_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
409                                                 unsigned arity, sort * const * domain, sort * range) {
410     if (arity != 2)
411         m_manager->raise_exception("invalid number of arguments to floating point operator");
412     if (!is_rm_sort(domain[0]))
413         m_manager->raise_exception("sort mismatch, expected RoundingMode as first argument");
414     if (!is_float_sort(domain[1]))
415         m_manager->raise_exception("sort mismatch, expected FloatingPoint as second argument");
416     symbol name;
417     switch (k) {
418     case OP_FPA_SQRT: name = "fp.sqrt";   break;
419     case OP_FPA_ROUND_TO_INTEGRAL: name = "fp.roundToIntegral";   break;
420     default:
421         UNREACHABLE();
422         break;
423     }
424     return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k));
425 }
426 
mk_fma(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)427 func_decl * fpa_decl_plugin::mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters,
428                                            unsigned arity, sort * const * domain, sort * range) {
429     if (arity != 4)
430         m_manager->raise_exception("invalid number of arguments to fused_ma operator");
431     if (!is_rm_sort(domain[0]))
432         m_manager->raise_exception("sort mismatch, expected RoundingMode as first argument");
433     if (domain[1] != domain[2] || domain[1] != domain[3] || !is_float_sort(domain[1]))
434         m_manager->raise_exception("sort mismatch, expected arguments 1,2,3 of equal FloatingPoint sort");
435     symbol name("fp.fma");
436     return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k));
437 }
438 
mk_to_fp(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)439 func_decl * fpa_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, parameter const * parameters,
440                                         unsigned arity, sort * const * domain, sort * range) {
441     if (m_bv_plugin && arity == 3 &&
442         is_sort_of(domain[0], m_bv_fid, BV_SORT) &&
443         is_sort_of(domain[1], m_bv_fid, BV_SORT) &&
444         is_sort_of(domain[2], m_bv_fid, BV_SORT)) {
445         // 3 BVs -> 1 FP
446         unsigned ebits = domain[1]->get_parameter(0).get_int();
447         unsigned sbits = domain[2]->get_parameter(0).get_int() + 1;
448         parameter ps[] = { parameter(ebits), parameter(sbits) };
449         sort * fp = mk_float_sort(ebits, sbits);
450         symbol name("to_fp");
451         return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, 2, ps));
452     }
453     else if (m_bv_plugin && arity == 1 && is_sort_of(domain[0], m_bv_fid, BV_SORT)) {
454         // 1 BV -> 1 FP
455         if (num_parameters != 2)
456             m_manager->raise_exception("invalid number of parameters to to_fp");
457         if (!parameters[0].is_int() || !parameters[1].is_int())
458             m_manager->raise_exception("invalid parameter type to to_fp");
459 
460         int ebits = parameters[0].get_int();
461         int sbits = parameters[1].get_int();
462 
463         if (domain[0]->get_parameter(0).get_int() != (ebits + sbits))
464             m_manager->raise_exception("sort mismatch; invalid bit-vector size, expected bitvector of size (ebits+sbits)");
465 
466         sort * fp = mk_float_sort(ebits, sbits);
467         symbol name("to_fp");
468         return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
469     }
470     else if (m_bv_plugin && arity == 2 &&
471              is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
472              is_sort_of(domain[1], m_bv_fid, BV_SORT)) {
473         // RoundingMode + 1 BV -> 1 FP
474         if (num_parameters != 2)
475             m_manager->raise_exception("invalid number of parameters to to_fp");
476         if (!parameters[0].is_int() || !parameters[1].is_int())
477             m_manager->raise_exception("invalid parameter type to to_fp");
478         int ebits = parameters[0].get_int();
479         int sbits = parameters[1].get_int();
480 
481         sort * fp = mk_float_sort(ebits, sbits);
482         symbol name("to_fp");
483         return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
484     }
485     else if (arity == 2 &&
486              is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
487              is_sort_of(domain[1], m_family_id, FLOATING_POINT_SORT)) {
488         // Rounding + 1 FP -> 1 FP
489         if (num_parameters != 2)
490             m_manager->raise_exception("invalid number of parameters to to_fp");
491         if (!parameters[0].is_int() || !parameters[1].is_int())
492             m_manager->raise_exception("invalid parameter type to to_fp");
493         int ebits = parameters[0].get_int();
494         int sbits = parameters[1].get_int();
495         if (!is_rm_sort(domain[0]))
496             m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort");
497         if (!is_sort_of(domain[1], m_family_id, FLOATING_POINT_SORT))
498             m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort");
499 
500         sort * fp = mk_float_sort(ebits, sbits);
501         symbol name("to_fp");
502         return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
503     }
504     else if (arity == 3 &&
505         is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
506         is_sort_of(domain[1], m_arith_fid, REAL_SORT) &&
507         is_sort_of(domain[2], m_arith_fid, INT_SORT))
508     {
509         // Rounding +  1 Real + 1 Int -> 1 FP
510         if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
511             m_manager->raise_exception("expecting two integer parameters to to_fp");
512 
513         sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
514         symbol name("to_fp");
515         return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
516     }
517     else if (arity == 3 &&
518              is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
519              is_sort_of(domain[1], m_arith_fid, INT_SORT) &&
520              is_sort_of(domain[2], m_arith_fid, REAL_SORT))
521     {
522         // Rounding +  1 Int + 1 Real -> 1 FP
523         if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
524             m_manager->raise_exception("expecting two integer parameters to to_fp");
525 
526         sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
527         symbol name("to_fp");
528         return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
529     }
530     else if (arity == 1 &&
531              is_sort_of(domain[0], m_arith_fid, REAL_SORT))
532     {
533         // 1 Real -> 1 FP
534         if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
535             m_manager->raise_exception("expecting two integer parameters to to_fp");
536         if (domain[1] != m_real_sort)
537             m_manager->raise_exception("sort mismatch, expected one argument of Real sort");
538 
539         sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
540         symbol name("to_fp");
541         return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
542     }
543     else if (arity == 2 &&
544              is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
545              is_sort_of(domain[1], m_arith_fid, REAL_SORT))
546     {
547         // Rounding + 1 Real -> 1 FP
548         if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
549             m_manager->raise_exception("expecting two integer parameters to to_fp");
550 
551         sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
552         symbol name("to_fp");
553         return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
554     }
555     else if (arity == 2 &&
556              is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
557              is_sort_of(domain[1], m_arith_fid, INT_SORT)) {
558         // Rounding + 1 Int -> 1 FP
559         if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
560             m_manager->raise_exception("expecting two integer parameters to to_fp");
561 
562         sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
563         symbol name("to_fp");
564         return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
565     }
566     else {
567         m_manager->raise_exception("Unexpected argument combination for (_ to_fp eb sb). Supported argument combinations are: "
568                                    "((_ BitVec 1) (_ BitVec eb) (_ BitVec sb-1)), "
569                                    "(_ BitVec (eb+sb)), "
570                                    "(Real), "
571                                    "(RoundingMode (_ BitVec (eb+sb))), "
572                                    "(RoundingMode (_ FloatingPoint eb' sb')), "
573                                    "(RoundingMode Int Real), "
574                                    "(RoundingMode Real Int), "
575                                    "(RoundingMode Int), and "
576                                    "(RoundingMode Real)."
577                                    );
578     }
579 
580     return nullptr;
581 }
582 
mk_to_fp_unsigned(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)583 func_decl * fpa_decl_plugin::mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters,
584                                                  unsigned arity, sort * const * domain, sort * range) {
585     SASSERT(m_bv_plugin);
586     if (arity != 2)
587         m_manager->raise_exception("invalid number of arguments to to_fp_unsigned");
588     if (!is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT))
589         m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort");
590     if (!is_sort_of(domain[1], m_bv_fid, BV_SORT))
591         m_manager->raise_exception("sort mismatch, expected second argument of bit-vector sort");
592 
593     // RoundingMode + 1 BV -> 1 FP
594     if (num_parameters != 2)
595         m_manager->raise_exception("invalid number of parameters to to_fp_unsigned");
596     if (!parameters[0].is_int() || !parameters[1].is_int())
597         m_manager->raise_exception("invalid parameter type to to_fp_unsigned");
598 
599     int ebits = parameters[0].get_int();
600     int sbits = parameters[1].get_int();
601 
602     sort * fp = mk_float_sort(ebits, sbits);
603     symbol name("to_fp_unsigned");
604     return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
605 }
606 
mk_fp(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)607 func_decl * fpa_decl_plugin::mk_fp(decl_kind k, unsigned num_parameters, parameter const * parameters,
608                                    unsigned arity, sort * const * domain, sort * range) {
609     if (arity != 3)
610         m_manager->raise_exception("invalid number of arguments to fp");
611     if (!is_sort_of(domain[0], m_bv_fid, BV_SORT) ||
612         (domain[0]->get_parameter(0).get_int() != 1) ||
613         !is_sort_of(domain[1], m_bv_fid, BV_SORT) ||
614         !is_sort_of(domain[2], m_bv_fid, BV_SORT))
615         m_manager->raise_exception("sort mismatch, expected three bit-vectors, the first one of size 1.");
616 
617     int eb = (domain[1])->get_parameter(0).get_int();
618     int sb = (domain[2])->get_parameter(0).get_int() + 1;
619     symbol name("fp");
620     sort * fp = mk_float_sort(eb, sb);
621     return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k));
622 }
623 
mk_to_ubv(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)624 func_decl * fpa_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters,
625                                        unsigned arity, sort * const * domain, sort * range) {
626     SASSERT(m_bv_plugin);
627     if (arity != 2)
628         m_manager->raise_exception("invalid number of arguments to fp.to_ubv");
629     if (num_parameters != 1)
630         m_manager->raise_exception("invalid number of parameters to fp.to_ubv");
631     if (!parameters[0].is_int())
632         m_manager->raise_exception("invalid parameter type; fp.to_ubv expects an int parameter");
633     if (!is_rm_sort(domain[0]))
634         m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort");
635     if (!is_sort_of(domain[1], m_family_id, FLOATING_POINT_SORT))
636         m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort");
637     if (parameters[0].get_int() <= 0)
638         m_manager->raise_exception("invalid parameter value; fp.to_ubv expects a parameter larger than 0");
639 
640     symbol name("fp.to_ubv");
641     sort * bvs = m_bv_plugin->mk_sort(BV_SORT, 1, parameters);
642     return m_manager->mk_func_decl(name, arity, domain, bvs, func_decl_info(m_family_id, k, num_parameters, parameters));
643 }
644 
mk_to_sbv(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)645 func_decl * fpa_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters,
646                                        unsigned arity, sort * const * domain, sort * range) {
647     SASSERT(m_bv_plugin);
648     if (arity != 2)
649         m_manager->raise_exception("invalid number of arguments to fp.to_sbv");
650     if (num_parameters != 1)
651         m_manager->raise_exception("invalid number of parameters to fp.to_sbv");
652     if (!parameters[0].is_int())
653         m_manager->raise_exception("invalid parameter type; fp.to_sbv expects an int parameter");
654     if (!is_rm_sort(domain[0]))
655         m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort");
656     if (!is_sort_of(domain[1], m_family_id, FLOATING_POINT_SORT))
657         m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort");
658     if (parameters[0].get_int() <= 0)
659         m_manager->raise_exception("invalid parameter value; fp.to_sbv expects a parameter larger than 0");
660 
661     symbol name("fp.to_sbv");
662     sort * bvs = m_bv_plugin->mk_sort(BV_SORT, 1, parameters);
663     return m_manager->mk_func_decl(name, arity, domain, bvs, func_decl_info(m_family_id, k, num_parameters, parameters));
664 }
665 
mk_to_real(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)666 func_decl * fpa_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters,
667                                           unsigned arity, sort * const * domain, sort * range) {
668     if (arity != 1)
669         m_manager->raise_exception("invalid number of arguments to fp.to_real");
670     if (!is_float_sort(domain[0]))
671         m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort");
672 
673     symbol name("fp.to_real");
674     return m_manager->mk_func_decl(name, 1, domain, m_real_sort, func_decl_info(m_family_id, k));
675 }
676 
mk_to_ieee_bv(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)677 func_decl * fpa_decl_plugin::mk_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
678                                            unsigned arity, sort * const * domain, sort * range) {
679     if (arity != 1)
680         m_manager->raise_exception("invalid number of arguments to fp.to_ieee_bv");
681     if (!is_float_sort(domain[0]))
682         m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort");
683 
684     unsigned float_sz = domain[0]->get_parameter(0).get_int() + domain[0]->get_parameter(1).get_int();
685     parameter ps[] = { parameter(float_sz) };
686     sort * bv_srt = m_bv_plugin->mk_sort(BV_SORT, 1, ps);
687     symbol name("fp.to_ieee_bv");
688     return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k));
689 }
690 
mk_bv2rm(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)691 func_decl * fpa_decl_plugin::mk_bv2rm(decl_kind k, unsigned num_parameters, parameter const * parameters,
692                                             unsigned arity, sort * const * domain, sort * range) {
693     if (arity != 1)
694         m_manager->raise_exception("invalid number of arguments to bv2rm");
695     if (!is_sort_of(domain[0], m_bv_fid, BV_SORT) || domain[0]->get_parameter(0).get_int() != 3)
696         m_manager->raise_exception("sort mismatch, expected argument of sort bitvector, size 3");
697     if (!is_rm_sort(range))
698         m_manager->raise_exception("sort mismatch, expected range of RoundingMode sort");
699 
700     parameter ps[] = { parameter(3) };
701     sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ps);
702     return m_manager->mk_func_decl(symbol("rm"), 1, &bv_srt, range, func_decl_info(m_family_id, k, num_parameters, parameters));
703 }
704 
mk_bv_wrap(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)705 func_decl * fpa_decl_plugin::mk_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters,
706                                                  unsigned arity, sort * const * domain, sort * range) {
707     if (arity != 1)
708         m_manager->raise_exception("invalid number of arguments to bv_wrap");
709     if (!is_float_sort(domain[0]) && !is_rm_sort(domain[0]))
710         m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint or RoundingMode sort");
711 
712     if (is_float_sort(domain[0]))
713     {
714         unsigned float_sz = domain[0]->get_parameter(0).get_int() + domain[0]->get_parameter(1).get_int();
715         parameter ps[] = { parameter(float_sz) };
716         sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ps);
717         return m_manager->mk_func_decl(symbol("bv_wrap"), 1, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
718     }
719     else {
720         parameter ps[] = { parameter(3) };
721         sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ps);
722         return m_manager->mk_func_decl(symbol("bv_wrap"), 1, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
723     }
724 }
725 
mk_func_decl(decl_kind k,unsigned num_parameters,parameter const * parameters,unsigned arity,sort * const * domain,sort * range)726 func_decl * fpa_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
727                                             unsigned arity, sort * const * domain, sort * range) {
728     switch (k) {
729     case OP_FPA_MINUS_INF:
730     case OP_FPA_PLUS_INF:
731     case OP_FPA_NAN:
732     case OP_FPA_MINUS_ZERO:
733     case OP_FPA_PLUS_ZERO:
734         return mk_float_const_decl(k, num_parameters, parameters, arity, domain, range);
735     case OP_FPA_RM_NEAREST_TIES_TO_EVEN:
736     case OP_FPA_RM_NEAREST_TIES_TO_AWAY:
737     case OP_FPA_RM_TOWARD_POSITIVE:
738     case OP_FPA_RM_TOWARD_NEGATIVE:
739     case OP_FPA_RM_TOWARD_ZERO:
740         return mk_rm_const_decl(k, num_parameters, parameters, arity, domain, range);
741     case OP_FPA_EQ:
742     case OP_FPA_LT:
743     case OP_FPA_GT:
744     case OP_FPA_LE:
745     case OP_FPA_GE:
746         return mk_bin_rel_decl(k, num_parameters, parameters, arity, domain, range);
747     case OP_FPA_IS_ZERO:
748     case OP_FPA_IS_NEGATIVE:
749     case OP_FPA_IS_POSITIVE:
750     case OP_FPA_IS_NAN:
751     case OP_FPA_IS_INF:
752     case OP_FPA_IS_NORMAL:
753     case OP_FPA_IS_SUBNORMAL:
754         return mk_unary_rel_decl(k, num_parameters, parameters, arity, domain, range);
755     case OP_FPA_ABS:
756     case OP_FPA_NEG:
757         return mk_unary_decl(k, num_parameters, parameters, arity, domain, range);
758     case OP_FPA_REM:
759     case OP_FPA_MIN:
760     case OP_FPA_MAX:
761     case OP_FPA_MIN_I:
762     case OP_FPA_MAX_I:
763         return mk_binary_decl(k, num_parameters, parameters, arity, domain, range);
764     case OP_FPA_ADD:
765     case OP_FPA_MUL:
766     case OP_FPA_DIV:
767         return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range);
768     case OP_FPA_SUB:
769         if (arity == 1)
770             return mk_unary_decl(OP_FPA_NEG, num_parameters, parameters, arity, domain, range);
771         else
772             return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range);
773     case OP_FPA_SQRT:
774     case OP_FPA_ROUND_TO_INTEGRAL:
775         return mk_rm_unary_decl(k, num_parameters, parameters, arity, domain, range);
776     case OP_FPA_FMA:
777         return mk_fma(k, num_parameters, parameters, arity, domain, range);
778     case OP_FPA_FP:
779         return mk_fp(k, num_parameters, parameters, arity, domain, range);
780     case OP_FPA_TO_UBV:
781     case OP_FPA_TO_UBV_I:
782         return mk_to_ubv(k, num_parameters, parameters, arity, domain, range);
783     case OP_FPA_TO_SBV:
784     case OP_FPA_TO_SBV_I:
785         return mk_to_sbv(k, num_parameters, parameters, arity, domain, range);
786     case OP_FPA_TO_REAL:
787         return mk_to_real(k, num_parameters, parameters, arity, domain, range);
788     case OP_FPA_TO_FP:
789         return mk_to_fp(k, num_parameters, parameters, arity, domain, range);
790     case OP_FPA_TO_FP_UNSIGNED:
791         return mk_to_fp_unsigned(k, num_parameters, parameters, arity, domain, range);
792     case OP_FPA_TO_IEEE_BV:
793         return mk_to_ieee_bv(k, num_parameters, parameters, arity, domain, range);
794 
795     case OP_FPA_BVWRAP:
796         return mk_bv_wrap(k, num_parameters, parameters, arity, domain, range);
797     case OP_FPA_BV2RM:
798         return mk_bv2rm(k, num_parameters, parameters, arity, domain, range);
799 
800     default:
801         m_manager->raise_exception("unsupported floating point operator");
802         return nullptr;
803     }
804 }
805 
get_op_names(svector<builtin_name> & op_names,symbol const & logic)806 void fpa_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
807     // These are the operators from the final draft of the SMT FloatingPoint standard
808     op_names.push_back(builtin_name("+oo", OP_FPA_PLUS_INF));
809     op_names.push_back(builtin_name("-oo", OP_FPA_MINUS_INF));
810     op_names.push_back(builtin_name("+zero", OP_FPA_PLUS_ZERO));
811     op_names.push_back(builtin_name("-zero", OP_FPA_MINUS_ZERO));
812     op_names.push_back(builtin_name("NaN", OP_FPA_NAN));
813 
814     op_names.push_back(builtin_name("roundNearestTiesToEven", OP_FPA_RM_NEAREST_TIES_TO_EVEN));
815     op_names.push_back(builtin_name("roundNearestTiesToAway", OP_FPA_RM_NEAREST_TIES_TO_AWAY));
816     op_names.push_back(builtin_name("roundTowardPositive", OP_FPA_RM_TOWARD_POSITIVE));
817     op_names.push_back(builtin_name("roundTowardNegative", OP_FPA_RM_TOWARD_NEGATIVE));
818     op_names.push_back(builtin_name("roundTowardZero", OP_FPA_RM_TOWARD_ZERO));
819 
820     op_names.push_back(builtin_name("RNE", OP_FPA_RM_NEAREST_TIES_TO_EVEN));
821     op_names.push_back(builtin_name("RNA", OP_FPA_RM_NEAREST_TIES_TO_AWAY));
822     op_names.push_back(builtin_name("RTP", OP_FPA_RM_TOWARD_POSITIVE));
823     op_names.push_back(builtin_name("RTN", OP_FPA_RM_TOWARD_NEGATIVE));
824     op_names.push_back(builtin_name("RTZ", OP_FPA_RM_TOWARD_ZERO));
825 
826     op_names.push_back(builtin_name("fp.abs", OP_FPA_ABS));
827     op_names.push_back(builtin_name("fp.neg", OP_FPA_NEG));
828     op_names.push_back(builtin_name("fp.add", OP_FPA_ADD));
829     op_names.push_back(builtin_name("fp.sub", OP_FPA_SUB));
830     op_names.push_back(builtin_name("fp.mul", OP_FPA_MUL));
831     op_names.push_back(builtin_name("fp.div", OP_FPA_DIV));
832     op_names.push_back(builtin_name("fp.fma", OP_FPA_FMA));
833     op_names.push_back(builtin_name("fp.sqrt", OP_FPA_SQRT));
834     op_names.push_back(builtin_name("fp.rem", OP_FPA_REM));
835     op_names.push_back(builtin_name("fp.roundToIntegral", OP_FPA_ROUND_TO_INTEGRAL));
836     op_names.push_back(builtin_name("fp.min", OP_FPA_MIN));
837     op_names.push_back(builtin_name("fp.max", OP_FPA_MAX));
838     op_names.push_back(builtin_name("fp.min_i", OP_FPA_MIN_I));
839     op_names.push_back(builtin_name("fp.max_i", OP_FPA_MAX_I));
840     op_names.push_back(builtin_name("fp.leq", OP_FPA_LE));
841     op_names.push_back(builtin_name("fp.lt",  OP_FPA_LT));
842     op_names.push_back(builtin_name("fp.geq", OP_FPA_GE));
843     op_names.push_back(builtin_name("fp.gt",  OP_FPA_GT));
844     op_names.push_back(builtin_name("fp.eq", OP_FPA_EQ));
845 
846     op_names.push_back(builtin_name("fp.isNormal", OP_FPA_IS_NORMAL));
847     op_names.push_back(builtin_name("fp.isSubnormal", OP_FPA_IS_SUBNORMAL));
848     op_names.push_back(builtin_name("fp.isZero", OP_FPA_IS_ZERO));
849     op_names.push_back(builtin_name("fp.isInfinite", OP_FPA_IS_INF));
850     op_names.push_back(builtin_name("fp.isNaN", OP_FPA_IS_NAN));
851     op_names.push_back(builtin_name("fp.isNegative", OP_FPA_IS_NEGATIVE));
852     op_names.push_back(builtin_name("fp.isPositive", OP_FPA_IS_POSITIVE));
853 
854     op_names.push_back(builtin_name("fp", OP_FPA_FP));
855     op_names.push_back(builtin_name("fp.to_ubv", OP_FPA_TO_UBV));
856     op_names.push_back(builtin_name("fp.to_sbv", OP_FPA_TO_SBV));
857     op_names.push_back(builtin_name("fp.to_ubv_I", OP_FPA_TO_UBV_I));
858     op_names.push_back(builtin_name("fp.to_sbv_I", OP_FPA_TO_SBV_I));
859     op_names.push_back(builtin_name("fp.to_real", OP_FPA_TO_REAL));
860 
861     op_names.push_back(builtin_name("to_fp", OP_FPA_TO_FP));
862     op_names.push_back(builtin_name("to_fp_unsigned", OP_FPA_TO_FP_UNSIGNED));
863 
864     /* Extensions */
865     op_names.push_back(builtin_name("to_ieee_bv", OP_FPA_TO_IEEE_BV));
866     op_names.push_back(builtin_name("fp.to_ieee_bv", OP_FPA_TO_IEEE_BV));
867 }
868 
get_sort_names(svector<builtin_name> & sort_names,symbol const & logic)869 void fpa_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbol const & logic) {
870     sort_names.push_back(builtin_name("FloatingPoint", FLOATING_POINT_SORT));
871     sort_names.push_back(builtin_name("RoundingMode", ROUNDING_MODE_SORT));
872 
873     // The final theory supports three common FloatingPoint sorts
874     sort_names.push_back(builtin_name("Float16", FLOAT16_SORT));
875     sort_names.push_back(builtin_name("Float32", FLOAT32_SORT));
876     sort_names.push_back(builtin_name("Float64", FLOAT64_SORT));
877     sort_names.push_back(builtin_name("Float128", FLOAT128_SORT));
878 }
879 
get_some_value(sort * s)880 expr * fpa_decl_plugin::get_some_value(sort * s) {
881     if (s->is_sort_of(m_family_id, FLOATING_POINT_SORT)) {
882         mpf tmp;
883         m_fm.mk_nan(s->get_parameter(0).get_int(), s->get_parameter(1).get_int(), tmp);
884         expr * res = mk_numeral(tmp);
885         m_fm.del(tmp);
886         return res;
887     }
888     else if (s->is_sort_of(m_family_id, ROUNDING_MODE_SORT)) {
889         func_decl * f = mk_rm_const_decl(OP_FPA_RM_TOWARD_ZERO, 0, nullptr, 0, nullptr, s);
890         return m_manager->mk_const(f);
891     }
892 
893     UNREACHABLE();
894     return nullptr;
895 }
896 
is_value(app * e) const897 bool fpa_decl_plugin::is_value(app * e) const {
898     if (e->get_family_id() != m_family_id)
899         return false;
900     switch (e->get_decl_kind()) {
901     case OP_FPA_RM_NEAREST_TIES_TO_EVEN:
902     case OP_FPA_RM_NEAREST_TIES_TO_AWAY:
903     case OP_FPA_RM_TOWARD_POSITIVE:
904     case OP_FPA_RM_TOWARD_NEGATIVE:
905     case OP_FPA_RM_TOWARD_ZERO:
906     case OP_FPA_NUM:
907     case OP_FPA_PLUS_INF:
908     case OP_FPA_MINUS_INF:
909     case OP_FPA_PLUS_ZERO:
910     case OP_FPA_MINUS_ZERO:
911     case OP_FPA_NAN:
912         return true;
913     case OP_FPA_FP:
914         return m_manager->is_value(e->get_arg(0)) &&
915                m_manager->is_value(e->get_arg(1)) &&
916                m_manager->is_value(e->get_arg(2));
917     default:
918         return false;
919     }
920 }
921 
is_unique_value(app * e) const922 bool fpa_decl_plugin::is_unique_value(app* e) const {
923     if (e->get_family_id() != m_family_id)
924         return false;
925     switch (e->get_decl_kind()) {
926     case OP_FPA_RM_NEAREST_TIES_TO_EVEN:
927     case OP_FPA_RM_NEAREST_TIES_TO_AWAY:
928     case OP_FPA_RM_TOWARD_POSITIVE:
929     case OP_FPA_RM_TOWARD_NEGATIVE:
930     case OP_FPA_RM_TOWARD_ZERO:
931         return true;
932     case OP_FPA_PLUS_INF:  /* No; +oo == (fp #b0 #b11 #b00) */
933     case OP_FPA_MINUS_INF: /* No; -oo == (fp #b1 #b11 #b00) */
934     case OP_FPA_PLUS_ZERO: /* No; +zero == (fp #b0 #b00 #b000) */
935     case OP_FPA_MINUS_ZERO: /* No; -zero == (fp #b1 #b00 #b000) */
936     case OP_FPA_NAN: /* No; NaN == (fp #b0 #b111111 #b0000001) */
937     case OP_FPA_NUM: /* see NaN */
938         return false;
939     case OP_FPA_FP: {
940         if (m_manager->is_value(e->get_arg(0)) &&
941             m_manager->is_value(e->get_arg(1)) &&
942             m_manager->is_value(e->get_arg(2))) {
943           bv_util bu(*m_manager);
944           return !bu.is_allone(e->get_arg(1)) && !bu.is_zero(e->get_arg(1));
945         }
946         return false;
947     }
948     default:
949         return false;
950     }
951 }
952 
fpa_util(ast_manager & m)953 fpa_util::fpa_util(ast_manager & m):
954     m_manager(m),
955     m_fid(m.mk_family_id("fpa")),
956     m_a_util(m),
957     m_bv_util(m) {
958     m_plugin = static_cast<fpa_decl_plugin*>(m.get_plugin(m_fid));
959 }
960 
~fpa_util()961 fpa_util::~fpa_util() {
962 }
963 
mk_float_sort(unsigned ebits,unsigned sbits)964 sort * fpa_util::mk_float_sort(unsigned ebits, unsigned sbits) {
965     parameter ps[2] = { parameter(ebits), parameter(sbits) };
966     return m().mk_sort(m_fid, FLOATING_POINT_SORT, 2, ps);
967 }
968 
get_ebits(sort * s) const969 unsigned fpa_util::get_ebits(sort * s) const {
970     SASSERT(is_float(s));
971     return static_cast<unsigned>(s->get_parameter(0).get_int());
972 }
973 
get_sbits(sort * s) const974 unsigned fpa_util::get_sbits(sort * s) const {
975     SASSERT(is_float(s));
976     return static_cast<unsigned>(s->get_parameter(1).get_int());
977 }
978 
mk_nan(unsigned ebits,unsigned sbits)979 app * fpa_util::mk_nan(unsigned ebits, unsigned sbits) {
980     scoped_mpf v(fm());
981     fm().mk_nan(ebits, sbits, v);
982     return mk_value(v);
983 }
984 
mk_pinf(unsigned ebits,unsigned sbits)985 app * fpa_util::mk_pinf(unsigned ebits, unsigned sbits) {
986     scoped_mpf v(fm());
987     fm().mk_pinf(ebits, sbits, v);
988     return mk_value(v);
989 }
990 
mk_ninf(unsigned ebits,unsigned sbits)991 app * fpa_util::mk_ninf(unsigned ebits, unsigned sbits) {
992     scoped_mpf v(fm());
993     fm().mk_ninf(ebits, sbits, v);
994     return mk_value(v);
995 }
996 
mk_pzero(unsigned ebits,unsigned sbits)997 app * fpa_util::mk_pzero(unsigned ebits, unsigned sbits) {
998     scoped_mpf v(fm());
999     fm().mk_pzero(ebits, sbits, v);
1000     return mk_value(v);
1001 }
1002 
mk_nzero(unsigned ebits,unsigned sbits)1003 app * fpa_util::mk_nzero(unsigned ebits, unsigned sbits) {
1004     scoped_mpf v(fm());
1005     fm().mk_nzero(ebits, sbits, v);
1006     return mk_value(v);
1007 }
1008 
contains_floats(ast * a)1009 bool fpa_util::contains_floats(ast * a) {
1010     switch (a->get_kind()) {
1011     case AST_APP: {
1012         app * aa = to_app(a);
1013         if (contains_floats(aa->get_decl()))
1014             return true;
1015         else
1016             for (unsigned i = 0; i < aa->get_num_args(); i++)
1017                 if (contains_floats(aa->get_arg(i)))
1018                     return true;
1019         break;
1020     }
1021     case AST_VAR:
1022         return contains_floats(to_var(a)->get_sort());
1023         break;
1024     case AST_QUANTIFIER: {
1025         quantifier * q = to_quantifier(a);
1026         for (unsigned i = 0; i < q->get_num_children(); i++)
1027             if (contains_floats(q->get_child(i)))
1028                 return true;
1029         for (unsigned i = 0; i < q->get_num_decls(); i++)
1030             if (contains_floats(q->get_decl_sort(i)))
1031                 return true;
1032         if (contains_floats(q->get_expr()))
1033             return true;
1034         break;
1035     }
1036     case AST_SORT: {
1037         sort * s = to_sort(a);
1038         if (is_float(s) || is_rm(s))
1039             return true;
1040         else {
1041             for (unsigned i = 0; i < s->get_num_parameters(); i++) {
1042                 parameter const & pi = s->get_parameter(i);
1043                 if (pi.is_ast() && contains_floats(pi.get_ast()))
1044                     return true;
1045             }
1046         }
1047         break;
1048     }
1049     case AST_FUNC_DECL: {
1050         func_decl * f = to_func_decl(a);
1051         for (unsigned i = 0; i < f->get_arity(); i++)
1052             if (contains_floats(f->get_domain(i)))
1053                 return true;
1054         if (contains_floats(f->get_range()))
1055             return true;
1056         for (unsigned i = 0; i < f->get_num_parameters(); i++) {
1057             parameter const & pi = f->get_parameter(i);
1058             if (pi.is_ast() && contains_floats(pi.get_ast()))
1059                 return true;
1060         }
1061         break;
1062     }
1063     default:
1064         UNREACHABLE();
1065     }
1066 
1067     return false;
1068 }
1069 
is_considered_uninterpreted(func_decl * f,unsigned n,expr * const * args)1070 bool fpa_util::is_considered_uninterpreted(func_decl * f, unsigned n, expr* const* args) {
1071     TRACE("fpa_util", expr_ref t(m().mk_app(f, n, args), m()); tout << mk_ismt2_pp(t, m()) << std::endl; );
1072 
1073     family_id ffid = plugin().get_family_id();
1074     if (f->get_family_id() != ffid)
1075         return false;
1076 
1077     if (is_decl_of(f, ffid, OP_FPA_TO_IEEE_BV)) {
1078         SASSERT(n == 1);
1079         expr* x = args[0];
1080         return is_nan(x);
1081     }
1082     else if (is_decl_of(f, ffid, OP_FPA_TO_SBV) ||
1083              is_decl_of(f, ffid, OP_FPA_TO_UBV) ||
1084              is_decl_of(f, ffid, OP_FPA_TO_SBV_I) ||
1085              is_decl_of(f, ffid, OP_FPA_TO_UBV_I)) {
1086         SASSERT(n == 2);
1087         SASSERT(f->get_num_parameters() == 1);
1088         bool is_signed = f->get_decl_kind() == OP_FPA_TO_SBV || f->get_decl_kind() == OP_FPA_TO_SBV_I;
1089         expr* rm = args[0];
1090         expr* x = args[1];
1091         unsigned bv_sz = f->get_parameter(0).get_int();
1092         mpf_rounding_mode rmv;
1093         scoped_mpf sv(fm());
1094         if (!is_rm_numeral(rm, rmv) || !is_numeral(x, sv)) return false;
1095         if (is_nan(x) || is_inf(x)) return true;
1096         unsynch_mpq_manager& mpqm = plugin().fm().mpq_manager();
1097         scoped_mpq r(mpqm);
1098         plugin().fm().to_sbv_mpq(rmv, sv, r);
1099         if (is_signed)
1100             return mpqm.bitsize(r) >= bv_sz;
1101         else
1102             return mpqm.is_neg(r) || mpqm.bitsize(r) > bv_sz;
1103     }
1104     else if (is_decl_of(f, ffid, OP_FPA_TO_REAL)) {
1105         SASSERT(n == 1);
1106         expr* x = args[0];
1107         return is_nan(x) || is_inf(x);
1108     }
1109 
1110     return plugin().is_considered_uninterpreted(f);
1111 }
1112