3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-21 05:13:39 +00:00

Resolved merge conflicts. Added FPA API input validity checks.

This commit is contained in:
Christoph M. Wintersteiger 2016-11-15 20:19:40 +00:00
commit 9053e6eba6
10 changed files with 786 additions and 192 deletions

View file

@ -909,14 +909,16 @@ extern "C" {
Z3_TRY; Z3_TRY;
LOG_Z3_fpa_get_numeral_sign(c, t, sgn); LOG_Z3_fpa_get_numeral_sign(c, t, sgn);
RESET_ERROR_CODE(); RESET_ERROR_CODE();
CHECK_NON_NULL(t, 0);
CHECK_VALID_AST(t, 0);
if (sgn == 0) { if (sgn == 0) {
SET_ERROR_CODE(Z3_INVALID_ARG); SET_ERROR_CODE(Z3_INVALID_ARG);
return 0; return 0;
} }
ast_manager & m = mk_c(c)->m(); ast_manager & m = mk_c(c)->m();
mpf_manager & mpfm = mk_c(c)->fpautil().fm(); mpf_manager & mpfm = mk_c(c)->fpautil().fm();
fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid());
family_id fid = mk_c(c)->get_fpa_fid(); family_id fid = mk_c(c)->get_fpa_fid();
fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(fid);
expr * e = to_expr(t); expr * e = to_expr(t);
if (!is_app(e) || is_app_of(e, fid, OP_FPA_NAN) || !is_fp(c, t)) { if (!is_app(e) || is_app_of(e, fid, OP_FPA_NAN) || !is_fp(c, t)) {
SET_ERROR_CODE(Z3_INVALID_ARG); SET_ERROR_CODE(Z3_INVALID_ARG);
@ -933,6 +935,71 @@ extern "C" {
Z3_CATCH_RETURN(0); Z3_CATCH_RETURN(0);
} }
Z3_ast Z3_API Z3_fpa_get_numeral_sign_bv(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_fpa_get_numeral_sign_bv(c, t);
RESET_ERROR_CODE();
CHECK_NON_NULL(t, 0);
CHECK_VALID_AST(t, 0);
ast_manager & m = mk_c(c)->m();
mpf_manager & mpfm = mk_c(c)->fpautil().fm();
family_id fid = mk_c(c)->get_fpa_fid();
fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(fid);
api::context * ctx = mk_c(c);
expr * e = to_expr(t);
if (!is_app(e) || is_app_of(e, fid, OP_FPA_NAN) || !is_fp(c, t)) {
SET_ERROR_CODE(Z3_INVALID_ARG);
RETURN_Z3(0);
}
scoped_mpf val(mpfm);
bool r = plugin->is_numeral(to_expr(t), val);
if (!r || mpfm.is_nan(val)) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
app * a;
if (mpfm.is_pos(val))
a = ctx->bvutil().mk_numeral(0, 1);
else
a = ctx->bvutil().mk_numeral(1, 1);
mk_c(c)->save_ast_trail(a);
RETURN_Z3(of_expr(a));
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_fpa_get_numeral_significand_bv(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_fpa_get_numeral_significand_bv(c, t);
RESET_ERROR_CODE();
CHECK_NON_NULL(t, 0);
CHECK_VALID_AST(t, 0);
ast_manager & m = mk_c(c)->m();
mpf_manager & mpfm = mk_c(c)->fpautil().fm();
unsynch_mpq_manager & mpqm = mpfm.mpq_manager();
family_id fid = mk_c(c)->get_fpa_fid();
fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(fid);
SASSERT(plugin != 0);
expr * e = to_expr(t);
if (!is_app(e) || is_app_of(e, fid, OP_FPA_NAN) || !is_fp(c, t)) {
SET_ERROR_CODE(Z3_INVALID_ARG);
RETURN_Z3(0);
}
scoped_mpf val(mpfm);
bool r = plugin->is_numeral(e, val);
if (!r || !(mpfm.is_normal(val) || mpfm.is_denormal(val) || mpfm.is_zero(val) || mpfm.is_inf(val))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
RETURN_Z3(0);
}
unsigned sbits = val.get().get_sbits();
scoped_mpq q(mpqm);
mpqm.set(q, mpfm.sig(val));
if (mpfm.is_inf(val)) mpqm.set(q, 0);
app * a = mk_c(c)->bvutil().mk_numeral(q.get(), sbits-1);
mk_c(c)->save_ast_trail(a);
RETURN_Z3(of_expr(a));
Z3_CATCH_RETURN(0);
}
Z3_string Z3_API Z3_fpa_get_numeral_significand_string(Z3_context c, Z3_ast t) { Z3_string Z3_API Z3_fpa_get_numeral_significand_string(Z3_context c, Z3_ast t) {
Z3_TRY; Z3_TRY;
LOG_Z3_fpa_get_numeral_significand_string(c, t); LOG_Z3_fpa_get_numeral_significand_string(c, t);
@ -952,8 +1019,8 @@ extern "C" {
} }
scoped_mpf val(mpfm); scoped_mpf val(mpfm);
bool r = plugin->is_numeral(e, val); bool r = plugin->is_numeral(e, val);
if (!r || !(mpfm.is_normal(val) || mpfm.is_denormal(val) || mpfm.is_zero(val))) { if (!r || !(mpfm.is_normal(val) || mpfm.is_denormal(val) || mpfm.is_zero(val) || mpfm.is_inf(val))) {
SET_ERROR_CODE(Z3_INVALID_ARG) SET_ERROR_CODE(Z3_INVALID_ARG);
return ""; return "";
} }
unsigned sbits = val.get().get_sbits(); unsigned sbits = val.get().get_sbits();
@ -972,6 +1039,8 @@ extern "C" {
Z3_TRY; Z3_TRY;
LOG_Z3_fpa_get_numeral_significand_uint64(c, t, n); LOG_Z3_fpa_get_numeral_significand_uint64(c, t, n);
RESET_ERROR_CODE(); RESET_ERROR_CODE();
CHECK_NON_NULL(t, 0);
CHECK_VALID_AST(t, 0);
if (n == 0) { if (n == 0) {
SET_ERROR_CODE(Z3_INVALID_ARG); SET_ERROR_CODE(Z3_INVALID_ARG);
return 0; return 0;
@ -992,7 +1061,7 @@ extern "C" {
bool r = plugin->is_numeral(e, val); bool r = plugin->is_numeral(e, val);
const mpz & z = mpfm.sig(val); const mpz & z = mpfm.sig(val);
if (!r || if (!r ||
!(mpfm.is_normal(val) || mpfm.is_denormal(val) || mpfm.is_zero(val)) || !(mpfm.is_normal(val) || mpfm.is_denormal(val) || mpfm.is_zero(val) || mpfm.is_inf(val)) ||
!mpzm.is_uint64(z)) { !mpzm.is_uint64(z)) {
SET_ERROR_CODE(Z3_INVALID_ARG); SET_ERROR_CODE(Z3_INVALID_ARG);
*n = 0; *n = 0;
@ -1003,10 +1072,12 @@ extern "C" {
Z3_CATCH_RETURN(0); Z3_CATCH_RETURN(0);
} }
Z3_string Z3_API Z3_fpa_get_numeral_exponent_string(Z3_context c, Z3_ast t) { Z3_string Z3_API Z3_fpa_get_numeral_exponent_string(Z3_context c, Z3_ast t, Z3_bool biased) {
Z3_TRY; Z3_TRY;
LOG_Z3_fpa_get_numeral_exponent_string(c, t); LOG_Z3_fpa_get_numeral_exponent_string(c, t, biased);
RESET_ERROR_CODE(); RESET_ERROR_CODE();
CHECK_NON_NULL(t, 0);
CHECK_VALID_AST(t, 0);
ast_manager & m = mk_c(c)->m(); ast_manager & m = mk_c(c)->m();
mpf_manager & mpfm = mk_c(c)->fpautil().fm(); mpf_manager & mpfm = mk_c(c)->fpautil().fm();
family_id fid = mk_c(c)->get_fpa_fid(); family_id fid = mk_c(c)->get_fpa_fid();
@ -1019,23 +1090,35 @@ extern "C" {
} }
scoped_mpf val(mpfm); scoped_mpf val(mpfm);
bool r = plugin->is_numeral(e, val); bool r = plugin->is_numeral(e, val);
if (!r || !(mpfm.is_normal(val) || mpfm.is_denormal(val) || mpfm.is_zero(val))) { if (!r || !(mpfm.is_normal(val) || mpfm.is_denormal(val) || mpfm.is_zero(val) || mpfm.is_inf(val))) {
SET_ERROR_CODE(Z3_INVALID_ARG); SET_ERROR_CODE(Z3_INVALID_ARG);
return ""; return "";
} }
mpf_exp_t exp = mpfm.is_zero(val) ? 0 : unsigned ebits = val.get().get_ebits();
mpfm.is_denormal(val) ? mpfm.mk_min_exp(val.get().get_ebits()) : mpf_exp_t exp;
mpfm.exp(val); if (biased) {
exp = mpfm.is_zero(val) ? 0 :
mpfm.is_inf(val) ? mpfm.mk_top_exp(ebits) :
mpfm.bias_exp(ebits, mpfm.exp(val));
}
else {
exp = mpfm.is_zero(val) ? 0 :
mpfm.is_inf(val) ? mpfm.mk_top_exp(ebits) :
mpfm.is_denormal(val) ? mpfm.mk_min_exp(ebits) :
mpfm.exp(val);
}
std::stringstream ss; std::stringstream ss;
ss << exp; ss << exp;
return mk_c(c)->mk_external_string(ss.str()); return mk_c(c)->mk_external_string(ss.str());
Z3_CATCH_RETURN(""); Z3_CATCH_RETURN("");
} }
Z3_bool Z3_API Z3_fpa_get_numeral_exponent_int64(Z3_context c, Z3_ast t, __int64 * n) { Z3_bool Z3_API Z3_fpa_get_numeral_exponent_int64(Z3_context c, Z3_ast t, __int64 * n, Z3_bool biased) {
Z3_TRY; Z3_TRY;
LOG_Z3_fpa_get_numeral_exponent_int64(c, t, n); LOG_Z3_fpa_get_numeral_exponent_int64(c, t, n, biased);
RESET_ERROR_CODE(); RESET_ERROR_CODE();
CHECK_NON_NULL(t, 0);
CHECK_VALID_AST(t, 0);
if (n == 0) { if (n == 0) {
SET_ERROR_CODE(Z3_INVALID_ARG); SET_ERROR_CODE(Z3_INVALID_ARG);
return 0; return 0;
@ -1053,22 +1136,73 @@ extern "C" {
} }
scoped_mpf val(mpfm); scoped_mpf val(mpfm);
bool r = plugin->is_numeral(e, val); bool r = plugin->is_numeral(e, val);
if (!r || !(mpfm.is_normal(val) || mpfm.is_denormal(val) || mpfm.is_zero(val))) { if (!r || !(mpfm.is_normal(val) || mpfm.is_denormal(val) || mpfm.is_zero(val) || mpfm.is_inf(val))) {
SET_ERROR_CODE(Z3_INVALID_ARG); SET_ERROR_CODE(Z3_INVALID_ARG);
*n = 0; *n = 0;
return 0; return 0;
} }
*n = mpfm.is_zero(val) ? 0 : unsigned ebits = val.get().get_ebits();
mpfm.is_denormal(val) ? mpfm.mk_min_exp(val.get().get_ebits()) : if (biased) {
mpfm.exp(val); *n = mpfm.is_zero(val) ? 0 :
mpfm.is_inf(val) ? mpfm.mk_top_exp(ebits) :
mpfm.bias_exp(ebits, mpfm.exp(val));
}
else {
*n = mpfm.is_zero(val) ? 0 :
mpfm.is_inf(val) ? mpfm.mk_top_exp(ebits) :
mpfm.is_denormal(val) ? mpfm.mk_min_exp(ebits) :
mpfm.exp(val);
}
return 1; return 1;
Z3_CATCH_RETURN(0); Z3_CATCH_RETURN(0);
} }
Z3_ast Z3_API Z3_fpa_get_numeral_exponent_bv(Z3_context c, Z3_ast t, Z3_bool biased) {
Z3_TRY;
LOG_Z3_fpa_get_numeral_exponent_bv(c, t, biased);
RESET_ERROR_CODE();
CHECK_NON_NULL(t, 0);
CHECK_VALID_AST(t, 0);
ast_manager & m = mk_c(c)->m();
mpf_manager & mpfm = mk_c(c)->fpautil().fm();
family_id fid = mk_c(c)->get_fpa_fid();
fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(fid);
expr * e = to_expr(t);
if (!is_app(e) || is_app_of(e, fid, OP_FPA_NAN) || !is_fp(c, t)) {
SET_ERROR_CODE(Z3_INVALID_ARG);
RETURN_Z3(0);
}
scoped_mpf val(mpfm);
bool r = plugin->is_numeral(e, val);
if (!r || !(mpfm.is_normal(val) || mpfm.is_denormal(val) || mpfm.is_zero(val) || mpfm.is_inf(val))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
RETURN_Z3(0);
}
unsigned ebits = val.get().get_ebits();
mpf_exp_t exp;
if (biased) {
exp = mpfm.is_zero(val) ? 0 :
mpfm.is_inf(val) ? mpfm.mk_top_exp(ebits) :
mpfm.bias_exp(ebits, mpfm.exp(val));
}
else {
exp = mpfm.is_zero(val) ? 0 :
mpfm.is_inf(val) ? mpfm.mk_top_exp(ebits) :
mpfm.is_denormal(val) ? mpfm.mk_min_exp(ebits) :
mpfm.exp(val);
}
app * a = mk_c(c)->bvutil().mk_numeral(exp, ebits);
mk_c(c)->save_ast_trail(a);
RETURN_Z3(of_expr(a));
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(Z3_context c, Z3_ast t) { Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(Z3_context c, Z3_ast t) {
Z3_TRY; Z3_TRY;
LOG_Z3_mk_fpa_to_ieee_bv(c, t); LOG_Z3_mk_fpa_to_ieee_bv(c, t);
RESET_ERROR_CODE(); RESET_ERROR_CODE();
CHECK_NON_NULL(t, 0);
CHECK_VALID_AST(t, 0);
if (!is_fp(c, t)) { if (!is_fp(c, t)) {
SET_ERROR_CODE(Z3_INVALID_ARG); SET_ERROR_CODE(Z3_INVALID_ARG);
RETURN_Z3(0); RETURN_Z3(0);
@ -1098,4 +1232,102 @@ extern "C" {
Z3_CATCH_RETURN(0); Z3_CATCH_RETURN(0);
} }
Z3_bool Z3_API Z3_fpa_is_numeral_nan(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_fpa_is_numeral_nan(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpautil();
if (!is_expr(t) || !fu.is_numeral(to_expr(t))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
return fu.is_nan(to_expr(t));
Z3_CATCH_RETURN(Z3_FALSE);
}
Z3_bool Z3_API Z3_fpa_is_numeral_inf(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_fpa_is_numeral_inf(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpautil();
if (!is_expr(t) || !fu.is_numeral(to_expr(t))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
return fu.is_inf(to_expr(t));
Z3_CATCH_RETURN(Z3_FALSE);
}
Z3_bool Z3_API Z3_fpa_is_numeral_zero(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_fpa_is_numeral_zero(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpautil();
if (!is_expr(t) || !fu.is_numeral(to_expr(t))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
return fu.is_zero(to_expr(t));
Z3_CATCH_RETURN(Z3_FALSE);
}
Z3_bool Z3_API Z3_fpa_is_numeral_normal(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_fpa_is_numeral_normal(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpautil();
if (!is_expr(t) || !fu.is_numeral(to_expr(t))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
return fu.is_normal(to_expr(t));
Z3_CATCH_RETURN(Z3_FALSE);
}
Z3_bool Z3_API Z3_fpa_is_numeral_subnormal(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_fpa_is_numeral_subnormal(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpautil();
if (!is_expr(t) || !fu.is_numeral(to_expr(t))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
return fu.is_subnormal(to_expr(t));
Z3_CATCH_RETURN(Z3_FALSE);
}
Z3_bool Z3_API Z3_fpa_is_numeral_positive(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_fpa_is_numeral_positive(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpautil();
if (!is_expr(t) || !fu.is_numeral(to_expr(t))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
return fu.is_positive(to_expr(t));
Z3_CATCH_RETURN(Z3_FALSE);
}
Z3_bool Z3_API Z3_fpa_is_numeral_negative(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_fpa_is_numeral_negative(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpautil();
if (!is_expr(t) || !fu.is_numeral(to_expr(t))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
return fu.is_negative(to_expr(t));
Z3_CATCH_RETURN(Z3_FALSE);
}
}; };

View file

@ -14,7 +14,7 @@ Author:
Christoph Wintersteiger (cwinter) 2013-06-10 Christoph Wintersteiger (cwinter) 2013-06-10
Notes: Notes:
--*/ --*/
using System; using System;
using System.Diagnostics.Contracts; using System.Diagnostics.Contracts;
@ -27,6 +27,20 @@ namespace Microsoft.Z3
[ContractVerification(true)] [ContractVerification(true)]
public class FPNum : FPExpr public class FPNum : FPExpr
{ {
/// <summary>
/// The sign of a floating-point numeral as a bit-vector expression
/// </summary>
/// <remarks>
/// NaN's do not have a bit-vector sign, so they are invalid arguments.
/// </remarks>
public BitVecExpr SignBV
{
get
{
return new BitVecExpr(Context, Native.Z3_fpa_get_numeral_sign_bv(Context.nCtx, NativeObject));
}
}
/// <summary> /// <summary>
/// Retrieves the sign of a floating-point literal /// Retrieves the sign of a floating-point literal
/// </summary> /// </summary>
@ -38,7 +52,7 @@ namespace Microsoft.Z3
get get
{ {
int res = 0; int res = 0;
if (Native.Z3_fpa_get_numeral_sign(Context.nCtx, NativeObject, ref res) == 0) if (Native.Z3_fpa_get_numeral_sign(Context.nCtx, NativeObject, ref res) == 0)
throw new Z3Exception("Sign is not a Boolean value"); throw new Z3Exception("Sign is not a Boolean value");
return res != 0; return res != 0;
} }
@ -63,7 +77,7 @@ namespace Microsoft.Z3
/// The significand value of a floating-point numeral as a UInt64 /// The significand value of a floating-point numeral as a UInt64
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This function extracts the significand bits, without the /// This function extracts the significand bits, without the
/// hidden bit or normalization. Throws an exception if the /// hidden bit or normalization. Throws an exception if the
/// significand does not fit into a UInt64. /// significand does not fit into a UInt64.
/// </remarks> /// </remarks>
@ -73,36 +87,90 @@ namespace Microsoft.Z3
{ {
UInt64 result = 0; UInt64 result = 0;
if (Native.Z3_fpa_get_numeral_significand_uint64(Context.nCtx, NativeObject, ref result) == 0) if (Native.Z3_fpa_get_numeral_significand_uint64(Context.nCtx, NativeObject, ref result) == 0)
throw new Z3Exception("Significand is not a 64 bit unsigned integer"); throw new Z3Exception("Significand is not a 64 bit unsigned integer");
return result; return result;
} }
} }
/// <summary> /// <summary>
/// Return the exponent value of a floating-point numeral as a string /// The significand of a floating-point numeral as a bit-vector expression
/// </summary> /// </summary>
public string Exponent /// <remarks>
/// +oo, -oo and NaN's do not have a bit-vector significand, so they are invalid arguments.
/// </remarks>
public BitVecExpr SignificandBV
{ {
get get
{ {
return Native.Z3_fpa_get_numeral_exponent_string(Context.nCtx, NativeObject); return new BitVecExpr(Context, Native.Z3_fpa_get_numeral_significand_bv(Context.nCtx, NativeObject));
} }
} }
/// <summary>
/// Return the (biased) exponent value of a floating-point numeral as a string
/// </summary>
public string Exponent(bool biased = true)
{
return Native.Z3_fpa_get_numeral_exponent_string(Context.nCtx, NativeObject, biased ? 1 : 0);
}
/// <summary> /// <summary>
/// Return the exponent value of a floating-point numeral as a signed 64-bit integer /// Return the exponent value of a floating-point numeral as a signed 64-bit integer
/// </summary> /// </summary>
public Int64 ExponentInt64 public Int64 ExponentInt64(bool biased = true)
{ {
get Int64 result = 0;
{ if (Native.Z3_fpa_get_numeral_exponent_int64(Context.nCtx, NativeObject, ref result, biased ? 1 : 0) == 0)
Int64 result = 0; throw new Z3Exception("Exponent is not a 64 bit integer");
if (Native.Z3_fpa_get_numeral_exponent_int64(Context.nCtx, NativeObject, ref result) == 0) return result;
throw new Z3Exception("Exponent is not a 64 bit integer");
return result;
}
} }
/// <summary>
/// The exponent of a floating-point numeral as a bit-vector expression
/// </summary>
/// <remarks>
/// +oo, -oo and NaN's do not have a bit-vector exponent, so they are invalid arguments.
/// </remarks>
public BitVecExpr ExponentBV(bool biased = true)
{
return new BitVecExpr(Context, Native.Z3_fpa_get_numeral_exponent_bv(Context.nCtx, NativeObject, biased ? 1 : 0));
}
/// <summary>
/// Indicates whether the numeral is a NaN.
/// </summary>
public bool IsNaN { get { return Native.Z3_fpa_is_numeral_nan(Context.nCtx, NativeObject) != 0; } }
/// <summary>
/// Indicates whether the numeral is a +oo or -oo.
/// </summary>
public bool IsInf { get { return Native.Z3_fpa_is_numeral_inf(Context.nCtx, NativeObject) != 0; } }
/// <summary>
/// Indicates whether the numeral is +zero or -zero.
/// </summary>
public bool IsZero{ get { return Native.Z3_fpa_is_numeral_zero(Context.nCtx, NativeObject) != 0; } }
/// <summary>
/// Indicates whether the numeral is normal.
/// </summary>
public bool IsNormal { get { return Native.Z3_fpa_is_numeral_normal(Context.nCtx, NativeObject) != 0; } }
/// <summary>
/// Indicates whether the numeral is subnormal.
/// </summary>
public bool IsSubnormal { get { return Native.Z3_fpa_is_numeral_subnormal(Context.nCtx, NativeObject) != 0; } }
/// <summary>
/// Indicates whether the numeral is positive.
/// </summary>
public bool IsPositive { get { return Native.Z3_fpa_is_numeral_positive(Context.nCtx, NativeObject) != 0; } }
/// <summary>
/// Indicates whether the numeral is negative.
/// </summary>
public bool IsNegative { get { return Native.Z3_fpa_is_numeral_negative(Context.nCtx, NativeObject) != 0; } }
#region Internal #region Internal
internal FPNum(Context ctx, IntPtr obj) internal FPNum(Context ctx, IntPtr obj)
: base(ctx, obj) : base(ctx, obj)
@ -113,7 +181,7 @@ namespace Microsoft.Z3
/// <summary> /// <summary>
/// Returns a string representation of the numeral. /// Returns a string representation of the numeral.
/// </summary> /// </summary>
public override string ToString() public override string ToString()
{ {
return Native.Z3_get_numeral_string(Context.nCtx, NativeObject); return Native.Z3_get_numeral_string(Context.nCtx, NativeObject);

View file

@ -20,7 +20,7 @@ package com.microsoft.z3;
* FloatingPoint Numerals * FloatingPoint Numerals
*/ */
public class FPNum extends FPExpr public class FPNum extends FPExpr
{ {
/** /**
* Retrieves the sign of a floating-point literal * Retrieves the sign of a floating-point literal
* Remarks: returns true if the numeral is negative * Remarks: returns true if the numeral is negative
@ -33,6 +33,15 @@ public class FPNum extends FPExpr
return res.value != 0; return res.value != 0;
} }
/**
* The sign of a floating-point numeral as a bit-vector expression
* Remarks: NaN's do not have a bit-vector sign, so they are invalid arguments.
* @throws Z3Exception
*/
public BitVecExpr getSignBV() {
return new BitVecExpr(getContext(), Native.fpaGetNumeralSignBv(getContext().nCtx(), getNativeObject()));
}
/** /**
* The significand value of a floating-point numeral as a string * The significand value of a floating-point numeral as a string
* Remarks: The significand s is always 0 &lt; s &lt; 2.0; the resulting string is long * Remarks: The significand s is always 0 &lt; s &lt; 2.0; the resulting string is long
@ -57,25 +66,117 @@ public class FPNum extends FPExpr
throw new Z3Exception("Significand is not a 64 bit unsigned integer"); throw new Z3Exception("Significand is not a 64 bit unsigned integer");
return res.value; return res.value;
} }
/**
* The significand of a floating-point numeral as a bit-vector expression
* Remarks: NaN is an invalid argument.
* @throws Z3Exception
*/
public BitVecExpr getSignificandBV() {
return new BitVecExpr(getContext(), Native.fpaGetNumeralSignificandBv(getContext().nCtx(), getNativeObject()));
}
/** /**
* Return the exponent value of a floating-point numeral as a string * Return the exponent value of a floating-point numeral as a string
* Remarks: NaN is an invalid argument.
* @throws Z3Exception * @throws Z3Exception
*/ */
public String getExponent() { public String getExponent(boolean biased) {
return Native.fpaGetNumeralExponentString(getContext().nCtx(), getNativeObject()); return Native.fpaGetNumeralExponentString(getContext().nCtx(), getNativeObject(), biased);
} }
/** /**
* Return the exponent value of a floating-point numeral as a signed 64-bit integer * Return the exponent value of a floating-point numeral as a signed 64-bit integer
* Remarks: NaN is an invalid argument.
* @throws Z3Exception * @throws Z3Exception
*/ */
public long getExponentInt64() { public long getExponentInt64(boolean biased) {
Native.LongPtr res = new Native.LongPtr(); Native.LongPtr res = new Native.LongPtr();
if (!Native.fpaGetNumeralExponentInt64(getContext().nCtx(), getNativeObject(), res)) if (!Native.fpaGetNumeralExponentInt64(getContext().nCtx(), getNativeObject(), res, biased))
throw new Z3Exception("Exponent is not a 64 bit integer"); throw new Z3Exception("Exponent is not a 64 bit integer");
return res.value; return res.value;
} }
/**
* The exponent of a floating-point numeral as a bit-vector expression
* Remarks: NaN is an invalid argument.
* @throws Z3Exception
*/
public BitVecExpr getExponentBV(boolean biased) {
return new BitVecExpr(getContext(), Native.fpaGetNumeralExponentBv(getContext().nCtx(), getNativeObject(), biased));
}
/**
* Indicates whether the numeral is a NaN.
* @throws Z3Exception on error
* @return a boolean
**/
public boolean isNaN()
{
return Native.fpaIsNumeralNan(getContext().nCtx(), getNativeObject());
}
/**
* Indicates whether the numeral is a +oo or -oo.
* @throws Z3Exception on error
* @return a boolean
**/
public boolean isInf()
{
return Native.fpaIsNumeralInf(getContext().nCtx(), getNativeObject());
}
/**
* Indicates whether the numeral is +zero or -zero.
* @throws Z3Exception on error
* @return a boolean
**/
public boolean isZero()
{
return Native.fpaIsNumeralZero(getContext().nCtx(), getNativeObject());
}
/**
* Indicates whether the numeral is normal.
* @throws Z3Exception on error
* @return a boolean
**/
public boolean isNormal()
{
return Native.fpaIsNumeralNormal(getContext().nCtx(), getNativeObject());
}
/**
* Indicates whether the numeral is subnormal.
* @throws Z3Exception on error
* @return a boolean
**/
public boolean isSubnormal()
{
return Native.fpaIsNumeralSubnormal(getContext().nCtx(), getNativeObject());
}
/**
* Indicates whether the numeral is positive.
* @throws Z3Exception on error
* @return a boolean
**/
public boolean isPositive()
{
return Native.fpaIsNumeralPositive(getContext().nCtx(), getNativeObject());
}
/**
* Indicates whether the numeral is negative.
* @throws Z3Exception on error
* @return a boolean
**/
public boolean isNegative()
{
return Native.fpaIsNumeralNegative(getContext().nCtx(), getNativeObject());
}
public FPNum(Context ctx, long obj) public FPNum(Context ctx, long obj)
{ {
@ -88,6 +189,5 @@ public class FPNum extends FPExpr
public String toString() public String toString()
{ {
return Native.getNumeralString(getContext().nCtx(), getNativeObject()); return Native.getNumeralString(getContext().nCtx(), getNativeObject());
} }
} }

View file

@ -1325,10 +1325,20 @@ struct
let get_ebits = Z3native.fpa_get_ebits let get_ebits = Z3native.fpa_get_ebits
let get_sbits = Z3native.fpa_get_sbits let get_sbits = Z3native.fpa_get_sbits
let get_numeral_sign = Z3native.fpa_get_numeral_sign let get_numeral_sign = Z3native.fpa_get_numeral_sign
let get_numeral_significand_string = Z3native.fpa_get_numeral_significand_string let get_numeral_sign_bv = Z3native.fpa_get_numeral_sign_bv
let get_numeral_significand_uint = Z3native.fpa_get_numeral_significand_uint64
let get_numeral_exponent_string = Z3native.fpa_get_numeral_exponent_string let get_numeral_exponent_string = Z3native.fpa_get_numeral_exponent_string
let get_numeral_exponent_int = Z3native.fpa_get_numeral_exponent_int64 let get_numeral_exponent_int = Z3native.fpa_get_numeral_exponent_int64
let get_numeral_exponent_bv = Z3native.fpa_get_numeral_exponent_bv
let get_numeral_significand_string = Z3native.fpa_get_numeral_significand_string
let get_numeral_significand_uint = Z3native.fpa_get_numeral_significand_uint64
let get_numeral_significand_bv = Z3native.fpa_get_numeral_significand_bv
let is_numeral_nan = Z3native.fpa_is_numeral_nan
let is_numeral_inf = Z3native.fpa_is_numeral_inf
let is_numeral_zero = Z3native.fpa_is_numeral_zero
let is_numeral_normal = Z3native.fpa_is_numeral_normal
let is_numeral_subnormal = Z3native.fpa_is_numeral_subnormal
let is_numeral_positive = Z3native.fpa_is_numeral_positive
let is_numeral_negative = Z3native.fpa_is_numeral_negative
let mk_to_ieee_bv = Z3native.mk_fpa_to_ieee_bv let mk_to_ieee_bv = Z3native.mk_fpa_to_ieee_bv
let mk_to_fp_int_real = Z3native.mk_fpa_to_fp_int_real let mk_to_fp_int_real = Z3native.mk_fpa_to_fp_int_real
let numeral_to_string x = Z3native.get_numeral_string (Expr.gc x) x let numeral_to_string x = Z3native.get_numeral_string (Expr.gc x) x

View file

@ -2141,21 +2141,54 @@ sig
(** Retrieves the sign of a floating-point literal. *) (** Retrieves the sign of a floating-point literal. *)
val get_numeral_sign : context -> Expr.expr -> bool * int val get_numeral_sign : context -> Expr.expr -> bool * int
(** Return the sign of a floating-point numeral as a bit-vector expression.
Remark: NaN's do not have a bit-vector sign, so they are invalid arguments. *)
val get_numeral_sign_bv : context -> Expr.expr -> Expr.expr
(** Return the exponent value of a floating-point numeral as a string *)
val get_numeral_exponent_string : context -> Expr.expr -> bool -> string
(** Return the exponent value of a floating-point numeral as a signed integer *)
val get_numeral_exponent_int : context -> Expr.expr -> bool -> bool * int
(** Return the exponent of a floating-point numeral as a bit-vector expression.
Remark: NaN's do not have a bit-vector exponent, so they are invalid arguments. *)
val get_numeral_exponent_bv : context -> Expr.expr -> bool -> Expr.expr
(** Return the significand value of a floating-point numeral as a bit-vector expression.
Remark: NaN's do not have a bit-vector significand, so they are invalid arguments. *)
val get_numeral_significand_bv : context -> Expr.expr -> Expr.expr
(** Return the significand value of a floating-point numeral as a string. *) (** Return the significand value of a floating-point numeral as a string. *)
val get_numeral_significand_string : context -> Expr.expr -> string val get_numeral_significand_string : context -> Expr.expr -> string
(** Return the significand value of a floating-point numeral as a uint64. (** Return the significand value of a floating-point numeral as a uint64.
Remark: This function extracts the significand bits, without the Remark: This function extracts the significand bits, without the
hidden bit or normalization. Throws an exception if the hidden bit or normalization. Throws an exception if the
significand does not fit into a uint64. *) significand does not fit into an int. *)
val get_numeral_significand_uint : context -> Expr.expr -> bool * int val get_numeral_significand_uint : context -> Expr.expr -> bool * int
(** Return the exponent value of a floating-point numeral as a string *) (** Indicates whether a floating-point numeral is a NaN. *)
val get_numeral_exponent_string : context -> Expr.expr -> string val is_numeral_nan : context -> Expr.expr -> bool
(** Return the exponent value of a floating-point numeral as a signed integer *) (** Indicates whether a floating-point numeral is +oo or -oo. *)
val get_numeral_exponent_int : context -> Expr.expr -> bool * int val is_numeral_inf : context -> Expr.expr -> bool
(** Indicates whether a floating-point numeral is +zero or -zero. *)
val is_numeral_zero : context -> Expr.expr -> bool
(** Indicates whether a floating-point numeral is normal. *)
val is_numeral_normal : context -> Expr.expr -> bool
(** Indicates whether a floating-point numeral is subnormal. *)
val is_numeral_subnormal : context -> Expr.expr -> bool
(** Indicates whether a floating-point numeral is positive. *)
val is_numeral_positive : context -> Expr.expr -> bool
(** Indicates whether a floating-point numeral is negative. *)
val is_numeral_negative : context -> Expr.expr -> bool
(** Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. *) (** Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. *)
val mk_to_ieee_bv : context -> Expr.expr -> Expr.expr val mk_to_ieee_bv : context -> Expr.expr -> Expr.expr
@ -3023,29 +3056,22 @@ sig
(** Assert a constraint (or multiple) into the solver. *) (** Assert a constraint (or multiple) into the solver. *)
val add : solver -> Expr.expr list -> unit val add : solver -> Expr.expr list -> unit
(** * Assert multiple constraints (cs) into the solver, and track them (in the (** Assert multiple constraints (cs) into the solver, and track them (in the
* unsat) core unsat) core using the Boolean constants in ps.
* using the Boolean constants in ps.
* This API is an alternative to {!check} with assumptions for extracting unsat cores.
* This API is an alternative to {!check} with assumptions for Both APIs can be used in the same solver. The unsat core will contain a combination
* extracting unsat cores. of the Boolean variables provided using {!assert_and_track} and the Boolean literals
* Both APIs can be used in the same solver. The unsat core will contain a provided using {!check} with assumptions. *)
* combination
* of the Boolean variables provided using {!assert_and_track}
* and the Boolean literals
* provided using {!check} with assumptions. *)
val assert_and_track_l : solver -> Expr.expr list -> Expr.expr list -> unit val assert_and_track_l : solver -> Expr.expr list -> Expr.expr list -> unit
(** * Assert a constraint (c) into the solver, and track it (in the unsat) core (** Assert a constraint (c) into the solver, and track it (in the unsat) core
* using the Boolean constant p. using the Boolean constant p.
*
* This API is an alternative to {!check} with assumptions for This API is an alternative to {!check} with assumptions for extracting unsat cores.
* extracting unsat cores. Both APIs can be used in the same solver. The unsat core will contain a combination
* Both APIs can be used in the same solver. The unsat core will contain a of the Boolean variables provided using {!assert_and_track} and the Boolean literals
* combination provided using {!check} with assumptions. *)
* of the Boolean variables provided using {!assert_and_track}
* and the Boolean literals
* provided using {!check} with assumptions. *)
val assert_and_track : solver -> Expr.expr -> Expr.expr -> unit val assert_and_track : solver -> Expr.expr -> Expr.expr -> unit
(** The number of assertions in the solver. *) (** The number of assertions in the solver. *)

View file

@ -8452,27 +8452,13 @@ def is_fprm_value(a):
### FP Numerals ### FP Numerals
class FPNumRef(FPRef): class FPNumRef(FPRef):
def isNaN(self): """The sign of the numeral.
return self.decl().kind() == Z3_OP_FPA_NAN
def isInf(self): >>> x = FPVal(+1.0, FPSort(8, 24))
return self.decl().kind() == Z3_OP_FPA_PLUS_INF or self.decl().kind() == Z3_OP_FPA_MINUS_INF
def isZero(self):
return self.decl().kind() == Z3_OP_FPA_PLUS_ZERO or self.decl().kind() == Z3_OP_FPA_MINUS_ZERO
def isNegative(self):
k = self.decl().kind()
return (self.num_args() == 0 and (k == Z3_OP_FPA_MINUS_INF or k == Z3_OP_FPA_MINUS_ZERO)) or (self.sign() == True)
"""
The sign of the numeral.
>>> x = FPNumRef(+1.0, FPSort(8, 24))
>>> x.sign() >>> x.sign()
False False
>>> x = FPNumRef(-1.0, FPSort(8, 24)) >>> x = FPVal(-1.0, FPSort(8, 24))
>>> x.sign() >>> x.sign()
True True
""" """
@ -8482,48 +8468,103 @@ class FPNumRef(FPRef):
raise Z3Exception("error retrieving the sign of a numeral.") raise Z3Exception("error retrieving the sign of a numeral.")
return l.value != 0 return l.value != 0
"""The sign of a floating-point numeral as a bit-vector expression.
Remark: NaN's are invalid arguments.
""" """
The significand of the numeral. def sign_as_bv(self):
return BitVecNumRef(Z3_fpa_get_numeral_sign_bv(self.ctx.ref(), self.as_ast()), self.ctx)
>>> x = FPNumRef(2.5, FPSort(8, 24)) """The significand of the numeral.
>>> x = FPVal(2.5, FPSort(8, 24))
>>> x.significand() >>> x.significand()
1.25 1.25
""" """
def significand(self): def significand(self):
return Z3_fpa_get_numeral_significand_string(self.ctx.ref(), self.as_ast()) return Z3_fpa_get_numeral_significand_string(self.ctx.ref(), self.as_ast())
""" """The significand of the numeral as a long.
The exponent of the numeral.
>>> x = FPNumRef(2.5, FPSort(8, 24)) >>> x = FPVal(2.5, FPSort(8, 24))
>>> x.significand_as_long()
1.25
"""
def significand_as_long(self):
return Z3_fpa_get_numeral_significand_uint64(self.ctx.ref(), self.as_ast())
"""The significand of the numeral as a bit-vector expression.
Remark: NaN are invalid arguments.
"""
def significand_as_bv(self):
return BitVecNumRef(Z3_fpa_get_numeral_significand_bv(self.ctx.ref(), self.as_ast()), self.ctx)
"""The exponent of the numeral.
>>> x = FPVal(2.5, FPSort(8, 24))
>>> x.exponent() >>> x.exponent()
1 1
""" """
def exponent(self): def exponent(self, biased=True):
return Z3_fpa_get_numeral_exponent_string(self.ctx.ref(), self.as_ast()) return Z3_fpa_get_numeral_exponent_string(self.ctx.ref(), self.as_ast(), biased)
""" """The exponent of the numeral as a long.
The exponent of the numeral as a long.
>>> x = FPNumRef(2.5, FPSort(8, 24)) >>> x = FPVal(2.5, FPSort(8, 24))
>>> x.exponent_as_long() >>> x.exponent_as_long()
1 1
""" """
def exponent_as_long(self): def exponent_as_long(self, biased=True):
ptr = (ctypes.c_longlong * 1)() ptr = (ctypes.c_longlong * 1)()
if not Z3_fpa_get_numeral_exponent_int64(self.ctx.ref(), self.as_ast(), ptr): if not Z3_fpa_get_numeral_exponent_int64(self.ctx.ref(), self.as_ast(), ptr, biased):
raise Z3Exception("error retrieving the exponent of a numeral.") raise Z3Exception("error retrieving the exponent of a numeral.")
return ptr[0] return ptr[0]
"""The exponent of the numeral as a bit-vector expression.
Remark: NaNs are invalid arguments.
"""
def exponent_as_bv(self, biased=True):
return BitVecNumRef(Z3_fpa_get_numeral_exponent_bv(self.ctx.ref(), self.as_ast(), biased), self.ctx)
"""Indicates whether the numeral is a NaN."""
def isNaN(self):
return Z3_fpa_is_numeral_nan(self.ctx.ref(), self.as_ast())
"""Indicates whether the numeral is +oo or -oo."""
def isInf(self):
return Z3_fpa_is_numeral_inf(self.ctx.ref(), self.as_ast())
"""Indicates whether the numeral is +zero or -zero."""
def isZero(self):
return Z3_fpa_is_numeral_zero(self.ctx.ref(), self.as_ast())
"""Indicates whether the numeral is normal."""
def isNormal(self):
return Z3_fpa_is_numeral_normal(self.ctx.ref(), self.as_ast())
"""Indicates whether the numeral is subnormal."""
def isSubnormal(self):
return Z3_fpa_is_numeral_subnormal(self.ctx.ref(), self.as_ast())
"""Indicates whether the numeral is postitive."""
def isPositive(self):
return Z3_fpa_is_numeral_positive(self.ctx.ref(), self.as_ast())
"""Indicates whether the numeral is negative."""
def isNegative(self):
return Z3_fpa_is_numeral_negative(self.ctx.ref(), self.as_ast())
""" """
The string representation of the numeral. The string representation of the numeral.
>>> x = FPNumRef(20, FPSort(8, 24)) >>> x = FPVal(20, FPSort(8, 24))
>>> x.as_string() >>> x.as_string()
1.25*(2**4) 1.25*(2**4)
""" """
def as_string(self): def as_string(self):
s = Z3_fpa_get_numeral_string(self.ctx.ref(), self.as_ast()) s = Z3_get_numeral_string(self.ctx.ref(), self.as_ast())
return ("FPVal(%s, %s)" % (s, self.sort())) return ("FPVal(%s, %s)" % (s, self.sort()))
def is_fp(a): def is_fp(a):
@ -8676,7 +8717,7 @@ def FPVal(sig, exp=None, fps=None, ctx=None):
>>> v = FPVal(20.0, FPSort(8, 24)) >>> v = FPVal(20.0, FPSort(8, 24))
>>> v >>> v
1.25*(2**4) 1.25*(2**4)
>>> print("0x%.8x" % v.exponent_as_long()) >>> print("0x%.8x" % v.exponent_as_long(False))
0x00000004 0x00000004
>>> v = FPVal(2.25, FPSort(8, 24)) >>> v = FPVal(2.25, FPSort(8, 24))
>>> v >>> v

View file

@ -620,8 +620,8 @@ class Formatter:
r = [] r = []
sgn = c_int(0) sgn = c_int(0)
sgnb = Z3_fpa_get_numeral_sign(a.ctx_ref(), a.ast, byref(sgn)) sgnb = Z3_fpa_get_numeral_sign(a.ctx_ref(), a.ast, byref(sgn))
exp = Z3_fpa_get_numeral_exponent_string(a.ctx_ref(), a.ast, False)
sig = Z3_fpa_get_numeral_significand_string(a.ctx_ref(), a.ast) sig = Z3_fpa_get_numeral_significand_string(a.ctx_ref(), a.ast)
exp = Z3_fpa_get_numeral_exponent_string(a.ctx_ref(), a.ast)
r.append(to_format('FPVal(')) r.append(to_format('FPVal('))
if sgnb and sgn.value != 0: if sgnb and sgn.value != 0:
r.append(to_format('-')) r.append(to_format('-'))
@ -650,8 +650,8 @@ class Formatter:
r = [] r = []
sgn = (ctypes.c_int)(0) sgn = (ctypes.c_int)(0)
sgnb = Z3_fpa_get_numeral_sign(a.ctx_ref(), a.ast, byref(sgn)) sgnb = Z3_fpa_get_numeral_sign(a.ctx_ref(), a.ast, byref(sgn))
exp = Z3_fpa_get_numeral_exponent_string(a.ctx_ref(), a.ast, False)
sig = Z3_fpa_get_numeral_significand_string(a.ctx_ref(), a.ast) sig = Z3_fpa_get_numeral_significand_string(a.ctx_ref(), a.ast)
exp = Z3_fpa_get_numeral_exponent_string(a.ctx_ref(), a.ast)
if sgnb and sgn.value != 0: if sgnb and sgn.value != 0:
r.append(to_format('-')) r.append(to_format('-'))
r.append(to_format(sig)) r.append(to_format(sig))

View file

@ -253,9 +253,9 @@ extern "C" {
This is the operator named `fp' in the SMT FP theory definition. This is the operator named `fp' in the SMT FP theory definition.
Note that \c sign is required to be a bit-vector of size 1. Significand and exponent Note that \c sign is required to be a bit-vector of size 1. Significand and exponent
are required to be greater than 1 and 2 respectively. The FloatingPoint sort are required to be longer than 1 and 2 respectively. The FloatingPoint sort
of the resulting expression is automatically determined from the bit-vector sizes of the resulting expression is automatically determined from the bit-vector sizes
of the arguments. of the arguments. The exponent is assumed to be in IEEE-754 biased representation.
\param c logical context \param c logical context
\param sgn sign \param sgn sign
@ -822,6 +822,100 @@ extern "C" {
*/ */
unsigned Z3_API Z3_fpa_get_sbits(Z3_context c, Z3_sort s); unsigned Z3_API Z3_fpa_get_sbits(Z3_context c, Z3_sort s);
/**
\brief Checks whether a given floating-point numeral is a NaN.
\param c logical context
\param t a floating-point numeral
def_API('Z3_fpa_is_numeral_nan', BOOL, (_in(CONTEXT), _in(AST)))
*/
Z3_bool Z3_API Z3_fpa_is_numeral_nan(Z3_context c, Z3_ast t);
/**
\brief Checks whether a given floating-point numeral is a +oo or -oo.
\param c logical context
\param t a floating-point numeral
def_API('Z3_fpa_is_numeral_inf', BOOL, (_in(CONTEXT), _in(AST)))
*/
Z3_bool Z3_API Z3_fpa_is_numeral_inf(Z3_context c, Z3_ast t);
/**
\brief Checks whether a given floating-point numeral is +zero or -zero.
\param c logical context
\param t a floating-point numeral
def_API('Z3_fpa_is_numeral_zero', BOOL, (_in(CONTEXT), _in(AST)))
*/
Z3_bool Z3_API Z3_fpa_is_numeral_zero(Z3_context c, Z3_ast t);
/**
\brief Checks whether a given floating-point numeral is normal.
\param c logical context
\param t a floating-point numeral
def_API('Z3_fpa_is_numeral_normal', BOOL, (_in(CONTEXT), _in(AST)))
*/
Z3_bool Z3_API Z3_fpa_is_numeral_normal(Z3_context c, Z3_ast t);
/**
\brief Checks whether a given floating-point numeral is subnormal.
\param c logical context
\param t a floating-point numeral
def_API('Z3_fpa_is_numeral_subnormal', BOOL, (_in(CONTEXT), _in(AST)))
*/
Z3_bool Z3_API Z3_fpa_is_numeral_subnormal(Z3_context c, Z3_ast t);
/**
\brief Checks whether a given floating-point numeral is positive.
\param c logical context
\param t a floating-point numeral
def_API('Z3_fpa_is_numeral_positive', BOOL, (_in(CONTEXT), _in(AST)))
*/
Z3_bool Z3_API Z3_fpa_is_numeral_positive(Z3_context c, Z3_ast t);
/**
\brief Checks whether a given floating-point numeral is negative.
\param c logical context
\param t a floating-point numeral
def_API('Z3_fpa_is_numeral_negative', BOOL, (_in(CONTEXT), _in(AST)))
*/
Z3_bool Z3_API Z3_fpa_is_numeral_negative(Z3_context c, Z3_ast t);
/**
\brief Retrieves the sign of a floating-point literal as a bit-vector expression.
\param c logical context
\param t a floating-point numeral
Remarks: NaN is an invalid argument.
def_API('Z3_fpa_get_numeral_sign_bv', AST, (_in(CONTEXT), _in(AST)))
*/
Z3_ast Z3_API Z3_fpa_get_numeral_sign_bv(Z3_context c, Z3_ast t);
/**
\brief Retrieves the significand of a floating-point literal as a bit-vector expression.
\param c logical context
\param t a floating-point numeral
Remarks: NaN is an invalid argument.
def_API('Z3_fpa_get_numeral_significand_bv', AST, (_in(CONTEXT), _in(AST)))
*/
Z3_ast Z3_API Z3_fpa_get_numeral_significand_bv(Z3_context c, Z3_ast t);
/** /**
\brief Retrieves the sign of a floating-point literal. \brief Retrieves the sign of a floating-point literal.
@ -858,23 +952,25 @@ extern "C" {
Remarks: This function extracts the significand bits in `t`, without the Remarks: This function extracts the significand bits in `t`, without the
hidden bit or normalization. Sets the Z3_INVALID_ARG error code if the hidden bit or normalization. Sets the Z3_INVALID_ARG error code if the
significand does not fit into a uint64. significand does not fit into a uint64. NaN is an invalid argument.
def_API('Z3_fpa_get_numeral_significand_uint64', BOOL, (_in(CONTEXT), _in(AST), _out(UINT64))) def_API('Z3_fpa_get_numeral_significand_uint64', BOOL, (_in(CONTEXT), _in(AST), _out(UINT64)))
*/ */
Z3_bool Z3_API Z3_fpa_get_numeral_significand_uint64(Z3_context c, Z3_ast t, __uint64 * n); Z3_bool Z3_API Z3_fpa_get_numeral_significand_uint64(Z3_context c, Z3_ast t, __uint64 * n);
/** /**
\brief Return the exponent value of a floating-point numeral as a string \brief Return the exponent value of a floating-point numeral as a string.
\param c logical context \param c logical context
\param t a floating-point numeral \param t a floating-point numeral
\param biased flag to indicate whether the result is in biased representation
Remarks: This function extracts the exponent in `t`, without normalization. Remarks: This function extracts the exponent in `t`, without normalization.
NaN is an invalid argument.
def_API('Z3_fpa_get_numeral_exponent_string', STRING, (_in(CONTEXT), _in(AST))) def_API('Z3_fpa_get_numeral_exponent_string', STRING, (_in(CONTEXT), _in(AST), _in(BOOL)))
*/ */
Z3_string Z3_API Z3_fpa_get_numeral_exponent_string(Z3_context c, Z3_ast t); Z3_string Z3_API Z3_fpa_get_numeral_exponent_string(Z3_context c, Z3_ast t, Z3_bool biased);
/** /**
\brief Return the exponent value of a floating-point numeral as a signed 64-bit integer \brief Return the exponent value of a floating-point numeral as a signed 64-bit integer
@ -882,12 +978,28 @@ extern "C" {
\param c logical context \param c logical context
\param t a floating-point numeral \param t a floating-point numeral
\param n exponent \param n exponent
\param biased flag to indicate whether the result is in biased representation
Remarks: This function extracts the exponent in `t`, without normalization. Remarks: This function extracts the exponent in `t`, without normalization.
NaN is an invalid argument.
def_API('Z3_fpa_get_numeral_exponent_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64))) def_API('Z3_fpa_get_numeral_exponent_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64), _in(BOOL)))
*/ */
Z3_bool Z3_API Z3_fpa_get_numeral_exponent_int64(Z3_context c, Z3_ast t, __int64 * n); Z3_bool Z3_API Z3_fpa_get_numeral_exponent_int64(Z3_context c, Z3_ast t, __int64 * n, Z3_bool biased);
/**
\brief Retrieves the exponent of a floating-point literal as a bit-vector expression.
\param c logical context
\param t a floating-point numeral
\param biased flag to indicate whether the result is in biased representation
Remarks: This function extracts the exponent in `t`, without normalization.
NaN is an invalid arguments.
def_API('Z3_fpa_get_numeral_exponent_bv', AST, (_in(CONTEXT), _in(AST), _in(BOOL)))
*/
Z3_ast Z3_API Z3_fpa_get_numeral_exponent_bv(Z3_context c, Z3_ast t, Z3_bool biased);
/** /**
\brief Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. \brief Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format.

View file

@ -288,11 +288,16 @@ public:
app * mk_nzero(sort * s) { return mk_nzero(get_ebits(s), get_sbits(s)); } app * mk_nzero(sort * s) { return mk_nzero(get_ebits(s), get_sbits(s)); }
bool is_nan(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_nan(v); } bool is_nan(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_nan(v); }
bool is_inf(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_inf(v); }
bool is_pinf(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_pinf(v); } bool is_pinf(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_pinf(v); }
bool is_ninf(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_ninf(v); } bool is_ninf(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_ninf(v); }
bool is_zero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_zero(v); } bool is_zero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_zero(v); }
bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_pzero(v); } bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_pzero(v); }
bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_nzero(v); } bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_nzero(v); }
bool is_normal(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_normal(v); }
bool is_subnormal(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_denormal(v); }
bool is_positive(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_pos(v); }
bool is_negative(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_neg(v); }
app * mk_fp(expr * sgn, expr * exp, expr * sig) { app * mk_fp(expr * sgn, expr * exp, expr * sig) {
SASSERT(m_bv_util.is_bv(sgn) && m_bv_util.get_bv_size(sgn) == 1); SASSERT(m_bv_util.is_bv(sgn) && m_bv_util.get_bv_size(sgn) == 1);

View file

@ -22,13 +22,13 @@ Revision History:
#include"ast_ll_pp.h" #include"ast_ll_pp.h"
namespace smt { namespace smt {
// --------------------------- // ---------------------------
// //
// Base class // Base class
// //
// --------------------------- // ---------------------------
conflict_resolution::conflict_resolution(ast_manager & m, conflict_resolution::conflict_resolution(ast_manager & m,
context & ctx, context & ctx,
dyn_ack_manager & dyn_ack_manager, dyn_ack_manager & dyn_ack_manager,
@ -42,7 +42,7 @@ namespace smt {
m_dyn_ack_manager(dyn_ack_manager), m_dyn_ack_manager(dyn_ack_manager),
m_assigned_literals(assigned_literals), m_assigned_literals(assigned_literals),
m_lemma_atoms(m), m_lemma_atoms(m),
m_todo_js_qhead(0), m_todo_js_qhead(0),
m_antecedents(0), m_antecedents(0),
m_watches(watches), m_watches(watches),
m_new_proofs(m), m_new_proofs(m),
@ -67,7 +67,7 @@ namespace smt {
} }
/** /**
\brief Find a common ancestor (anc) of n1 and n2 in the 'proof' tree. \brief Find a common ancestor (anc) of n1 and n2 in the 'proof' tree.
The common ancestor is used to produce irredundant transitivity proofs. The common ancestor is used to produce irredundant transitivity proofs.
n1 = a1 = ... = ai = ANC = ... = root n1 = a1 = ... = ai = ANC = ... = root
@ -100,7 +100,7 @@ namespace smt {
*/ */
void conflict_resolution::eq_justification2literals(enode * lhs, enode * rhs, eq_justification js) { void conflict_resolution::eq_justification2literals(enode * lhs, enode * rhs, eq_justification js) {
SASSERT(m_antecedents); SASSERT(m_antecedents);
TRACE("conflict_detail", TRACE("conflict_detail",
ast_manager& m = get_manager(); ast_manager& m = get_manager();
tout << mk_pp(lhs->get_owner(), m) << " = " << mk_pp(rhs->get_owner(), m); tout << mk_pp(lhs->get_owner(), m) << " = " << mk_pp(rhs->get_owner(), m);
switch (js.get_kind()) { switch (js.get_kind()) {
@ -133,7 +133,7 @@ namespace smt {
mark_eq(lhs->get_arg(1), rhs->get_arg(0)); mark_eq(lhs->get_arg(1), rhs->get_arg(0));
} }
else { else {
for (unsigned i = 0; i < num_args; i++) for (unsigned i = 0; i < num_args; i++)
mark_eq(lhs->get_arg(i), rhs->get_arg(i)); mark_eq(lhs->get_arg(i), rhs->get_arg(i));
} }
break; break;
@ -146,9 +146,9 @@ namespace smt {
/** /**
\brief Process the transitivity 'proof' from n1 and n2, where \brief Process the transitivity 'proof' from n1 and n2, where
n1 and n2 are in the same branch n1 and n2 are in the same branch
n1 -> ... -> n2 n1 -> ... -> n2
This method may update m_antecedents, m_todo_js and m_todo_eqs. This method may update m_antecedents, m_todo_js and m_todo_eqs.
The resultant set of literals is stored in m_antecedents. The resultant set of literals is stored in m_antecedents.
@ -163,7 +163,7 @@ namespace smt {
/** /**
\brief Process the justification of n1 = n2. \brief Process the justification of n1 = n2.
This method may update m_antecedents, m_todo_js and m_todo_eqs. This method may update m_antecedents, m_todo_js and m_todo_eqs.
The resultant set of literals is stored in m_antecedents. The resultant set of literals is stored in m_antecedents.
@ -180,8 +180,8 @@ namespace smt {
The result is stored in result. The result is stored in result.
\remark This method does not reset the vectors m_antecedents, m_todo_js, m_todo_eqs, nor reset the \remark This method does not reset the vectors m_antecedents, m_todo_js, m_todo_eqs, nor reset the
marks in the justification objects. marks in the justification objects.
*/ */
void conflict_resolution::justification2literals_core(justification * js, literal_vector & result) { void conflict_resolution::justification2literals_core(justification * js, literal_vector & result) {
SASSERT(m_todo_js_qhead <= m_todo_js.size()); SASSERT(m_todo_js_qhead <= m_todo_js.size());
@ -294,13 +294,13 @@ namespace smt {
if (js) if (js)
r = std::max(r, get_justification_max_lvl(js)); r = std::max(r, get_justification_max_lvl(js));
break; break;
} }
case b_justification::BIN_CLAUSE: case b_justification::BIN_CLAUSE:
r = std::max(r, m_ctx.get_assign_level(js.get_literal())); r = std::max(r, m_ctx.get_assign_level(js.get_literal()));
break; break;
case b_justification::AXIOM: case b_justification::AXIOM:
break; break;
case b_justification::JUSTIFICATION: case b_justification::JUSTIFICATION:
r = std::max(r, get_justification_max_lvl(js.get_justification())); r = std::max(r, get_justification_max_lvl(js.get_justification()));
break; break;
default: default:
@ -313,8 +313,8 @@ namespace smt {
bool_var var = antecedent.var(); bool_var var = antecedent.var();
unsigned lvl = m_ctx.get_assign_level(var); unsigned lvl = m_ctx.get_assign_level(var);
SASSERT(var < static_cast<int>(m_ctx.get_num_bool_vars())); SASSERT(var < static_cast<int>(m_ctx.get_num_bool_vars()));
TRACE("conflict", tout << "processing antecedent (level " << lvl << "):"; TRACE("conflict", tout << "processing antecedent (level " << lvl << "):";
m_ctx.display_literal(tout, antecedent); m_ctx.display_literal(tout, antecedent);
m_ctx.display_detailed_literal(tout << " ", antecedent); tout << "\n";); m_ctx.display_detailed_literal(tout << " ", antecedent); tout << "\n";);
if (!m_ctx.is_marked(var) && lvl > m_ctx.get_base_level()) { if (!m_ctx.is_marked(var) && lvl > m_ctx.get_base_level()) {
@ -386,17 +386,17 @@ namespace smt {
consequent = false_literal; consequent = false_literal;
if (not_l != null_literal) if (not_l != null_literal)
consequent = ~not_l; consequent = ~not_l;
m_conflict_lvl = get_max_lvl(consequent, js); m_conflict_lvl = get_max_lvl(consequent, js);
TRACE("conflict_bug", TRACE("conflict_bug",
tout << "conflict_lvl: " << m_conflict_lvl << " scope_lvl: " << m_ctx.get_scope_level() << " base_lvl: " << m_ctx.get_base_level() tout << "conflict_lvl: " << m_conflict_lvl << " scope_lvl: " << m_ctx.get_scope_level() << " base_lvl: " << m_ctx.get_base_level()
<< " search_lvl: " << m_ctx.get_search_level() << "\n"; << " search_lvl: " << m_ctx.get_search_level() << "\n";
tout << "js.kind: " << js.get_kind() << "\n"; tout << "js.kind: " << js.get_kind() << "\n";
tout << "consequent: " << consequent << ": "; tout << "consequent: " << consequent << ": ";
m_ctx.display_literal_verbose(tout, consequent); tout << "\n"; m_ctx.display_literal_verbose(tout, consequent); tout << "\n";
m_ctx.display(tout, js); tout << "\n"; m_ctx.display(tout, js); tout << "\n";
); );
// m_conflict_lvl can be smaller than m_ctx.get_search_level() when: // m_conflict_lvl can be smaller than m_ctx.get_search_level() when:
// there are user level scopes created using the Z3 API, and // there are user level scopes created using the Z3 API, and
@ -413,7 +413,7 @@ namespace smt {
} }
TRACE("conflict", tout << "conflict_lvl: " << m_conflict_lvl << "\n";); TRACE("conflict", tout << "conflict_lvl: " << m_conflict_lvl << "\n";);
SASSERT(!m_assigned_literals.empty()); SASSERT(!m_assigned_literals.empty());
SASSERT(m_todo_js.empty()); SASSERT(m_todo_js.empty());
@ -425,32 +425,32 @@ namespace smt {
/** /**
\brief Cleanup datastructures used during resolve(), minimize lemma (when minimization is enabled), \brief Cleanup datastructures used during resolve(), minimize lemma (when minimization is enabled),
compute m_new_scope_lvl and m_lemma_iscope_lvl, generate proof if needed. compute m_new_scope_lvl and m_lemma_iscope_lvl, generate proof if needed.
This method assumes that the lemma is stored in m_lemma (and the associated atoms in m_lemma_atoms). This method assumes that the lemma is stored in m_lemma (and the associated atoms in m_lemma_atoms).
\warning This method assumes the literals in m_lemma[1] ... m_lemma[m_lemma.size() - 1] are marked. \warning This method assumes the literals in m_lemma[1] ... m_lemma[m_lemma.size() - 1] are marked.
*/ */
void conflict_resolution::finalize_resolve(b_justification conflict, literal not_l) { void conflict_resolution::finalize_resolve(b_justification conflict, literal not_l) {
unmark_justifications(0); unmark_justifications(0);
TRACE("conflict", TRACE("conflict",
tout << "before minimization:\n"; tout << "before minimization:\n";
m_ctx.display_literals(tout, m_lemma); m_ctx.display_literals(tout, m_lemma);
tout << "\n";); tout << "\n";);
TRACE("conflict_verbose", TRACE("conflict_verbose",
tout << "before minimization:\n"; tout << "before minimization:\n";
m_ctx.display_literals_verbose(tout, m_lemma); m_ctx.display_literals_verbose(tout, m_lemma);
tout << "\n";); tout << "\n";);
if (m_params.m_minimize_lemmas) if (m_params.m_minimize_lemmas)
minimize_lemma(); minimize_lemma();
TRACE("conflict", TRACE("conflict",
tout << "after minimization:\n"; tout << "after minimization:\n";
m_ctx.display_literals(tout, m_lemma); m_ctx.display_literals(tout, m_lemma);
tout << "\n";); tout << "\n";);
TRACE("conflict_verbose", TRACE("conflict_verbose",
tout << "after minimization:\n"; tout << "after minimization:\n";
m_ctx.display_literals_verbose(tout, m_lemma); m_ctx.display_literals_verbose(tout, m_lemma);
@ -459,7 +459,7 @@ namespace smt {
TRACE("conflict_bug", TRACE("conflict_bug",
m_ctx.display_literals_verbose(tout, m_lemma); m_ctx.display_literals_verbose(tout, m_lemma);
tout << "\n";); tout << "\n";);
literal_vector::iterator it = m_lemma.begin(); literal_vector::iterator it = m_lemma.begin();
literal_vector::iterator end = m_lemma.end(); literal_vector::iterator end = m_lemma.end();
m_new_scope_lvl = m_ctx.get_search_level(); m_new_scope_lvl = m_ctx.get_search_level();
@ -478,11 +478,11 @@ namespace smt {
m_lemma_iscope_lvl = lvl; m_lemma_iscope_lvl = lvl;
} }
} }
TRACE("conflict", TRACE("conflict",
tout << "new scope level: " << m_new_scope_lvl << "\n"; tout << "new scope level: " << m_new_scope_lvl << "\n";
tout << "intern. scope level: " << m_lemma_iscope_lvl << "\n";); tout << "intern. scope level: " << m_lemma_iscope_lvl << "\n";);
if (m_manager.proofs_enabled()) if (m_manager.proofs_enabled())
mk_conflict_proof(conflict, not_l); mk_conflict_proof(conflict, not_l);
} }
@ -505,7 +505,7 @@ namespace smt {
TRACE("conflict", tout << "not_l: "; m_ctx.display_literal(tout, not_l); tout << "\n";); TRACE("conflict", tout << "not_l: "; m_ctx.display_literal(tout, not_l); tout << "\n";);
process_antecedent(not_l, num_marks); process_antecedent(not_l, num_marks);
} }
do { do {
if (get_manager().has_trace_stream()) { if (get_manager().has_trace_stream()) {
@ -542,7 +542,7 @@ namespace smt {
process_antecedent(~l, num_marks); process_antecedent(~l, num_marks);
} }
justification * js = cls->get_justification(); justification * js = cls->get_justification();
if (js) if (js)
process_justification(js, num_marks); process_justification(js, num_marks);
break; break;
} }
@ -558,13 +558,13 @@ namespace smt {
default: default:
UNREACHABLE(); UNREACHABLE();
} }
while (true) { while (true) {
literal l = m_assigned_literals[idx]; literal l = m_assigned_literals[idx];
if (m_ctx.is_marked(l.var())) if (m_ctx.is_marked(l.var()))
break; break;
CTRACE("conflict", m_ctx.get_assign_level(l) != m_conflict_lvl && m_ctx.get_assign_level(l) != m_ctx.get_base_level(), CTRACE("conflict", m_ctx.get_assign_level(l) != m_conflict_lvl && m_ctx.get_assign_level(l) != m_ctx.get_base_level(),
tout << "assign_level(l): " << m_ctx.get_assign_level(l) << ", conflict_lvl: " << m_conflict_lvl << ", l: "; m_ctx.display_literal(tout, l); tout << "assign_level(l): " << m_ctx.get_assign_level(l) << ", conflict_lvl: " << m_conflict_lvl << ", l: "; m_ctx.display_literal(tout, l);
tout << "\n";); tout << "\n";);
SASSERT(m_ctx.get_assign_level(l) == m_conflict_lvl || SASSERT(m_ctx.get_assign_level(l) == m_conflict_lvl ||
// it may also be an (out-of-order) asserted literal // it may also be an (out-of-order) asserted literal
@ -580,7 +580,7 @@ namespace smt {
idx--; idx--;
num_marks--; num_marks--;
m_ctx.unset_mark(c_var); m_ctx.unset_mark(c_var);
} }
while (num_marks > 0); while (num_marks > 0);
TRACE("conflict", tout << "FUIP: "; m_ctx.display_literal(tout, consequent); tout << "\n";); TRACE("conflict", tout << "FUIP: "; m_ctx.display_literal(tout, consequent); tout << "\n";);
@ -589,8 +589,8 @@ namespace smt {
m_lemma_atoms.set(0, m_ctx.bool_var2expr(consequent.var())); m_lemma_atoms.set(0, m_ctx.bool_var2expr(consequent.var()));
// TODO: // TODO:
// //
// equality optimization should go here. // equality optimization should go here.
// //
finalize_resolve(conflict, not_l); finalize_resolve(conflict, not_l);
@ -600,7 +600,7 @@ namespace smt {
/** /**
\brief Return an approximation for the set of scope levels where the literals in m_lemma \brief Return an approximation for the set of scope levels where the literals in m_lemma
were assigned. were assigned.
*/ */
level_approx_set conflict_resolution::get_lemma_approx_level_set() { level_approx_set conflict_resolution::get_lemma_approx_level_set() {
level_approx_set result; level_approx_set result;
@ -640,7 +640,7 @@ namespace smt {
unsigned lvl = m_ctx.get_assign_level(var); unsigned lvl = m_ctx.get_assign_level(var);
if (!m_ctx.is_marked(var) && lvl > m_ctx.get_base_level()) { if (!m_ctx.is_marked(var) && lvl > m_ctx.get_base_level()) {
if (m_lvl_set.may_contain(lvl)) { if (m_lvl_set.may_contain(lvl)) {
m_ctx.set_mark(var); m_ctx.set_mark(var);
m_unmark.push_back(var); m_unmark.push_back(var);
m_lemma_min_stack.push_back(var); m_lemma_min_stack.push_back(var);
} }
@ -667,18 +667,18 @@ namespace smt {
} }
/** /**
\brief Return true if lit is implied by other marked literals \brief Return true if lit is implied by other marked literals
and/or literals assigned at the base level. and/or literals assigned at the base level.
The set lvl_set is used as an optimization. The set lvl_set is used as an optimization.
The idea is to stop the recursive search with a failure The idea is to stop the recursive search with a failure
as soon as we find a literal assigned in a level that is not in lvl_set. as soon as we find a literal assigned in a level that is not in lvl_set.
*/ */
bool conflict_resolution::implied_by_marked(literal lit) { bool conflict_resolution::implied_by_marked(literal lit) {
m_lemma_min_stack.reset(); // avoid recursive function m_lemma_min_stack.reset(); // avoid recursive function
m_lemma_min_stack.push_back(lit.var()); m_lemma_min_stack.push_back(lit.var());
unsigned old_size = m_unmark.size(); unsigned old_size = m_unmark.size();
unsigned old_js_qhead = m_todo_js_qhead; unsigned old_js_qhead = m_todo_js_qhead;
while (!m_lemma_min_stack.empty()) { while (!m_lemma_min_stack.empty()) {
bool_var var = m_lemma_min_stack.back(); bool_var var = m_lemma_min_stack.back();
m_lemma_min_stack.pop_back(); m_lemma_min_stack.pop_back();
@ -739,7 +739,7 @@ namespace smt {
m_unmark.reset(); m_unmark.reset();
m_lvl_set = get_lemma_approx_level_set(); m_lvl_set = get_lemma_approx_level_set();
unsigned sz = m_lemma.size(); unsigned sz = m_lemma.size();
unsigned i = 1; // the first literal is the FUIP unsigned i = 1; // the first literal is the FUIP
unsigned j = 1; unsigned j = 1;
@ -756,7 +756,7 @@ namespace smt {
j++; j++;
} }
} }
reset_unmark_and_justifications(0, 0); reset_unmark_and_justifications(0, 0);
m_lemma .shrink(j); m_lemma .shrink(j);
m_lemma_atoms.shrink(j); m_lemma_atoms.shrink(j);
@ -810,7 +810,7 @@ namespace smt {
} }
if (m_manager.coarse_grain_proofs()) if (m_manager.coarse_grain_proofs())
return pr; return pr;
TRACE("norm_eq_proof", TRACE("norm_eq_proof",
tout << "#" << n1->get_owner_id() << " = #" << n2->get_owner_id() << "\n"; tout << "#" << n1->get_owner_id() << " = #" << n2->get_owner_id() << "\n";
tout << mk_ll_pp(pr, m_manager, true, false);); tout << mk_ll_pp(pr, m_manager, true, false););
SASSERT(m_manager.is_eq(fact) || m_manager.is_iff(fact)); SASSERT(m_manager.is_eq(fact) || m_manager.is_iff(fact));
@ -906,7 +906,7 @@ namespace smt {
return 0; return 0;
} }
} }
/** /**
\brief Return the proof object associated with the given literal if it already \brief Return the proof object associated with the given literal if it already
exists. Otherwise, return 0 and add l to the todo-list. exists. Otherwise, return 0 and add l to the todo-list.
@ -939,13 +939,13 @@ namespace smt {
// p1: is a proof of "A" // p1: is a proof of "A"
// p2: is a proof of "not A" // p2: is a proof of "not A"
// [unit-resolution p1 p2]: false // [unit-resolution p1 p2]: false
// //
// Let us assume that "A" was assigned first during propagation. // Let us assume that "A" was assigned first during propagation.
// Then, the "resolve" method will never select "not A" as a hypothesis. // Then, the "resolve" method will never select "not A" as a hypothesis.
// "not_A" will be the not_l argument in this method. // "not_A" will be the not_l argument in this method.
// Since we are assuming that "A" was assigned first", m_ctx.get_justification("A") will be // Since we are assuming that "A" was assigned first", m_ctx.get_justification("A") will be
// p1. // p1.
// //
// So, the test "m_ctx.get_justification(l.var()) == js" is used to check // So, the test "m_ctx.get_justification(l.var()) == js" is used to check
// if l was assigned before ~l. // if l was assigned before ~l.
if ((m_ctx.is_marked(l.var()) && m_ctx.get_justification(l.var()) == js) || (js.get_kind() == b_justification::AXIOM)) { if ((m_ctx.is_marked(l.var()) && m_ctx.get_justification(l.var()) == js) || (js.get_kind() == b_justification::AXIOM)) {
@ -1022,11 +1022,11 @@ namespace smt {
tout << mk_pp(m_manager.get_fact(prs[i]), m_manager) << "\n"; tout << mk_pp(m_manager.get_fact(prs[i]), m_manager) << "\n";
} }
tout << "consequent:\n" << mk_pp(l_exr, m_manager) << "\n";); tout << "consequent:\n" << mk_pp(l_exr, m_manager) << "\n";);
TRACE("get_proof", TRACE("get_proof",
tout << l.index() << " " << true_literal.index() << " " << false_literal.index() << " "; tout << l.index() << " " << true_literal.index() << " " << false_literal.index() << " ";
m_ctx.display_literal(tout, l); tout << " --->\n"; m_ctx.display_literal(tout, l); tout << " --->\n";
tout << mk_ll_pp(l_exr, m_manager);); tout << mk_ll_pp(l_exr, m_manager););
CTRACE("get_proof_bug_after", CTRACE("get_proof_bug_after",
invocation_counter >= DUMP_AFTER_NUM_INVOCATIONS, invocation_counter >= DUMP_AFTER_NUM_INVOCATIONS,
tout << l.index() << " " << true_literal.index() << " " << false_literal.index() << " "; tout << l.index() << " " << true_literal.index() << " " << false_literal.index() << " ";
m_ctx.display_literal(tout, l); tout << " --->\n"; m_ctx.display_literal(tout, l); tout << " --->\n";
@ -1040,7 +1040,7 @@ namespace smt {
} }
} }
} }
/** /**
\brief Return the proof object associated with the given justification \brief Return the proof object associated with the given justification
if it already exists. Otherwise, return 0 and add js to the todo-list. if it already exists. Otherwise, return 0 and add js to the todo-list.
@ -1094,7 +1094,7 @@ namespace smt {
i = 2; i = 2;
} }
} }
for (; i < num_lits; i++) for (; i < num_lits; i++)
if (get_proof(~cls->get_literal(i)) == 0) if (get_proof(~cls->get_literal(i)) == 0)
visited = false; visited = false;
return visited; return visited;
@ -1109,7 +1109,7 @@ namespace smt {
SASSERT(pr); SASSERT(pr);
TRACE("proof_gen_bug", tout << "lit2pr_saved: #" << l << "\n";); TRACE("proof_gen_bug", tout << "lit2pr_saved: #" << l << "\n";);
m_lit2proof.insert(l, pr); m_lit2proof.insert(l, pr);
TRACE("mk_proof", TRACE("mk_proof",
tout << mk_bounded_pp(m_ctx.bool_var2expr(l.var()), m_manager, 10) << "\n"; tout << mk_bounded_pp(m_ctx.bool_var2expr(l.var()), m_manager, 10) << "\n";
tout << "storing proof for: "; m_ctx.display_literal(tout, l); tout << "\n"; tout << "storing proof for: "; m_ctx.display_literal(tout, l); tout << "\n";
tout << mk_ll_pp(pr, m_manager);); tout << mk_ll_pp(pr, m_manager););
@ -1118,7 +1118,7 @@ namespace smt {
/** /**
\brief Given that lhs = ... = rhs, and lhs reaches rhs in the 'proof' tree branch. \brief Given that lhs = ... = rhs, and lhs reaches rhs in the 'proof' tree branch.
Then, return true if all proof objects needed to create the proof steps are already Then, return true if all proof objects needed to create the proof steps are already
available. Otherwise return false and update m_todo_pr with info about the proof available. Otherwise return false and update m_todo_pr with info about the proof
objects that need to be created. objects that need to be created.
*/ */
bool conflict_resolution::visit_trans_proof(enode * lhs, enode * rhs) { bool conflict_resolution::visit_trans_proof(enode * lhs, enode * rhs) {
@ -1174,7 +1174,7 @@ namespace smt {
/** /**
\brief Return true if all proof objects that are used to build the proof that lhs = rhs were \brief Return true if all proof objects that are used to build the proof that lhs = rhs were
already built. If the result is false, then m_todo_pr is updated with info about the proof already built. If the result is false, then m_todo_pr is updated with info about the proof
objects that need to be created. objects that need to be created.
*/ */
bool conflict_resolution::visit_eq_justications(enode * lhs, enode * rhs) { bool conflict_resolution::visit_eq_justications(enode * lhs, enode * rhs) {
@ -1226,7 +1226,7 @@ namespace smt {
if (prs1.size() == 1) if (prs1.size() == 1)
pr = prs1[0]; pr = prs1[0];
else { else {
TRACE("mk_transitivity", TRACE("mk_transitivity",
unsigned sz = prs1.size(); unsigned sz = prs1.size();
for (unsigned i = 0; i < sz; i++) { for (unsigned i = 0; i < sz; i++) {
tout << mk_ll_pp(prs1[i], m_manager) << "\n"; tout << mk_ll_pp(prs1[i], m_manager) << "\n";
@ -1288,7 +1288,7 @@ namespace smt {
} }
case tp_elem::LITERAL: { case tp_elem::LITERAL: {
literal l = to_literal(elem.m_lidx); literal l = to_literal(elem.m_lidx);
if (m_lit2proof.contains(l)) if (m_lit2proof.contains(l))
m_todo_pr.pop_back(); m_todo_pr.pop_back();
else { else {
b_justification js = m_ctx.get_justification(l.var()); b_justification js = m_ctx.get_justification(l.var());
@ -1342,11 +1342,11 @@ namespace smt {
void conflict_resolution::process_antecedent_for_unsat_core(literal antecedent) { void conflict_resolution::process_antecedent_for_unsat_core(literal antecedent) {
bool_var var = antecedent.var(); bool_var var = antecedent.var();
TRACE("conflict", tout << "processing antecedent: "; TRACE("conflict", tout << "processing antecedent: ";
m_ctx.display_literal_info(tout << antecedent << " ", antecedent); m_ctx.display_literal_info(tout << antecedent << " ", antecedent);
tout << (m_ctx.is_marked(var)?"marked":"not marked"); tout << (m_ctx.is_marked(var)?"marked":"not marked");
tout << "\n";); tout << "\n";);
if (!m_ctx.is_marked(var)) { if (!m_ctx.is_marked(var)) {
m_ctx.set_mark(var); m_ctx.set_mark(var);
m_unmark.push_back(var); m_unmark.push_back(var);
@ -1355,7 +1355,7 @@ namespace smt {
m_assumptions.push_back(antecedent); m_assumptions.push_back(antecedent);
} }
} }
void conflict_resolution::process_justification_for_unsat_core(justification * js) { void conflict_resolution::process_justification_for_unsat_core(justification * js) {
literal_vector & antecedents = m_tmp_literal_vector; literal_vector & antecedents = m_tmp_literal_vector;
antecedents.reset(); antecedents.reset();
@ -1370,7 +1370,7 @@ namespace smt {
SASSERT(m_ctx.tracking_assumptions()); SASSERT(m_ctx.tracking_assumptions());
m_assumptions.reset(); m_assumptions.reset();
m_unmark.reset(); m_unmark.reset();
SASSERT(m_conflict_lvl <= m_ctx.get_search_level()); SASSERT(m_conflict_lvl <= m_ctx.get_search_level());
unsigned search_lvl = m_ctx.get_search_level(); unsigned search_lvl = m_ctx.get_search_level();
@ -1378,17 +1378,17 @@ namespace smt {
literal consequent = false_literal; literal consequent = false_literal;
if (not_l != null_literal) { if (not_l != null_literal) {
consequent = ~not_l; consequent = ~not_l;
} }
int idx = skip_literals_above_conflict_level(); int idx = skip_literals_above_conflict_level();
if (not_l != null_literal) if (not_l != null_literal)
process_antecedent_for_unsat_core(consequent); process_antecedent_for_unsat_core(consequent);
if (m_assigned_literals.empty()) { if (m_assigned_literals.empty()) {
goto end_unsat_core; goto end_unsat_core;
} }
while (true) { while (true) {
TRACE("unsat_core_bug", tout << consequent << " js.get_kind(): " << js.get_kind() << ", idx: " << idx << "\n";); TRACE("unsat_core_bug", tout << consequent << " js.get_kind(): " << js.get_kind() << ", idx: " << idx << "\n";);
switch (js.get_kind()) { switch (js.get_kind()) {
@ -1411,7 +1411,7 @@ namespace smt {
process_antecedent_for_unsat_core(~l); process_antecedent_for_unsat_core(~l);
} }
justification * js = cls->get_justification(); justification * js = cls->get_justification();
if (js) if (js)
process_justification_for_unsat_core(js); process_justification_for_unsat_core(js);
break; break;
} }
@ -1430,17 +1430,17 @@ namespace smt {
if (m_ctx.is_assumption(consequent.var())) { if (m_ctx.is_assumption(consequent.var())) {
m_assumptions.push_back(consequent); m_assumptions.push_back(consequent);
} }
while (idx >= 0) { while (idx >= 0) {
literal l = m_assigned_literals[idx]; literal l = m_assigned_literals[idx];
TRACE("unsat_core_bug", tout << "l: " << l << ", get_assign_level(l): " << m_ctx.get_assign_level(l) << ", is_marked(l): " << m_ctx.is_marked(l.var()) << "\n";); TRACE("unsat_core_bug", tout << "l: " << l << ", get_assign_level(l): " << m_ctx.get_assign_level(l) << ", is_marked(l): " << m_ctx.is_marked(l.var()) << "\n";);
if (m_ctx.get_assign_level(l) < search_lvl) if (m_ctx.get_assign_level(l) < search_lvl)
goto end_unsat_core; goto end_unsat_core;
if (m_ctx.is_marked(l.var())) if (m_ctx.is_marked(l.var()))
break; break;
idx--; idx--;
} }
if (idx < 0) { if (idx < 0) {
goto end_unsat_core; goto end_unsat_core;
} }
@ -1456,12 +1456,12 @@ namespace smt {
TRACE("unsat_core", tout << "assumptions:\n"; m_ctx.display_literals(tout, m_assumptions); tout << "\n";); TRACE("unsat_core", tout << "assumptions:\n"; m_ctx.display_literals(tout, m_assumptions); tout << "\n";);
reset_unmark_and_justifications(0, 0); reset_unmark_and_justifications(0, 0);
} }
conflict_resolution * mk_conflict_resolution(ast_manager & m, conflict_resolution * mk_conflict_resolution(ast_manager & m,
context & ctx, context & ctx,
dyn_ack_manager & dack_manager, dyn_ack_manager & dack_manager,
smt_params const & params, smt_params const & params,
literal_vector const & assigned_literals, literal_vector const & assigned_literals,
vector<watch_list> & watches) { vector<watch_list> & watches) {
return alloc(conflict_resolution, m, ctx, dack_manager, params, assigned_literals, watches); return alloc(conflict_resolution, m, ctx, dack_manager, params, assigned_literals, watches);
} }