From d6ac98a494fc6b5e3d6fa9e82250b53ad1027051 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 11 Dec 2014 12:05:52 +0000 Subject: [PATCH] FPA API: reintroduced to_ieee_bv Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 11 +++++++++++ src/api/z3_fpa.h | 13 +++++++++++++ src/ast/float_decl_plugin.cpp | 20 ++++++++++++++++++++ src/ast/float_decl_plugin.h | 15 +++++++++++---- src/ast/rewriter/float_rewriter.cpp | 1 + src/smt/theory_fpa.cpp | 19 ++++++++++++++++++- 6 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 12d32c04a..876e3cff5 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -398,4 +398,15 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } + + Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_to_ieee_bv(c, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_float_to_ieee_bv(to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + }; diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 6042fc044..50ad49590 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -555,6 +555,19 @@ extern "C" { */ Z3_ast Z3_API Z3_mk_fpa_convert(__in Z3_context c, __in Z3_sort s, __in Z3_ast rm, __in Z3_ast t); + /** + \brief Conversion of a floating point term to a bit-vector term in IEEE754 format. + + \param c logical context. + \param t floating-point term. + + t must have floating point sort. The size of the resulting bit-vector is automatically determined. + + def_API('Z3_mk_fpa_to_ieee_bv', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t); + + /*@}*/ /*@}*/ diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 3941d3a97..231d826b2 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -565,6 +565,21 @@ func_decl * float_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, return m_manager->mk_func_decl(name, 1, domain, m_real_sort, func_decl_info(m_family_id, k)); } +func_decl * float_decl_plugin::mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { + if (arity != 1) + m_manager->raise_exception("invalid number of arguments to asIEEEBV"); + if (!is_float_sort(domain[0])) + m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort"); + + unsigned float_sz = domain[0]->get_parameter(0).get_int() + domain[0]->get_parameter(1).get_int(); + parameter ps[] = { parameter(float_sz) }; + sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ps); + symbol name("to_ieee_bv"); + return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); +} + + func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { switch (k) { @@ -629,6 +644,8 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters return mk_to_fp(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_TO_FP_UNSIGNED: return mk_to_fp_unsigned(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_TO_IEEE_BV: + return mk_float_to_ieee_bv(k, num_parameters, parameters, arity, domain, range); default: m_manager->raise_exception("unsupported floating point operator"); return 0; @@ -687,6 +704,9 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("to_fp", OP_FLOAT_TO_FP)); op_names.push_back(builtin_name("to_fp_unsigned", OP_FLOAT_TO_FP_UNSIGNED)); + + /* Extensions */ + op_names.push_back(builtin_name("to_ieee_bv", OP_FLOAT_TO_IEEE_BV)); } void float_decl_plugin::get_sort_names(svector & sort_names, symbol const & logic) { diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index 92610444a..dbd3dda2e 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -82,6 +82,9 @@ enum float_op_kind { OP_FLOAT_TO_UBV, OP_FLOAT_TO_SBV, OP_FLOAT_TO_REAL, + + /* Extensions */ + OP_FLOAT_TO_IEEE_BV, LAST_FLOAT_OP }; @@ -139,12 +142,14 @@ class float_decl_plugin : public decl_plugin { func_decl * mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); - + unsigned arity, sort * const * domain, sort * range); + func_decl * mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); + virtual void set_manager(ast_manager * m, family_id id); unsigned mk_id(mpf const & v); void recycled_id(unsigned id); @@ -276,6 +281,8 @@ public: app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); } bool is_neg(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_NEG); } + + app * mk_float_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_TO_IEEE_BV, arg1); } }; #endif diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index 436194844..d1e1ab00e 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -68,6 +68,7 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c case OP_FLOAT_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(args[0], args[1], result); break; case OP_FLOAT_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(args[0], args[1], result); break; case OP_FLOAT_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break; + case OP_FLOAT_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; } return st; } diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index b1947ceb5..5efac6596 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -135,7 +135,13 @@ namespace smt { simp(a->get_arg(2), exp, pr_exp); m_converter.mk_triple(sgn, sig, exp, bv_term); - } + } + else if (term->get_decl_kind() == OP_FLOAT_TO_IEEE_BV) { + SASSERT(is_app(t)); + expr_ref bv_e(m); + proof_ref bv_pr(m); + simp(t, bv_term, bv_pr); + } else NOT_IMPLEMENTED_YET(); @@ -414,6 +420,17 @@ namespace smt { ctx.mark_as_relevant(bv_sig); ctx.mark_as_relevant(bv_exp); } + else if (n->get_decl()->get_decl_kind() == OP_FLOAT_TO_IEEE_BV) { + expr_ref eq(m); + app * ex_a = to_app(ex); + if (n->get_id() > ex_a->get_id()) + std::swap(n, ex_a); + eq = m.mk_eq(n, ex_a); + ctx.internalize(eq, false); + literal l = ctx.get_literal(eq); + ctx.mk_th_axiom(get_id(), 1, &l); + ctx.mark_as_relevant(l); + } else NOT_IMPLEMENTED_YET(); }