3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-07-26 14:07:54 +00:00
This commit is contained in:
Nikolaj Bjorner 2016-11-17 04:26:36 +02:00
commit 123b50ed3c
20 changed files with 962 additions and 323 deletions

View file

@ -237,22 +237,8 @@ VS_RUNTIME_PATS = [re.compile('vcomp.*\.dll'),
re.compile('msvcp.*\.dll'), re.compile('msvcp.*\.dll'),
re.compile('msvcr.*\.dll')] re.compile('msvcr.*\.dll')]
VS_RUNTIME_FILES = []
def cp_vs_runtime_visitor(pattern, dir, files):
global VS_RUNTIME_FILES
for filename in files:
for pat in VS_RUNTIME_PATS:
if pat.match(filename):
if fnmatch(filename, pattern):
fname = os.path.join(dir, filename)
if not os.path.isdir(fname):
VS_RUNTIME_FILES.append(fname)
break
# Copy Visual Studio Runtime libraries # Copy Visual Studio Runtime libraries
def cp_vs_runtime_core(x64): def cp_vs_runtime_core(x64):
global VS_RUNTIME_FILES
if x64: if x64:
platform = "x64" platform = "x64"
@ -261,7 +247,15 @@ def cp_vs_runtime_core(x64):
vcdir = os.environ['VCINSTALLDIR'] vcdir = os.environ['VCINSTALLDIR']
path = '%sredist\\%s' % (vcdir, platform) path = '%sredist\\%s' % (vcdir, platform)
VS_RUNTIME_FILES = [] VS_RUNTIME_FILES = []
os.walk(path, cp_vs_runtime_visitor, '*.dll') for root, dirs, files in os.walk(path):
for filename in files:
if fnmatch(filename, '*.dll'):
for pat in VS_RUNTIME_PATS:
if pat.match(filename):
fname = os.path.join(root, filename)
if not os.path.isdir(fname):
VS_RUNTIME_FILES.append(fname)
bin_dist_path = os.path.join(DIST_DIR, get_dist_path(x64), 'bin') bin_dist_path = os.path.join(DIST_DIR, get_dist_path(x64), 'bin')
for f in VS_RUNTIME_FILES: for f in VS_RUNTIME_FILES:
shutil.copy(f, bin_dist_path) shutil.copy(f, bin_dist_path)

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;
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); 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;
} }
unsigned ebits = val.get().get_ebits();
if (biased) {
*n = mpfm.is_zero(val) ? 0 : *n = mpfm.is_zero(val) ? 0 :
mpfm.is_denormal(val) ? mpfm.mk_min_exp(val.get().get_ebits()) : 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); 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

@ -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>
@ -79,30 +93,84 @@ namespace Microsoft.Z3
} }
/// <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; Int64 result = 0;
if (Native.Z3_fpa_get_numeral_exponent_int64(Context.nCtx, NativeObject, ref result) == 0) if (Native.Z3_fpa_get_numeral_exponent_int64(Context.nCtx, NativeObject, ref result, biased ? 1 : 0) == 0)
throw new Z3Exception("Exponent is not a 64 bit integer"); throw new Z3Exception("Exponent is not a 64 bit integer");
return result; 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)

View file

