mirror of
https://github.com/Z3Prover/z3
synced 2025-10-03 22:43:56 +00:00
Merge branch 'pure' of https://git01.codeplex.com/z3 into contrib
This commit is contained in:
commit
6a496a1bfb
560 changed files with 52025 additions and 9358 deletions
|
@ -640,6 +640,7 @@ basic_decl_plugin::basic_decl_plugin():
|
|||
m_iff_decl(0),
|
||||
m_xor_decl(0),
|
||||
m_not_decl(0),
|
||||
m_interp_decl(0),
|
||||
m_implies_decl(0),
|
||||
|
||||
m_proof_sort(0),
|
||||
|
@ -863,6 +864,7 @@ void basic_decl_plugin::set_manager(ast_manager * m, family_id id) {
|
|||
m_iff_decl = mk_bool_op_decl("iff", OP_IFF, 2, false, true, false, false, true);
|
||||
m_xor_decl = mk_bool_op_decl("xor", OP_XOR, 2, true, true);
|
||||
m_not_decl = mk_bool_op_decl("not", OP_NOT, 1);
|
||||
m_interp_decl = mk_bool_op_decl("interp", OP_INTERP, 1);
|
||||
m_implies_decl = mk_implies_decl();
|
||||
|
||||
m_proof_sort = m->mk_sort(symbol("Proof"), sort_info(id, PROOF_SORT));
|
||||
|
@ -887,6 +889,7 @@ void basic_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol co
|
|||
op_names.push_back(builtin_name("or", OP_OR));
|
||||
op_names.push_back(builtin_name("xor", OP_XOR));
|
||||
op_names.push_back(builtin_name("not", OP_NOT));
|
||||
op_names.push_back(builtin_name("interp", OP_INTERP));
|
||||
op_names.push_back(builtin_name("=>", OP_IMPLIES));
|
||||
if (logic == symbol::null) {
|
||||
// user friendly aliases
|
||||
|
@ -898,6 +901,7 @@ void basic_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol co
|
|||
op_names.push_back(builtin_name("||", OP_OR));
|
||||
op_names.push_back(builtin_name("equals", OP_EQ));
|
||||
op_names.push_back(builtin_name("equiv", OP_IFF));
|
||||
op_names.push_back(builtin_name("@@", OP_INTERP));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -918,6 +922,7 @@ void basic_decl_plugin::finalize() {
|
|||
DEC_REF(m_and_decl);
|
||||
DEC_REF(m_or_decl);
|
||||
DEC_REF(m_not_decl);
|
||||
DEC_REF(m_interp_decl);
|
||||
DEC_REF(m_iff_decl);
|
||||
DEC_REF(m_xor_decl);
|
||||
DEC_REF(m_implies_decl);
|
||||
|
@ -1016,6 +1021,7 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
case OP_AND: return m_and_decl;
|
||||
case OP_OR: return m_or_decl;
|
||||
case OP_NOT: return m_not_decl;
|
||||
case OP_INTERP: return m_interp_decl;
|
||||
case OP_IFF: return m_iff_decl;
|
||||
case OP_IMPLIES: return m_implies_decl;
|
||||
case OP_XOR: return m_xor_decl;
|
||||
|
@ -1051,6 +1057,7 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
case OP_AND: return m_and_decl;
|
||||
case OP_OR: return m_or_decl;
|
||||
case OP_NOT: return m_not_decl;
|
||||
case OP_INTERP: return m_interp_decl;
|
||||
case OP_IFF: return m_iff_decl;
|
||||
case OP_IMPLIES: return m_implies_decl;
|
||||
case OP_XOR: return m_xor_decl;
|
||||
|
@ -1843,6 +1850,7 @@ func_decl * ast_manager::mk_func_decl(symbol const & name, unsigned arity, sort
|
|||
|
||||
void ast_manager::check_sort(func_decl const * decl, unsigned num_args, expr * const * args) const {
|
||||
ast_manager& m = const_cast<ast_manager&>(*this);
|
||||
|
||||
if (decl->is_associative()) {
|
||||
sort * expected = decl->get_domain(0);
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
|
@ -1887,7 +1895,18 @@ void ast_manager::check_sorts_core(ast const * n) const {
|
|||
if (n->get_kind() != AST_APP)
|
||||
return; // nothing else to check...
|
||||
app const * a = to_app(n);
|
||||
check_sort(a->get_decl(), a->get_num_args(), a->get_args());
|
||||
func_decl* d = a->get_decl();
|
||||
check_sort(d, a->get_num_args(), a->get_args());
|
||||
if (a->get_num_args() == 2 &&
|
||||
!d->is_flat_associative() &&
|
||||
d->is_right_associative()) {
|
||||
check_sorts_core(a->get_arg(1));
|
||||
}
|
||||
if (a->get_num_args() == 2 &&
|
||||
!d->is_flat_associative() &&
|
||||
d->is_left_associative()) {
|
||||
check_sorts_core(a->get_arg(0));
|
||||
}
|
||||
}
|
||||
|
||||
bool ast_manager::check_sorts(ast const * n) const {
|
||||
|
@ -3146,4 +3165,14 @@ void scoped_mark::pop_scope(unsigned num_scopes) {
|
|||
}
|
||||
}
|
||||
|
||||
// Added by KLM for use in GDB
|
||||
|
||||
// show an expr_ref on stdout
|
||||
|
||||
void prexpr(expr_ref &e){
|
||||
std::cout << mk_pp(e.get(), e.get_manager()) << std::endl;
|
||||
}
|
||||
|
||||
void ast_manager::show_id_gen(){
|
||||
std::cout << "id_gen: " << m_expr_id_gen.show_hash() << " " << m_decl_id_gen.show_hash() << "\n";
|
||||
}
|
||||
|
|
|
@ -1006,7 +1006,7 @@ enum basic_sort_kind {
|
|||
};
|
||||
|
||||
enum basic_op_kind {
|
||||
OP_TRUE, OP_FALSE, OP_EQ, OP_DISTINCT, OP_ITE, OP_AND, OP_OR, OP_IFF, OP_XOR, OP_NOT, OP_IMPLIES, OP_OEQ, LAST_BASIC_OP,
|
||||
OP_TRUE, OP_FALSE, OP_EQ, OP_DISTINCT, OP_ITE, OP_AND, OP_OR, OP_IFF, OP_XOR, OP_NOT, OP_IMPLIES, OP_OEQ, OP_INTERP, LAST_BASIC_OP,
|
||||
|
||||
PR_UNDEF, PR_TRUE, PR_ASSERTED, PR_GOAL, PR_MODUS_PONENS, PR_REFLEXIVITY, PR_SYMMETRY, PR_TRANSITIVITY, PR_TRANSITIVITY_STAR, PR_MONOTONICITY, PR_QUANT_INTRO,
|
||||
PR_DISTRIBUTIVITY, PR_AND_ELIM, PR_NOT_OR_ELIM, PR_REWRITE, PR_REWRITE_STAR, PR_PULL_QUANT,
|
||||
|
@ -1028,6 +1028,7 @@ protected:
|
|||
func_decl * m_iff_decl;
|
||||
func_decl * m_xor_decl;
|
||||
func_decl * m_not_decl;
|
||||
func_decl * m_interp_decl;
|
||||
func_decl * m_implies_decl;
|
||||
ptr_vector<func_decl> m_eq_decls; // cached eqs
|
||||
ptr_vector<func_decl> m_ite_decls; // cached ites
|
||||
|
@ -1417,6 +1418,8 @@ protected:
|
|||
public:
|
||||
typedef expr_dependency_array_manager::ref expr_dependency_array;
|
||||
|
||||
void show_id_gen();
|
||||
|
||||
protected:
|
||||
small_object_allocator m_alloc;
|
||||
family_manager m_family_manager;
|
||||
|
@ -2000,6 +2003,7 @@ public:
|
|||
app * mk_distinct_expanded(unsigned num_args, expr * const * args);
|
||||
app * mk_true() { return m_true; }
|
||||
app * mk_false() { return m_false; }
|
||||
app * mk_interp(expr * arg) { return mk_app(m_basic_family_id, OP_INTERP, arg); }
|
||||
|
||||
func_decl* mk_and_decl() {
|
||||
sort* domain[2] = { m_bool_sort, m_bool_sort };
|
||||
|
|
|
@ -472,6 +472,25 @@ class smt2_printer {
|
|||
ast_manager & m() const { return m_manager; }
|
||||
ast_manager & fm() const { return format_ns::fm(m()); }
|
||||
|
||||
std::string ensure_quote(symbol const& s) {
|
||||
std::string str;
|
||||
if (is_smt2_quoted_symbol(s))
|
||||
str = mk_smt2_quoted_symbol(s);
|
||||
else
|
||||
str = s.str();
|
||||
return str;
|
||||
}
|
||||
|
||||
symbol ensure_quote_sym(symbol const& s) {
|
||||
if (is_smt2_quoted_symbol(s)) {
|
||||
std::string str;
|
||||
str = mk_smt2_quoted_symbol(s);
|
||||
return symbol(str.c_str());
|
||||
}
|
||||
else
|
||||
return s;
|
||||
}
|
||||
|
||||
void pp_var(var * v) {
|
||||
format * f;
|
||||
if (v->get_idx() < m_var_names.size()) {
|
||||
|
@ -501,11 +520,7 @@ class smt2_printer {
|
|||
}
|
||||
|
||||
format * pp_simple_attribute(char const * attr, symbol const & s) {
|
||||
std::string str;
|
||||
if (is_smt2_quoted_symbol(s))
|
||||
str = mk_smt2_quoted_symbol(s);
|
||||
else
|
||||
str = s.str();
|
||||
std::string str = ensure_quote(s);
|
||||
return mk_compose(m(), mk_string(m(), attr), mk_string(m(), str.c_str()));
|
||||
}
|
||||
|
||||
|
@ -773,7 +788,7 @@ class smt2_printer {
|
|||
void register_var_names(quantifier * q) {
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
symbol name = q->get_decl_name(i);
|
||||
symbol name = ensure_quote_sym(q->get_decl_name(i));
|
||||
if (name.is_numerical()) {
|
||||
unsigned idx = 1;
|
||||
name = next_name("x", idx);
|
||||
|
@ -997,6 +1012,7 @@ public:
|
|||
unsigned idx = 1;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
symbol name = next_name(var_prefix, idx);
|
||||
name = ensure_quote_sym(name);
|
||||
var_names.push_back(name);
|
||||
m_var_names_set.insert(name);
|
||||
m_var_names.push_back(name);
|
||||
|
|
|
@ -569,8 +569,8 @@ class smt_printer {
|
|||
m_out << ")";
|
||||
}
|
||||
|
||||
if (m_is_smt2 && q->get_num_patterns() > 0) {
|
||||
m_out << "(!";
|
||||
if (m_is_smt2 && (q->get_num_patterns() > 0 || q->get_qid() != symbol::null)) {
|
||||
m_out << "(! ";
|
||||
}
|
||||
{
|
||||
smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, false, m_is_smt2, m_simplify_implies, m_indent, m_num_var_names, m_var_names);
|
||||
|
@ -609,7 +609,11 @@ class smt_printer {
|
|||
m_out << "}";
|
||||
}
|
||||
}
|
||||
if (m_is_smt2 && q->get_num_patterns() > 0) {
|
||||
|
||||
if (q->get_qid() != symbol::null)
|
||||
m_out << " :qid " << q->get_qid();
|
||||
|
||||
if (m_is_smt2 && (q->get_num_patterns() > 0 || q->get_qid() != symbol::null)) {
|
||||
m_out << ")";
|
||||
}
|
||||
m_out << ")";
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
ast_util.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Helper functions
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2007-06-08.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "ast_util.h"
|
||||
|
||||
app * mk_list_assoc_app(ast_manager & m, func_decl * f, unsigned num_args, expr * const * args) {
|
||||
|
@ -138,3 +156,38 @@ expr * get_clause_literal(ast_manager & m, expr * cls, unsigned idx) {
|
|||
SASSERT(m.is_or(cls));
|
||||
return to_app(cls)->get_arg(idx);
|
||||
}
|
||||
|
||||
expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
if (num_args == 0)
|
||||
return m.mk_true();
|
||||
else if (num_args == 1)
|
||||
return args[0];
|
||||
else
|
||||
return m.mk_and(num_args, args);
|
||||
}
|
||||
|
||||
expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
if (num_args == 0)
|
||||
return m.mk_false();
|
||||
else if (num_args == 1)
|
||||
return args[0];
|
||||
else
|
||||
return m.mk_or(num_args, args);
|
||||
}
|
||||
|
||||
expr * mk_not(ast_manager & m, expr * arg) {
|
||||
expr * atom;
|
||||
if (m.is_not(arg, atom))
|
||||
return atom;
|
||||
else
|
||||
return m.mk_not(arg);
|
||||
}
|
||||
|
||||
expr * expand_distinct(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
expr_ref_buffer new_diseqs(m);
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
for (unsigned j = i + 1; j < num_args; j++)
|
||||
new_diseqs.push_back(m.mk_not(m.mk_eq(args[i], args[j])));
|
||||
}
|
||||
return mk_and(m, new_diseqs.size(), new_diseqs.c_ptr());
|
||||
}
|
||||
|
|
|
@ -95,5 +95,36 @@ bool is_clause(ast_manager & m, expr * n);
|
|||
unsigned get_clause_num_literals(ast_manager & m, expr * cls);
|
||||
expr * get_clause_literal(ast_manager & m, expr * cls, unsigned idx);
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Goodies for creating Boolean expressions
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
/**
|
||||
Return (and args[0] ... args[num_args-1]) if num_args >= 2
|
||||
Return args[0] if num_args == 1
|
||||
Return true if num_args == 0
|
||||
*/
|
||||
expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
|
||||
/**
|
||||
Return (or args[0] ... args[num_args-1]) if num_args >= 2
|
||||
Return args[0] if num_args == 1
|
||||
Return false if num_args == 0
|
||||
*/
|
||||
expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
|
||||
/**
|
||||
Return a if arg = (not a)
|
||||
Retur (not arg) otherwise
|
||||
*/
|
||||
expr * mk_not(ast_manager & m, expr * arg);
|
||||
|
||||
/**
|
||||
Return the expression (and (not (= args[0] args[1])) (not (= args[0] args[2])) ... (not (= args[num_args-2] args[num_args-1])))
|
||||
*/
|
||||
expr * expand_distinct(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
|
||||
#endif /* _AST_UTIL_H_ */
|
||||
|
||||
|
|
|
@ -210,6 +210,10 @@ func_decl * bv_decl_plugin::mk_unary(ptr_vector<func_decl> & decls, decl_kind k,
|
|||
|
||||
func_decl * bv_decl_plugin::mk_int2bv(unsigned bv_size, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain) {
|
||||
if (bv_size == 0) {
|
||||
m_manager->raise_exception("bit-vector size must be greater than zero");
|
||||
}
|
||||
|
||||
force_ptr_array_size(m_int2bv, bv_size + 1);
|
||||
|
||||
if (arity != 1) {
|
||||
|
@ -415,6 +419,9 @@ func_decl * bv_decl_plugin::mk_num_decl(unsigned num_parameters, parameter const
|
|||
return 0;
|
||||
}
|
||||
unsigned bv_size = parameters[1].get_int();
|
||||
if (bv_size == 0) {
|
||||
m_manager->raise_exception("bit-vector size must be greater than zero");
|
||||
}
|
||||
// TODO: sign an error if the parameters[0] is out of range, that is, it is a value not in [0, 2^{bv_size})
|
||||
// This cannot be enforced now, since some Z3 modules try to generate these invalid numerals.
|
||||
// After SMT-COMP, I should find all offending modules.
|
||||
|
|
|
@ -84,7 +84,8 @@ class datatype_decl {
|
|||
ptr_vector<constructor_decl> m_constructors;
|
||||
public:
|
||||
datatype_decl(const symbol & n, unsigned num_constructors, constructor_decl * const * constructors):
|
||||
m_name(n), m_constructors(num_constructors, constructors) {}
|
||||
m_name(n), m_constructors(num_constructors, constructors) {
|
||||
}
|
||||
~datatype_decl() {
|
||||
std::for_each(m_constructors.begin(), m_constructors.end(), delete_proc<constructor_decl>());
|
||||
}
|
||||
|
|
|
@ -599,7 +599,23 @@ namespace datalog {
|
|||
return 0;
|
||||
}
|
||||
result = mk_compare(OP_DL_LT, m_lt_sym, domain);
|
||||
break;
|
||||
break;
|
||||
|
||||
case OP_DL_REP: {
|
||||
if (!check_domain(0, 0, num_parameters) ||
|
||||
!check_domain(1, 1, arity)) return 0;
|
||||
func_decl_info info(m_family_id, k, 0, 0);
|
||||
result = m_manager->mk_func_decl(symbol("rep"), 1, domain, range, info);
|
||||
break;
|
||||
}
|
||||
|
||||
case OP_DL_ABS: {
|
||||
if (!check_domain(0, 0, num_parameters) ||
|
||||
!check_domain(1, 1, arity)) return 0;
|
||||
func_decl_info info(m_family_id, k, 0, 0);
|
||||
result = m_manager->mk_func_decl(symbol("abs"), 1, domain, range, info);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
m_manager->raise_exception("operator not recognized");
|
||||
|
@ -657,7 +673,9 @@ namespace datalog {
|
|||
SASSERT(value == 1);
|
||||
return m.mk_true();
|
||||
}
|
||||
m.raise_exception("unrecognized sort");
|
||||
std::stringstream strm;
|
||||
strm << "sort '" << mk_pp(s, m) << "' is not recognized as a sort that contains numeric values.\nUse Bool, BitVec, Int, Real, or a Finite domain sort";
|
||||
m.raise_exception(strm.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ namespace datalog {
|
|||
OP_RA_CLONE,
|
||||
OP_DL_CONSTANT,
|
||||
OP_DL_LT,
|
||||
OP_DL_REP,
|
||||
OP_DL_ABS,
|
||||
LAST_RA_OP
|
||||
};
|
||||
|
||||
|
|
|
@ -40,11 +40,10 @@ void float_decl_plugin::set_manager(ast_manager * m, family_id id) {
|
|||
SASSERT(m_int_sort != 0); // arith_decl_plugin must be installed before float_decl_plugin.
|
||||
m_manager->inc_ref(m_int_sort);
|
||||
|
||||
if (m_manager->has_plugin(symbol("bv"))) {
|
||||
// bv plugin is optional, so m_bv_plugin may be 0
|
||||
// BV is not optional anymore.
|
||||
SASSERT(m_manager->has_plugin(symbol("bv")));
|
||||
m_bv_fid = m_manager->mk_family_id("bv");
|
||||
m_bv_plugin = static_cast<bv_decl_plugin*>(m_manager->get_plugin(m_bv_fid));
|
||||
}
|
||||
}
|
||||
|
||||
float_decl_plugin::~float_decl_plugin() {
|
||||
|
@ -85,10 +84,40 @@ bool float_decl_plugin::is_value(expr * n, mpf & val) {
|
|||
m_fm.set(val, m_values[to_app(n)->get_decl()->get_parameter(0).get_ext_id()]);
|
||||
return true;
|
||||
}
|
||||
else if (is_app_of(n, m_family_id, OP_FLOAT_MINUS_INF)) {
|
||||
unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
|
||||
unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
|
||||
m_fm.mk_ninf(ebits, sbits, val);
|
||||
return true;
|
||||
}
|
||||
else if (is_app_of(n, m_family_id, OP_FLOAT_PLUS_INF)) {
|
||||
unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
|
||||
unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
|
||||
m_fm.mk_pinf(ebits, sbits, val);
|
||||
return true;
|
||||
}
|
||||
else if (is_app_of(n, m_family_id, OP_FLOAT_NAN)) {
|
||||
unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
|
||||
unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
|
||||
m_fm.mk_nan(ebits, sbits, val);
|
||||
return true;
|
||||
}
|
||||
else if (is_app_of(n, m_family_id, OP_FLOAT_PLUS_ZERO)) {
|
||||
unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
|
||||
unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
|
||||
m_fm.mk_pzero(ebits, sbits, val);
|
||||
return true;
|
||||
}
|
||||
else if (is_app_of(n, m_family_id, OP_FLOAT_MINUS_ZERO)) {
|
||||
unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
|
||||
unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
|
||||
m_fm.mk_nzero(ebits, sbits, val);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool float_decl_plugin::is_rm(expr * n, mpf_rounding_mode & val) {
|
||||
bool float_decl_plugin::is_rm_value(expr * n, mpf_rounding_mode & val) {
|
||||
if (is_app_of(n, m_family_id, OP_RM_NEAREST_TIES_TO_AWAY)) {
|
||||
val = MPF_ROUND_NEAREST_TAWAY;
|
||||
return true;
|
||||
|
@ -138,7 +167,7 @@ sort * float_decl_plugin::mk_float_sort(unsigned ebits, unsigned sbits) {
|
|||
parameter ps[2] = { p1, p2 };
|
||||
sort_size sz;
|
||||
sz = sort_size::mk_very_big(); // TODO: refine
|
||||
return m_manager->mk_sort(symbol("FP"), sort_info(m_family_id, FLOAT_SORT, sz, 2, ps));
|
||||
return m_manager->mk_sort(symbol("FloatingPoint"), sort_info(m_family_id, FLOAT_SORT, sz, 2, ps));
|
||||
}
|
||||
|
||||
sort * float_decl_plugin::mk_rm_sort() {
|
||||
|
@ -158,6 +187,14 @@ sort * float_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, paramete
|
|||
return mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
case ROUNDING_MODE_SORT:
|
||||
return mk_rm_sort();
|
||||
case FLOAT16_SORT:
|
||||
return mk_float_sort(5, 11);
|
||||
case FLOAT32_SORT:
|
||||
return mk_float_sort(8, 24);
|
||||
case FLOAT64_SORT:
|
||||
return mk_float_sort(11, 53);
|
||||
case FLOAT128_SORT:
|
||||
return mk_float_sort(15, 133);
|
||||
default:
|
||||
m_manager->raise_exception("unknown floating point theory sort");
|
||||
return 0;
|
||||
|
@ -195,6 +232,9 @@ func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_par
|
|||
if (num_parameters == 1 && parameters[0].is_ast() && is_sort(parameters[0].get_ast()) && is_float_sort(to_sort(parameters[0].get_ast()))) {
|
||||
s = to_sort(parameters[0].get_ast());
|
||||
}
|
||||
else if (num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()) {
|
||||
s = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
}
|
||||
else if (range != 0 && is_float_sort(range)) {
|
||||
s = range;
|
||||
}
|
||||
|
@ -208,17 +248,18 @@ func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_par
|
|||
unsigned ebits = s->get_parameter(0).get_int();
|
||||
unsigned sbits = s->get_parameter(1).get_int();
|
||||
scoped_mpf val(m_fm);
|
||||
if (k == OP_FLOAT_NAN) {
|
||||
m_fm.mk_nan(ebits, sbits, val);
|
||||
|
||||
switch (k)
|
||||
{
|
||||
case OP_FLOAT_NAN: m_fm.mk_nan(ebits, sbits, val);
|
||||
SASSERT(m_fm.is_nan(val));
|
||||
break;
|
||||
case OP_FLOAT_MINUS_INF: m_fm.mk_ninf(ebits, sbits, val); break;
|
||||
case OP_FLOAT_PLUS_INF: m_fm.mk_pinf(ebits, sbits, val); break;
|
||||
case OP_FLOAT_MINUS_ZERO: m_fm.mk_nzero(ebits, sbits, val); break;
|
||||
case OP_FLOAT_PLUS_ZERO: m_fm.mk_pzero(ebits, sbits, val); break;
|
||||
}
|
||||
else if (k == OP_FLOAT_MINUS_INF) {
|
||||
m_fm.mk_ninf(ebits, sbits, val);
|
||||
}
|
||||
else {
|
||||
SASSERT(k == OP_FLOAT_PLUS_INF);
|
||||
m_fm.mk_pinf(ebits, sbits, val);
|
||||
}
|
||||
|
||||
return mk_value_decl(val);
|
||||
}
|
||||
|
||||
|
@ -227,14 +268,14 @@ func_decl * float_decl_plugin::mk_bin_rel_decl(decl_kind k, unsigned num_paramet
|
|||
if (arity != 2)
|
||||
m_manager->raise_exception("invalid number of arguments to floating point relation");
|
||||
if (domain[0] != domain[1] || !is_float_sort(domain[0]))
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
m_manager->raise_exception("sort mismatch, expected equal FloatingPoint sorts as arguments");
|
||||
symbol name;
|
||||
switch (k) {
|
||||
case OP_FLOAT_EQ: name = "=="; break;
|
||||
case OP_FLOAT_LT: name = "<"; break;
|
||||
case OP_FLOAT_GT: name = ">"; break;
|
||||
case OP_FLOAT_LE: name = "<="; break;
|
||||
case OP_FLOAT_GE: name = ">="; break;
|
||||
case OP_FLOAT_EQ: name = "fp.eq"; break;
|
||||
case OP_FLOAT_LT: name = "fp.lt"; break;
|
||||
case OP_FLOAT_GT: name = "fp.gt"; break;
|
||||
case OP_FLOAT_LE: name = "fp.lte"; break;
|
||||
case OP_FLOAT_GE: name = "fp.gte"; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -249,13 +290,18 @@ func_decl * float_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_param
|
|||
if (arity != 1)
|
||||
m_manager->raise_exception("invalid number of arguments to floating point relation");
|
||||
if (!is_float_sort(domain[0]))
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort");
|
||||
symbol name;
|
||||
switch (k) {
|
||||
case OP_FLOAT_IS_ZERO: name = "isZero"; break;
|
||||
case OP_FLOAT_IS_NZERO: name = "isNZero"; break;
|
||||
case OP_FLOAT_IS_PZERO: name = "isPZero"; break;
|
||||
case OP_FLOAT_IS_SIGN_MINUS: name = "isSignMinus"; break;
|
||||
case OP_FLOAT_IS_ZERO: name = "fp.isZero"; break;
|
||||
case OP_FLOAT_IS_NZERO: name = "fp.isNZero"; break;
|
||||
case OP_FLOAT_IS_PZERO: name = "fp.isPZero"; break;
|
||||
case OP_FLOAT_IS_NEGATIVE: name = "fp.isNegative"; break;
|
||||
case OP_FLOAT_IS_POSITIVE: name = "fp.isPositive"; break;
|
||||
case OP_FLOAT_IS_NAN: name = "fp.isNaN"; break;
|
||||
case OP_FLOAT_IS_INF: name = "fp.isInfinite"; break;
|
||||
case OP_FLOAT_IS_NORMAL: name = "fp.isNormal"; break;
|
||||
case OP_FLOAT_IS_SUBNORMAL: name = "fp.isSubnormal"; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -268,11 +314,11 @@ func_decl * float_decl_plugin::mk_unary_decl(decl_kind k, unsigned num_parameter
|
|||
if (arity != 1)
|
||||
m_manager->raise_exception("invalid number of arguments to floating point operator");
|
||||
if (!is_float_sort(domain[0]))
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort");
|
||||
symbol name;
|
||||
switch (k) {
|
||||
case OP_FLOAT_ABS: name = "abs"; break;
|
||||
case OP_FLOAT_UMINUS: name = "-"; break;
|
||||
case OP_FLOAT_ABS: name = "fp.abs"; break;
|
||||
case OP_FLOAT_NEG: name = "fp.neg"; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -285,12 +331,12 @@ func_decl * float_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_paramete
|
|||
if (arity != 2)
|
||||
m_manager->raise_exception("invalid number of arguments to floating point operator");
|
||||
if (domain[0] != domain[1] || !is_float_sort(domain[0]))
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
m_manager->raise_exception("sort mismatch, expected arguments of equal FloatingPoint sorts");
|
||||
symbol name;
|
||||
switch (k) {
|
||||
case OP_FLOAT_REM: name = "remainder"; break;
|
||||
case OP_FLOAT_MIN: name = "min"; break;
|
||||
case OP_FLOAT_MAX: name = "max"; break;
|
||||
case OP_FLOAT_REM: name = "fp.rem"; break;
|
||||
case OP_FLOAT_MIN: name = "fp.min"; break;
|
||||
case OP_FLOAT_MAX: name = "fp.max"; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -302,14 +348,16 @@ func_decl * float_decl_plugin::mk_rm_binary_decl(decl_kind k, unsigned num_param
|
|||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 3)
|
||||
m_manager->raise_exception("invalid number of arguments to floating point operator");
|
||||
if (!is_rm_sort(domain[0]) || domain[1] != domain[2] || !is_float_sort(domain[1]))
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
if (!is_rm_sort(domain[0]))
|
||||
m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort");
|
||||
if (domain[1] != domain[2] || !is_float_sort(domain[1]))
|
||||
m_manager->raise_exception("sort mismatch, expected arguments 1 and 2 of equal FloatingPoint sorts");
|
||||
symbol name;
|
||||
switch (k) {
|
||||
case OP_FLOAT_ADD: name = "+"; break;
|
||||
case OP_FLOAT_SUB: name = "-"; break;
|
||||
case OP_FLOAT_MUL: name = "*"; break;
|
||||
case OP_FLOAT_DIV: name = "/"; break;
|
||||
case OP_FLOAT_ADD: name = "fp.add"; break;
|
||||
case OP_FLOAT_SUB: name = "fp.sub"; break;
|
||||
case OP_FLOAT_MUL: name = "fp.mul"; break;
|
||||
case OP_FLOAT_DIV: name = "fp.div"; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -321,12 +369,14 @@ func_decl * float_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parame
|
|||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 2)
|
||||
m_manager->raise_exception("invalid number of arguments to floating point operator");
|
||||
if (!is_rm_sort(domain[0]) || !is_float_sort(domain[1]))
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
if (!is_rm_sort(domain[0]))
|
||||
m_manager->raise_exception("sort mismatch, expected RoundingMode as first argument");
|
||||
if (!is_float_sort(domain[1]))
|
||||
m_manager->raise_exception("sort mismatch, expected FloatingPoint as second argument");
|
||||
symbol name;
|
||||
switch (k) {
|
||||
case OP_FLOAT_SQRT: name = "squareRoot"; break;
|
||||
case OP_FLOAT_ROUND_TO_INTEGRAL: name = "roundToIntegral"; break;
|
||||
case OP_FLOAT_SQRT: name = "fp.sqrt"; break;
|
||||
case OP_FLOAT_ROUND_TO_INTEGRAL: name = "fp.roundToIntegral"; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -334,13 +384,15 @@ func_decl * float_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parame
|
|||
return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k));
|
||||
}
|
||||
|
||||
func_decl * float_decl_plugin::mk_fused_ma(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
func_decl * float_decl_plugin::mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 4)
|
||||
m_manager->raise_exception("invalid number of arguments to fused_ma operator");
|
||||
if (!is_rm_sort(domain[0]) || domain[1] != domain[2] || domain[1] != domain[3] || !is_float_sort(domain[1]))
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
symbol name("fusedMA");
|
||||
if (!is_rm_sort(domain[0]))
|
||||
m_manager->raise_exception("sort mismatch, expected RoundingMode as first argument");
|
||||
if (domain[1] != domain[2] || domain[1] != domain[3] || !is_float_sort(domain[1]))
|
||||
m_manager->raise_exception("sort mismatch, expected arguments 1,2,3 of equal FloatingPoint sort");
|
||||
symbol name("fp.fma");
|
||||
return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k));
|
||||
}
|
||||
|
||||
|
@ -350,39 +402,82 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters,
|
|||
is_sort_of(domain[0], m_bv_fid, BV_SORT) &&
|
||||
is_sort_of(domain[1], m_bv_fid, BV_SORT) &&
|
||||
is_sort_of(domain[2], m_bv_fid, BV_SORT)) {
|
||||
// When the bv_decl_plugin is installed, then we know how to convert 3 bit-vectors into a float!
|
||||
// 3 BVs -> 1 FP
|
||||
sort * fp = mk_float_sort(domain[2]->get_parameter(0).get_int(), domain[1]->get_parameter(0).get_int()+1);
|
||||
symbol name("asFloat");
|
||||
symbol name("fp");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
}
|
||||
else if (m_bv_plugin && arity == 1 && is_sort_of(domain[0], m_bv_fid, BV_SORT)) {
|
||||
// 1 BV -> 1 FP
|
||||
if (num_parameters != 2)
|
||||
m_manager->raise_exception("invalid number of parameters to to_fp");
|
||||
if (!parameters[0].is_int() || !parameters[1].is_int())
|
||||
m_manager->raise_exception("invalid parameter type to to_fp");
|
||||
int ebits = parameters[0].get_int();
|
||||
int sbits = parameters[1].get_int();
|
||||
|
||||
sort * fp = mk_float_sort(ebits, sbits);
|
||||
symbol name("to_fp");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
else if (m_bv_plugin && arity == 2 &&
|
||||
is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
|
||||
is_sort_of(domain[1], m_bv_fid, BV_SORT)) {
|
||||
// Rounding + 1 BV -> 1 FP
|
||||
if (num_parameters != 2)
|
||||
m_manager->raise_exception("invalid number of parameters to to_fp");
|
||||
if (!parameters[0].is_int() || !parameters[1].is_int())
|
||||
m_manager->raise_exception("invalid parameter type to to_fp");
|
||||
int ebits = parameters[0].get_int();
|
||||
int sbits = parameters[1].get_int();
|
||||
|
||||
sort * fp = mk_float_sort(ebits, sbits);
|
||||
symbol name("to_fp");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
else if (arity == 2 &&
|
||||
is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
|
||||
is_sort_of(domain[1], m_family_id, FLOAT_SORT)) {
|
||||
// Rounding + 1 FP -> 1 FP
|
||||
if (num_parameters != 2)
|
||||
m_manager->raise_exception("invalid number of parameters to to_fp");
|
||||
if (!parameters[0].is_int() || !parameters[1].is_int())
|
||||
m_manager->raise_exception("invalid parameter type to to_fp");
|
||||
int ebits = parameters[0].get_int();
|
||||
int sbits = parameters[1].get_int();
|
||||
if (!is_rm_sort(domain[0]))
|
||||
m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort");
|
||||
if (!is_sort_of(domain[1], m_family_id, FLOAT_SORT))
|
||||
m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort");
|
||||
|
||||
sort * fp = mk_float_sort(ebits, sbits);
|
||||
symbol name("to_fp");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
else {
|
||||
// .. Otherwise we only know how to convert rationals/reals.
|
||||
// 1 Real -> 1 FP
|
||||
if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
|
||||
m_manager->raise_exception("expecting two integer parameters to asFloat");
|
||||
m_manager->raise_exception("expecting two integer parameters to to_fp");
|
||||
if (arity != 2 && arity != 3)
|
||||
m_manager->raise_exception("invalid number of arguments to asFloat operator");
|
||||
m_manager->raise_exception("invalid number of arguments to to_fp operator");
|
||||
if (arity == 3 && domain[2] != m_int_sort)
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
if (!is_rm_sort(domain[0]) ||
|
||||
!(domain[1] == m_real_sort || is_sort_of(domain[1], m_family_id, FLOAT_SORT)))
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
m_manager->raise_exception("sort mismatch, expected second argument of Int sort");
|
||||
if (domain[1] != m_real_sort)
|
||||
m_manager->raise_exception("sort mismatch, expected second argument of Real sort");
|
||||
|
||||
sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
symbol name("asFloat");
|
||||
symbol name("to_fp");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
}
|
||||
|
||||
func_decl * float_decl_plugin::mk_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
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 (!m_bv_plugin)
|
||||
m_manager->raise_exception("asIEEEBV unsupported; use a logic with BV support");
|
||||
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");
|
||||
|
||||
// When the bv_decl_plugin is installed, then we know how to convert a float to an IEEE bit-vector.
|
||||
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);
|
||||
|
@ -390,6 +485,46 @@ func_decl * float_decl_plugin::mk_to_ieee_bv(decl_kind k, unsigned num_parameter
|
|||
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_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 3)
|
||||
m_manager->raise_exception("invalid number of arguments to fp");
|
||||
if (!is_sort_of(domain[0], m_bv_fid, BV_SORT) ||
|
||||
!is_sort_of(domain[1], m_bv_fid, BV_SORT) ||
|
||||
!is_sort_of(domain[2], m_bv_fid, BV_SORT))
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
|
||||
sort * fp = mk_float_sort(domain[1]->get_parameter(0).get_int(), domain[2]->get_parameter(0).get_int() + 1);
|
||||
symbol name("fp");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k));
|
||||
}
|
||||
|
||||
func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (!m_bv_plugin)
|
||||
m_manager->raise_exception("to_fp_unsigned unsupported; use a logic with BV support");
|
||||
if (arity != 2)
|
||||
m_manager->raise_exception("invalid number of arguments to to_fp_unsigned");
|
||||
if (is_rm_sort(domain[0]))
|
||||
m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort");
|
||||
if (!is_sort_of(domain[1], m_bv_fid, BV_SORT))
|
||||
m_manager->raise_exception("sort mismatch, expected second argument of BV sort");
|
||||
|
||||
sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
symbol name("fp.t_ubv");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k));
|
||||
}
|
||||
|
||||
func_decl * float_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
NOT_IMPLEMENTED_YET();
|
||||
}
|
||||
|
||||
func_decl * float_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
NOT_IMPLEMENTED_YET();
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -414,10 +549,15 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
case OP_FLOAT_IS_ZERO:
|
||||
case OP_FLOAT_IS_NZERO:
|
||||
case OP_FLOAT_IS_PZERO:
|
||||
case OP_FLOAT_IS_SIGN_MINUS:
|
||||
case OP_FLOAT_IS_NEGATIVE:
|
||||
case OP_FLOAT_IS_POSITIVE:
|
||||
case OP_FLOAT_IS_NAN:
|
||||
case OP_FLOAT_IS_INF:
|
||||
case OP_FLOAT_IS_NORMAL:
|
||||
case OP_FLOAT_IS_SUBNORMAL:
|
||||
return mk_unary_rel_decl(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FLOAT_ABS:
|
||||
case OP_FLOAT_UMINUS:
|
||||
case OP_FLOAT_NEG:
|
||||
return mk_unary_decl(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FLOAT_REM:
|
||||
case OP_FLOAT_MIN:
|
||||
|
@ -429,16 +569,24 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FLOAT_SUB:
|
||||
if (arity == 1)
|
||||
return mk_unary_decl(OP_FLOAT_UMINUS, num_parameters, parameters, arity, domain, range);
|
||||
return mk_unary_decl(OP_FLOAT_NEG, num_parameters, parameters, arity, domain, range);
|
||||
else
|
||||
return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FLOAT_SQRT:
|
||||
case OP_FLOAT_ROUND_TO_INTEGRAL:
|
||||
return mk_rm_unary_decl(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FLOAT_FUSED_MA:
|
||||
return mk_fused_ma(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_TO_IEEE_BV:
|
||||
return mk_to_ieee_bv(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FLOAT_FMA:
|
||||
return mk_fma(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);
|
||||
case OP_FLOAT_FP:
|
||||
return mk_from3bv(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FLOAT_TO_UBV:
|
||||
return mk_to_ubv(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FLOAT_TO_SBV:
|
||||
return mk_to_sbv(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FLOAT_TO_REAL:
|
||||
return mk_to_real(k, num_parameters, parameters, arity, domain, range);
|
||||
default:
|
||||
m_manager->raise_exception("unsupported floating point operator");
|
||||
return 0;
|
||||
|
@ -446,50 +594,67 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
}
|
||||
|
||||
void float_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
|
||||
op_names.push_back(builtin_name("plusInfinity", OP_FLOAT_PLUS_INF));
|
||||
op_names.push_back(builtin_name("minusInfinity", OP_FLOAT_MINUS_INF));
|
||||
// These are the operators from the final draft of the SMT FloatingPoint standard
|
||||
op_names.push_back(builtin_name("+oo", OP_FLOAT_PLUS_INF));
|
||||
op_names.push_back(builtin_name("-oo", OP_FLOAT_MINUS_INF));
|
||||
op_names.push_back(builtin_name("+zero", OP_FLOAT_PLUS_ZERO));
|
||||
op_names.push_back(builtin_name("-zero", OP_FLOAT_MINUS_ZERO));
|
||||
op_names.push_back(builtin_name("NaN", OP_FLOAT_NAN));
|
||||
|
||||
op_names.push_back(builtin_name("roundNearestTiesToEven", OP_RM_NEAREST_TIES_TO_EVEN));
|
||||
op_names.push_back(builtin_name("roundNearestTiesToAway", OP_RM_NEAREST_TIES_TO_AWAY));
|
||||
op_names.push_back(builtin_name("roundTowardPositive", OP_RM_TOWARD_POSITIVE));
|
||||
op_names.push_back(builtin_name("roundTowardNegative", OP_RM_TOWARD_NEGATIVE));
|
||||
op_names.push_back(builtin_name("roundTowardZero", OP_RM_TOWARD_ZERO));
|
||||
|
||||
op_names.push_back(builtin_name("+", OP_FLOAT_ADD));
|
||||
op_names.push_back(builtin_name("-", OP_FLOAT_SUB));
|
||||
op_names.push_back(builtin_name("/", OP_FLOAT_DIV));
|
||||
op_names.push_back(builtin_name("*", OP_FLOAT_MUL));
|
||||
op_names.push_back(builtin_name("RNE", OP_RM_NEAREST_TIES_TO_EVEN));
|
||||
op_names.push_back(builtin_name("RNA", OP_RM_NEAREST_TIES_TO_AWAY));
|
||||
op_names.push_back(builtin_name("RTP", OP_RM_TOWARD_POSITIVE));
|
||||
op_names.push_back(builtin_name("RTN", OP_RM_TOWARD_NEGATIVE));
|
||||
op_names.push_back(builtin_name("RTZ", OP_RM_TOWARD_ZERO));
|
||||
|
||||
op_names.push_back(builtin_name("abs", OP_FLOAT_ABS));
|
||||
op_names.push_back(builtin_name("remainder", OP_FLOAT_REM));
|
||||
op_names.push_back(builtin_name("fusedMA", OP_FLOAT_FUSED_MA));
|
||||
op_names.push_back(builtin_name("squareRoot", OP_FLOAT_SQRT));
|
||||
op_names.push_back(builtin_name("roundToIntegral", OP_FLOAT_ROUND_TO_INTEGRAL));
|
||||
|
||||
op_names.push_back(builtin_name("==", OP_FLOAT_EQ));
|
||||
|
||||
op_names.push_back(builtin_name("<", OP_FLOAT_LT));
|
||||
op_names.push_back(builtin_name(">", OP_FLOAT_GT));
|
||||
op_names.push_back(builtin_name("<=", OP_FLOAT_LE));
|
||||
op_names.push_back(builtin_name(">=", OP_FLOAT_GE));
|
||||
op_names.push_back(builtin_name("fp.abs", OP_FLOAT_ABS));
|
||||
op_names.push_back(builtin_name("fp.neg", OP_FLOAT_NEG));
|
||||
op_names.push_back(builtin_name("fp.add", OP_FLOAT_ADD));
|
||||
op_names.push_back(builtin_name("fp.sub", OP_FLOAT_SUB));
|
||||
op_names.push_back(builtin_name("fp.mul", OP_FLOAT_MUL));
|
||||
op_names.push_back(builtin_name("fp.div", OP_FLOAT_DIV));
|
||||
op_names.push_back(builtin_name("fp.fma", OP_FLOAT_FMA));
|
||||
op_names.push_back(builtin_name("fp.sqrt", OP_FLOAT_SQRT));
|
||||
op_names.push_back(builtin_name("fp.rem", OP_FLOAT_REM));
|
||||
op_names.push_back(builtin_name("fp.roundToIntegral", OP_FLOAT_ROUND_TO_INTEGRAL));
|
||||
op_names.push_back(builtin_name("fp.min", OP_FLOAT_MIN));
|
||||
op_names.push_back(builtin_name("fp.max", OP_FLOAT_MAX));
|
||||
op_names.push_back(builtin_name("fp.leq", OP_FLOAT_LE));
|
||||
op_names.push_back(builtin_name("fp.lt", OP_FLOAT_LT));
|
||||
op_names.push_back(builtin_name("fp.geq", OP_FLOAT_GE));
|
||||
op_names.push_back(builtin_name("fp.gt", OP_FLOAT_GT));
|
||||
op_names.push_back(builtin_name("fp.eq", OP_FLOAT_EQ));
|
||||
|
||||
op_names.push_back(builtin_name("isZero", OP_FLOAT_IS_ZERO));
|
||||
op_names.push_back(builtin_name("isNZero", OP_FLOAT_IS_NZERO));
|
||||
op_names.push_back(builtin_name("isPZero", OP_FLOAT_IS_PZERO));
|
||||
op_names.push_back(builtin_name("isSignMinus", OP_FLOAT_IS_SIGN_MINUS));
|
||||
op_names.push_back(builtin_name("fp.isNormal", OP_FLOAT_IS_NORMAL));
|
||||
op_names.push_back(builtin_name("fp.isSubnormal", OP_FLOAT_IS_SUBNORMAL));
|
||||
op_names.push_back(builtin_name("fp.isZero", OP_FLOAT_IS_ZERO));
|
||||
op_names.push_back(builtin_name("fp.isInfinite", OP_FLOAT_IS_INF));
|
||||
op_names.push_back(builtin_name("fp.isNaN", OP_FLOAT_IS_NAN));
|
||||
op_names.push_back(builtin_name("fp.isNegative", OP_FLOAT_IS_NEGATIVE));
|
||||
op_names.push_back(builtin_name("fp.isPositive", OP_FLOAT_IS_POSITIVE));
|
||||
|
||||
op_names.push_back(builtin_name("min", OP_FLOAT_MIN));
|
||||
op_names.push_back(builtin_name("max", OP_FLOAT_MAX));
|
||||
|
||||
op_names.push_back(builtin_name("asFloat", OP_TO_FLOAT));
|
||||
|
||||
if (m_bv_plugin)
|
||||
op_names.push_back(builtin_name("asIEEEBV", OP_TO_IEEE_BV));
|
||||
op_names.push_back(builtin_name("fp", OP_FLOAT_FP));
|
||||
op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV));
|
||||
op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV));
|
||||
|
||||
op_names.push_back(builtin_name("to_fp", OP_TO_FLOAT));
|
||||
}
|
||||
|
||||
void float_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbol const & logic) {
|
||||
sort_names.push_back(builtin_name("FP", FLOAT_SORT));
|
||||
sort_names.push_back(builtin_name("FloatingPoint", FLOAT_SORT));
|
||||
sort_names.push_back(builtin_name("RoundingMode", ROUNDING_MODE_SORT));
|
||||
|
||||
// The final theory supports three common FloatingPoint sorts
|
||||
sort_names.push_back(builtin_name("Float16", FLOAT16_SORT));
|
||||
sort_names.push_back(builtin_name("Float32", FLOAT32_SORT));
|
||||
sort_names.push_back(builtin_name("Float64", FLOAT64_SORT));
|
||||
sort_names.push_back(builtin_name("Float128", FLOAT128_SORT));
|
||||
}
|
||||
|
||||
expr * float_decl_plugin::get_some_value(sort * s) {
|
||||
|
@ -511,6 +676,11 @@ bool float_decl_plugin::is_value(app * e) const {
|
|||
case OP_RM_TOWARD_NEGATIVE:
|
||||
case OP_RM_TOWARD_ZERO:
|
||||
case OP_FLOAT_VALUE:
|
||||
case OP_FLOAT_PLUS_INF:
|
||||
case OP_FLOAT_MINUS_INF:
|
||||
case OP_FLOAT_PLUS_ZERO:
|
||||
case OP_FLOAT_MINUS_ZERO:
|
||||
case OP_FLOAT_NAN:
|
||||
return true;
|
||||
case OP_TO_FLOAT:
|
||||
return m_manager->is_value(e->get_arg(0));
|
||||
|
|
|
@ -27,7 +27,11 @@ Revision History:
|
|||
|
||||
enum float_sort_kind {
|
||||
FLOAT_SORT,
|
||||
ROUNDING_MODE_SORT
|
||||
ROUNDING_MODE_SORT,
|
||||
FLOAT16_SORT,
|
||||
FLOAT32_SORT,
|
||||
FLOAT64_SORT,
|
||||
FLOAT128_SORT
|
||||
};
|
||||
|
||||
enum float_op_kind {
|
||||
|
@ -37,22 +41,23 @@ enum float_op_kind {
|
|||
OP_RM_TOWARD_NEGATIVE,
|
||||
OP_RM_TOWARD_ZERO,
|
||||
|
||||
|
||||
OP_FLOAT_VALUE,
|
||||
OP_FLOAT_PLUS_INF,
|
||||
OP_FLOAT_MINUS_INF,
|
||||
OP_FLOAT_NAN,
|
||||
OP_FLOAT_PLUS_ZERO,
|
||||
OP_FLOAT_MINUS_ZERO,
|
||||
|
||||
OP_FLOAT_ADD,
|
||||
OP_FLOAT_SUB,
|
||||
OP_FLOAT_UMINUS,
|
||||
OP_FLOAT_NEG,
|
||||
OP_FLOAT_MUL,
|
||||
OP_FLOAT_DIV,
|
||||
OP_FLOAT_REM,
|
||||
OP_FLOAT_ABS,
|
||||
OP_FLOAT_MIN,
|
||||
OP_FLOAT_MAX,
|
||||
OP_FLOAT_FUSED_MA, // x*y + z
|
||||
OP_FLOAT_FMA, // x*y + z
|
||||
OP_FLOAT_SQRT,
|
||||
OP_FLOAT_ROUND_TO_INTEGRAL,
|
||||
|
||||
|
@ -61,13 +66,24 @@ enum float_op_kind {
|
|||
OP_FLOAT_GT,
|
||||
OP_FLOAT_LE,
|
||||
OP_FLOAT_GE,
|
||||
OP_FLOAT_IS_NAN,
|
||||
OP_FLOAT_IS_INF,
|
||||
OP_FLOAT_IS_ZERO,
|
||||
OP_FLOAT_IS_NZERO,
|
||||
OP_FLOAT_IS_NORMAL,
|
||||
OP_FLOAT_IS_SUBNORMAL,
|
||||
OP_FLOAT_IS_PZERO,
|
||||
OP_FLOAT_IS_SIGN_MINUS,
|
||||
OP_FLOAT_IS_NZERO,
|
||||
OP_FLOAT_IS_NEGATIVE,
|
||||
OP_FLOAT_IS_POSITIVE,
|
||||
|
||||
OP_TO_FLOAT,
|
||||
OP_TO_IEEE_BV,
|
||||
OP_FLOAT_TO_IEEE_BV,
|
||||
|
||||
OP_FLOAT_FP,
|
||||
OP_FLOAT_TO_FP,
|
||||
OP_FLOAT_TO_UBV,
|
||||
OP_FLOAT_TO_SBV,
|
||||
OP_FLOAT_TO_REAL,
|
||||
|
||||
LAST_FLOAT_OP
|
||||
};
|
||||
|
@ -115,13 +131,21 @@ class float_decl_plugin : public decl_plugin {
|
|||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_rm_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_fused_ma(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_to_float(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
func_decl * mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_from3bv(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);
|
||||
func_decl * mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
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);
|
||||
|
||||
|
||||
virtual void set_manager(ast_manager * m, family_id id);
|
||||
unsigned mk_id(mpf const & v);
|
||||
void recycled_id(unsigned id);
|
||||
|
@ -149,7 +173,8 @@ public:
|
|||
app * mk_value(mpf const & v);
|
||||
bool is_value(expr * n) { return is_app_of(n, m_family_id, OP_FLOAT_VALUE); }
|
||||
bool is_value(expr * n, mpf & val);
|
||||
bool is_rm(expr * n, mpf_rounding_mode & val);
|
||||
bool is_rm_value(expr * n, mpf_rounding_mode & val);
|
||||
bool is_rm_value(expr * n) { mpf_rounding_mode t; return is_rm_value(n, t); }
|
||||
|
||||
mpf const & get_value(unsigned id) const {
|
||||
SASSERT(m_value_table.contains(id));
|
||||
|
@ -174,11 +199,14 @@ public:
|
|||
family_id get_fid() const { return m_fid; }
|
||||
family_id get_family_id() const { return m_fid; }
|
||||
arith_util & au() { return m_a_util; }
|
||||
float_decl_plugin & plugin() { return *m_plugin; }
|
||||
|
||||
sort * mk_float_sort(unsigned ebits, unsigned sbits);
|
||||
sort * mk_rm_sort() { return m().mk_sort(m_fid, ROUNDING_MODE_SORT); }
|
||||
bool is_float(sort * s) { return is_sort_of(s, m_fid, FLOAT_SORT); }
|
||||
bool is_rm(sort * s) { return is_sort_of(s, m_fid, ROUNDING_MODE_SORT); }
|
||||
bool is_rm(sort * s) { return is_sort_of(s, m_fid, ROUNDING_MODE_SORT); }
|
||||
bool is_float(expr * e) { return is_float(m_manager.get_sort(e)); }
|
||||
bool is_rm(expr * e) { return is_rm(m_manager.get_sort(e)); }
|
||||
unsigned get_ebits(sort * s);
|
||||
unsigned get_sbits(sort * s);
|
||||
|
||||
|
@ -197,8 +225,8 @@ public:
|
|||
|
||||
app * mk_value(mpf const & v) { return m_plugin->mk_value(v); }
|
||||
bool is_value(expr * n) { return m_plugin->is_value(n); }
|
||||
bool is_value(expr * n, mpf & v) { return m_plugin->is_value(n, v); }
|
||||
bool is_rm(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm(n, v); }
|
||||
bool is_value(expr * n, mpf & v) { return m_plugin->is_value(n, v); }
|
||||
bool is_rm_value(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm_value(n, v); }
|
||||
|
||||
app * mk_pzero(unsigned ebits, unsigned sbits);
|
||||
app * mk_nzero(unsigned ebits, unsigned sbits);
|
||||
|
@ -219,16 +247,16 @@ public:
|
|||
app * mk_mul(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_MUL, arg1, arg2, arg3); }
|
||||
app * mk_sub(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_SUB, arg1, arg2, arg3); }
|
||||
app * mk_div(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_DIV, arg1, arg2, arg3); }
|
||||
app * mk_uminus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_UMINUS, arg1); }
|
||||
app * mk_neg(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_NEG, arg1); }
|
||||
app * mk_rem(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_REM, arg1, arg2); }
|
||||
app * mk_max(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MAX, arg1, arg2); }
|
||||
app * mk_min(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MIN, arg1, arg2); }
|
||||
app * mk_abs(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1, arg2); }
|
||||
app * mk_abs(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1); }
|
||||
app * mk_sqrt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_SQRT, arg1, arg2); }
|
||||
app * mk_round(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ROUND_TO_INTEGRAL, arg1, arg2); }
|
||||
app * mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) {
|
||||
app * mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) {
|
||||
expr * args[4] = { arg1, arg2, arg3, arg4 };
|
||||
return m().mk_app(m_fid, OP_FLOAT_FUSED_MA, 4, args);
|
||||
return m().mk_app(m_fid, OP_FLOAT_FMA, 4, args);
|
||||
}
|
||||
|
||||
app * mk_float_eq(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_EQ, arg1, arg2); }
|
||||
|
@ -237,14 +265,20 @@ public:
|
|||
app * mk_le(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_LE, arg1, arg2); }
|
||||
app * mk_ge(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_GE, arg1, arg2); }
|
||||
|
||||
app * mk_is_nan(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NAN, arg1); }
|
||||
app * mk_is_inf(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_INF, arg1); }
|
||||
app * mk_is_zero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_ZERO, arg1); }
|
||||
app * mk_is_normal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NORMAL, arg1); }
|
||||
app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SUBNORMAL, arg1); }
|
||||
app * mk_is_nzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NZERO, arg1); }
|
||||
app * mk_is_pzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_PZERO, arg1); }
|
||||
app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SIGN_MINUS, arg1); }
|
||||
app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); }
|
||||
app * mk_is_positive(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_POSITIVE, arg1); }
|
||||
app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); }
|
||||
|
||||
bool is_uminus(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_UMINUS); }
|
||||
bool is_neg(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_NEG); }
|
||||
|
||||
app * mk_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_TO_IEEE_BV, arg1); }
|
||||
app * mk_float_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_TO_IEEE_BV, arg1); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
2868
src/ast/fpa/fpa2bv_converter.cpp
Normal file
2868
src/ast/fpa/fpa2bv_converter.cpp
Normal file
File diff suppressed because it is too large
Load diff
176
src/ast/fpa/fpa2bv_converter.h
Normal file
176
src/ast/fpa/fpa2bv_converter.h
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
fpa2bv_converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Conversion routines for Floating Point -> Bit-Vector
|
||||
|
||||
Author:
|
||||
|
||||
Christoph (cwinter) 2012-02-09
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _FPA2BV_CONVERTER_
|
||||
#define _FPA2BV_CONVERTER_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"ref_util.h"
|
||||
#include"float_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"basic_simplifier_plugin.h"
|
||||
|
||||
typedef enum { BV_RM_TIES_TO_AWAY=0, BV_RM_TIES_TO_EVEN=1, BV_RM_TO_NEGATIVE=2, BV_RM_TO_POSITIVE=3, BV_RM_TO_ZERO=4 } BV_RM_VAL;
|
||||
|
||||
struct func_decl_triple {
|
||||
func_decl_triple () { f_sgn = 0; f_sig = 0; f_exp = 0; }
|
||||
func_decl_triple (func_decl * sgn, func_decl * sig, func_decl * exp)
|
||||
{
|
||||
f_sgn = sgn;
|
||||
f_sig = sig;
|
||||
f_exp = exp;
|
||||
}
|
||||
func_decl * f_sgn;
|
||||
func_decl * f_sig;
|
||||
func_decl * f_exp;
|
||||
};
|
||||
|
||||
class fpa2bv_converter {
|
||||
ast_manager & m;
|
||||
basic_simplifier_plugin m_simp;
|
||||
float_util m_util;
|
||||
bv_util m_bv_util;
|
||||
arith_util m_arith_util;
|
||||
mpf_manager & m_mpf_manager;
|
||||
unsynch_mpz_manager & m_mpz_manager;
|
||||
float_decl_plugin * m_plugin;
|
||||
|
||||
obj_map<func_decl, expr*> m_const2bv;
|
||||
obj_map<func_decl, expr*> m_rm_const2bv;
|
||||
obj_map<func_decl, func_decl*> m_uf2bvuf;
|
||||
obj_map<func_decl, func_decl_triple> m_uf23bvuf;
|
||||
|
||||
public:
|
||||
fpa2bv_converter(ast_manager & m);
|
||||
~fpa2bv_converter();
|
||||
|
||||
float_util & fu() { return m_util; }
|
||||
bv_util & bu() { return m_bv_util; }
|
||||
|
||||
bool is_float(sort * s) { return m_util.is_float(s); }
|
||||
bool is_float(expr * e) { return is_app(e) && m_util.is_float(to_app(e)->get_decl()->get_range()); }
|
||||
bool is_rm(expr * e) { return m_util.is_rm(e); }
|
||||
bool is_rm(sort * s) { return m_util.is_rm(s); }
|
||||
bool is_float_family(func_decl * f) { return f->get_family_id() == m_util.get_family_id(); }
|
||||
|
||||
void mk_triple(expr * sign, expr * significand, expr * exponent, expr_ref & result) {
|
||||
SASSERT(m_bv_util.is_bv(sign) && m_bv_util.get_bv_size(sign) == 1);
|
||||
SASSERT(m_bv_util.is_bv(significand));
|
||||
SASSERT(m_bv_util.is_bv(exponent));
|
||||
result = m.mk_app(m_util.get_family_id(), OP_TO_FLOAT, sign, significand, exponent);
|
||||
}
|
||||
|
||||
void mk_eq(expr * a, expr * b, expr_ref & result);
|
||||
void mk_ite(expr * c, expr * t, expr * f, expr_ref & result);
|
||||
|
||||
void mk_rounding_mode(func_decl * f, expr_ref & result);
|
||||
void mk_value(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_const(func_decl * f, expr_ref & result);
|
||||
void mk_rm_const(func_decl * f, expr_ref & result);
|
||||
void mk_uninterpreted_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_var(unsigned base_inx, sort * srt, expr_ref & result);
|
||||
|
||||
void mk_plus_inf(func_decl * f, expr_ref & result);
|
||||
void mk_minus_inf(func_decl * f, expr_ref & result);
|
||||
void mk_nan(func_decl * f, expr_ref & result);
|
||||
void mk_nzero(func_decl *f, expr_ref & result);
|
||||
void mk_pzero(func_decl *f, expr_ref & result);
|
||||
|
||||
void mk_add(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_sub(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_neg(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_mul(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_div(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_rem(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_abs(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_min(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_fma(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_sqrt(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_round_to_integral(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
|
||||
void mk_float_eq(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_float_lt(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_float_gt(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_float_le(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_float_ge(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
|
||||
void mk_is_zero(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_is_nzero(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_is_pzero(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_is_negative(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_is_positive(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_is_nan(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_is_inf(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_is_normal(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_is_subnormal(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
|
||||
void mk_to_float(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
|
||||
void mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
|
||||
obj_map<func_decl, expr*> const & const2bv() const { return m_const2bv; }
|
||||
obj_map<func_decl, expr*> const & rm_const2bv() const { return m_rm_const2bv; }
|
||||
obj_map<func_decl, func_decl*> const & uf2bvuf() const { return m_uf2bvuf; }
|
||||
obj_map<func_decl, func_decl_triple> const & uf23bvuf() const { return m_uf23bvuf; }
|
||||
|
||||
void dbg_decouple(const char * prefix, expr_ref & e);
|
||||
expr_ref_vector extra_assertions;
|
||||
|
||||
protected:
|
||||
void split(expr * e, expr * & sgn, expr * & sig, expr * & exp) const;
|
||||
|
||||
void mk_is_nan(expr * e, expr_ref & result);
|
||||
void mk_is_inf(expr * e, expr_ref & result);
|
||||
void mk_is_pinf(expr * e, expr_ref & result);
|
||||
void mk_is_ninf(expr * e, expr_ref & result);
|
||||
void mk_is_pos(expr * e, expr_ref & result);
|
||||
void mk_is_neg(expr * e, expr_ref & result);
|
||||
void mk_is_zero(expr * e, expr_ref & result);
|
||||
void mk_is_nzero(expr * e, expr_ref & result);
|
||||
void mk_is_pzero(expr * e, expr_ref & result);
|
||||
void mk_is_denormal(expr * e, expr_ref & result);
|
||||
void mk_is_normal(expr * e, expr_ref & result);
|
||||
|
||||
void mk_is_rm(expr * e, BV_RM_VAL rm, expr_ref & result);
|
||||
|
||||
void mk_top_exp(unsigned sz, expr_ref & result);
|
||||
void mk_bot_exp(unsigned sz, expr_ref & result);
|
||||
void mk_min_exp(unsigned ebits, expr_ref & result);
|
||||
void mk_max_exp(unsigned ebits, expr_ref & result);
|
||||
|
||||
void mk_leading_zeros(expr * e, unsigned max_bits, expr_ref & result);
|
||||
|
||||
void mk_bias(expr * e, expr_ref & result);
|
||||
void mk_unbias(expr * e, expr_ref & result);
|
||||
|
||||
void unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & lz, bool normalize);
|
||||
void round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & result);
|
||||
|
||||
void add_core(unsigned sbits, unsigned ebits, expr_ref & rm,
|
||||
expr_ref & c_sgn, expr_ref & c_sig, expr_ref & c_exp, expr_ref & d_sgn, expr_ref & d_sig, expr_ref & d_exp,
|
||||
expr_ref & res_sgn, expr_ref & res_sig, expr_ref & res_exp);
|
||||
};
|
||||
|
||||
#endif
|
275
src/ast/fpa/fpa2bv_rewriter.h
Normal file
275
src/ast/fpa/fpa2bv_rewriter.h
Normal file
|
@ -0,0 +1,275 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
fpa2bv_rewriter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Rewriter for converting FPA to BV
|
||||
|
||||
Author:
|
||||
|
||||
Christoph (cwinter) 2012-02-09
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _FPA2BV_REWRITER_H_
|
||||
#define _FPA2BV_REWRITER_H_
|
||||
|
||||
#include"cooperate.h"
|
||||
#include"rewriter_def.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"fpa2bv_converter.h"
|
||||
|
||||
struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
|
||||
ast_manager & m_manager;
|
||||
expr_ref_vector m_out;
|
||||
fpa2bv_converter & m_conv;
|
||||
sort_ref_vector m_bindings;
|
||||
|
||||
unsigned long long m_max_memory;
|
||||
unsigned m_max_steps;
|
||||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
|
||||
fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c, params_ref const & p):
|
||||
m_manager(m),
|
||||
m_out(m),
|
||||
m_conv(c),
|
||||
m_bindings(m) {
|
||||
updt_params(p);
|
||||
// We need to make sure that the mananger has the BV plugin loaded.
|
||||
symbol s_bv("bv");
|
||||
if (!m_manager.has_plugin(s_bv))
|
||||
m_manager.register_plugin(s_bv, alloc(bv_decl_plugin));
|
||||
}
|
||||
|
||||
~fpa2bv_rewriter_cfg() {
|
||||
}
|
||||
|
||||
void cleanup_buffers() {
|
||||
m_out.finalize();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
|
||||
m_max_steps = p.get_uint("max_steps", UINT_MAX);
|
||||
}
|
||||
|
||||
bool max_steps_exceeded(unsigned num_steps) const {
|
||||
cooperate("fpa2bv");
|
||||
return num_steps > m_max_steps;
|
||||
}
|
||||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
TRACE("fpa2bv_rw", tout << "APP: " << f->get_name() << std::endl; );
|
||||
|
||||
if (num == 0 && f->get_family_id() == null_family_id && m_conv.is_float(f->get_range())) {
|
||||
m_conv.mk_const(f, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
if (num == 0 && f->get_family_id() == null_family_id && m_conv.is_rm(f->get_range())) {
|
||||
m_conv.mk_rm_const(f, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
if (m().is_eq(f)) {
|
||||
SASSERT(num == 2);
|
||||
SASSERT(m().get_sort(args[0]) == m().get_sort(args[1]));
|
||||
sort * ds = f->get_domain()[0];
|
||||
if (m_conv.is_float(ds)) {
|
||||
m_conv.mk_eq(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (m_conv.is_rm(ds)) {
|
||||
result = m().mk_eq(args[0], args[1]);
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
if (m().is_ite(f)) {
|
||||
SASSERT(num == 3);
|
||||
if (m_conv.is_float(args[1])) {
|
||||
m_conv.mk_ite(args[0], args[1], args[2], result);
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
if (m_conv.is_float_family(f)) {
|
||||
switch (f->get_decl_kind()) {
|
||||
case OP_RM_NEAREST_TIES_TO_AWAY:
|
||||
case OP_RM_NEAREST_TIES_TO_EVEN:
|
||||
case OP_RM_TOWARD_NEGATIVE:
|
||||
case OP_RM_TOWARD_POSITIVE:
|
||||
case OP_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE;
|
||||
case OP_FLOAT_VALUE: m_conv.mk_value(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_PLUS_INF: m_conv.mk_plus_inf(f, result); return BR_DONE;
|
||||
case OP_FLOAT_MINUS_INF: m_conv.mk_minus_inf(f, result); return BR_DONE;
|
||||
case OP_FLOAT_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE;
|
||||
case OP_FLOAT_MINUS_ZERO: m_conv.mk_nzero(f, result); return BR_DONE;
|
||||
case OP_FLOAT_NAN: m_conv.mk_nan(f, result); return BR_DONE;
|
||||
case OP_FLOAT_ADD: m_conv.mk_add(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_SUB: m_conv.mk_sub(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_NEG: m_conv.mk_neg(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_MUL: m_conv.mk_mul(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_MIN: m_conv.mk_min(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_MAX: m_conv.mk_max(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_EQ: m_conv.mk_float_eq(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_LT: m_conv.mk_float_lt(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_GT: m_conv.mk_float_gt(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_LE: m_conv.mk_float_le(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_GE: m_conv.mk_float_ge(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_IS_NZERO: m_conv.mk_is_nzero(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_IS_PZERO: m_conv.mk_is_pzero(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_IS_NAN: m_conv.mk_is_nan(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE;
|
||||
case OP_TO_FLOAT: m_conv.mk_to_float(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE;
|
||||
case OP_FLOAT_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE;
|
||||
default:
|
||||
TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n";
|
||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;);
|
||||
NOT_IMPLEMENTED_YET();
|
||||
}
|
||||
}
|
||||
|
||||
if (f->get_family_id() == null_family_id)
|
||||
{
|
||||
bool is_float_uf = m_conv.is_float(f->get_range());
|
||||
unsigned i = 0;
|
||||
while (!is_float_uf && i < num)
|
||||
{
|
||||
is_float_uf = m_conv.is_float(f->get_domain()[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (is_float_uf)
|
||||
{
|
||||
m_conv.mk_uninterpreted_function(f, num, args, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
bool pre_visit(expr * t)
|
||||
{
|
||||
TRACE("fpa2bv", tout << "pre_visit: " << mk_ismt2_pp(t, m()) << std::endl;);
|
||||
|
||||
if (is_quantifier(t)) {
|
||||
quantifier * q = to_quantifier(t);
|
||||
TRACE("fpa2bv", tout << "pre_visit quantifier [" << q->get_id() << "]: " << mk_ismt2_pp(q->get_expr(), m()) << std::endl;);
|
||||
sort_ref_vector new_bindings(m_manager);
|
||||
for (unsigned i = 0 ; i < q->get_num_decls(); i++)
|
||||
new_bindings.push_back(q->get_decl_sort(i));
|
||||
SASSERT(new_bindings.size() == q->get_num_decls());
|
||||
m_bindings.append(new_bindings);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
unsigned curr_sz = m_bindings.size();
|
||||
SASSERT(old_q->get_num_decls() <= curr_sz);
|
||||
unsigned num_decls = old_q->get_num_decls();
|
||||
unsigned old_sz = curr_sz - num_decls;
|
||||
string_buffer<> name_buffer;
|
||||
ptr_buffer<sort> new_decl_sorts;
|
||||
sbuffer<symbol> new_decl_names;
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
symbol const & n = old_q->get_decl_name(i);
|
||||
sort * s = old_q->get_decl_sort(i);
|
||||
if (m_conv.is_float(s)) {
|
||||
unsigned ebits = m_conv.fu().get_ebits(s);
|
||||
unsigned sbits = m_conv.fu().get_sbits(s);
|
||||
name_buffer.reset();
|
||||
name_buffer << n << ".bv";
|
||||
new_decl_names.push_back(symbol(name_buffer.c_str()));
|
||||
new_decl_sorts.push_back(m_conv.bu().mk_sort(sbits+ebits));
|
||||
}
|
||||
else {
|
||||
new_decl_sorts.push_back(s);
|
||||
new_decl_names.push_back(n);
|
||||
}
|
||||
}
|
||||
result = m().mk_quantifier(old_q->is_forall(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
|
||||
new_body, old_q->get_weight(), old_q->get_qid(), old_q->get_skid(),
|
||||
old_q->get_num_patterns(), new_patterns, old_q->get_num_no_patterns(), new_no_patterns);
|
||||
result_pr = 0;
|
||||
m_bindings.shrink(old_sz);
|
||||
TRACE("fpa2bv", tout << "reduce_quantifier[" << old_q->get_depth() << "]: " <<
|
||||
mk_ismt2_pp(old_q->get_expr(), m()) << std::endl <<
|
||||
" new body: " << mk_ismt2_pp(new_body, m()) << std::endl;
|
||||
tout << "result = " << mk_ismt2_pp(result, m()) << std::endl;);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool reduce_var(var * t, expr_ref & result, proof_ref & result_pr) {
|
||||
if (t->get_idx() >= m_bindings.size())
|
||||
return false;
|
||||
// unsigned inx = m_bindings.size() - t->get_idx() - 1;
|
||||
|
||||
expr_ref new_exp(m());
|
||||
sort * s = t->get_sort();
|
||||
if (m_conv.is_float(s))
|
||||
{
|
||||
expr_ref new_var(m());
|
||||
unsigned ebits = m_conv.fu().get_ebits(s);
|
||||
unsigned sbits = m_conv.fu().get_sbits(s);
|
||||
new_var = m().mk_var(t->get_idx(), m_conv.bu().mk_sort(sbits+ebits));
|
||||
m_conv.mk_triple(m_conv.bu().mk_extract(sbits+ebits-1, sbits+ebits-1, new_var),
|
||||
m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var),
|
||||
m_conv.bu().mk_extract(ebits-1, 0, new_var),
|
||||
new_exp);
|
||||
}
|
||||
else
|
||||
new_exp = m().mk_var(t->get_idx(), s);
|
||||
|
||||
result = new_exp;
|
||||
result_pr = 0;
|
||||
TRACE("fpa2bv", tout << "reduce_var: " << mk_ismt2_pp(t, m()) << " -> " << mk_ismt2_pp(result, m()) << std::endl;);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template class rewriter_tpl<fpa2bv_rewriter_cfg>;
|
||||
|
||||
struct fpa2bv_rewriter : public rewriter_tpl<fpa2bv_rewriter_cfg> {
|
||||
fpa2bv_rewriter_cfg m_cfg;
|
||||
fpa2bv_rewriter(ast_manager & m, fpa2bv_converter & c, params_ref const & p):
|
||||
rewriter_tpl<fpa2bv_rewriter_cfg>(m, m.proofs_enabled(), m_cfg),
|
||||
m_cfg(m, c, p) {
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -41,7 +41,7 @@ void quasi_macros::find_occurrences(expr * e) {
|
|||
|
||||
// we remember whether we have seen an expr once, or more than once;
|
||||
// when we see it the second time, we don't have to visit it another time,
|
||||
// as we are only intersted in finding unique function applications.
|
||||
// as we are only interested in finding unique function applications.
|
||||
m_visited_once.reset();
|
||||
m_visited_more.reset();
|
||||
|
||||
|
@ -61,7 +61,7 @@ void quasi_macros::find_occurrences(expr * e) {
|
|||
case AST_VAR: break;
|
||||
case AST_QUANTIFIER: m_todo.push_back(to_quantifier(cur)->get_expr()); break;
|
||||
case AST_APP:
|
||||
if (is_uninterp(cur) && !is_ground(cur)) {
|
||||
if (is_non_ground_uninterp(cur)) {
|
||||
func_decl * f = to_app(cur)->get_decl();
|
||||
m_occurrences.insert_if_not_there(f, 0);
|
||||
occurrences_map::iterator it = m_occurrences.find_iterator(f);
|
||||
|
@ -76,6 +76,10 @@ void quasi_macros::find_occurrences(expr * e) {
|
|||
}
|
||||
};
|
||||
|
||||
bool quasi_macros::is_non_ground_uninterp(expr const * e) const {
|
||||
return is_non_ground(e) && is_uninterp(e);
|
||||
}
|
||||
|
||||
bool quasi_macros::is_unique(func_decl * f) const {
|
||||
return m_occurrences.find(f) == 1;
|
||||
}
|
||||
|
@ -149,6 +153,7 @@ bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
|
|||
// Our definition of a quasi-macro:
|
||||
// Forall X. f[X] = T[X], where f[X] is a term starting with symbol f, f is uninterpreted,
|
||||
// f[X] contains all universally quantified variables, and f does not occur in T[X].
|
||||
TRACE("quasi_macros", tout << "Checking for quasi macro: " << mk_pp(e, m_manager) << std::endl;);
|
||||
|
||||
if (is_quantifier(e) && to_quantifier(e)->is_forall()) {
|
||||
quantifier * q = to_quantifier(e);
|
||||
|
@ -157,23 +162,23 @@ bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
|
|||
expr * lhs = to_app(qe)->get_arg(0);
|
||||
expr * rhs = to_app(qe)->get_arg(1);
|
||||
|
||||
if (is_uninterp(lhs) && is_unique(to_app(lhs)->get_decl()) &&
|
||||
if (is_non_ground_uninterp(lhs) && is_unique(to_app(lhs)->get_decl()) &&
|
||||
!depends_on(rhs, to_app(lhs)->get_decl()) && fully_depends_on(to_app(lhs), q)) {
|
||||
a = to_app(lhs);
|
||||
t = rhs;
|
||||
return true;
|
||||
} else if (is_uninterp(rhs) && is_unique(to_app(rhs)->get_decl()) &&
|
||||
} else if (is_non_ground_uninterp(rhs) && is_unique(to_app(rhs)->get_decl()) &&
|
||||
!depends_on(lhs, to_app(rhs)->get_decl()) && fully_depends_on(to_app(rhs), q)) {
|
||||
a = to_app(rhs);
|
||||
t = lhs;
|
||||
return true;
|
||||
}
|
||||
} else if (m_manager.is_not(qe) && is_uninterp(to_app(qe)->get_arg(0)) &&
|
||||
} else if (m_manager.is_not(qe) && is_non_ground_uninterp(to_app(qe)->get_arg(0)) &&
|
||||
is_unique(to_app(to_app(qe)->get_arg(0))->get_decl())) { // this is like f(...) = false
|
||||
a = to_app(to_app(qe)->get_arg(0));
|
||||
t = m_manager.mk_false();
|
||||
return true;
|
||||
} else if (is_uninterp(qe) && is_unique(to_app(qe)->get_decl())) { // this is like f(...) = true
|
||||
} else if (is_non_ground_uninterp(qe) && is_unique(to_app(qe)->get_decl())) { // this is like f(...) = true
|
||||
a = to_app(qe);
|
||||
t = m_manager.mk_true();
|
||||
return true;
|
||||
|
|
|
@ -45,6 +45,7 @@ class quasi_macros {
|
|||
expr_mark m_visited_more;
|
||||
|
||||
bool is_unique(func_decl * f) const;
|
||||
bool is_non_ground_uninterp(expr const * e) const;
|
||||
bool fully_depends_on(app * a, quantifier * q) const;
|
||||
bool depends_on(expr * e, func_decl * f) const;
|
||||
|
||||
|
|
|
@ -479,7 +479,7 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
|||
// otherwise t2 is also a quantifier.
|
||||
return true;
|
||||
}
|
||||
UNREACHABLE();
|
||||
IF_VERBOSE(0, verbose_stream() << "does not match last rule: " << mk_pp(p, m) << "\n";);
|
||||
return false;
|
||||
}
|
||||
case PR_DER: {
|
||||
|
@ -488,13 +488,12 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
|||
match_fact(p, fact) &&
|
||||
match_iff(fact.get(), t1, t2) &&
|
||||
match_quantifier(t1, is_forall, decls1, body1) &&
|
||||
is_forall &&
|
||||
match_or(body1.get(), terms1)) {
|
||||
is_forall) {
|
||||
// TBD: check that terms are set of equalities.
|
||||
// t2 is an instance of a predicate in terms1
|
||||
return true;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
IF_VERBOSE(0, verbose_stream() << "does not match last rule: " << mk_pp(p, m) << "\n";);
|
||||
return false;
|
||||
}
|
||||
case PR_HYPOTHESIS: {
|
||||
|
@ -832,7 +831,7 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
|||
}
|
||||
else {
|
||||
IF_VERBOSE(0, verbose_stream() << "Could not establish complementarity for:\n" <<
|
||||
mk_pp(lit1, m) << "\n" << mk_pp(lit2, m) << "\n";);
|
||||
mk_pp(lit1, m) << "\n" << mk_pp(lit2, m) << "\n" << mk_pp(p, m) << "\n";);
|
||||
}
|
||||
fmls[i] = premise1;
|
||||
}
|
||||
|
|
|
@ -753,12 +753,7 @@ br_status arith_rewriter::mk_rem_core(expr * arg1, expr * arg2, expr_ref & resul
|
|||
}
|
||||
else if (m_util.is_numeral(arg2, v2, is_int) && is_int && !v2.is_zero()) {
|
||||
if (is_add(arg1) || is_mul(arg1)) {
|
||||
ptr_buffer<expr> new_args;
|
||||
unsigned num_args = to_app(arg1)->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; i++)
|
||||
new_args.push_back(m_util.mk_rem(to_app(arg1)->get_arg(i), arg2));
|
||||
result = m().mk_app(to_app(arg1)->get_decl(), new_args.size(), new_args.c_ptr());
|
||||
return BR_REWRITE2;
|
||||
return BR_FAILED;
|
||||
}
|
||||
else {
|
||||
if (v2.is_neg()) {
|
||||
|
|
|
@ -118,7 +118,7 @@ public:
|
|||
|
||||
void mk_eq(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_eq_core(arg1, arg2, result) == BR_FAILED)
|
||||
result = m_util.mk_le(arg1, arg2);
|
||||
result = m_util.mk_eq(arg1, arg2);
|
||||
}
|
||||
void mk_le(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_le_core(arg1, arg2, result) == BR_FAILED)
|
||||
|
|
|
@ -108,6 +108,7 @@ void var_counter::count_vars(ast_manager & m, const app * pred, int coef) {
|
|||
unsigned var_counter::get_max_var(bool& has_var) {
|
||||
has_var = false;
|
||||
unsigned max_var = 0;
|
||||
ptr_vector<quantifier> qs;
|
||||
while (!m_todo.empty()) {
|
||||
expr* e = m_todo.back();
|
||||
m_todo.pop_back();
|
||||
|
@ -117,14 +118,7 @@ unsigned var_counter::get_max_var(bool& has_var) {
|
|||
m_visited.mark(e, true);
|
||||
switch(e->get_kind()) {
|
||||
case AST_QUANTIFIER: {
|
||||
var_counter aux_counter;
|
||||
quantifier* q = to_quantifier(e);
|
||||
bool has_var1 = false;
|
||||
unsigned max_v = aux_counter.get_max_var(has_var1);
|
||||
if (max_v > max_var + q->get_num_decls()) {
|
||||
max_var = max_v - q->get_num_decls();
|
||||
has_var = true;
|
||||
}
|
||||
qs.push_back(to_quantifier(e));
|
||||
break;
|
||||
}
|
||||
case AST_VAR: {
|
||||
|
@ -147,6 +141,20 @@ unsigned var_counter::get_max_var(bool& has_var) {
|
|||
}
|
||||
}
|
||||
m_visited.reset();
|
||||
|
||||
while (!qs.empty()) {
|
||||
var_counter aux_counter;
|
||||
quantifier* q = qs.back();
|
||||
qs.pop_back();
|
||||
aux_counter.m_todo.push_back(q->get_expr());
|
||||
bool has_var1 = false;
|
||||
unsigned max_v = aux_counter.get_max_var(has_var1);
|
||||
if (max_v >= max_var + q->get_num_decls()) {
|
||||
max_var = max_v - q->get_num_decls();
|
||||
has_var = has_var || has_var1;
|
||||
}
|
||||
}
|
||||
|
||||
return max_var;
|
||||
}
|
||||
|
||||
|
|
|
@ -323,6 +323,9 @@ MK_PARAMETRIC_UNARY_REDUCE(reduce_sign_extend, mk_sign_extend);
|
|||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
result_pr = 0;
|
||||
TRACE("bit_blaster", tout << f->get_name() << " ";
|
||||
for (unsigned i = 0; i < num; ++i) tout << mk_pp(args[i], m()) << " ";
|
||||
tout << "\n";);
|
||||
if (num == 0 && f->get_family_id() == null_family_id && butil().is_bv_sort(f->get_range())) {
|
||||
mk_const(f, result);
|
||||
return BR_DONE;
|
||||
|
|
|
@ -828,6 +828,12 @@ void bit_blaster_tpl<Cfg>::mk_eq(unsigned sz, expr * const * a_bits, expr * cons
|
|||
|
||||
template<typename Cfg>
|
||||
void bit_blaster_tpl<Cfg>::mk_rotate_left(unsigned sz, expr * const * a_bits, unsigned n, expr_ref_vector & out_bits) {
|
||||
TRACE("bit_blaster", tout << n << ": " << sz << " ";
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
tout << mk_pp(a_bits[i], m()) << " ";
|
||||
}
|
||||
tout << "\n";
|
||||
);
|
||||
n = n % sz;
|
||||
for (unsigned i = sz - n; i < sz; i++)
|
||||
out_bits.push_back(a_bits[i]);
|
||||
|
@ -905,18 +911,34 @@ void bit_blaster_tpl<Cfg>::mk_shl(unsigned sz, expr * const * a_bits, expr * con
|
|||
out_bits.push_back(a_bits[i]);
|
||||
}
|
||||
else {
|
||||
expr_ref_vector eqs(m());
|
||||
mk_eqs(sz, b_bits, eqs);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
out_bits.append(sz, a_bits);
|
||||
|
||||
unsigned i = 0;
|
||||
expr_ref_vector new_out_bits(m());
|
||||
for (; i < sz; ++i) {
|
||||
checkpoint();
|
||||
expr_ref out(m());
|
||||
mk_ite(eqs.get(i), a_bits[0], m().mk_false(), out);
|
||||
for (unsigned j = 1; j <= i; j++) {
|
||||
unsigned shift_i = 1 << i;
|
||||
if (shift_i >= sz) break;
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
expr_ref new_out(m());
|
||||
mk_ite(eqs.get(i - j), a_bits[j], out, new_out);
|
||||
out = new_out;
|
||||
expr* a_j = m().mk_false();
|
||||
if (shift_i <= j) a_j = out_bits[j-shift_i].get();
|
||||
mk_ite(b_bits[i], a_j, out_bits[j].get(), new_out);
|
||||
new_out_bits.push_back(new_out);
|
||||
}
|
||||
out_bits.push_back(out);
|
||||
out_bits.reset();
|
||||
out_bits.append(new_out_bits);
|
||||
new_out_bits.reset();
|
||||
}
|
||||
expr_ref is_large(m());
|
||||
is_large = m().mk_false();
|
||||
for (; i < sz; ++i) {
|
||||
mk_or(is_large, b_bits[i], is_large);
|
||||
}
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
expr_ref new_out(m());
|
||||
mk_ite(is_large, m().mk_false(), out_bits[j].get(), new_out);
|
||||
out_bits[j] = new_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -933,19 +955,32 @@ void bit_blaster_tpl<Cfg>::mk_lshr(unsigned sz, expr * const * a_bits, expr * co
|
|||
out_bits.push_back(m().mk_false());
|
||||
}
|
||||
else {
|
||||
expr_ref_vector eqs(m());
|
||||
mk_eqs(sz, b_bits, eqs);
|
||||
out_bits.resize(sz);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
out_bits.append(sz, a_bits);
|
||||
unsigned i = 0;
|
||||
for (; i < sz; ++i) {
|
||||
checkpoint();
|
||||
expr_ref out(m());
|
||||
mk_ite(eqs.get(i), a_bits[sz-1], m().mk_false(), out);
|
||||
for (unsigned j = 1; j <= i; j++) {
|
||||
expr_ref_vector new_out_bits(m());
|
||||
unsigned shift_i = 1 << i;
|
||||
if (shift_i >= sz) break;
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
expr_ref new_out(m());
|
||||
mk_ite(eqs.get(i - j), a_bits[sz - j - 1], out, new_out);
|
||||
out = new_out;
|
||||
expr* a_j = m().mk_false();
|
||||
if (shift_i + j < sz) a_j = out_bits[j+shift_i].get();
|
||||
mk_ite(b_bits[i], a_j, out_bits[j].get(), new_out);
|
||||
new_out_bits.push_back(new_out);
|
||||
}
|
||||
out_bits.set(sz - i - 1, out);
|
||||
out_bits.reset();
|
||||
out_bits.append(new_out_bits);
|
||||
}
|
||||
expr_ref is_large(m());
|
||||
is_large = m().mk_false();
|
||||
for (; i < sz; ++i) {
|
||||
mk_or(is_large, b_bits[i], is_large);
|
||||
}
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
expr_ref new_out(m());
|
||||
mk_ite(is_large, m().mk_false(), out_bits[j].get(), new_out);
|
||||
out_bits[j] = new_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -962,20 +997,32 @@ void bit_blaster_tpl<Cfg>::mk_ashr(unsigned sz, expr * const * a_bits, expr * co
|
|||
out_bits.push_back(a_bits[sz-1]);
|
||||
}
|
||||
else {
|
||||
expr_ref_vector eqs(m());
|
||||
mk_eqs(sz, b_bits, eqs);
|
||||
out_bits.resize(sz);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
out_bits.append(sz, a_bits);
|
||||
unsigned i = 0;
|
||||
for (; i < sz; ++i) {
|
||||
checkpoint();
|
||||
expr_ref out(m());
|
||||
out = a_bits[sz-1];
|
||||
for (unsigned j = 1; j <= i; j++) {
|
||||
expr_ref_vector new_out_bits(m());
|
||||
unsigned shift_i = 1 << i;
|
||||
if (shift_i >= sz) break;
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
expr_ref new_out(m());
|
||||
mk_ite(eqs.get(i - j), a_bits[sz - j - 1], out, new_out);
|
||||
out = new_out;
|
||||
expr* a_j = a_bits[sz-1];
|
||||
if (shift_i + j < sz) a_j = out_bits[j+shift_i].get();
|
||||
mk_ite(b_bits[i], a_j, out_bits[j].get(), new_out);
|
||||
new_out_bits.push_back(new_out);
|
||||
}
|
||||
TRACE("bit_blaster_tpl<Cfg>", tout << (sz - i - 1) << " :\n" << mk_pp(out, m()) << "\n";);
|
||||
out_bits.set(sz - i - 1, out);
|
||||
out_bits.reset();
|
||||
out_bits.append(new_out_bits);
|
||||
}
|
||||
expr_ref is_large(m());
|
||||
is_large = m().mk_false();
|
||||
for (; i < sz; ++i) {
|
||||
mk_or(is_large, b_bits[i], is_large);
|
||||
}
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
expr_ref new_out(m());
|
||||
mk_ite(is_large, a_bits[sz-1], out_bits[j].get(), new_out);
|
||||
out_bits[j] = new_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1004,7 +1051,7 @@ void bit_blaster_tpl<Cfg>::mk_ext_rotate_left_right(unsigned sz, expr * const *
|
|||
out = a_bits[i];
|
||||
for (unsigned j = 1; j < sz; j++) {
|
||||
expr_ref new_out(m());
|
||||
unsigned src = (Left ? (i - j) : (i + j)) % sz;
|
||||
unsigned src = (Left ? (sz + i - j) : (i + j)) % sz;
|
||||
mk_ite(eqs.get(j), a_bits[src], out, new_out);
|
||||
out = new_out;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ Notes:
|
|||
#include"poly_rewriter_def.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
||||
|
||||
mk_extract_proc::mk_extract_proc(bv_util & u):
|
||||
m_util(u),
|
||||
m_high(0),
|
||||
|
|
|
@ -106,3 +106,10 @@ void expr_safe_replace::reset() {
|
|||
m_dst.reset();
|
||||
m_subst.reset();
|
||||
}
|
||||
|
||||
void expr_safe_replace::apply_substitution(expr* s, expr* def, expr_ref& t) {
|
||||
reset();
|
||||
insert(s, def);
|
||||
(*this)(t, t);
|
||||
reset();
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ public:
|
|||
|
||||
void operator()(expr* src, expr_ref& e);
|
||||
|
||||
void apply_substitution(expr* s, expr* def, expr_ref& t);
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
|
|
|
@ -36,17 +36,17 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
|
|||
br_status st = BR_FAILED;
|
||||
SASSERT(f->get_family_id() == get_fid());
|
||||
switch (f->get_decl_kind()) {
|
||||
case OP_TO_FLOAT: st = mk_to_float(f, num_args, args, result); break;
|
||||
case OP_TO_FLOAT: st = mk_to_fp(f, num_args, args, result); break;
|
||||
case OP_FLOAT_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break;
|
||||
case OP_FLOAT_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break;
|
||||
case OP_FLOAT_UMINUS: SASSERT(num_args == 1); st = mk_uminus(args[0], result); break;
|
||||
case OP_FLOAT_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break;
|
||||
case OP_FLOAT_MUL: SASSERT(num_args == 3); st = mk_mul(args[0], args[1], args[2], result); break;
|
||||
case OP_FLOAT_DIV: SASSERT(num_args == 3); st = mk_div(args[0], args[1], args[2], result); break;
|
||||
case OP_FLOAT_REM: SASSERT(num_args == 2); st = mk_rem(args[0], args[1], result); break;
|
||||
case OP_FLOAT_ABS: SASSERT(num_args == 1); st = mk_abs(args[0], result); break;
|
||||
case OP_FLOAT_MIN: SASSERT(num_args == 2); st = mk_min(args[0], args[1], result); break;
|
||||
case OP_FLOAT_MAX: SASSERT(num_args == 2); st = mk_max(args[0], args[1], result); break;
|
||||
case OP_FLOAT_FUSED_MA: SASSERT(num_args == 4); st = mk_fused_ma(args[0], args[1], args[2], args[3], result); break;
|
||||
case OP_FLOAT_FMA: SASSERT(num_args == 4); st = mk_fma(args[0], args[1], args[2], args[3], result); break;
|
||||
case OP_FLOAT_SQRT: SASSERT(num_args == 2); st = mk_sqrt(args[0], args[1], result); break;
|
||||
case OP_FLOAT_ROUND_TO_INTEGRAL: SASSERT(num_args == 2); st = mk_round(args[0], args[1], result); break;
|
||||
|
||||
|
@ -58,13 +58,22 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
|
|||
case OP_FLOAT_IS_ZERO: SASSERT(num_args == 1); st = mk_is_zero(args[0], result); break;
|
||||
case OP_FLOAT_IS_NZERO: SASSERT(num_args == 1); st = mk_is_nzero(args[0], result); break;
|
||||
case OP_FLOAT_IS_PZERO: SASSERT(num_args == 1); st = mk_is_pzero(args[0], result); break;
|
||||
case OP_FLOAT_IS_SIGN_MINUS: SASSERT(num_args == 1); st = mk_is_sign_minus(args[0], result); break;
|
||||
case OP_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break;
|
||||
case OP_FLOAT_IS_NAN: SASSERT(num_args == 1); st = mk_is_nan(args[0], result); break;
|
||||
case OP_FLOAT_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break;
|
||||
case OP_FLOAT_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break;
|
||||
case OP_FLOAT_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break;
|
||||
case OP_FLOAT_IS_NEGATIVE: SASSERT(num_args == 1); st = mk_is_negative(args[0], result); break;
|
||||
case OP_FLOAT_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break;
|
||||
case OP_FLOAT_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break;
|
||||
case OP_FLOAT_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break;
|
||||
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;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
br_status float_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(f->get_num_parameters() == 2);
|
||||
SASSERT(f->get_parameter(0).is_int());
|
||||
SASSERT(f->get_parameter(1).is_int());
|
||||
|
@ -73,35 +82,39 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
|
|||
|
||||
if (num_args == 2) {
|
||||
mpf_rounding_mode rm;
|
||||
if (!m_util.is_rm(args[0], rm))
|
||||
if (!m_util.is_rm_value(args[0], rm))
|
||||
return BR_FAILED;
|
||||
|
||||
rational q;
|
||||
mpf q_mpf;
|
||||
if (m_util.au().is_numeral(args[1], q)) {
|
||||
TRACE("fp_rewriter", tout << "q: " << q << std::endl; );
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq());
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
m_util.fm().del(v);
|
||||
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (m_util.is_value(args[1], q_mpf)) {
|
||||
else if (m_util.is_value(args[1], q_mpf)) {
|
||||
TRACE("fp_rewriter", tout << "q: " << m_util.fm().to_string(q_mpf) << std::endl; );
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q_mpf);
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
|
||||
return BR_DONE;
|
||||
}
|
||||
else
|
||||
return BR_FAILED;
|
||||
}
|
||||
else if (num_args == 3 &&
|
||||
m_util.is_rm(m().get_sort(args[0])) &&
|
||||
m_util.is_rm(args[0]) &&
|
||||
m_util.au().is_real(args[1]) &&
|
||||
m_util.au().is_int(args[2])) {
|
||||
|
||||
mpf_rounding_mode rm;
|
||||
if (!m_util.is_rm(args[0], rm))
|
||||
if (!m_util.is_rm_value(args[0], rm))
|
||||
return BR_FAILED;
|
||||
|
||||
rational q;
|
||||
|
@ -113,7 +126,6 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
|
|||
return BR_FAILED;
|
||||
|
||||
TRACE("fp_rewriter", tout << "q: " << q << ", e: " << e << "\n";);
|
||||
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq(), e.to_mpq().numerator());
|
||||
result = m_util.mk_value(v);
|
||||
|
@ -127,7 +139,7 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
|
|||
|
||||
br_status float_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
|
||||
mpf_rounding_mode rm;
|
||||
if (m_util.is_rm(arg1, rm)) {
|
||||
if (m_util.is_rm_value(arg1, rm)) {
|
||||
scoped_mpf v2(m_util.fm()), v3(m_util.fm());
|
||||
if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) {
|
||||
scoped_mpf t(m_util.fm());
|
||||
|
@ -142,13 +154,13 @@ br_status float_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref
|
|||
|
||||
br_status float_rewriter::mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
|
||||
// a - b = a + (-b)
|
||||
result = m_util.mk_add(arg1, arg2, m_util.mk_uminus(arg3));
|
||||
result = m_util.mk_add(arg1, arg2, m_util.mk_neg(arg3));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
|
||||
mpf_rounding_mode rm;
|
||||
if (m_util.is_rm(arg1, rm)) {
|
||||
if (m_util.is_rm_value(arg1, rm)) {
|
||||
scoped_mpf v2(m_util.fm()), v3(m_util.fm());
|
||||
if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) {
|
||||
scoped_mpf t(m_util.fm());
|
||||
|
@ -163,7 +175,7 @@ br_status float_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref
|
|||
|
||||
br_status float_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
|
||||
mpf_rounding_mode rm;
|
||||
if (m_util.is_rm(arg1, rm)) {
|
||||
if (m_util.is_rm_value(arg1, rm)) {
|
||||
scoped_mpf v2(m_util.fm()), v3(m_util.fm());
|
||||
if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) {
|
||||
scoped_mpf t(m_util.fm());
|
||||
|
@ -176,7 +188,7 @@ br_status float_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_uminus(expr * arg1, expr_ref & result) {
|
||||
br_status float_rewriter::mk_neg(expr * arg1, expr_ref & result) {
|
||||
if (m_util.is_nan(arg1)) {
|
||||
// -nan --> nan
|
||||
result = arg1;
|
||||
|
@ -192,7 +204,7 @@ br_status float_rewriter::mk_uminus(expr * arg1, expr_ref & result) {
|
|||
result = m_util.mk_plus_inf(m().get_sort(arg1));
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.is_uminus(arg1)) {
|
||||
if (m_util.is_neg(arg1)) {
|
||||
// - - a --> a
|
||||
result = to_app(arg1)->get_arg(0);
|
||||
return BR_DONE;
|
||||
|
@ -227,7 +239,7 @@ br_status float_rewriter::mk_abs(expr * arg1, expr_ref & result) {
|
|||
return BR_DONE;
|
||||
}
|
||||
result = m().mk_ite(m_util.mk_is_sign_minus(arg1),
|
||||
m_util.mk_uminus(arg1),
|
||||
m_util.mk_neg(arg1),
|
||||
arg1);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
@ -272,9 +284,9 @@ br_status float_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
return BR_REWRITE_FULL;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) {
|
||||
br_status float_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) {
|
||||
mpf_rounding_mode rm;
|
||||
if (m_util.is_rm(arg1, rm)) {
|
||||
if (m_util.is_rm_value(arg1, rm)) {
|
||||
scoped_mpf v2(m_util.fm()), v3(m_util.fm()), v4(m_util.fm());
|
||||
if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3) && m_util.is_value(arg4, v4)) {
|
||||
scoped_mpf t(m_util.fm());
|
||||
|
@ -289,7 +301,7 @@ br_status float_rewriter::mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, exp
|
|||
|
||||
br_status float_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
mpf_rounding_mode rm;
|
||||
if (m_util.is_rm(arg1, rm)) {
|
||||
if (m_util.is_rm_value(arg1, rm)) {
|
||||
scoped_mpf v2(m_util.fm());
|
||||
if (m_util.is_value(arg2, v2)) {
|
||||
scoped_mpf t(m_util.fm());
|
||||
|
@ -304,7 +316,7 @@ br_status float_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
|
||||
br_status float_rewriter::mk_round(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
mpf_rounding_mode rm;
|
||||
if (m_util.is_rm(arg1, rm)) {
|
||||
if (m_util.is_rm_value(arg1, rm)) {
|
||||
scoped_mpf v2(m_util.fm());
|
||||
if (m_util.is_value(arg2, v2)) {
|
||||
scoped_mpf t(m_util.fm());
|
||||
|
@ -346,7 +358,7 @@ br_status float_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
if (m_util.is_minus_inf(arg1)) {
|
||||
// -oo < arg2 --> not(arg2 = -oo) and not(arg2 = NaN)
|
||||
result = m().mk_and(m().mk_not(m().mk_eq(arg2, arg1)), mk_neq_nan(arg2));
|
||||
return BR_REWRITE2;
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
if (m_util.is_minus_inf(arg2)) {
|
||||
// arg1 < -oo --> false
|
||||
|
@ -361,7 +373,7 @@ br_status float_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
if (m_util.is_plus_inf(arg2)) {
|
||||
// arg1 < +oo --> not(arg1 = +oo) and not(arg1 = NaN)
|
||||
result = m().mk_and(m().mk_not(m().mk_eq(arg1, arg2)), mk_neq_nan(arg1));
|
||||
return BR_REWRITE2;
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
|
||||
|
@ -428,7 +440,47 @@ br_status float_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) {
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_sign_minus(expr * arg1, expr_ref & result) {
|
||||
br_status float_rewriter::mk_is_nan(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_nan(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_inf(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_inf(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_normal(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_normal(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_denormal(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_negative(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_neg(v)) ? m().mk_true() : m().mk_false();
|
||||
|
@ -438,11 +490,26 @@ br_status float_rewriter::mk_is_sign_minus(expr * arg1, expr_ref & result) {
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_positive(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_neg(v) || m_util.fm().is_nan(v)) ? m().mk_false() : m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
||||
// This the SMT =
|
||||
br_status float_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
|
||||
if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) {
|
||||
result = (v1 == v2) ? m().mk_true() : m().mk_false();
|
||||
// Note: == is the floats-equality, here we need normal equality.
|
||||
result = (m_fm.is_nan(v1) && m_fm.is_nan(v2)) ? m().mk_true() :
|
||||
(m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1)!=m_fm.sgn(v2)) ? m().mk_false() :
|
||||
(v1 == v2) ? m().mk_true() :
|
||||
m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
|
@ -452,3 +519,38 @@ br_status float_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result
|
|||
br_status float_rewriter::mk_to_ieee_bv(expr * arg1, expr_ref & result) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
|
||||
bv_util bu(m());
|
||||
rational r1, r2, r3;
|
||||
unsigned bvs1, bvs2, bvs3;
|
||||
|
||||
if (bu.is_numeral(arg1, r1, bvs1) && bu.is_numeral(arg2, r2, bvs2) && bu.is_numeral(arg3, r3, bvs3)) {
|
||||
SASSERT(m_util.fm().mpz_manager().is_one(r2.to_mpq().denominator()));
|
||||
SASSERT(m_util.fm().mpz_manager().is_one(r3.to_mpq().denominator()));
|
||||
SASSERT(m_util.fm().mpz_manager().is_int64(r3.to_mpq().numerator()));
|
||||
scoped_mpf v(m_util.fm());
|
||||
mpf_exp_t biased_exp = m_util.fm().mpz_manager().get_int64(r2.to_mpq().numerator());
|
||||
m_util.fm().set(v, bvs2, bvs3 + 1,
|
||||
r1.is_one(),
|
||||
r3.to_mpq().numerator(),
|
||||
m_util.fm().unbias_exp(bvs2, biased_exp));
|
||||
TRACE("fp_rewriter", tout << "v = " << m_util.fm().to_string(v) << std::endl;);
|
||||
result = m_util.mk_value(v);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_to_sbv(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_to_real(expr * arg1, expr_ref & result) {
|
||||
return BR_FAILED;
|
||||
}
|
|
@ -45,17 +45,16 @@ public:
|
|||
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_eq_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
|
||||
br_status mk_to_float(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result);
|
||||
br_status mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & result);
|
||||
br_status mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result);
|
||||
br_status mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result);
|
||||
br_status mk_uminus(expr * arg1, expr_ref & result);
|
||||
br_status mk_neg(expr * arg1, expr_ref & result);
|
||||
br_status mk_rem(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_abs(expr * arg1, expr_ref & result);
|
||||
br_status mk_min(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_max(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result);
|
||||
br_status mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result);
|
||||
br_status mk_sqrt(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_round(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_float_eq(expr * arg1, expr * arg2, expr_ref & result);
|
||||
|
@ -66,9 +65,21 @@ public:
|
|||
br_status mk_is_zero(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_nzero(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_pzero(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_sign_minus(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_nan(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_inf(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_normal(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_subnormal(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_negative(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_positive(expr * arg1, expr_ref & result);
|
||||
|
||||
br_status mk_to_ieee_bv(expr * arg1, expr_ref & result);
|
||||
|
||||
br_status mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result);
|
||||
br_status mk_to_fp_unsigned(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_to_sbv(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_to_real(expr * arg1, expr_ref & result);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -73,6 +73,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
m_a_rw.updt_params(p);
|
||||
m_bv_rw.updt_params(p);
|
||||
m_ar_rw.updt_params(p);
|
||||
m_f_rw.updt_params(p);
|
||||
updt_local_params(p);
|
||||
}
|
||||
|
||||
|
|
55
src/ast/scoped_proof.h
Normal file
55
src/ast/scoped_proof.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
scoped_proof.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Scoped proof environments. Toggles enabling proofs.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-08-28
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SCOPED_PROOF__H_
|
||||
#define _SCOPED_PROOF__H_
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
class scoped_proof_mode {
|
||||
ast_manager& m;
|
||||
proof_gen_mode m_mode;
|
||||
public:
|
||||
scoped_proof_mode(ast_manager& m, proof_gen_mode mode): m(m) {
|
||||
m_mode = m.proof_mode();
|
||||
m.toggle_proof_mode(mode);
|
||||
}
|
||||
~scoped_proof_mode() {
|
||||
m.toggle_proof_mode(m_mode);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class scoped_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_proof(ast_manager& m): scoped_proof_mode(m, PGM_FINE) {}
|
||||
};
|
||||
|
||||
class scoped_no_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_no_proof(ast_manager& m): scoped_proof_mode(m, PGM_DISABLED) {}
|
||||
};
|
||||
|
||||
class scoped_restore_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_restore_proof(ast_manager& m): scoped_proof_mode(m, m.proof_mode()) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -68,7 +68,7 @@ bool array_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * co
|
|||
set_reduce_invoked();
|
||||
if (m_presimp)
|
||||
return false;
|
||||
#if _DEBUG
|
||||
#if Z3DEBUG
|
||||
for (unsigned i = 0; i < num_args && i < f->get_arity(); ++i) {
|
||||
SASSERT(m_manager.get_sort(args[i]) == f->get_domain(i));
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ bool bv_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * const
|
|||
}
|
||||
SASSERT(result.get());
|
||||
|
||||
TRACE("bv_simplifier",
|
||||
TRACE("bv_simplifier",
|
||||
tout << mk_pp(f, m_manager) << "\n";
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
tout << mk_pp(args[i], m_manager) << " ";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue