", line)
- tgt.write(line);
- elif (not in_class and (s.startswith("{") or s.startswith("}"))) or s.startswith("[") or s.startswith("#"):
- # tgt.write("// Skipping: " + s)
- pass
- elif line == "}\n":
- pass
- else:
- # indent = line.find(s)
- # tgt.write("// LINE: " + line)
- if line.find(": base") != -1:
- line = re.sub(": base\((?P[^\{]*)\)", "{ super(\g
);", line)
- line = line[4:]
- obraces = line.count("{")
- cbraces = line.count("}")
- mbraces = obraces - cbraces
- # tgt.write("// obraces = " + str(obraces) + "\n")
- if obraces == 1:
- skip_brace = 1
- else:
- for i in range(0, mbraces):
- line = line.replace("\n", "}\n")
- if (s.find("public") != -1 or s.find("protected") != -1 or s.find("internal") != -1) and s.find("(") != -1:
- line = re.sub(" = [\w.]+(?P[,;\)])", "\g", line)
- a = type_replace(line)
- a = enum_replace(a)
- a = re.sub("(?P[\(, ])params ", "\g", a)
- a = a.replace("base.", "super.")
- a = re.sub("Contract.\w+\([\s\S]*\);", "", a)
- a = rename_native(a)
- a = re.sub("~\w+\(\)", "protected void finalize()", a)
-
- if missing_foreach_brace == 1:
- # a = a.replace("\n", " // checked " + str(foreach_opened_brace) + "\n")
- if foreach_opened_brace == 0 and a.find("{") != -1:
- foreach_opened_brace = 1
- elif foreach_opened_brace == 0 and a.find("}") == -1:
- a = a.replace("\n", "}}\n")
- foreach_opened_brace = 0
- missing_foreach_brace = 0
- elif foreach_opened_brace == 1 and a.find("}") != -1:
- a = a.replace("\n", "}}\n")
- foreach_opened_brace = 0
- missing_foreach_brace = 0
-
-# if a.find("foreach") != -1:
-# missing_foreach_brace = 1
-# a = re.sub("foreach\s*\((?P[\w <>,]+)\s+(?P\w+)\s+in\s+(?P\w+)\)",
- # "{ Iterator fe_i = \g.iterator(); while (fe_i.hasNext()) { \g \g = (long)fe_i.next(); ",
-# a)
- a = re.sub("foreach\s*\((?P[\w <>,]+)\s+(?P\w+)\s+in\s+(?P\w+)\)",
- "for (\g \g: \g)",
- a)
- if a.find("long o: m_queue") != -1:
- a = a.replace("long", "Long")
- a = a.replace("readonly ", "")
- a = a.replace("const ", "final ")
- a = a.replace("String ToString", "String toString")
- a = a.replace(".ToString", ".toString")
- a = a.replace("internal ", "")
- a = a.replace("new static", "static")
- a = a.replace("new public", "public")
- a = a.replace("override ", "")
- a = a.replace("virtual ", "")
- a = a.replace("o as AST", "(AST) o")
- a = a.replace("o as Sort", "(Sort) o")
- a = a.replace("other as AST", "(AST) other")
- a = a.replace("o as FuncDecl", "(FuncDecl) o")
- a = a.replace("IntPtr obj", "long obj")
- a = a.replace("IntPtr o", "long o")
- a = a.replace("new long()", "0")
- a = a.replace("long.Zero", "0")
- a = a.replace("object o", "Object o")
- a = a.replace("object other", "Object other")
- a = a.replace("IntPtr res = IntPtr.Zero;", "Native.IntPtr res = new Native.IntPtr();")
- a = a.replace("out res", "res")
- a = a.replace("GC.ReRegisterForFinalize(m_ctx);", "")
- a = a.replace("GC.SuppressFinalize(this);", "")
- a = a.replace(".Length", ".length")
- a = a.replace("m_queue.Count", "m_queue.size()")
- a = a.replace("m_queue.Add", "m_queue.add")
- a = a.replace("m_queue.Clear", "m_queue.clear")
- a = a.replace("for (long ", "for (int ")
- a = a.replace("ReferenceEquals(Context, ctx)", "Context() == ctx")
- a = a.replace("BigInteger.Parse", "new BigInteger")
- if had_ulong_res == 0 and a.find("ulong res = 0") != -1:
- a = a.replace("ulong res = 0;", "LongPtr res = new LongPtr();")
- elif had_ulong_res == 1:
- a = a.replace("ref res)", "res)")
- if a.find("return res;") != -1:
- a = a.replace("return res;", "return res.value;")
- had_ulong_res = 0
- a = a.replace("lock (", "synchronized (")
- if in_static_class:
- a = a.replace("static", "")
- a = re.sub("ref (?P\w+)", "\g", a)
- subst_getters(a, getters)
- a = re.sub("NativeObject = (?P.*);", "setNativeObject(\g);", a)
- a = replace_generals(a)
- tgt.write(a)
- tgt.close()
-
-mk_java_bindings()
diff --git a/src/api/ml/z3_theory_stubs.c b/src/api/ml/z3_theory_stubs.c
index d17a1790d..a48b94553 100644
--- a/src/api/ml/z3_theory_stubs.c
+++ b/src/api/ml/z3_theory_stubs.c
@@ -1,5 +1,5 @@
/*++
-Copyright (c) 2010 Microsoft Corporation
+Copyright (c) Microsoft Corporation
Module Name:
diff --git a/src/api/python/z3.py b/src/api/python/z3.py
index 27da530b4..b87cf20b3 100644
--- a/src/api/python/z3.py
+++ b/src/api/python/z3.py
@@ -38,7 +38,7 @@ Z3 exceptions:
... n = x + y
... except Z3Exception as ex:
... print("failed: %s" % ex)
-failed: 'sort mismatch'
+failed: sort mismatch
"""
from z3core import *
from z3types import *
@@ -1396,7 +1396,7 @@ def BoolVector(prefix, sz, ctx=None):
return [ Bool('%s__%s' % (prefix, i)) for i in range(sz) ]
def FreshBool(prefix='b', ctx=None):
- """Return a fresh Bolean constant in the given context using the given prefix.
+ """Return a fresh Boolean constant in the given context using the given prefix.
If `ctx=None`, then the global context is used.
@@ -6162,7 +6162,7 @@ class Fixedpoint(Z3PPObject):
Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, head.as_ast(), name)
else:
body = _get_args(body)
- f = self.abstract(Implies(And(body),head))
+ f = self.abstract(Implies(And(body,self.ctx),head))
Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name)
def rule(self, head, body = None, name = None):
@@ -6190,7 +6190,7 @@ class Fixedpoint(Z3PPObject):
if sz == 1:
query = query[0]
else:
- query = And(query)
+ query = And(query, self.ctx)
query = self.abstract(query, False)
r = Z3_fixedpoint_query(self.ctx.ref(), self.fixedpoint, query.as_ast())
return CheckSatResult(r)
@@ -6209,7 +6209,7 @@ class Fixedpoint(Z3PPObject):
name = ""
name = to_symbol(name, self.ctx)
body = _get_args(body)
- f = self.abstract(Implies(And(body),head))
+ f = self.abstract(Implies(And(body, self.ctx),head))
Z3_fixedpoint_update_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name)
def get_answer(self):
diff --git a/src/api/z3_algebraic.h b/src/api/z3_algebraic.h
index eef791170..8b6d97aa8 100644
--- a/src/api/z3_algebraic.h
+++ b/src/api/z3_algebraic.h
@@ -23,7 +23,19 @@ Notes:
#ifdef __cplusplus
extern "C" {
-#endif // __cplusplus
+#endif // __cplusplus
+
+ /**
+ \defgroup capi C API
+
+ */
+
+ /*@{*/
+
+ /**
+ @name Algebraic Numbers API
+ */
+ /*@{*/
/**
\brief Return Z3_TRUE if \c can be used as value in the Z3 real algebraic
@@ -218,6 +230,8 @@ extern "C" {
*/
int Z3_API Z3_algebraic_eval(__in Z3_context c, __in Z3_ast p, __in unsigned n, __in Z3_ast a[]);
+ /*@}*/
+ /*@}*/
#ifdef __cplusplus
};
diff --git a/src/api/z3_api.h b/src/api/z3_api.h
index 258c7de9a..ed4f5bf6a 100644
--- a/src/api/z3_api.h
+++ b/src/api/z3_api.h
@@ -773,7 +773,6 @@ typedef enum
The premises of the rules is a sequence of clauses.
The first clause argument is the main clause of the rule.
- One literal from the second, third, .. clause is resolved
with a literal from the first (main) clause.
Premises of the rules are of the form
@@ -1159,8 +1158,8 @@ typedef enum {
- Z3_FILE_ACCESS_ERRROR: A file could not be accessed.
- Z3_INVALID_USAGE: API call is invalid in the current state.
- Z3_INTERNAL_FATAL: An error internal to Z3 occurred.
- - Z3_DEC_REF_ERROR: Trying to decrement the reference counter of an AST that was deleted or the reference counter was not initialized\mlonly.\endmlonly\conly with #Z3_inc_ref.
- - Z3_EXCEPTION: Internal Z3 exception. Additional details can be retrieved using \mlonly #Z3_get_error_msg. \endmlonly \conly #Z3_get_error_msg_ex.
+ - Z3_DEC_REF_ERROR: Trying to decrement the reference counter of an AST that was deleted or the reference counter was not initialized \mlonly.\endmlonly \conly with #Z3_inc_ref.
+ - Z3_EXCEPTION: Internal Z3 exception. Additional details can be retrieved using #Z3_get_error_msg.
*/
typedef enum
{
@@ -1304,8 +1303,6 @@ extern "C" {
\sa Z3_global_param_set
- The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value.
-
\remark This function cannot be invoked simultaneously from different threads without synchronization.
The result string stored in param_value is stored in shared location.
diff --git a/src/api/z3_interp.h b/src/api/z3_interp.h
index 729851988..6ae26c0ed 100644
--- a/src/api/z3_interp.h
+++ b/src/api/z3_interp.h
@@ -24,7 +24,14 @@ extern "C" {
#endif // __cplusplus
/**
- @name Interpolation
+ \defgroup capi C API
+
+ */
+
+ /*@{*/
+
+ /**
+ @name Interpolation API
*/
/*@{*/
@@ -184,6 +191,8 @@ extern "C" {
\param cnsts Returns sequence of formulas (do not free)
\param parents Returns the parents vector (or NULL for sequence)
\param error Returns an error message in case of failure (do not free the string)
+ \param num_theory Number of theory terms
+ \param theory Theory terms
Returns true on success.
@@ -232,6 +241,8 @@ extern "C" {
\param parents The parents vector (or NULL for sequence)
\param interps The interpolant to check
\param error Returns an error message if interpolant incorrect (do not free the string)
+ \param num_theory Number of theory terms
+ \param theory Theory terms
Return value is Z3_L_TRUE if interpolant is verified, Z3_L_FALSE if
incorrect, and Z3_L_UNDEF if unknown.
@@ -258,6 +269,8 @@ extern "C" {
\param cnsts Array of constraints
\param parents The parents vector (or NULL for sequence)
\param filename The file name to write
+ \param num_theory Number of theory terms
+ \param theory Theory terms
def_API('Z3_write_interpolation_problem', VOID, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in(STRING), _in(UINT), _in_array(5, AST)))
*/
@@ -270,6 +283,9 @@ extern "C" {
__in unsigned num_theory,
__in_ecount(num_theory) Z3_ast theory[]);
+ /*@}*/
+ /*@}*/
+
#ifdef __cplusplus
};
#endif // __cplusplus
diff --git a/src/api/z3_polynomial.h b/src/api/z3_polynomial.h
index 614e654f9..f55a63dd4 100644
--- a/src/api/z3_polynomial.h
+++ b/src/api/z3_polynomial.h
@@ -24,6 +24,19 @@ Notes:
extern "C" {
#endif // __cplusplus
+ /**
+ \defgroup capi C API
+
+ */
+
+ /*@{*/
+
+
+ /**
+ @name Polynomials API
+ */
+ /*@{*/
+
/**
\brief Return the nonzero subresultants of \c p and \c q with respect to the "variable" \c x.
@@ -38,6 +51,9 @@ extern "C" {
Z3_ast_vector Z3_API Z3_polynomial_subresultants(__in Z3_context c, __in Z3_ast p, __in Z3_ast q, __in Z3_ast x);
+ /*@}*/
+ /*@}*/
+
#ifdef __cplusplus
};
#endif // __cplusplus
diff --git a/src/api/z3_rcf.h b/src/api/z3_rcf.h
index e2b4b7e05..04fe40253 100644
--- a/src/api/z3_rcf.h
+++ b/src/api/z3_rcf.h
@@ -25,6 +25,18 @@ Notes:
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
+
+ /**
+ \defgroup capi C API
+
+ */
+
+ /*@{*/
+
+ /**
+ @name Real Closed Fields API
+ */
+ /*@{*/
/**
\brief Delete a RCF numeral created using the RCF API.
@@ -192,6 +204,9 @@ extern "C" {
*/
void Z3_API Z3_rcf_get_numerator_denominator(__in Z3_context c, __in Z3_rcf_num a, __out Z3_rcf_num * n, __out Z3_rcf_num * d);
+ /*@}*/
+ /*@}*/
+
#ifdef __cplusplus
};
#endif // __cplusplus
diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp
index 5466df069..f51101d79 100644
--- a/src/ast/float_decl_plugin.cpp
+++ b/src/ast/float_decl_plugin.cpp
@@ -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(m_manager->get_plugin(m_bv_fid));
- }
}
float_decl_plugin::~float_decl_plugin() {
@@ -103,6 +102,18 @@ bool float_decl_plugin::is_value(expr * n, mpf & val) {
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;
}
@@ -156,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() {
@@ -176,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;
@@ -229,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);
}
@@ -248,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;
@@ -270,17 +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_NAN: name = "isNaN"; break;
- case OP_FLOAT_IS_INF: name = "isInfinite"; break;
- case OP_FLOAT_IS_NORMAL: name = "isNormal"; break;
- case OP_FLOAT_IS_SUBNORMAL: name = "isSubnormal"; 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;
@@ -293,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;
@@ -310,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 = "fp.min"; break;
- case OP_FLOAT_MAX: name = "fp.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;
@@ -327,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;
@@ -346,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;
@@ -359,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));
}
@@ -375,12 +402,13 @@ 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())
@@ -389,37 +417,67 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters,
int sbits = parameters[1].get_int();
sort * fp = mk_float_sort(ebits, sbits);
- 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));
+ }
+ 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);
@@ -429,41 +487,34 @@ func_decl * float_decl_plugin::mk_to_ieee_bv(decl_kind k, unsigned num_parameter
func_decl * float_decl_plugin::mk_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
- if (!m_bv_plugin)
- m_manager->raise_exception("fp unsupported; use a logic with BV support");
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 mismtach");
+ 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_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters,
+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 mismtach");
+ 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 mismtach");
+ 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("to_fp_unsigned");
+ 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_ubv(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_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
NOT_IMPLEMENTED_YET();
@@ -498,14 +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:
@@ -517,20 +569,18 @@ 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_FP_UNSIGNED:
- return mk_to_fp_unsigned(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:
@@ -544,8 +594,11 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
}
void float_decl_plugin::get_op_names(svector & 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));
@@ -554,46 +607,6 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co
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("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("isNaN", OP_FLOAT_IS_NAN));
- op_names.push_back(builtin_name("isInfinite", OP_FLOAT_IS_INF));
- 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("isNormal", OP_FLOAT_IS_NORMAL));
- op_names.push_back(builtin_name("isSubnormal", OP_FLOAT_IS_SUBNORMAL));
- op_names.push_back(builtin_name("isSignMinus", OP_FLOAT_IS_SIGN_MINUS));
-
- // Disabled min/max, clashes with user-defined min/max functions
- // 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));
-
- // These are the operators from the final draft of the SMT FloatingPoints 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("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));
@@ -601,44 +614,47 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co
op_names.push_back(builtin_name("RTZ", OP_RM_TOWARD_ZERO));
op_names.push_back(builtin_name("fp.abs", OP_FLOAT_ABS));
- op_names.push_back(builtin_name("fp.neg", OP_FLOAT_UMINUS));
+ 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_FUSED_MA));
+ 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.eq", OP_FLOAT_EQ));
+ 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("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.min", OP_FLOAT_MIN));
- op_names.push_back(builtin_name("fp.max", OP_FLOAT_MAX));
- op_names.push_back(builtin_name("to_fp", OP_TO_FLOAT));
+ op_names.push_back(builtin_name("fp.isNegative", OP_FLOAT_IS_NEGATIVE));
+ op_names.push_back(builtin_name("fp.isPositive", OP_FLOAT_IS_POSITIVE));
- if (m_bv_plugin) {
- op_names.push_back(builtin_name("fp", OP_FLOAT_FP));
- op_names.push_back(builtin_name("to_fp_unsigned", OP_FLOAT_TO_FP_UNSIGNED));
- 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("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("fp.toReal", ?));
+ op_names.push_back(builtin_name("to_fp", OP_TO_FLOAT));
}
void float_decl_plugin::get_sort_names(svector & 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));
- // In the SMT FPA final draft, FP is called FloatingPoint
- sort_names.push_back(builtin_name("FloatingPoint", FLOAT_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) {
@@ -662,6 +678,8 @@ bool float_decl_plugin::is_value(app * e) const {
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:
diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h
index 58c37080d..c7ec04932 100644
--- a/src/ast/float_decl_plugin.h
+++ b/src/ast/float_decl_plugin.h
@@ -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,
@@ -68,13 +73,14 @@ enum float_op_kind {
OP_FLOAT_IS_SUBNORMAL,
OP_FLOAT_IS_PZERO,
OP_FLOAT_IS_NZERO,
- OP_FLOAT_IS_SIGN_MINUS,
+ 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_UNSIGNED,
+ OP_FLOAT_TO_FP,
OP_FLOAT_TO_UBV,
OP_FLOAT_TO_SBV,
OP_FLOAT_TO_REAL,
@@ -125,16 +131,14 @@ 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,
- unsigned arity, sort * const * domain, sort * range);
+ func_decl * mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
+ unsigned arity, sort * const * domain, sort * range);
func_decl * mk_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
- func_decl * mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters,
- unsigned arity, sort * const * domain, sort * range);
func_decl * mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters,
@@ -195,6 +199,7 @@ 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); }
@@ -242,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) { 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); }
@@ -267,11 +272,13 @@ public:
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
diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp
index d6f362902..5f92b4d94 100644
--- a/src/ast/fpa/fpa2bv_converter.cpp
+++ b/src/ast/fpa/fpa2bv_converter.cpp
@@ -136,12 +136,13 @@ void fpa2bv_converter::mk_const(func_decl * f, expr_ref & result) {
unsigned sbits = m_util.get_sbits(srt);
expr_ref sgn(m), s(m), e(m);
- sort_ref s_sgn(m), s_sig(m), s_exp(m);
- s_sgn = m_bv_util.mk_sort(1);
- s_sig = m_bv_util.mk_sort(sbits-1);
- s_exp = m_bv_util.mk_sort(ebits);
#ifdef Z3DEBUG
+ sort_ref s_sgn(m), s_sig(m), s_exp(m);
+ s_sgn = m_bv_util.mk_sort(1);
+ s_sig = m_bv_util.mk_sort(sbits - 1);
+ s_exp = m_bv_util.mk_sort(ebits);
+
std::string p("fpa2bv");
std::string name = f->get_name().str();
@@ -149,9 +150,17 @@ void fpa2bv_converter::mk_const(func_decl * f, expr_ref & result) {
s = m.mk_fresh_const((p + "_sig_" + name).c_str(), s_sig);
e = m.mk_fresh_const((p + "_exp_" + name).c_str(), s_exp);
#else
- sgn = m.mk_fresh_const(0, s_sgn);
- s = m.mk_fresh_const(0, s_sig);
- e = m.mk_fresh_const(0, s_exp);
+ expr_ref bv(m);
+ unsigned bv_sz = 1 + ebits + (sbits - 1);
+ bv = m.mk_fresh_const(0, m_bv_util.mk_sort(bv_sz));
+
+ sgn = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv);
+ e = m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv);
+ s = m_bv_util.mk_extract(sbits - 2, 0, bv);
+
+ SASSERT(m_bv_util.get_bv_size(sgn) == 1);
+ SASSERT(m_bv_util.get_bv_size(s) == sbits-1);
+ SASSERT(m_bv_util.get_bv_size(e) == ebits);
#endif
mk_triple(sgn, s, e, result);
@@ -595,12 +604,12 @@ void fpa2bv_converter::mk_add(func_decl * f, unsigned num, expr * const * args,
void fpa2bv_converter::mk_sub(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 3);
expr_ref t(m);
- mk_uminus(f, 1, &args[2], t);
+ mk_neg(f, 1, &args[2], t);
expr * nargs[3] = { args[0], args[1], t };
mk_add(f, 3, nargs, result);
}
-void fpa2bv_converter::mk_uminus(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
+void fpa2bv_converter::mk_neg(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 1);
expr * sgn, * s, * e;
split(args[0], sgn, s, e);
@@ -906,7 +915,7 @@ void fpa2bv_converter::mk_div(func_decl * f, unsigned num, expr * const * args,
TRACE("fpa2bv_div", tout << "DIV = " << mk_ismt2_pp(result, m) << std::endl; );
}
-void fpa2bv_converter::mk_remainder(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
+void fpa2bv_converter::mk_rem(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 2);
// Remainder is always exact, so there is no rounding mode.
@@ -1114,7 +1123,7 @@ void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args,
mk_triple(r_sgn, r_sig, r_exp, result);
}
-void fpa2bv_converter::mk_fusedma(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
+void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 4);
// fusedma means (x * y) + z
@@ -1835,9 +1844,18 @@ void fpa2bv_converter::mk_is_subnormal(func_decl * f, unsigned num, expr * const
mk_is_denormal(args[0], result);
}
-void fpa2bv_converter::mk_is_sign_minus(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
+void fpa2bv_converter::mk_is_negative(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 1);
mk_is_neg(args[0], result);
+ TRACE("fpa2bv_is_negative", tout << "result = " << mk_ismt2_pp(result, m) << std::endl;);
+}
+
+void fpa2bv_converter::mk_is_positive(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
+ SASSERT(num == 1);
+ expr_ref t1(m), t2(m);
+ mk_is_nan(args[0], t1);
+ mk_is_pos(args[0], t2);
+ result = m.mk_and(m.mk_not(t1), t2);
}
void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
@@ -2123,7 +2141,7 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a
void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 1);
expr * sgn, * s, * e;
- split(args[0], sgn, s, e);
+ split(args[0], sgn, s, e);
result = m_bv_util.mk_concat(m_bv_util.mk_concat(sgn, e), s);
}
@@ -2132,19 +2150,55 @@ void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, e
mk_triple(args[0], args[2], args[1], result);
}
-void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
- NOT_IMPLEMENTED_YET();
-}
-
void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
+ SASSERT(num == 2);
+ SASSERT(f->get_num_parameters() == 1);
+ SASSERT(f->get_parameter(0).is_int());
+
+ unsigned ebits = m_util.get_ebits(f->get_range());
+ unsigned sbits = m_util.get_sbits(f->get_range());
+ int width = f->get_parameter(0).get_int();
+
+ expr * rm = args[0];
+ expr * x = args[1];
+
+ expr * sgn, *s, *e;
+ split(x, sgn, s, e);
+
NOT_IMPLEMENTED_YET();
}
void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
+ SASSERT(num == 2);
+ SASSERT(f->get_num_parameters() == 1);
+ SASSERT(f->get_parameter(0).is_int());
+
+ unsigned ebits = m_util.get_ebits(f->get_range());
+ unsigned sbits = m_util.get_sbits(f->get_range());
+ int width = f->get_parameter(0).get_int();
+
+ expr * rm = args[0];
+ expr * x = args[1];
+
+ expr * sgn, *s, *e;
+ split(x, sgn, s, e);
+
NOT_IMPLEMENTED_YET();
}
void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
+ SASSERT(num == 1);
+
+ unsigned ebits = m_util.get_ebits(f->get_range());
+ unsigned sbits = m_util.get_sbits(f->get_range());
+ int width = f->get_parameter(0).get_int();
+
+ expr * rm = args[0];
+ expr * x = args[1];
+
+ expr * sgn, *s, *e;
+ split(x, sgn, s, e);
+
NOT_IMPLEMENTED_YET();
}
diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h
index dcb508ffd..eb539d8ae 100644
--- a/src/ast/fpa/fpa2bv_converter.h
+++ b/src/ast/fpa/fpa2bv_converter.h
@@ -94,14 +94,14 @@ public:
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_uminus(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_remainder(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_fusedma(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);
@@ -114,7 +114,8 @@ public:
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_sign_minus(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);
diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h
index 225aad668..7a245b71a 100644
--- a/src/ast/fpa/fpa2bv_rewriter.h
+++ b/src/ast/fpa/fpa2bv_rewriter.h
@@ -65,8 +65,6 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
bool max_steps_exceeded(unsigned num_steps) const {
cooperate("fpa2bv");
- if (memory::get_allocation_size() > m_max_memory)
- throw tactic_exception(TACTIC_MAX_MEMORY_MSG);
return num_steps > m_max_steps;
}
@@ -117,17 +115,19 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
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_UMINUS: m_conv.mk_uminus(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_remainder(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_FUSED_MA: m_conv.mk_fusedma(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;
@@ -142,18 +142,18 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
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_SIGN_MINUS: m_conv.mk_is_sign_minus(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_TO_IEEE_BV: m_conv.mk_to_ieee_bv(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_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(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;);
- throw tactic_exception("NYI");
+ NOT_IMPLEMENTED_YET();
}
}
diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp
index a4212d579..7dc34dd11 100644
--- a/src/ast/rewriter/float_rewriter.cpp
+++ b/src/ast/rewriter/float_rewriter.cpp
@@ -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;
@@ -62,10 +62,10 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
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_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_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_FP_UNSIGNED: SASSERT(num_args == 2); st = mk_to_fp_unsigned(args[0], args[1], 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;
@@ -73,7 +73,7 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
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());
@@ -154,7 +154,7 @@ 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;
}
@@ -188,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;
@@ -204,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;
@@ -239,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;
}
@@ -284,7 +284,7 @@ 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_value(arg1, rm)) {
scoped_mpf v2(m_util.fm()), v3(m_util.fm()), v4(m_util.fm());
@@ -480,7 +480,7 @@ br_status float_rewriter::mk_is_subnormal(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_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();
@@ -490,6 +490,17 @@ 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());
@@ -532,10 +543,6 @@ br_status float_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref
return BR_FAILED;
}
-br_status float_rewriter::mk_to_fp_unsigned(expr * arg1, expr * arg2, expr_ref & result) {
- return BR_FAILED;
-}
-
br_status float_rewriter::mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result) {
return BR_FAILED;
}
diff --git a/src/ast/rewriter/float_rewriter.h b/src/ast/rewriter/float_rewriter.h
index 0f44d227c..4d8cec856 100644
--- a/src/ast/rewriter/float_rewriter.h
+++ b/src/ast/rewriter/float_rewriter.h
@@ -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);
@@ -70,10 +69,12 @@ public:
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_sign_minus(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);
diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp
index 836ade9ce..a80c5bc6c 100644
--- a/src/cmd_context/basic_cmds.cpp
+++ b/src/cmd_context/basic_cmds.cpp
@@ -241,7 +241,6 @@ protected:
symbol m_produce_models;
symbol m_produce_assignments;
symbol m_produce_interpolants;
- symbol m_check_interpolants;
symbol m_regular_output_channel;
symbol m_diagnostic_output_channel;
symbol m_random_seed;
@@ -256,7 +255,6 @@ protected:
s == m_print_success || s == m_print_warning || s == m_expand_definitions ||
s == m_interactive_mode || s == m_produce_proofs || s == m_produce_unsat_cores ||
s == m_produce_models || s == m_produce_assignments || s == m_produce_interpolants ||
- s == m_check_interpolants ||
s == m_regular_output_channel || s == m_diagnostic_output_channel ||
s == m_random_seed || s == m_verbosity || s == m_global_decls;
}
@@ -275,7 +273,6 @@ public:
m_produce_models(":produce-models"),
m_produce_assignments(":produce-assignments"),
m_produce_interpolants(":produce-interpolants"),
- m_check_interpolants(":check-interpolants"),
m_regular_output_channel(":regular-output-channel"),
m_diagnostic_output_channel(":diagnostic-output-channel"),
m_random_seed(":random-seed"),
@@ -347,9 +344,6 @@ class set_option_cmd : public set_get_option_cmd {
check_not_initialized(ctx, m_produce_interpolants);
ctx.set_produce_interpolants(to_bool(value));
}
- else if (m_option == m_check_interpolants) {
- ctx.set_check_interpolants(to_bool(value));
- }
else if (m_option == m_produce_unsat_cores) {
check_not_initialized(ctx, m_produce_unsat_cores);
ctx.set_produce_unsat_cores(to_bool(value));
diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp
index 42497ef5a..67a0489f7 100644
--- a/src/cmd_context/cmd_context.cpp
+++ b/src/cmd_context/cmd_context.cpp
@@ -410,10 +410,6 @@ void cmd_context::set_produce_interpolants(bool f) {
// set_solver_factory(mk_smt_solver_factory());
}
-void cmd_context::set_check_interpolants(bool f) {
- m_params.m_check_interpolants = f;
-}
-
bool cmd_context::produce_models() const {
return m_params.m_model;
}
@@ -427,10 +423,6 @@ bool cmd_context::produce_interpolants() const {
return m_params.m_proof;
}
-bool cmd_context::check_interpolants() const {
- return m_params.m_check_interpolants;
-}
-
bool cmd_context::produce_unsat_cores() const {
return m_params.m_unsat_core;
}
diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h
index 091e0765d..c9996c48f 100644
--- a/src/cmd_context/cmd_context.h
+++ b/src/cmd_context/cmd_context.h
@@ -296,7 +296,6 @@ public:
bool produce_models() const;
bool produce_proofs() const;
bool produce_interpolants() const;
- bool check_interpolants() const;
bool produce_unsat_cores() const;
bool well_sorted_check_enabled() const;
bool validate_model_enabled() const;
@@ -304,7 +303,6 @@ public:
void set_produce_unsat_cores(bool flag);
void set_produce_proofs(bool flag);
void set_produce_interpolants(bool flag);
- void set_check_interpolants(bool flag);
bool produce_assignments() const { return m_produce_assignments; }
void set_produce_assignments(bool flag) { m_produce_assignments = flag; }
void set_status(status st) { m_status = st; }
diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp
index 71b251610..f4ec140ef 100644
--- a/src/cmd_context/context_params.cpp
+++ b/src/cmd_context/context_params.cpp
@@ -61,9 +61,6 @@ void context_params::set(char const * param, char const * value) {
else if (p == "proof") {
set_bool(m_proof, param, value);
}
- else if (p == "check_interpolants") {
- set_bool(m_check_interpolants, param, value);
- }
else if (p == "model") {
set_bool(m_model, param, value);
}
@@ -105,7 +102,6 @@ void context_params::updt_params(params_ref const & p) {
m_well_sorted_check = p.get_bool("type_check", p.get_bool("well_sorted_check", true));
m_auto_config = p.get_bool("auto_config", true);
m_proof = p.get_bool("proof", false);
- m_check_interpolants = p.get_bool("check_interpolants", false);
m_model = p.get_bool("model", true);
m_model_validate = p.get_bool("model_validate", false);
m_trace = p.get_bool("trace", false);
@@ -120,7 +116,6 @@ void context_params::collect_param_descrs(param_descrs & d) {
d.insert("well_sorted_check", CPK_BOOL, "type checker", "true");
d.insert("type_check", CPK_BOOL, "type checker (alias for well_sorted_check)", "true");
d.insert("auto_config", CPK_BOOL, "use heuristics to automatically select solver and configure it", "true");
- d.insert("check_interpolants", CPK_BOOL, "check correctness of interpolants", "false");
d.insert("model_validate", CPK_BOOL, "validate models produced by solvers", "false");
d.insert("trace", CPK_BOOL, "trace generation for VCC", "false");
d.insert("trace_file_name", CPK_STRING, "trace out file name (see option 'trace')", "z3.log");
diff --git a/src/cmd_context/context_params.h b/src/cmd_context/context_params.h
index e26fd3fe5..506e559db 100644
--- a/src/cmd_context/context_params.h
+++ b/src/cmd_context/context_params.h
@@ -30,7 +30,6 @@ public:
bool m_auto_config;
bool m_proof;
bool m_interpolants;
- bool m_check_interpolants;
bool m_debug_ref_count;
bool m_trace;
std::string m_trace_file_name;
diff --git a/src/cmd_context/interpolant_cmds.cpp b/src/cmd_context/interpolant_cmds.cpp
index cb83b52f6..42646a99d 100644
--- a/src/cmd_context/interpolant_cmds.cpp
+++ b/src/cmd_context/interpolant_cmds.cpp
@@ -65,7 +65,7 @@ static void show_interpolant_and_maybe_check(cmd_context & ctx,
s.cleanup();
// verify, for the paranoid...
- if(check || ctx.check_interpolants()){
+ if(check || interp_params(m_params).check()){
std::ostringstream err;
ast_manager &_m = ctx.m();
diff --git a/src/duality/duality.h b/src/duality/duality.h
index c1c9797f3..edd89d78f 100644
--- a/src/duality/duality.h
+++ b/src/duality/duality.h
@@ -104,6 +104,8 @@ namespace Duality {
FuncDecl RenumberPred(const FuncDecl &f, int n);
+ FuncDecl NumberPred(const FuncDecl &f, int n);
+
Term ExtractStores(hash_map &memo, const Term &t, std::vector &cnstrs, hash_map &renaming);
@@ -488,9 +490,10 @@ protected:
std::vector Incoming;
Term dual;
Node *map;
+ unsigned recursion_bound;
Node(const FuncDecl &_Name, const Transformer &_Annotation, const Transformer &_Bound, const Transformer &_Underapprox, const Term &_dual, RPFP *_owner, int _number)
- : Name(_Name), Annotation(_Annotation), Bound(_Bound), Underapprox(_Underapprox), dual(_dual) {owner = _owner; number = _number; Outgoing = 0;}
+ : Name(_Name), Annotation(_Annotation), Bound(_Bound), Underapprox(_Underapprox), dual(_dual) {owner = _owner; number = _number; Outgoing = 0; recursion_bound = UINT_MAX;}
};
/** Create a node in the graph. The input is a term R(v_1...v_n)
@@ -829,7 +832,7 @@ protected:
#ifdef _WINDOWS
__declspec(dllexport)
#endif
- void FromClauses(const std::vector &clauses);
+ void FromClauses(const std::vector &clauses, const std::vector *bounds = 0);
void FromFixpointContext(fixedpoint fp, std::vector &queries);
@@ -902,6 +905,10 @@ protected:
int CumulativeDecisions();
+ void GreedyReduceNodes(std::vector &nodes);
+
+ check_result CheckWithConstrainedNodes(std::vector &posnodes,std::vector &negnodes);
+
solver &slvr(){
return *ls->slvr;
}
diff --git a/src/duality/duality_profiling.cpp b/src/duality/duality_profiling.cpp
index d5dac0811..5bcda972a 100755
--- a/src/duality/duality_profiling.cpp
+++ b/src/duality/duality_profiling.cpp
@@ -125,8 +125,18 @@ namespace Duality {
void timer_stop(const char *name){
if(current->name != name || !current->parent){
+#if 0
std::cerr << "imbalanced timer_start and timer_stop";
exit(1);
+#endif
+ // in case we lost a timer stop due to an exception
+ while(current->name != name && current->parent)
+ current = current->parent;
+ if(current->parent){
+ current->time += (current_time() - current->start_time);
+ current = current->parent;
+ }
+ return;
}
current->time += (current_time() - current->start_time);
current = current->parent;
diff --git a/src/duality/duality_rpfp.cpp b/src/duality/duality_rpfp.cpp
index ef37dd8a2..f2824c9b0 100755
--- a/src/duality/duality_rpfp.cpp
+++ b/src/duality/duality_rpfp.cpp
@@ -2816,6 +2816,62 @@ namespace Duality {
}
}
+ void foobar(){
+ }
+
+ void RPFP::GreedyReduceNodes(std::vector &nodes){
+ std::vector lits;
+ for(unsigned i = 0; i < nodes.size(); i++){
+ Term b; std::vector v;
+ RedVars(nodes[i], b, v);
+ lits.push_back(!b);
+ expr bv = dualModel.eval(b);
+ if(eq(bv,ctx.bool_val(true))){
+ check_result res = slvr_check(lits.size(),&lits[0]);
+ if(res == unsat)
+ lits.pop_back();
+ else
+ foobar();
+ }
+ }
+ }
+
+ check_result RPFP::CheckWithConstrainedNodes(std::vector &posnodes,std::vector &negnodes){
+ timer_start("Check");
+ std::vector lits;
+ for(unsigned i = 0; i < posnodes.size(); i++){
+ Term b; std::vector v;
+ RedVars(posnodes[i], b, v);
+ lits.push_back(b);
+ }
+ for(unsigned i = 0; i < negnodes.size(); i++){
+ Term b; std::vector v;
+ RedVars(negnodes[i], b, v);
+ lits.push_back(!b);
+ }
+ check_result res = slvr_check(lits.size(),&lits[0]);
+ if(res == unsat && posnodes.size()){
+ lits.resize(posnodes.size());
+ res = slvr_check(lits.size(),&lits[0]);
+ }
+ dualModel = slvr().get_model();
+#if 0
+ if(!dualModel.null()){
+ std::cout << "posnodes called:\n";
+ for(unsigned i = 0; i < posnodes.size(); i++)
+ if(!Empty(posnodes[i]))
+ std::cout << posnodes[i]->Name.name() << "\n";
+ std::cout << "negnodes called:\n";
+ for(unsigned i = 0; i < negnodes.size(); i++)
+ if(!Empty(negnodes[i]))
+ std::cout << negnodes[i]->Name.name() << "\n";
+ }
+#endif
+ timer_stop("Check");
+ return res;
+ }
+
+
void RPFP_caching::FilterCore(std::vector &core, std::vector &full_core){
hash_set core_set;
std::copy(full_core.begin(),full_core.end(),std::inserter(core_set,core_set.begin()));
@@ -3333,6 +3389,17 @@ namespace Duality {
return ctx.function(name.c_str(), arity, &domain[0], f.range());
}
+ Z3User::FuncDecl Z3User::NumberPred(const FuncDecl &f, int n)
+ {
+ std::string name = f.name().str();
+ name = name + "_" + string_of_int(n);
+ int arity = f.arity();
+ std::vector domain;
+ for(int i = 0; i < arity; i++)
+ domain.push_back(f.domain(i));
+ return ctx.function(name.c_str(), arity, &domain[0], f.range());
+ }
+
// Scan the clause body for occurrences of the predicate unknowns
RPFP::Term RPFP::ScanBody(hash_map &memo,
@@ -3570,7 +3637,7 @@ namespace Duality {
#define USE_QE_LITE
- void RPFP::FromClauses(const std::vector &unskolemized_clauses){
+ void RPFP::FromClauses(const std::vector &unskolemized_clauses, const std::vector *bounds){
hash_map pmap;
func_decl fail_pred = ctx.fresh_func_decl("@Fail", ctx.bool_sort());
@@ -3663,6 +3730,7 @@ namespace Duality {
pmap[R] = node;
if (is_query)
node->Bound = CreateRelation(std::vector(), ctx.bool_val(false));
+ node->recursion_bound = bounds ? 0 : UINT_MAX;
}
}
@@ -3728,6 +3796,8 @@ namespace Duality {
Transformer T = CreateTransformer(Relparams,Indparams,body);
Edge *edge = CreateEdge(Parent,T,Children);
edge->labeled = labeled;; // remember for label extraction
+ if(bounds)
+ Parent->recursion_bound = std::max(Parent->recursion_bound,(*bounds)[i]);
// edges.push_back(edge);
}
diff --git a/src/duality/duality_solver.cpp b/src/duality/duality_solver.cpp
index 681582415..69759f9bb 100644
--- a/src/duality/duality_solver.cpp
+++ b/src/duality/duality_solver.cpp
@@ -33,6 +33,7 @@ Revision History:
#include