@ -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
@ -59,24 +68,116 @@ public class FPNum extends FPExpr
} }
/** /**
* Return the exponent value of a floating-point numeral as a string * The significand of a floating-point numeral as a bit-vector expression
* Remarks: NaN is an invalid argument.
* @throws Z3Exception * @throws Z3Exception
*/ */
public String getExponent() { public BitVecExpr getSignificandBV() {
return Native.fpaGetNumeralExponentString(getContext().nCtx(), getNativeObject()); return new BitVecExpr(getContext(), Native.fpaGetNumeralSignificandBv(getContext().nCtx(), getNativeObject()));
}
/**
* Return the exponent value of a floating-point numeral as a string
* Remarks: NaN is an invalid argument.
* @throws Z3Exception
*/
public String getExponent(boolean biased) {
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)
{ {
super(ctx, obj); super(ctx, obj);
@ -89,5 +190,4 @@ public class FPNum extends FPExpr
{ {
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,20 +2141,53 @@ 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

@ -8453,26 +8453,12 @@ 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.
The significand of the numeral.
>>> x = FPNumRef(2.5, FPSort(8, 24)) Remark: NaN's are invalid arguments.
"""
def sign_as_bv(self):
return BitVecNumRef(Z3_fpa_get_numeral_sign_bv(self.ctx.ref(), self.as_ast()), self.ctx)
"""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

@ -102,10 +102,14 @@ namespace sat {
unsigned m_val1; unsigned m_val1;
unsigned m_val2; unsigned m_val2;
public: public:
bin_clause(literal l1, literal l2, bool learned):m_val1(l1.to_uint()), m_val2((l2.to_uint() << 1) + static_cast<unsigned>(learned)) {} bin_clause(literal l1, literal l2, bool learned) :m_val1(l1.to_uint()), m_val2((l2.to_uint() << 1) + static_cast<unsigned>(learned)) {}
literal get_literal1() const { return to_literal(m_val1); } literal get_literal1() const { return to_literal(m_val1); }
literal get_literal2() const { return to_literal(m_val2 >> 1); } literal get_literal2() const { return to_literal(m_val2 >> 1); }
bool is_learned() const { return (m_val2 & 1) == 1; } bool is_learned() const { return (m_val2 & 1) == 1; }
bool operator==(const bin_clause & other) const {
return (m_val1 == other.m_val1 && m_val2 == other.m_val2) ||
(m_val1 == other.m_val2 && m_val2 == other.m_val1);
}
}; };
class tmp_clause { class tmp_clause {

View file

@ -239,7 +239,7 @@ namespace sat {
m_counter *= 2; m_counter *= 2;
} }
CASSERT("probing", s.check_invariant()); CASSERT("probing", s.check_invariant());
free_memory(); finalize();
return r; return r;
} }
@ -255,9 +255,10 @@ namespace sat {
// TODO // TODO
} }
void probing::free_memory() { void probing::finalize() {
m_assigned.cleanup(); m_assigned.finalize();
m_to_assert.finalize(); m_to_assert.finalize();
m_cached_bins.finalize();
} }
void probing::collect_statistics(statistics & st) const { void probing::collect_statistics(statistics & st) const {

View file

@ -69,7 +69,7 @@ namespace sat {
void updt_params(params_ref const & p); void updt_params(params_ref const & p);
static void collect_param_descrs(param_descrs & d); static void collect_param_descrs(param_descrs & d);
void free_memory(); void finalize();
void collect_statistics(statistics & st) const; void collect_statistics(statistics & st) const;
void reset_statistics(); void reset_statistics();

View file

@ -63,6 +63,7 @@ namespace sat {
} }
simplifier::~simplifier() { simplifier::~simplifier() {
finalize();
} }
inline watch_list & simplifier::get_wlist(literal l) { return s.get_wlist(l); } inline watch_list & simplifier::get_wlist(literal l) { return s.get_wlist(l); }
@ -96,7 +97,7 @@ namespace sat {
inline void simplifier::remove_clause_core(clause & c) { inline void simplifier::remove_clause_core(clause & c) {
unsigned sz = c.size(); unsigned sz = c.size();
for (unsigned i = 0; i < sz; i++) for (unsigned i = 0; i < sz; i++)
insert_todo(c[i].var()); insert_elim_todo(c[i].var());
m_sub_todo.erase(c); m_sub_todo.erase(c);
c.set_removed(true); c.set_removed(true);
TRACE("resolution_bug", tout << "del_clause: " << c << "\n";); TRACE("resolution_bug", tout << "del_clause: " << c << "\n";);
@ -116,6 +117,7 @@ namespace sat {
inline void simplifier::remove_bin_clause_half(literal l1, literal l2, bool learned) { inline void simplifier::remove_bin_clause_half(literal l1, literal l2, bool learned) {
SASSERT(s.get_wlist(~l1).contains(watched(l2, learned))); SASSERT(s.get_wlist(~l1).contains(watched(l2, learned)));
s.get_wlist(~l1).erase(watched(l2, learned)); s.get_wlist(~l1).erase(watched(l2, learned));
m_sub_bin_todo.erase(bin_clause(l1, l2, learned));
} }
void simplifier::init_visited() { void simplifier::init_visited() {
@ -123,21 +125,38 @@ namespace sat {
m_visited.resize(2*s.num_vars(), false); m_visited.resize(2*s.num_vars(), false);
} }
void simplifier::free_memory() { void simplifier::finalize() {
m_use_list.finalize(); m_use_list.finalize();
m_sub_todo.finalize(); m_sub_todo.finalize();
m_sub_bin_todo.finalize(); m_sub_bin_todo.finalize();
m_elim_todo.finalize();
m_visited.finalize(); m_visited.finalize();
m_bs_cs.finalize(); m_bs_cs.finalize();
m_bs_ls.finalize(); m_bs_ls.finalize();
} }
void simplifier::initialize() {
m_need_cleanup = false;
s.m_cleaner(true);
m_last_sub_trail_sz = s.m_trail.size();
m_use_list.init(s.num_vars());
m_sub_todo.reset();
m_sub_bin_todo.reset();
m_elim_todo.reset();
init_visited();
TRACE("after_cleanup", s.display(tout););
CASSERT("sat_solver", s.check_invariant());
}
void simplifier::operator()(bool learned) { void simplifier::operator()(bool learned) {
if (s.inconsistent()) if (s.inconsistent())
return; return;
if (!m_subsumption && !m_elim_blocked_clauses && !m_resolution) if (!m_subsumption && !m_elim_blocked_clauses && !m_resolution)
return; return;
initialize();
CASSERT("sat_solver", s.check_invariant()); CASSERT("sat_solver", s.check_invariant());
TRACE("before_simplifier", s.display(tout);); TRACE("before_simplifier", s.display(tout););
@ -157,10 +176,10 @@ namespace sat {
} }
register_clauses(s.m_clauses); register_clauses(s.m_clauses);
if (!learned && (m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls)) if (!learned && (m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls))
elim_blocked_clauses(); elim_blocked_clauses();
if (!learned) if (!learned)
m_num_calls++; m_num_calls++;
@ -199,7 +218,7 @@ namespace sat {
} }
CASSERT("sat_solver", s.check_invariant()); CASSERT("sat_solver", s.check_invariant());
TRACE("after_simplifier", s.display(tout); tout << "model_converter:\n"; s.m_mc.display(tout);); TRACE("after_simplifier", s.display(tout); tout << "model_converter:\n"; s.m_mc.display(tout););
free_memory(); finalize();
} }
/** /**
@ -619,7 +638,7 @@ namespace sat {
TRACE("elim_lit", tout << "processing: " << c << "\n";); TRACE("elim_lit", tout << "processing: " << c << "\n";);
m_need_cleanup = true; m_need_cleanup = true;
m_num_elim_lits++; m_num_elim_lits++;
insert_todo(l.var()); insert_elim_todo(l.var());
c.elim(l); c.elim(l);
clause_use_list & occurs = m_use_list.get(l); clause_use_list & occurs = m_use_list.get(l);
occurs.erase_not_removed(c); occurs.erase_not_removed(c);
@ -924,8 +943,8 @@ namespace sat {
model_converter::entry * new_entry = 0; model_converter::entry * new_entry = 0;
if (s.is_external(l.var()) || s.was_eliminated(l.var())) if (s.is_external(l.var()) || s.was_eliminated(l.var()))
return; return;
{
{
m_to_remove.reset(); m_to_remove.reset();
{ {
clause_use_list & occs = s.m_use_list.get(l); clause_use_list & occs = s.m_use_list.get(l);
@ -1237,12 +1256,14 @@ namespace sat {
for (; it2 != end2; ++it2) { for (; it2 != end2; ++it2) {
if (it2->is_binary_clause() && it2->get_literal() == l) { if (it2->is_binary_clause() && it2->get_literal() == l) {
TRACE("bin_clause_bug", tout << "removing: " << l << " " << it2->get_literal() << "\n";); TRACE("bin_clause_bug", tout << "removing: " << l << " " << it2->get_literal() << "\n";);
m_sub_bin_todo.erase(bin_clause(l2, l, it2->is_learned()));
continue; continue;
} }
*itprev = *it2; *itprev = *it2;
itprev++; itprev++;
} }
wlist2.set_end(itprev); wlist2.set_end(itprev);
m_sub_bin_todo.erase(bin_clause(l, l2, it->is_learned()));
} }
} }
TRACE("bin_clause_bug", tout << "collapsing watch_list of: " << l << "\n";); TRACE("bin_clause_bug", tout << "collapsing watch_list of: " << l << "\n";);

View file

@ -97,6 +97,8 @@ namespace sat {
void checkpoint(); void checkpoint();
void initialize();
void init_visited(); void init_visited();
void mark_visited(literal l) { m_visited[l.index()] = true; } void mark_visited(literal l) { m_visited[l.index()] = true; }
void unmark_visited(literal l) { m_visited[l.index()] = false; } void unmark_visited(literal l) { m_visited[l.index()] = false; }
@ -172,15 +174,20 @@ namespace sat {
simplifier(solver & s, params_ref const & p); simplifier(solver & s, params_ref const & p);
~simplifier(); ~simplifier();
void insert_todo(bool_var v) { m_elim_todo.insert(v); } void insert_elim_todo(bool_var v) { m_elim_todo.insert(v); }
void reset_todo() { m_elim_todo.reset(); }
void reset_todos() {
m_elim_todo.reset();
m_sub_todo.reset();
m_sub_bin_todo.reset();
}
void operator()(bool learned); void operator()(bool learned);
void updt_params(params_ref const & p); void updt_params(params_ref const & p);
static void collect_param_descrs(param_descrs & d); static void collect_param_descrs(param_descrs & d);
void free_memory(); void finalize();
void collect_statistics(statistics & st) const; void collect_statistics(statistics & st) const;
void reset_statistics(); void reset_statistics();

View file

@ -141,7 +141,7 @@ namespace sat {
m_prev_phase.push_back(PHASE_NOT_AVAILABLE); m_prev_phase.push_back(PHASE_NOT_AVAILABLE);
m_assigned_since_gc.push_back(false); m_assigned_since_gc.push_back(false);
m_case_split_queue.mk_var_eh(v); m_case_split_queue.mk_var_eh(v);
m_simplifier.insert_todo(v); m_simplifier.insert_elim_todo(v);
SASSERT(!was_eliminated(v)); SASSERT(!was_eliminated(v));
return v; return v;
} }
@ -2674,7 +2674,7 @@ namespace sat {
m_phase.shrink(v); m_phase.shrink(v);
m_prev_phase.shrink(v); m_prev_phase.shrink(v);
m_assigned_since_gc.shrink(v); m_assigned_since_gc.shrink(v);
m_simplifier.reset_todo(); m_simplifier.reset_todos();
} }
} }
@ -3042,7 +3042,7 @@ namespace sat {
if (scope_lvl() > 0 || inconsistent()) if (scope_lvl() > 0 || inconsistent())
return; return;
m_simplifier(learned); m_simplifier(learned);
m_simplifier.free_memory(); m_simplifier.finalize();
if (m_ext) if (m_ext)
m_ext->clauses_modifed(); m_ext->clauses_modifed();
} }

View file

@ -237,7 +237,11 @@ namespace sat {
lbool status(clause const & c) const; lbool status(clause const & c) const;
clause_offset get_offset(clause const & c) const { return m_cls_allocator.get_offset(&c); } clause_offset get_offset(clause const & c) const { return m_cls_allocator.get_offset(&c); }
void checkpoint() { void checkpoint() {
if (!m_rlimit.inc()) { throw solver_exception(Z3_CANCELED_MSG); } if (!m_rlimit.inc()) {
m_mc.reset();
m_model_is_current = false;
throw solver_exception(Z3_CANCELED_MSG);
}
++m_num_checkpoints; ++m_num_checkpoints;
if (m_num_checkpoints < 10) return; if (m_num_checkpoints < 10) return;
m_num_checkpoints = 0; m_num_checkpoints = 0;

View file

@ -200,7 +200,7 @@ namespace sat {
iterator begin() const { return m_set.begin(); } iterator begin() const { return m_set.begin(); }
iterator end() const { return m_set.end(); } iterator end() const { return m_set.end(); }
void reset() { m_set.reset(); m_in_set.reset(); } void reset() { m_set.reset(); m_in_set.reset(); }
void cleanup() { m_set.finalize(); m_in_set.finalize(); } void finalize() { m_set.finalize(); m_in_set.finalize(); }
uint_set& operator&=(uint_set const& other) { uint_set& operator&=(uint_set const& other) {
unsigned j = 0; unsigned j = 0;
for (unsigned i = 0; i < m_set.size(); ++i) { for (unsigned i = 0; i < m_set.size(); ++i) {
@ -259,7 +259,7 @@ namespace sat {
bool empty() const { return m_set.empty(); } bool empty() const { return m_set.empty(); }
unsigned size() const { return m_set.size(); } unsigned size() const { return m_set.size(); }
void reset() { m_set.reset(); } void reset() { m_set.reset(); }
void cleanup() { m_set.cleanup(); } void finalize() { m_set.finalize(); }
class iterator { class iterator {
uint_set::iterator m_it; uint_set::iterator m_it;
public: public:

View file

@ -334,6 +334,7 @@ namespace smt {
TRACE("t_fpa_detail", tout << "term: " << mk_ismt2_pp(e, get_manager()) << std::endl; TRACE("t_fpa_detail", tout << "term: " << mk_ismt2_pp(e, get_manager()) << std::endl;
tout << "converted term: " << mk_ismt2_pp(e_conv, get_manager()) << std::endl;); tout << "converted term: " << mk_ismt2_pp(e_conv, get_manager()) << std::endl;);
try {
if (m_fpa_util.is_rm(e)) { if (m_fpa_util.is_rm(e)) {
SASSERT(m_fpa_util.is_bv2rm(e_conv)); SASSERT(m_fpa_util.is_bv2rm(e_conv));
expr_ref bv_rm(m); expr_ref bv_rm(m);
@ -351,6 +352,12 @@ namespace smt {
} }
else else
UNREACHABLE(); UNREACHABLE();
}
catch (rewriter_exception &)
{
m_th_rw.reset();
throw;
}
return res; return res;
} }
@ -743,8 +750,15 @@ namespace smt {
// These are the conversion functions fp.to_* */ // These are the conversion functions fp.to_* */
SASSERT(!m_fpa_util.is_float(n) && !m_fpa_util.is_rm(n)); SASSERT(!m_fpa_util.is_float(n) && !m_fpa_util.is_rm(n));
} }
else else {
UNREACHABLE(); /* Theory variables can be merged when (= bv-term (bvwrap fp-term)),
in which case context::relevant_eh may call theory_fpa::relevant_eh
after theory_bv::relevant_eh, regardless of whether theory_fpa is
interested in this term. But, this can only happen because of
(bvwrap ...) terms, i.e., `n' must be a bit-vector expression,
which we can safely ignore. */
SASSERT(m_bv_util.is_bv(n));
}
} }
void theory_fpa::reset_eh() { void theory_fpa::reset_eh() {