3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 18:31:49 +00:00

Merge pull request #1873 from xlauko/master

Add a floating-point support to c++ api.
This commit is contained in:
Nikolaj Bjorner 2018-10-12 10:52:55 -07:00 committed by GitHub
commit efb12331e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -138,11 +138,22 @@ namespace z3 {
\brief A Context manages all other Z3 objects, global configuration options, etc.
*/
class context {
public:
enum class rounding_mode {
RNA,
RNE,
RTP,
RTN,
RTZ
};
private:
bool m_enable_exceptions;
rounding_mode m_rounding_mode;
Z3_context m_ctx;
void init(config & c) {
m_ctx = Z3_mk_context_rc(c);
m_enable_exceptions = true;
m_rounding_mode = rounding_mode::RNA;
Z3_set_error_handler(m_ctx, 0);
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
}
@ -171,7 +182,7 @@ namespace z3 {
}
/**
\brief The C++ API uses by defaults exceptions on errors.
\brief The C++ API uses by defaults exceptions on errors.
For applications that don't work well with exceptions (there should be only few)
you have the ability to turn off exceptions. The tradeoffs are that applications
have to be very careful about using check_error() after calls that may result in an
@ -247,6 +258,26 @@ namespace z3 {
*/
sort array_sort(sort d, sort r);
sort array_sort(sort_vector const& d, sort r);
/**
\brief Return a floating point sort.
\c ebits is a number of exponent bits,
\c sbits is a number of significand bits,
\pre where ebits must be larger than 1 and sbits must be larger than 2.
*/
sort fpa_sort(unsigned ebits, unsigned sbits);
/**
\brief Return a FloatingPoint sort with given precision bitwidth (16, 32, 64 or 128).
*/
template<size_t precision>
sort fpa_sort();
/**
\brief Return a RoundingMode sort.
*/
sort fpa_rounding_mode();
/**
\breif Sets RoundingMode of FloatingPoints.
*/
void set_rounding_mode(rounding_mode rm);
/**
\brief Return an enumeration sort: enum_names[0], ..., enum_names[n-1].
\c cs and \c ts are output parameters. The method stores in \c cs the constants corresponding to the enumerated elements,
@ -284,6 +315,10 @@ namespace z3 {
expr int_const(char const * name);
expr real_const(char const * name);
expr bv_const(char const * name, unsigned sz);
expr fpa_const(char const * name, unsigned ebits, unsigned sbits);
template<size_t precision>
expr fpa_const(char const * name);
expr bool_val(bool b);
@ -307,6 +342,9 @@ namespace z3 {
expr bv_val(char const * n, unsigned sz);
expr bv_val(unsigned n, bool const* bits);
expr fpa_val(double n);
expr fpa_val(float n);
expr string_val(char const* s);
expr string_val(std::string const& s);
@ -465,6 +503,7 @@ namespace z3 {
public:
sort(context & c):ast(c) {}
sort(context & c, Z3_sort s):ast(c, reinterpret_cast<Z3_ast>(s)) {}
sort(context & c, Z3_ast a):ast(c, a) {}
sort(sort const & s):ast(s) {}
operator Z3_sort() const { return reinterpret_cast<Z3_sort>(m_ast); }
/**
@ -523,6 +562,10 @@ namespace z3 {
\brief Return true if this sort is a Finite domain sort.
*/
bool is_finite_domain() const { return sort_kind() == Z3_FINITE_DOMAIN_SORT; }
/**
\brief Return true if this sort is a Floating point sort.
*/
bool is_fpa() const { return sort_kind() == Z3_FLOATING_POINT_SORT; }
/**
\brief Return the size of this Bit-vector sort.
@ -531,6 +574,9 @@ namespace z3 {
*/
unsigned bv_size() const { assert(is_bv()); unsigned r = Z3_get_bv_sort_size(ctx(), *this); check_error(); return r; }
unsigned fpa_ebits() const { assert(is_fpa()); unsigned r = Z3_fpa_get_ebits(ctx(), *this); check_error(); return r; }
unsigned fpa_sbits() const { assert(is_fpa()); unsigned r = Z3_fpa_get_sbits(ctx(), *this); check_error(); return r; }
/**
\brief Return the domain of this Array sort.
@ -634,7 +680,7 @@ namespace z3 {
\brief Return true if this is a regular expression.
*/
bool is_re() const { return get_sort().is_re(); }
/**
\brief Return true if this is a Finite-domain expression.
@ -644,6 +690,10 @@ namespace z3 {
*/
bool is_finite_domain() const { return get_sort().is_finite_domain(); }
/**
\brief Return true if this is a FloatingPoint expression. .
*/
bool is_fpa() const { return get_sort().is_fpa(); }
/**
\brief Return true if this expression is a numeral.
@ -696,29 +746,29 @@ namespace z3 {
\brief Return true if this expression is well sorted (aka type correct).
*/
bool is_well_sorted() const { bool r = Z3_is_well_sorted(ctx(), m_ast) != 0; check_error(); return r; }
/**
\brief Return string representation of numeral or algebraic number
This method assumes the expression is numeral or algebraic
\pre is_numeral() || is_algebraic()
*/
std::string get_decimal_string(int precision) const {
assert(is_numeral() || is_algebraic());
return std::string(Z3_get_numeral_decimal_string(ctx(), m_ast, precision));
}
/**
\brief Return int value of numeral, throw if result cannot fit in
machine int
It only makes sense to use this function if the caller can ensure that
the result is an integer or if exceptions are enabled.
the result is an integer or if exceptions are enabled.
If exceptions are disabled, then use the is_numeral_i function.
\pre is_numeral()
*/
int get_numeral_int() const {
int get_numeral_int() const {
int result = 0;
if (!is_numeral_i(result)) {
assert(ctx().enable_exceptions());
@ -727,13 +777,13 @@ namespace z3 {
}
return result;
}
/**
\brief Return uint value of numeral, throw if result cannot fit in
machine uint
It only makes sense to use this function if the caller can ensure that
the result is an integer or if exceptions are enabled.
the result is an integer or if exceptions are enabled.
If exceptions are disabled, then use the is_numeral_u function.
\pre is_numeral()
*/
@ -747,11 +797,11 @@ namespace z3 {
}
return result;
}
/**
\brief Return \c int64_t value of numeral, throw if result cannot fit in
\c int64_t.
\pre is_numeral()
*/
int64_t get_numeral_int64() const {
@ -764,11 +814,11 @@ namespace z3 {
}
return result;
}
/**
\brief Return \c uint64_t value of numeral, throw if result cannot fit in
\c uint64_t.
\pre is_numeral()
*/
uint64_t get_numeral_uint64() const {
@ -786,7 +836,7 @@ namespace z3 {
return Z3_get_bool_value(ctx(), m_ast);
}
expr numerator() const {
expr numerator() const {
assert(is_numeral());
Z3_ast r = Z3_get_numerator(ctx(), m_ast);
check_error();
@ -794,7 +844,7 @@ namespace z3 {
}
expr denominator() const {
expr denominator() const {
assert(is_numeral());
Z3_ast r = Z3_get_denominator(ctx(), m_ast);
check_error();
@ -803,6 +853,17 @@ namespace z3 {
operator Z3_app() const { assert(is_app()); return reinterpret_cast<Z3_app>(m_ast); }
/**
\brief Return a RoundingMode sort.
*/
sort fpa_rounding_mode() {
assert(is_fpa());
Z3_sort s = ctx().fpa_rounding_mode();
check_error();
return sort(ctx(), s);
}
/**
\brief Return the declaration associated with this application.
This method assumes the expression is an application.
@ -905,7 +966,7 @@ namespace z3 {
bool is_implies() const { return is_app() && Z3_OP_IMPLIES == decl().decl_kind(); }
bool is_eq() const { return is_app() && Z3_OP_EQ == decl().decl_kind(); }
bool is_ite() const { return is_app() && Z3_OP_ITE == decl().decl_kind(); }
friend expr distinct(expr_vector const& args);
friend expr concat(expr const& a, expr const& b);
friend expr concat(expr_vector const& args);
@ -992,23 +1053,34 @@ namespace z3 {
friend expr nor(expr const& a, expr const& b);
friend expr xnor(expr const& a, expr const& b);
friend expr min(expr const& a, expr const& b);
friend expr max(expr const& a, expr const& b);
expr rotate_left(unsigned i) { Z3_ast r = Z3_mk_rotate_left(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
expr rotate_right(unsigned i) { Z3_ast r = Z3_mk_rotate_right(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
expr repeat(unsigned i) { Z3_ast r = Z3_mk_repeat(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
friend expr abs(expr const & a);
friend expr sqrt(expr const & a, expr const & rm);
friend expr operator~(expr const & a);
expr extract(unsigned hi, unsigned lo) const { Z3_ast r = Z3_mk_extract(ctx(), hi, lo, *this); ctx().check_error(); return expr(ctx(), r); }
expr extract(unsigned hi, unsigned lo) const { Z3_ast r = Z3_mk_extract(ctx(), hi, lo, *this); ctx().check_error(); return expr(ctx(), r); }
unsigned lo() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 1)); }
unsigned hi() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 0)); }
/**
\brief FloatingPoint fused multiply-add.
*/
friend expr fma(expr const& a, expr const& b, expr const& c);
/**
\brief sequence and regular expression operations.
+ is overloaded as sequence concatenation and regular expression union.
concat is overloaded to handle sequences and regular expressions
*/
expr extract(expr const& offset, expr const& length) const {
expr extract(expr const& offset, expr const& length) const {
check_context(*this, offset); check_context(offset, length);
Z3_ast r = Z3_mk_seq_extract(ctx(), *this, offset, length); check_error(); return expr(ctx(), r);
Z3_ast r = Z3_mk_seq_extract(ctx(), *this, offset, length); check_error(); return expr(ctx(), r);
}
expr replace(expr const& src, expr const& dst) const {
check_context(*this, src); check_context(src, dst);
@ -1049,19 +1121,19 @@ namespace z3 {
return expr(ctx(), r);
}
friend expr range(expr const& lo, expr const& hi);
friend expr range(expr const& lo, expr const& hi);
/**
\brief create a looping regular expression.
*/
expr loop(unsigned lo) {
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, 0);
check_error();
return expr(ctx(), r);
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, 0);
check_error();
return expr(ctx(), r);
}
expr loop(unsigned lo, unsigned hi) {
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, hi);
check_error();
return expr(ctx(), r);
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, hi);
check_error();
return expr(ctx(), r);
}
@ -1094,7 +1166,7 @@ namespace z3 {
inline expr implies(expr const & a, expr const & b) {
assert(a.is_bool() && b.is_bool());
assert(a.is_bool() && b.is_bool());
_Z3_MK_BIN_(a, b, Z3_mk_implies);
}
inline expr implies(expr const & a, bool b) { return implies(a, a.ctx().bool_val(b)); }
@ -1109,7 +1181,13 @@ namespace z3 {
inline expr mod(expr const & a, int b) { return mod(a, a.ctx().num_val(b, a.get_sort())); }
inline expr mod(int a, expr const & b) { return mod(b.ctx().num_val(a, b.get_sort()), b); }
inline expr rem(expr const& a, expr const& b) { _Z3_MK_BIN_(a, b, Z3_mk_rem); }
inline expr rem(expr const& a, expr const& b) {
if (a.is_fpa() && b.is_fpa()) {
_Z3_MK_BIN_(a, b, Z3_mk_fpa_rem);
} else {
_Z3_MK_BIN_(a, b, Z3_mk_rem);
}
}
inline expr rem(expr const & a, int b) { return rem(a, a.ctx().num_val(b, a.get_sort())); }
inline expr rem(int a, expr const & b) { return rem(b.ctx().num_val(a, b.get_sort()), b); }
@ -1158,8 +1236,8 @@ namespace z3 {
a.check_error();
return expr(a.ctx(), r);
}
inline expr operator==(expr const & a, int b) { assert(a.is_arith() || a.is_bv()); return a == a.ctx().num_val(b, a.get_sort()); }
inline expr operator==(int a, expr const & b) { assert(b.is_arith() || b.is_bv()); return b.ctx().num_val(a, b.get_sort()) == b; }
inline expr operator==(expr const & a, int b) { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a == a.ctx().num_val(b, a.get_sort()); }
inline expr operator==(int a, expr const & b) { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) == b; }
inline expr operator!=(expr const & a, expr const & b) {
check_context(a, b);
@ -1168,8 +1246,8 @@ namespace z3 {
a.check_error();
return expr(a.ctx(), r);
}
inline expr operator!=(expr const & a, int b) { assert(a.is_arith() || a.is_bv()); return a != a.ctx().num_val(b, a.get_sort()); }
inline expr operator!=(int a, expr const & b) { assert(b.is_arith() || b.is_bv()); return b.ctx().num_val(a, b.get_sort()) != b; }
inline expr operator!=(expr const & a, int b) { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a != a.ctx().num_val(b, a.get_sort()); }
inline expr operator!=(int a, expr const & b) { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) != b; }
inline expr operator+(expr const & a, expr const & b) {
check_context(a, b);
@ -1188,6 +1266,9 @@ namespace z3 {
Z3_ast _args[2] = { a, b };
r = Z3_mk_re_union(a.ctx(), 2, _args);
}
else if (a.is_fpa() && b.is_fpa()) {
r = Z3_mk_fpa_add(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
}
else {
// operator is not supported by given arguments.
assert(false);
@ -1208,6 +1289,9 @@ namespace z3 {
else if (a.is_bv() && b.is_bv()) {
r = Z3_mk_bvmul(a.ctx(), a, b);
}
else if (a.is_fpa() && b.is_fpa()) {
r = Z3_mk_fpa_mul(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
}
else {
// operator is not supported by given arguments.
assert(false);
@ -1245,6 +1329,9 @@ namespace z3 {
else if (a.is_bv() && b.is_bv()) {
r = Z3_mk_bvsdiv(a.ctx(), a, b);
}
else if (a.is_fpa() && b.is_fpa()) {
r = Z3_mk_fpa_div(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
}
else {
// operator is not supported by given arguments.
assert(false);
@ -1263,6 +1350,9 @@ namespace z3 {
else if (a.is_bv()) {
r = Z3_mk_bvneg(a.ctx(), a);
}
else if (a.is_fpa()) {
r = Z3_mk_fpa_neg(a.ctx(), a);
}
else {
// operator is not supported by given arguments.
assert(false);
@ -1281,6 +1371,9 @@ namespace z3 {
else if (a.is_bv() && b.is_bv()) {
r = Z3_mk_bvsub(a.ctx(), a, b);
}
else if (a.is_fpa() && b.is_fpa()) {
r = Z3_mk_fpa_sub(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
}
else {
// operator is not supported by given arguments.
assert(false);
@ -1300,6 +1393,9 @@ namespace z3 {
else if (a.is_bv() && b.is_bv()) {
r = Z3_mk_bvsle(a.ctx(), a, b);
}
else if (a.is_fpa() && b.is_fpa()) {
r = Z3_mk_fpa_leq(a.ctx(), a, b);
}
else {
// operator is not supported by given arguments.
assert(false);
@ -1322,6 +1418,9 @@ namespace z3 {
else if (a.is_bv() && b.is_bv()) {
r = Z3_mk_bvslt(a.ctx(), a, b);
}
else if (a.is_fpa() && b.is_fpa()) {
r = Z3_mk_fpa_lt(a.ctx(), a, b);
}
else {
// operator is not supported by given arguments.
assert(false);
@ -1341,6 +1440,9 @@ namespace z3 {
else if (a.is_bv() && b.is_bv()) {
r = Z3_mk_bvsgt(a.ctx(), a, b);
}
else if (a.is_fpa() && b.is_fpa()) {
r = Z3_mk_fpa_gt(a.ctx(), a, b);
}
else {
// operator is not supported by given arguments.
assert(false);
@ -1366,17 +1468,30 @@ namespace z3 {
inline expr nand(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvnand(a.ctx(), a, b); return expr(a.ctx(), r); }
inline expr nor(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvnor(a.ctx(), a, b); return expr(a.ctx(), r); }
inline expr xnor(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvxnor(a.ctx(), a, b); return expr(a.ctx(), r); }
inline expr min(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_fpa_min(a.ctx(), a, b); return expr(a.ctx(), r); }
inline expr max(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_fpa_max(a.ctx(), a, b); return expr(a.ctx(), r); }
inline expr abs(expr const & a) { Z3_ast r = Z3_mk_fpa_abs(a.ctx(), a); return expr(a.ctx(), r); }
inline expr sqrt(expr const & a, expr const& rm) {
check_context(a, rm);
assert(a.is_fpa());
Z3_ast r = Z3_mk_fpa_sqrt(a.ctx(), rm, a);
return expr(a.ctx(), r);
}
inline expr operator~(expr const & a) { Z3_ast r = Z3_mk_bvnot(a.ctx(), a); return expr(a.ctx(), r); }
inline expr fma(expr const& a, expr const& b, expr const& c, expr const& rm) {
check_context(a, b); check_context(a, c); check_context(a, rm);
assert(a.is_fpa() && b.is_fpa() && c.is_fpa());
Z3_ast r = Z3_mk_fpa_fma(a.ctx(), rm, a, b, c);
a.check_error();
return expr(a.ctx(), r);
}
/**
\brief Create the if-then-else expression <tt>ite(c, t, e)</tt>
\pre c.is_bool()
*/
inline expr ite(expr const & c, expr const & t, expr const & e) {
check_context(c, t); check_context(c, e);
assert(c.is_bool());
@ -1453,45 +1568,45 @@ namespace z3 {
inline expr smod(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvsmod(a.ctx(), a, b)); }
inline expr smod(expr const & a, int b) { return smod(a, a.ctx().num_val(b, a.get_sort())); }
inline expr smod(int a, expr const & b) { return smod(b.ctx().num_val(a, b.get_sort()), b); }
/**
\brief unsigned reminder operator for bitvectors
*/
inline expr urem(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvurem(a.ctx(), a, b)); }
inline expr urem(expr const & a, int b) { return urem(a, a.ctx().num_val(b, a.get_sort())); }
inline expr urem(int a, expr const & b) { return urem(b.ctx().num_val(a, b.get_sort()), b); }
/**
\brief shift left operator for bitvectors
*/
inline expr shl(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvshl(a.ctx(), a, b)); }
inline expr shl(expr const & a, int b) { return shl(a, a.ctx().num_val(b, a.get_sort())); }
inline expr shl(int a, expr const & b) { return shl(b.ctx().num_val(a, b.get_sort()), b); }
/**
\brief logic shift right operator for bitvectors
*/
inline expr lshr(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvlshr(a.ctx(), a, b)); }
inline expr lshr(expr const & a, int b) { return lshr(a, a.ctx().num_val(b, a.get_sort())); }
inline expr lshr(int a, expr const & b) { return lshr(b.ctx().num_val(a, b.get_sort()), b); }
/**
\brief arithmetic shift right operator for bitvectors
*/
inline expr ashr(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvashr(a.ctx(), a, b)); }
inline expr ashr(expr const & a, int b) { return ashr(a, a.ctx().num_val(b, a.get_sort())); }
inline expr ashr(int a, expr const & b) { return ashr(b.ctx().num_val(a, b.get_sort()), b); }
/**
\brief Extend the given bit-vector with zeros to the (unsigned) equivalent bitvector of size m+i, where m is the size of the given bit-vector.
*/
inline expr zext(expr const & a, unsigned i) { return to_expr(a.ctx(), Z3_mk_zero_ext(a.ctx(), i, a)); }
/**
\brief Sign-extend of the given bit-vector to the (signed) equivalent bitvector of size m+i, where m is the size of the given bit-vector.
*/
inline expr sext(expr const & a, unsigned i) { return to_expr(a.ctx(), Z3_mk_sign_ext(a.ctx(), i, a)); }
template<typename T> class cast_ast;
template<> class cast_ast<ast> {
@ -1563,7 +1678,7 @@ namespace z3 {
unsigned m_index;
public:
iterator(ast_vector_tpl const* v, unsigned i): m_vector(v), m_index(i) {}
iterator(iterator& other): m_vector(other.m_vector), m_index(other.m_index) {}
iterator(iterator& other): m_vector(other.m_vector), m_index(other.m_index) {}
iterator operator=(iterator const& other) { m_vector = other.m_vector; m_index = other.m_index; return *this; }
bool operator==(iterator const& other) {
@ -1773,7 +1888,7 @@ namespace z3 {
return expr(ctx, r);
}
inline expr mk_or(expr_vector const& args) {
inline expr mk_or(expr_vector const& args) {
array<Z3_ast> _args(args);
Z3_ast r = Z3_mk_or(args.ctx(), _args.size(), _args.ptr());
args.check_error();
@ -1852,7 +1967,7 @@ namespace z3 {
model(context & c):object(c) { init(Z3_mk_model(c)); }
model(context & c, Z3_model m):object(c) { init(m); }
model(model const & s):object(s) { init(s.m_model); }
model(model& src, context& dst, translate) : object(dst) { init(Z3_model_translate(src.ctx(), src, dst)); }
model(model& src, context& dst, translate) : object(dst) { init(Z3_model_translate(src.ctx(), src, dst)); }
~model() { Z3_model_dec_ref(ctx(), m_model); }
operator Z3_model() const { return m_model; }
model & operator=(model const & s) {
@ -1884,7 +1999,7 @@ namespace z3 {
}
// returns interpretation of constant declaration c.
// If c is not assigned any value in the model it returns
// If c is not assigned any value in the model it returns
// an expression with a null ast reference.
expr get_const_interp(func_decl c) const {
check_context(*this, c);
@ -1898,7 +2013,7 @@ namespace z3 {
check_error();
return func_interp(ctx(), r);
}
// returns true iff the model contains an interpretation
// for function f.
bool has_interp(func_decl f) const {
@ -1945,7 +2060,7 @@ namespace z3 {
bool is_uint(unsigned i) const { Z3_bool r = Z3_stats_is_uint(ctx(), m_stats, i); check_error(); return r != 0; }
bool is_double(unsigned i) const { Z3_bool r = Z3_stats_is_double(ctx(), m_stats, i); check_error(); return r != 0; }
unsigned uint_value(unsigned i) const { unsigned r = Z3_stats_get_uint_value(ctx(), m_stats, i); check_error(); return r; }
double double_value(unsigned i) const { double r = Z3_stats_get_double_value(ctx(), m_stats, i); check_error(); return r; }
double double_value(unsigned i) const { double r = Z3_stats_get_double_value(ctx(), m_stats, i); check_error(); return r; }
friend std::ostream & operator<<(std::ostream & out, stats const & s);
};
inline std::ostream & operator<<(std::ostream & out, stats const & s) { out << Z3_stats_to_string(s.ctx(), s); return out; }
@ -2001,7 +2116,7 @@ namespace z3 {
void add(expr const & e, char const * p) {
add(e, ctx().bool_const(p));
}
// fails for some compilers:
// fails for some compilers:
// void add(expr_vector const& v) { check_context(*this, v); for (expr e : v) add(e); }
void from_file(char const* file) { Z3_solver_from_file(ctx(), m_solver, file); ctx().check_parser_error(); }
void from_string(char const* s) { Z3_solver_from_string(ctx(), m_solver, s); ctx().check_parser_error(); }
@ -2066,11 +2181,11 @@ namespace z3 {
param_descrs get_param_descrs() { return param_descrs(ctx(), Z3_solver_get_param_descrs(ctx(), m_solver)); }
expr_vector cube(expr_vector& vars, unsigned cutoff) {
Z3_ast_vector r = Z3_solver_cube(ctx(), m_solver, vars, cutoff);
check_error();
return expr_vector(ctx(), r);
}
expr_vector cube(expr_vector& vars, unsigned cutoff) {
Z3_ast_vector r = Z3_solver_cube(ctx(), m_solver, vars, cutoff);
check_error();
return expr_vector(ctx(), r);
}
class cube_iterator {
solver& m_solver;
@ -2118,7 +2233,7 @@ namespace z3 {
cube_iterator operator++(int) { assert(false); return *this; }
expr_vector const * operator->() const { return &(operator*()); }
expr_vector const& operator*() const { return m_cube; }
bool operator==(cube_iterator const& other) {
return other.m_end == m_end;
};
@ -2407,7 +2522,7 @@ namespace z3 {
class optimize : public object {
Z3_optimize m_opt;
public:
class handle {
unsigned m_h;
@ -2456,16 +2571,16 @@ namespace z3 {
Z3_optimize_pop(ctx(), m_opt);
}
check_result check() { Z3_lbool r = Z3_optimize_check(ctx(), m_opt, 0, 0); check_error(); return to_check_result(r); }
check_result check(expr_vector const& asms) {
check_result check(expr_vector const& asms) {
unsigned n = asms.size();
array<Z3_ast> _asms(n);
for (unsigned i = 0; i < n; i++) {
check_context(*this, asms[i]);
_asms[i] = asms[i];
}
Z3_lbool r = Z3_optimize_check(ctx(), m_opt, n, _asms.ptr());
check_error();
return to_check_result(r);
Z3_lbool r = Z3_optimize_check(ctx(), m_opt, n, _asms.ptr());
check_error();
return to_check_result(r);
}
model get_model() const { Z3_model m = Z3_optimize_get_model(ctx(), m_opt); check_error(); return model(ctx(), m); }
expr_vector unsat_core() const { Z3_ast_vector r = Z3_optimize_get_unsat_core(ctx(), m_opt); check_error(); return expr_vector(ctx(), r); }
@ -2495,25 +2610,25 @@ namespace z3 {
public:
fixedpoint(context& c):object(c) { m_fp = Z3_mk_fixedpoint(c); Z3_fixedpoint_inc_ref(c, m_fp); }
~fixedpoint() { Z3_fixedpoint_dec_ref(ctx(), m_fp); }
operator Z3_fixedpoint() const { return m_fp; }
operator Z3_fixedpoint() const { return m_fp; }
void from_string(char const* s) { Z3_fixedpoint_from_string(ctx(), m_fp, s); check_error(); }
void from_file(char const* s) { Z3_fixedpoint_from_file(ctx(), m_fp, s); check_error(); }
void add_rule(expr& rule, symbol const& name) { Z3_fixedpoint_add_rule(ctx(), m_fp, rule, name); check_error(); }
void add_fact(func_decl& f, unsigned * args) { Z3_fixedpoint_add_fact(ctx(), m_fp, f, f.arity(), args); check_error(); }
check_result query(expr& q) { Z3_lbool r = Z3_fixedpoint_query(ctx(), m_fp, q); check_error(); return to_check_result(r); }
check_result query(func_decl_vector& relations) {
check_result query(func_decl_vector& relations) {
array<Z3_func_decl> rs(relations);
Z3_lbool r = Z3_fixedpoint_query_relations(ctx(), m_fp, rs.size(), rs.ptr());
check_error();
return to_check_result(r);
Z3_lbool r = Z3_fixedpoint_query_relations(ctx(), m_fp, rs.size(), rs.ptr());
check_error();
return to_check_result(r);
}
expr get_answer() { Z3_ast r = Z3_fixedpoint_get_answer(ctx(), m_fp); check_error(); return expr(ctx(), r); }
std::string reason_unknown() { return Z3_fixedpoint_get_reason_unknown(ctx(), m_fp); }
void update_rule(expr& rule, symbol const& name) { Z3_fixedpoint_update_rule(ctx(), m_fp, rule, name); check_error(); }
unsigned get_num_levels(func_decl& p) { unsigned r = Z3_fixedpoint_get_num_levels(ctx(), m_fp, p); check_error(); return r; }
expr get_cover_delta(int level, func_decl& p) {
Z3_ast r = Z3_fixedpoint_get_cover_delta(ctx(), m_fp, level, p);
check_error();
expr get_cover_delta(int level, func_decl& p) {
Z3_ast r = Z3_fixedpoint_get_cover_delta(ctx(), m_fp, level, p);
check_error();
return expr(ctx(), r);
}
void add_cover(int level, func_decl& p, expr& property) { Z3_fixedpoint_add_cover(ctx(), m_fp, level, p, property); check_error(); }
@ -2527,7 +2642,7 @@ namespace z3 {
std::string to_string() { return Z3_fixedpoint_to_string(ctx(), m_fp, 0, 0); }
std::string to_string(expr_vector const& queries) {
array<Z3_ast> qs(queries);
return Z3_fixedpoint_to_string(ctx(), m_fp, qs.size(), qs.ptr());
return Z3_fixedpoint_to_string(ctx(), m_fp, qs.size(), qs.ptr());
}
void push() { Z3_fixedpoint_push(ctx(), m_fp); check_error(); }
void pop() { Z3_fixedpoint_pop(ctx(), m_fp); check_error(); }
@ -2562,11 +2677,36 @@ namespace z3 {
inline sort context::string_sort() { Z3_sort s = Z3_mk_string_sort(m_ctx); check_error(); return sort(*this, s); }
inline sort context::seq_sort(sort& s) { Z3_sort r = Z3_mk_seq_sort(m_ctx, s); check_error(); return sort(*this, r); }
inline sort context::re_sort(sort& s) { Z3_sort r = Z3_mk_re_sort(m_ctx, s); check_error(); return sort(*this, r); }
inline sort context::fpa_sort(unsigned ebits, unsigned sbits) { Z3_sort s = Z3_mk_fpa_sort(m_ctx, ebits, sbits); check_error(); return sort(*this, s); }
template<>
inline sort context::fpa_sort<16>() { return fpa_sort(5, 11); }
template<>
inline sort context::fpa_sort<32>() { return fpa_sort(8, 24); }
template<>
inline sort context::fpa_sort<64>() { return fpa_sort(11, 53); }
template<>
inline sort context::fpa_sort<128>() { return fpa_sort(15, 113); }
inline sort context::fpa_rounding_mode() {
switch (m_rounding_mode) {
case rounding_mode::RNA: return sort(*this, Z3_mk_fpa_rna(m_ctx));
case rounding_mode::RNE: return sort(*this, Z3_mk_fpa_rne(m_ctx));
case rounding_mode::RTP: return sort(*this, Z3_mk_fpa_rtp(m_ctx));
case rounding_mode::RTN: return sort(*this, Z3_mk_fpa_rtn(m_ctx));
case rounding_mode::RTZ: return sort(*this, Z3_mk_fpa_rtz(m_ctx));
}
}
inline void context::set_rounding_mode(rounding_mode rm) { m_rounding_mode = rm; }
inline sort context::array_sort(sort d, sort r) { Z3_sort s = Z3_mk_array_sort(m_ctx, d, r); check_error(); return sort(*this, s); }
inline sort context::array_sort(sort_vector const& d, sort r) {
array<Z3_sort> dom(d);
Z3_sort s = Z3_mk_array_sort_n(m_ctx, dom.size(), dom.ptr(), r); check_error(); return sort(*this, s);
Z3_sort s = Z3_mk_array_sort_n(m_ctx, dom.size(), dom.ptr(), r); check_error(); return sort(*this, s);
}
inline sort context::enumeration_sort(char const * name, unsigned n, char const * const * enum_names, func_decl_vector & cs, func_decl_vector & ts) {
array<Z3_symbol> _enum_names(n);
@ -2681,6 +2821,10 @@ namespace z3 {
inline expr context::int_const(char const * name) { return constant(name, int_sort()); }
inline expr context::real_const(char const * name) { return constant(name, real_sort()); }
inline expr context::bv_const(char const * name, unsigned sz) { return constant(name, bv_sort(sz)); }
inline expr context::fpa_const(char const * name, unsigned ebits, unsigned sbits) { return constant(name, fpa_sort(ebits, sbits)); }
template<size_t precision>
inline expr context::fpa_const(char const * name) { return constant(name, fpa_sort<precision>()); }
inline expr context::bool_val(bool b) { return b ? expr(*this, Z3_mk_true(m_ctx)) : expr(*this, Z3_mk_false(m_ctx)); }
@ -2702,12 +2846,15 @@ namespace z3 {
inline expr context::bv_val(int64_t n, unsigned sz) { sort s = bv_sort(sz); Z3_ast r = Z3_mk_int64(m_ctx, n, s); check_error(); return expr(*this, r); }
inline expr context::bv_val(uint64_t n, unsigned sz) { sort s = bv_sort(sz); Z3_ast r = Z3_mk_unsigned_int64(m_ctx, n, s); check_error(); return expr(*this, r); }
inline expr context::bv_val(char const * n, unsigned sz) { sort s = bv_sort(sz); Z3_ast r = Z3_mk_numeral(m_ctx, n, s); check_error(); return expr(*this, r); }
inline expr context::bv_val(unsigned n, bool const* bits) {
inline expr context::bv_val(unsigned n, bool const* bits) {
array<Z3_bool> _bits(n);
for (unsigned i = 0; i < n; ++i) _bits[i] = bits[i] ? 1 : 0;
Z3_ast r = Z3_mk_bv_numeral(m_ctx, n, _bits.ptr()); check_error(); return expr(*this, r);
Z3_ast r = Z3_mk_bv_numeral(m_ctx, n, _bits.ptr()); check_error(); return expr(*this, r);
}
inline expr context::fpa_val(double n) { sort s = fpa_sort<64>(); Z3_ast r = Z3_mk_fpa_numeral_double(m_ctx, n, s); check_error(); return expr(*this, r); }
inline expr context::fpa_val(float n) { sort s = fpa_sort<32>(); Z3_ast r = Z3_mk_fpa_numeral_float(m_ctx, n, s); check_error(); return expr(*this, r); }
inline expr context::string_val(char const* s) { Z3_ast r = Z3_mk_string(m_ctx, s); check_error(); return expr(*this, r); }
inline expr context::string_val(std::string const& s) { Z3_ast r = Z3_mk_string(m_ctx, s.c_str()); check_error(); return expr(*this, r); }
@ -2831,8 +2978,8 @@ namespace z3 {
a.check_error();
return expr(a.ctx(), r);
}
inline expr select(expr const & a, int i) {
return select(a, a.ctx().num_val(i, a.get_sort().array_domain()));
inline expr select(expr const & a, int i) {
return select(a, a.ctx().num_val(i, a.get_sort().array_domain()));
}
inline expr select(expr const & a, expr_vector const & i) {
check_context(a, i);
@ -2862,10 +3009,10 @@ namespace z3 {
return expr(a.ctx(), r);
}
inline expr as_array(func_decl & f) {
Z3_ast r = Z3_mk_as_array(f.ctx(), f);
f.check_error();
return expr(f.ctx(), r);
inline expr as_array(func_decl & f) {
Z3_ast r = Z3_mk_as_array(f.ctx(), f);
f.check_error();
return expr(f.ctx(), r);
}
#define MK_EXPR1(_fn, _arg) \
@ -2897,21 +3044,21 @@ namespace z3 {
inline expr set_del(expr const& s, expr const& e) {
MK_EXPR2(Z3_mk_set_del, s, e);
}
}
inline expr set_union(expr const& a, expr const& b) {
check_context(a, b);
check_context(a, b);
Z3_ast es[2] = { a, b };
Z3_ast r = Z3_mk_set_union(a.ctx(), 2, es);
a.check_error();
a.check_error();
return expr(a.ctx(), r);
}
inline expr set_intersect(expr const& a, expr const& b) {
check_context(a, b);
check_context(a, b);
Z3_ast es[2] = { a, b };
Z3_ast r = Z3_mk_set_intersect(a.ctx(), 2, es);
a.check_error();
a.check_error();
return expr(a.ctx(), r);
}
@ -2995,10 +3142,10 @@ namespace z3 {
MK_EXPR1(Z3_mk_re_complement, a);
}
inline expr range(expr const& lo, expr const& hi) {
check_context(lo, hi);
Z3_ast r = Z3_mk_re_range(lo.ctx(), lo, hi);
lo.check_error();
return expr(lo.ctx(), r);
check_context(lo, hi);
Z3_ast r = Z3_mk_re_range(lo.ctx(), lo, hi);
lo.check_error();
return expr(lo.ctx(), r);
}
@ -3009,7 +3156,7 @@ namespace z3 {
Z3_ast_vector r = Z3_parse_smtlib2_string(*this, s, 0, 0, 0, 0, 0, 0);
check_error();
return expr_vector(*this, r);
}
inline expr_vector context::parse_file(char const* s) {
Z3_ast_vector r = Z3_parse_smtlib2_file(*this, s, 0, 0, 0, 0, 0, 0);