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