3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-06 01:24:08 +00:00

Merge branch 'fpa-api' of https://git01.codeplex.com/z3 into unstable

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>

Conflicts:
	src/tactic/portfolio/default_tactic.cpp
This commit is contained in:
Christoph M. Wintersteiger 2015-01-21 14:25:31 +00:00
commit d56d63e3e8
110 changed files with 11348 additions and 4084 deletions

View file

@ -2595,6 +2595,100 @@ void substitute_vars_example() {
Z3_del_context(ctx);
}
/**
\brief Demonstrates some basic features of the FloatingPoint theory.
*/
void fpa_example() {
Z3_config cfg;
Z3_context ctx;
Z3_sort double_sort, rm_sort;
Z3_symbol s_rm, s_x, s_y, s_x_plus_y;
Z3_ast rm, x, y, n, x_plus_y, c1, c2, c3, c4, c5, c6;
printf("\nFPA-example\n");
LOG_MSG("FPA-example");
cfg = Z3_mk_config();
ctx = Z3_mk_context(cfg);
Z3_del_config(cfg);
double_sort = Z3_mk_fpa_sort(ctx, 11, 53);
rm_sort = Z3_mk_fpa_rounding_mode_sort(ctx);
{
// Show that there are x, y s.t. (x + y) = 42.0 (with rounding mode).
s_rm = Z3_mk_string_symbol(ctx, "rm");
rm = Z3_mk_const(ctx, s_rm, rm_sort);
s_x = Z3_mk_string_symbol(ctx, "x");
s_y = Z3_mk_string_symbol(ctx, "y");
x = Z3_mk_const(ctx, s_x, double_sort);
y = Z3_mk_const(ctx, s_y, double_sort);
n = Z3_mk_fpa_numeral_double(ctx, 42.0, double_sort);
s_x_plus_y = Z3_mk_string_symbol(ctx, "x_plus_y");
x_plus_y = Z3_mk_const(ctx, s_x_plus_y, double_sort);
c1 = Z3_mk_eq(ctx, x_plus_y, Z3_mk_fpa_add(ctx, rm, x, y));
Z3_ast args[2] = { c1, Z3_mk_eq(ctx, x_plus_y, n) };
c2 = Z3_mk_and(ctx, 2, (Z3_ast*)&args);
Z3_ast args2[2] = { c2, Z3_mk_not(ctx, Z3_mk_eq(ctx, rm, Z3_mk_fpa_rtz(ctx))) };
c3 = Z3_mk_and(ctx, 2, (Z3_ast*)&args2);
Z3_ast and_args[3] = {
Z3_mk_not(ctx, Z3_mk_fpa_is_zero(ctx, y)),
Z3_mk_not(ctx, Z3_mk_fpa_is_nan(ctx, y)),
Z3_mk_not(ctx, Z3_mk_fpa_is_infinite(ctx, y)) };
Z3_ast args3[2] = { c3, Z3_mk_and(ctx, 3, and_args) };
c4 = Z3_mk_and(ctx, 2, (Z3_ast*)&args3);
printf("c4: %s\n", Z3_ast_to_string(ctx, c4));
Z3_push(ctx);
Z3_assert_cnstr(ctx, c4);
check(ctx, Z3_L_TRUE);
Z3_pop(ctx, 1);
}
{
// Show that the following are equal:
// (fp #b0 #b10000000001 #xc000000000000)
// ((_ to_fp 11 53) #x401c000000000000))
// ((_ to_fp 11 53) RTZ 1.75 2)))
// ((_ to_fp 11 53) RTZ 7.0)))
Z3_ast args3[3];
Z3_push(ctx);
c1 = Z3_mk_fpa_fp(ctx,
Z3_mk_numeral(ctx, "0", Z3_mk_bv_sort(ctx, 1)),
Z3_mk_numeral(ctx, "1025", Z3_mk_bv_sort(ctx, 11)),
Z3_mk_numeral(ctx, "3377699720527872", Z3_mk_bv_sort(ctx, 52)));
c2 = Z3_mk_fpa_to_fp_bv(ctx,
Z3_mk_numeral(ctx, "4619567317775286272", Z3_mk_bv_sort(ctx, 64)),
Z3_mk_fpa_sort(ctx, 11, 53));
c3 = Z3_mk_fpa_to_fp_real_int(ctx,
Z3_mk_fpa_rtz(ctx),
Z3_mk_numeral(ctx, "1.75", Z3_mk_real_sort(ctx)),
Z3_mk_numeral(ctx, "2", Z3_mk_int_sort(ctx)),
Z3_mk_fpa_sort(ctx, 11, 53));
c4 = Z3_mk_fpa_to_fp_real(ctx,
Z3_mk_fpa_rtz(ctx),
Z3_mk_numeral(ctx, "7.0", Z3_mk_real_sort(ctx)),
Z3_mk_fpa_sort(ctx, 11, 53));
args3[0] = Z3_mk_eq(ctx, c1, c2);
args3[1] = Z3_mk_eq(ctx, c1, c3);
args3[2] = Z3_mk_eq(ctx, c1, c4);
c5 = Z3_mk_and(ctx, 3, args3);
printf("c5: %s\n", Z3_ast_to_string(ctx, c5));
Z3_assert_cnstr(ctx, c5);
check(ctx, Z3_L_TRUE);
Z3_pop(ctx, 1);
}
Z3_del_context(ctx);
}
/*@}*/
/*@}*/
@ -2640,5 +2734,6 @@ int main() {
smt2parser_example();
substitute_example();
substitute_vars_example();
fpa_example();
return 0;
}

View file

@ -2028,6 +2028,84 @@ namespace test_mapi
// Console.WriteLine("{0}", ctx.MkEq(s1, t1));
}
public static void FloatingPointExample1(Context ctx)
{
Console.WriteLine("FloatingPointExample1");
FPSort s = ctx.MkFPSort(11, 53);
Console.WriteLine("Sort: {0}", s);
FPNum x = (FPNum)ctx.MkNumeral("-1e1", s); /* -1 * 10^1 = -10 */
FPNum y = (FPNum)ctx.MkNumeral("-10", s); /* -10 */
FPNum z = (FPNum)ctx.MkNumeral("-1.25p3", s); /* -1.25 * 2^3 = -1.25 * 8 = -10 */
Console.WriteLine("x={0}; y={1}; z={2}", x.ToString(), y.ToString(), z.ToString());
BoolExpr a = ctx.MkAnd(ctx.MkFPEq(x, y), ctx.MkFPEq(y, z));
Check(ctx, ctx.MkNot(a), Status.UNSATISFIABLE);
/* nothing is equal to NaN according to floating-point
* equality, so NaN == k should be unsatisfiable. */
FPExpr k = (FPExpr)ctx.MkConst("x", s);
FPExpr nan = ctx.MkFPNaN(s);
/* solver that runs the default tactic for QF_FP. */
Solver slvr = ctx.MkSolver("QF_FP");
slvr.Add(ctx.MkFPEq(nan, k));
if (slvr.Check() != Status.UNSATISFIABLE)
throw new TestFailedException();
Console.WriteLine("OK, unsat:" + Environment.NewLine + slvr);
/* NaN is equal to NaN according to normal equality. */
slvr = ctx.MkSolver("QF_FP");
slvr.Add(ctx.MkEq(nan, nan));
if (slvr.Check() != Status.SATISFIABLE)
throw new TestFailedException();
Console.WriteLine("OK, sat:" + Environment.NewLine + slvr);
/* Let's prove -1e1 * -1.25e3 == +100 */
x = (FPNum)ctx.MkNumeral("-1e1", s);
y = (FPNum)ctx.MkNumeral("-1.25p3", s);
FPExpr x_plus_y = (FPExpr)ctx.MkConst("x_plus_y", s);
FPNum r = (FPNum)ctx.MkNumeral("100", s);
slvr = ctx.MkSolver("QF_FP");
slvr.Add(ctx.MkEq(x_plus_y, ctx.MkFPMul(ctx.MkFPRoundNearestTiesToAway(), x, y)));
slvr.Add(ctx.MkNot(ctx.MkFPEq(x_plus_y, r)));
if (slvr.Check() != Status.UNSATISFIABLE)
throw new TestFailedException();
Console.WriteLine("OK, unsat:" + Environment.NewLine + slvr);
}
public static void FloatingPointExample2(Context ctx)
{
Console.WriteLine("FloatingPointExample2");
FPSort double_sort = ctx.MkFPSort(11, 53);
FPRMSort rm_sort = ctx.MkFPRoundingModeSort();
FPRMExpr rm = (FPRMExpr)ctx.MkConst(ctx.MkSymbol("rm"), rm_sort);
BitVecExpr x = (BitVecExpr)ctx.MkConst(ctx.MkSymbol("x"), ctx.MkBitVecSort(64));
FPExpr y = (FPExpr)ctx.MkConst(ctx.MkSymbol("y"), double_sort);
FPExpr fp_val = ctx.MkFP(42, double_sort);
BoolExpr c1 = ctx.MkEq(y, fp_val);
BoolExpr c2 = ctx.MkEq(x, ctx.MkFPToBV(rm, y, 64, false));
BoolExpr c3 = ctx.MkEq(x, ctx.MkBV(42, 64));
BoolExpr c4 = ctx.MkEq(ctx.MkNumeral(42, ctx.RealSort), ctx.MkFPToReal(fp_val));
BoolExpr c5 = ctx.MkAnd(c1, c2, c3, c4);
Console.WriteLine("c5 = " + c5);
/* Generic solver */
Solver s = ctx.MkSolver();
s.Assert(c5);
Console.WriteLine(s);
if (s.Check() != Status.SATISFIABLE)
throw new TestFailedException();
Console.WriteLine("OK, model: {0}", s.Model.ToString());
}
static void Main(string[] args)
{
try
@ -2069,6 +2147,8 @@ namespace test_mapi
FindSmallModelExample(ctx);
SimplifierExample(ctx);
FiniteDomainExample(ctx);
FloatingPointExample1(ctx);
FloatingPointExample2(ctx);
}
// These examples need proof generation turned on.

View file

@ -1095,7 +1095,7 @@ class JavaExample
// / Shows how to use Solver(logic)
// / <param name="ctx"></param>
// / @param ctx
void logicExample(Context ctx) throws Z3Exception, TestFailedException
{
System.out.println("LogicTest");
@ -2157,6 +2157,86 @@ class JavaExample
// System.out.println(ctx.mkEq(s1, t1));
}
public void floatingPointExample1(Context ctx) throws Z3Exception, TestFailedException
{
System.out.println("FloatingPointExample1");
Log.append("FloatingPointExample1");
FPSort s = ctx.mkFPSort(11, 53);
System.out.println("Sort: " + s);
FPNum x = (FPNum)ctx.mkNumeral("-1e1", s); /* -1 * 10^1 = -10 */
FPNum y = (FPNum)ctx.mkNumeral("-10", s); /* -10 */
FPNum z = (FPNum)ctx.mkNumeral("-1.25p3", s); /* -1.25 * 2^3 = -1.25 * 8 = -10 */
System.out.println("x=" + x.toString() +
"; y=" + y.toString() +
"; z=" + z.toString());
BoolExpr a = ctx.mkAnd(ctx.mkFPEq(x, y), ctx.mkFPEq(y, z));
check(ctx, ctx.mkNot(a), Status.UNSATISFIABLE);
/* nothing is equal to NaN according to floating-point
* equality, so NaN == k should be unsatisfiable. */
FPExpr k = (FPExpr)ctx.mkConst("x", s);
FPExpr nan = ctx.mkFPNaN(s);
/* solver that runs the default tactic for QF_FP. */
Solver slvr = ctx.mkSolver("QF_FP");
slvr.add(ctx.mkFPEq(nan, k));
if (slvr.check() != Status.UNSATISFIABLE)
throw new TestFailedException();
System.out.println("OK, unsat:" + System.getProperty("line.separator") + slvr);
/* NaN is equal to NaN according to normal equality. */
slvr = ctx.mkSolver("QF_FP");
slvr.add(ctx.mkEq(nan, nan));
if (slvr.check() != Status.SATISFIABLE)
throw new TestFailedException();
System.out.println("OK, sat:" + System.getProperty("line.separator") + slvr);
/* Let's prove -1e1 * -1.25e3 == +100 */
x = (FPNum)ctx.mkNumeral("-1e1", s);
y = (FPNum)ctx.mkNumeral("-1.25p3", s);
FPExpr x_plus_y = (FPExpr)ctx.mkConst("x_plus_y", s);
FPNum r = (FPNum)ctx.mkNumeral("100", s);
slvr = ctx.mkSolver("QF_FP");
slvr.add(ctx.mkEq(x_plus_y, ctx.mkFPMul(ctx.mkFPRoundNearestTiesToAway(), x, y)));
slvr.add(ctx.mkNot(ctx.mkFPEq(x_plus_y, r)));
if (slvr.check() != Status.UNSATISFIABLE)
throw new TestFailedException();
System.out.println("OK, unsat:" + System.getProperty("line.separator") + slvr);
}
public void floatingPointExample2(Context ctx) throws Z3Exception, TestFailedException
{
System.out.println("FloatingPointExample2");
Log.append("FloatingPointExample2");
FPSort double_sort = ctx.mkFPSort(11, 53);
FPRMSort rm_sort = ctx.mkFPRoundingModeSort();
FPRMExpr rm = (FPRMExpr)ctx.mkConst(ctx.mkSymbol("rm"), rm_sort);
BitVecExpr x = (BitVecExpr)ctx.mkConst(ctx.mkSymbol("x"), ctx.mkBitVecSort(64));
FPExpr y = (FPExpr)ctx.mkConst(ctx.mkSymbol("y"), double_sort);
FPExpr fp_val = ctx.mkFP(42, double_sort);
BoolExpr c1 = ctx.mkEq(y, fp_val);
BoolExpr c2 = ctx.mkEq(x, ctx.mkFPToBV(rm, y, 64, false));
BoolExpr c3 = ctx.mkEq(x, ctx.mkBV(42, 64));
BoolExpr c4 = ctx.mkEq(ctx.mkNumeral(42, ctx.getRealSort()), ctx.mkFPToReal(fp_val));
BoolExpr c5 = ctx.mkAnd(c1, c2, c3, c4);
System.out.println("c5 = " + c5);
/* Generic solver */
Solver s = ctx.mkSolver();
s.add(c5);
if (s.check() != Status.SATISFIABLE)
throw new TestFailedException();
System.out.println("OK, model: " + s.getModel().toString());
}
public static void main(String[] args)
{
JavaExample p = new JavaExample();
@ -2200,6 +2280,8 @@ class JavaExample
p.findSmallModelExample(ctx);
p.simplifierExample(ctx);
p.finiteDomainExample(ctx);
p.floatingPointExample1(ctx);
p.floatingPointExample2(ctx);
}
{ // These examples need proof generation turned on.

View file

@ -53,8 +53,8 @@ def init_project_def():
add_lib('user_plugin', ['smt'], 'smt/user_plugin')
add_lib('bv_tactics', ['tactic', 'bit_blaster'], 'tactic/bv')
add_lib('fuzzing', ['ast'], 'test/fuzzing')
add_lib('fpa_tactics', ['fpa', 'core_tactics', 'bv_tactics', 'sat_tactic'], 'tactic/fpa')
add_lib('smt_tactic', ['smt'], 'smt/tactic')
add_lib('fpa_tactics', ['fpa', 'core_tactics', 'bv_tactics', 'sat_tactic', 'smt_tactic'], 'tactic/fpa')
add_lib('sls_tactic', ['tactic', 'normal_forms', 'core_tactics', 'bv_tactics'], 'tactic/sls')
add_lib('qe', ['smt','sat'], 'qe')
add_lib('duality', ['smt', 'interp', 'qe'])
@ -75,7 +75,7 @@ def init_project_def():
# dll_name='foci2',
# export_files=['foci2stub.cpp'])
# add_lib('interp', ['solver','foci2'])
API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h', 'z3_interp.h']
API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h', 'z3_interp.h', 'z3_fpa.h']
add_lib('api', ['portfolio', 'user_plugin', 'smtparser', 'realclosure', 'interp'],
includes2install=['z3.h', 'z3_v1.h', 'z3_macros.h'] + API_files)
add_exe('shell', ['api', 'sat', 'extra_cmds'], exe_name='z3')

View file

@ -124,6 +124,7 @@ SYMBOL = 9
PRINT_MODE = 10
ERROR_CODE = 11
DOUBLE = 12
FLOAT = 13
FIRST_OBJ_ID = 100
@ -131,28 +132,28 @@ def is_obj(ty):
return ty >= FIRST_OBJ_ID
Type2Str = { VOID : 'void', VOID_PTR : 'void*', INT : 'int', UINT : 'unsigned', INT64 : '__int64', UINT64 : '__uint64', DOUBLE : 'double',
STRING : 'Z3_string', STRING_PTR : 'Z3_string_ptr', BOOL : 'Z3_bool', SYMBOL : 'Z3_symbol',
FLOAT : 'float', STRING : 'Z3_string', STRING_PTR : 'Z3_string_ptr', BOOL : 'Z3_bool', SYMBOL : 'Z3_symbol',
PRINT_MODE : 'Z3_ast_print_mode', ERROR_CODE : 'Z3_error_code'
}
Type2PyStr = { VOID_PTR : 'ctypes.c_void_p', INT : 'ctypes.c_int', UINT : 'ctypes.c_uint', INT64 : 'ctypes.c_longlong',
UINT64 : 'ctypes.c_ulonglong', DOUBLE : 'ctypes.c_double',
UINT64 : 'ctypes.c_ulonglong', DOUBLE : 'ctypes.c_double', FLOAT : 'ctypes.c_float',
STRING : 'ctypes.c_char_p', STRING_PTR : 'ctypes.POINTER(ctypes.c_char_p)', BOOL : 'ctypes.c_bool', SYMBOL : 'Symbol',
PRINT_MODE : 'ctypes.c_uint', ERROR_CODE : 'ctypes.c_uint'
}
# Mapping to .NET types
Type2Dotnet = { VOID : 'void', VOID_PTR : 'IntPtr', INT : 'int', UINT : 'uint', INT64 : 'Int64', UINT64 : 'UInt64', DOUBLE : 'double',
STRING : 'string', STRING_PTR : 'byte**', BOOL : 'int', SYMBOL : 'IntPtr',
FLOAT : 'float', STRING : 'string', STRING_PTR : 'byte**', BOOL : 'int', SYMBOL : 'IntPtr',
PRINT_MODE : 'uint', ERROR_CODE : 'uint' }
# Mapping to Java types
Type2Java = { VOID : 'void', VOID_PTR : 'long', INT : 'int', UINT : 'int', INT64 : 'long', UINT64 : 'long', DOUBLE : 'double',
STRING : 'String', STRING_PTR : 'StringPtr',
FLOAT : 'float', STRING : 'String', STRING_PTR : 'StringPtr',
BOOL : 'boolean', SYMBOL : 'long', PRINT_MODE : 'int', ERROR_CODE : 'int'}
Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', INT64 : 'jlong', UINT64 : 'jlong', DOUBLE : 'jdouble',
STRING : 'jstring', STRING_PTR : 'jobject',
FLOAT : 'jfloat', STRING : 'jstring', STRING_PTR : 'jobject',
BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint'}
@ -927,6 +928,9 @@ def def_API(name, result, params):
elif ty == DOUBLE:
log_c.write(" D(a%s);\n" % i)
exe_c.write("in.get_double(%s)" % i)
elif ty == FLOAT:
log_c.write(" D(a%s);\n" % i)
exe_c.write("in.get_float(%s)" % i)
elif ty == BOOL:
log_c.write(" I(a%s);\n" % i)
exe_c.write("in.get_bool(%s)" % i)

View file

@ -648,6 +648,12 @@ extern "C" {
else if (fid == mk_c(c)->get_datalog_fid() && k == datalog::DL_FINITE_SORT) {
return Z3_FINITE_DOMAIN_SORT;
}
else if (fid == mk_c(c)->get_fpa_fid() && k == FLOATING_POINT_SORT) {
return Z3_FLOATING_POINT_SORT;
}
else if (fid == mk_c(c)->get_fpa_fid() && k == ROUNDING_MODE_SORT) {
return Z3_ROUNDING_MODE_SORT;
}
else {
return Z3_UNKNOWN_SORT;
}
@ -1113,6 +1119,62 @@ extern "C" {
return Z3_OP_UNINTERPRETED;
}
}
if (mk_c(c)->get_fpa_fid() == _d->get_family_id()) {
switch (_d->get_decl_kind()) {
case OP_FPA_RM_NEAREST_TIES_TO_EVEN: return Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN;
case OP_FPA_RM_NEAREST_TIES_TO_AWAY: return Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY;
case OP_FPA_RM_TOWARD_POSITIVE: return Z3_OP_FPA_RM_TOWARD_POSITIVE;
case OP_FPA_RM_TOWARD_NEGATIVE: return Z3_OP_FPA_RM_TOWARD_NEGATIVE;
case OP_FPA_RM_TOWARD_ZERO: return Z3_OP_FPA_RM_TOWARD_ZERO;
case OP_FPA_NUM: return Z3_OP_FPA_NUM;
case OP_FPA_PLUS_INF: return Z3_OP_FPA_PLUS_INF;
case OP_FPA_MINUS_INF: return Z3_OP_FPA_MINUS_INF;
case OP_FPA_NAN: return Z3_OP_FPA_NAN;
case OP_FPA_MINUS_ZERO: return Z3_OP_FPA_MINUS_ZERO;
case OP_FPA_PLUS_ZERO: return Z3_OP_FPA_PLUS_ZERO;
case OP_FPA_ADD: return Z3_OP_FPA_ADD;
case OP_FPA_SUB: return Z3_OP_FPA_SUB;
case OP_FPA_NEG: return Z3_OP_FPA_NEG;
case OP_FPA_MUL: return Z3_OP_FPA_MUL;
case OP_FPA_DIV: return Z3_OP_FPA_DIV;
case OP_FPA_REM: return Z3_OP_FPA_REM;
case OP_FPA_ABS: return Z3_OP_FPA_ABS;
case OP_FPA_MIN: return Z3_OP_FPA_MIN;
case OP_FPA_MAX: return Z3_OP_FPA_MAX;
case OP_FPA_FMA: return Z3_OP_FPA_FMA;
case OP_FPA_SQRT: return Z3_OP_FPA_SQRT;
case OP_FPA_EQ: return Z3_OP_FPA_EQ;
case OP_FPA_ROUND_TO_INTEGRAL: return Z3_OP_FPA_ROUND_TO_INTEGRAL;
case OP_FPA_LT: return Z3_OP_FPA_LT;
case OP_FPA_GT: return Z3_OP_FPA_GT;
case OP_FPA_LE: return Z3_OP_FPA_LE;
case OP_FPA_GE: return Z3_OP_FPA_GE;
case OP_FPA_IS_NAN: return Z3_OP_FPA_IS_NAN;
case OP_FPA_IS_INF: return Z3_OP_FPA_IS_INF;
case OP_FPA_IS_ZERO: return Z3_OP_FPA_IS_ZERO;
case OP_FPA_IS_NORMAL: return Z3_OP_FPA_IS_NORMAL;
case OP_FPA_IS_SUBNORMAL: return Z3_OP_FPA_IS_SUBNORMAL;
case OP_FPA_IS_NEGATIVE: return Z3_OP_FPA_IS_NEGATIVE;
case OP_FPA_IS_POSITIVE: return Z3_OP_FPA_IS_POSITIVE;
case OP_FPA_FP: return Z3_OP_FPA_FP;
case OP_FPA_TO_FP: return Z3_OP_FPA_TO_FP;
case OP_FPA_TO_FP_UNSIGNED: return Z3_OP_FPA_TO_FP_UNSIGNED;
case OP_FPA_TO_UBV: return Z3_OP_FPA_TO_UBV;
case OP_FPA_TO_SBV: return Z3_OP_FPA_TO_SBV;
case OP_FPA_TO_REAL: return Z3_OP_FPA_TO_REAL;
case OP_FPA_TO_IEEE_BV: return Z3_OP_FPA_TO_IEEE_BV;
case OP_FPA_INTERNAL_BVWRAP:
case OP_FPA_INTERNAL_BVUNWRAP:
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED:
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
return Z3_OP_UNINTERPRETED;
default:
UNREACHABLE();
return Z3_OP_UNINTERPRETED;
}
}
if (mk_c(c)->m().get_label_family_id() == _d->get_family_id()) {
switch(_d->get_decl_kind()) {

View file

@ -88,6 +88,7 @@ namespace api {
m_arith_util(m()),
m_bv_util(m()),
m_datalog_util(m()),
m_fpa_util(m()),
m_last_result(m()),
m_ast_trail(m()),
m_replay_stack() {
@ -112,6 +113,7 @@ namespace api {
m_array_fid = m().mk_family_id("array");
m_dt_fid = m().mk_family_id("datatype");
m_datalog_fid = m().mk_family_id("datalog_relation");
m_fpa_fid = m().mk_family_id("fpa");
m_dt_plugin = static_cast<datatype_decl_plugin*>(m().get_plugin(m_dt_fid));
if (!m_user_ref_count) {

View file

@ -27,6 +27,7 @@ Revision History:
#include"bv_decl_plugin.h"
#include"datatype_decl_plugin.h"
#include"dl_decl_plugin.h"
#include"fpa_decl_plugin.h"
#include"smt_kernel.h"
#include"smt_params.h"
#include"event_handler.h"
@ -56,6 +57,7 @@ namespace api {
arith_util m_arith_util;
bv_util m_bv_util;
datalog::dl_decl_util m_datalog_util;
fpa_util m_fpa_util;
// Support for old solver API
smt_params m_fparams;
@ -75,6 +77,7 @@ namespace api {
family_id m_bv_fid;
family_id m_dt_fid;
family_id m_datalog_fid;
family_id m_fpa_fid;
datatype_decl_plugin * m_dt_plugin;
std::string m_string_buffer; // temporary buffer used to cache strings sent to the "external" world.
@ -115,12 +118,14 @@ namespace api {
arith_util & autil() { return m_arith_util; }
bv_util & bvutil() { return m_bv_util; }
datalog::dl_decl_util & datalog_util() { return m_datalog_util; }
fpa_util & fpa_util() { return m_fpa_util; }
family_id get_basic_fid() const { return m_basic_fid; }
family_id get_array_fid() const { return m_array_fid; }
family_id get_arith_fid() const { return m_arith_fid; }
family_id get_bv_fid() const { return m_bv_fid; }
family_id get_dt_fid() const { return m_dt_fid; }
family_id get_datalog_fid() const { return m_datalog_fid; }
family_id get_fpa_fid() const { return m_fpa_fid; }
datatype_decl_plugin * get_dt_plugin() const { return m_dt_plugin; }
Z3_error_code get_error_code() const { return m_error_code; }

793
src/api/api_fpa.cpp Normal file
View file

@ -0,0 +1,793 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
api_fpa.cpp
Abstract:
Additional APIs for floating-point arithmetic (FP).
Author:
Christoph M. Wintersteiger (cwinter) 2013-06-05
Notes:
--*/
#include<iostream>
#include"z3.h"
#include"api_log_macros.h"
#include"api_context.h"
#include"fpa_decl_plugin.h"
extern "C" {
Z3_sort Z3_API Z3_mk_fpa_rounding_mode_sort(Z3_context c) {
Z3_TRY;
LOG_Z3_mk_fpa_rounding_mode_sort(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_sort r = of_sort(ctx->fpa_util().mk_rm_sort());
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_even(Z3_context c)
{
Z3_TRY;
LOG_Z3_mk_fpa_round_nearest_ties_to_even(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_even());
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_rne(Z3_context c) {
Z3_TRY;
LOG_Z3_mk_fpa_rne(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_even());
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_away(Z3_context c)
{
Z3_TRY;
LOG_Z3_mk_fpa_round_nearest_ties_to_away(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_away());
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_rna(Z3_context c) {
Z3_TRY;
LOG_Z3_mk_fpa_rna(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_away());
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(Z3_context c)
{
Z3_TRY;
LOG_Z3_mk_fpa_round_toward_positive(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_positive());
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_rtp(Z3_context c) {
Z3_TRY;
LOG_Z3_mk_fpa_rtp(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_positive());
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(Z3_context c)
{
Z3_TRY;
LOG_Z3_mk_fpa_round_toward_negative(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_negative());
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_rtn(Z3_context c) {
Z3_TRY;
LOG_Z3_mk_fpa_rtn(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_negative());
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(Z3_context c)
{
Z3_TRY;
LOG_Z3_mk_fpa_round_toward_zero(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_zero());
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_rtz(Z3_context c) {
Z3_TRY;
LOG_Z3_mk_fpa_rtz(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_zero());
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_sort Z3_API Z3_mk_fpa_sort(Z3_context c, unsigned ebits, unsigned sbits) {
Z3_TRY;
LOG_Z3_mk_fpa_sort(c, ebits, sbits);
RESET_ERROR_CODE();
if (ebits < 2 || sbits < 3) {
SET_ERROR_CODE(Z3_INVALID_ARG);
}
api::context * ctx = mk_c(c);
Z3_sort r = of_sort(ctx->fpa_util().mk_float_sort(ebits, sbits));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_sort Z3_API Z3_mk_fpa_sort_half(Z3_context c) {
return Z3_mk_fpa_sort(c, 5, 11);
}
Z3_sort Z3_API Z3_mk_fpa_sort_16(Z3_context c) {
return Z3_mk_fpa_sort(c, 5, 11);
}
Z3_sort Z3_API Z3_mk_fpa_sort_single(Z3_context c) {
return Z3_mk_fpa_sort(c, 8, 24);
}
Z3_sort Z3_API Z3_mk_fpa_sort_32(Z3_context c) {
return Z3_mk_fpa_sort(c, 8, 24);
}
Z3_sort Z3_API Z3_mk_fpa_sort_double(Z3_context c) {
return Z3_mk_fpa_sort(c, 11, 53);
}
Z3_sort Z3_API Z3_mk_fpa_sort_64(Z3_context c) {
return Z3_mk_fpa_sort(c, 11, 53);
}
Z3_sort Z3_API Z3_mk_fpa_sort_quadruple(Z3_context c) {
return Z3_mk_fpa_sort(c, 15, 113);
}
Z3_sort Z3_API Z3_mk_fpa_sort_128(Z3_context c) {
return Z3_mk_fpa_sort(c, 15, 113);
}
Z3_ast Z3_API Z3_mk_fpa_nan(Z3_context c, Z3_sort s) {
Z3_TRY;
LOG_Z3_mk_fpa_nan(c, s);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_nan(to_sort(s)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_inf(Z3_context c, Z3_sort s, Z3_bool negative) {
Z3_TRY;
LOG_Z3_mk_fpa_inf(c, s, negative);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(negative != 0 ? ctx->fpa_util().mk_ninf(to_sort(s)) :
ctx->fpa_util().mk_pinf(to_sort(s)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_zero(Z3_context c, Z3_sort s, Z3_bool negative) {
Z3_TRY;
LOG_Z3_mk_fpa_inf(c, s, negative);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(negative != 0 ? ctx->fpa_util().mk_nzero(to_sort(s)) :
ctx->fpa_util().mk_pzero(to_sort(s)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_fp(Z3_context c, Z3_ast sgn, Z3_ast exp, Z3_ast sig) {
Z3_TRY;
LOG_Z3_mk_fpa_fp(c, sgn, sig, exp);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_fp(to_expr(sgn), to_expr(sig), to_expr(exp)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_numeral_float(Z3_context c, float v, Z3_sort ty) {
Z3_TRY;
LOG_Z3_mk_fpa_numeral_float(c, v, ty);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
scoped_mpf tmp(ctx->fpa_util().fm());
ctx->fpa_util().fm().set(tmp,
ctx->fpa_util().get_ebits(to_sort(ty)),
ctx->fpa_util().get_sbits(to_sort(ty)),
v);
Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_numeral_double(Z3_context c, double v, Z3_sort ty) {
Z3_TRY;
LOG_Z3_mk_fpa_numeral_double(c, v, ty);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
scoped_mpf tmp(ctx->fpa_util().fm());
ctx->fpa_util().fm().set(tmp, ctx->fpa_util().get_ebits(to_sort(ty)), ctx->fpa_util().get_sbits(to_sort(ty)), v);
Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_numeral_int(Z3_context c, signed v, Z3_sort ty) {
Z3_TRY;
LOG_Z3_mk_fpa_numeral_int(c, v, ty);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
scoped_mpf tmp(ctx->fpa_util().fm());
ctx->fpa_util().fm().set(tmp,
ctx->fpa_util().get_ebits(to_sort(ty)),
ctx->fpa_util().get_sbits(to_sort(ty)),
v);
Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_numeral_uint_int(Z3_context c, Z3_bool sgn, unsigned sig, signed exp, Z3_sort ty) {
Z3_TRY;
LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
scoped_mpf tmp(ctx->fpa_util().fm());
ctx->fpa_util().fm().set(tmp,
ctx->fpa_util().get_ebits(to_sort(ty)),
ctx->fpa_util().get_sbits(to_sort(ty)),
sgn != 0, sig, exp);
Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_numeral_uint64_int64(Z3_context c, Z3_bool sgn, __uint64 sig, __int64 exp, Z3_sort ty) {
Z3_TRY;
LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
scoped_mpf tmp(ctx->fpa_util().fm());
ctx->fpa_util().fm().set(tmp,
ctx->fpa_util().get_ebits(to_sort(ty)),
ctx->fpa_util().get_sbits(to_sort(ty)),
sgn != 0, sig, exp);
Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_abs(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_abs(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_abs(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_neg(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_neg(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_neg(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_add(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_add(c, rm, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_add(to_expr(rm), to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_sub(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_add(c, rm, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_sub(to_expr(rm), to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_mul(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_add(c, rm, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_mul(to_expr(rm), to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_div(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_add(c, rm, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_div(to_expr(rm), to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_fma(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2, Z3_ast t3) {
Z3_TRY;
LOG_Z3_mk_fpa_fma(c, rm, t1, t2, t3);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_fma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_sqrt(Z3_context c, Z3_ast rm, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_sqrt(c, rm, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_sqrt(to_expr(rm), to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_rem(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_rem(c, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_rem(to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_round_to_integral(Z3_context c, Z3_ast rm, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_round_to_integral(c, rm, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_round_to_integral(to_expr(rm), to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_min(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_min(c, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_min(to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_max(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_max(c, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_max(to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_leq(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_leq(c, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_le(to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_lt(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_lt(c, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_lt(to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_geq(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_geq(c, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_ge(to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_gt(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_gt(c, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_gt(to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_eq(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_eq(c, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_float_eq(to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_is_normal(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_is_normal(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_is_normal(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_is_subnormal(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_is_subnormal(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_is_subnormal(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_is_zero(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_is_zero(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_is_zero(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_is_infinite(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_is_infinite(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_is_inf(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_is_nan(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_is_nan(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_is_nan(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_is_negative(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_is_negative(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_is_negative(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_is_positive(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_is_positive(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_is_positive(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_fp_bv(Z3_context c, Z3_ast bv, Z3_sort s) {
Z3_TRY;
LOG_Z3_mk_fpa_to_fp_bv(c, bv, s);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpa_util();
if (!ctx->bvutil().is_bv(to_expr(bv)) ||
!fu.is_float(to_sort(s))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(bv)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_fp_float(Z3_context c, Z3_ast rm, Z3_ast t, Z3_sort s) {
Z3_TRY;
LOG_Z3_mk_fpa_to_fp_float(c, rm, t, s);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpa_util();
if (!fu.is_rm(to_expr(rm)) ||
!fu.is_float(to_expr(t)) ||
!fu.is_float(to_sort(s))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_fp_real(Z3_context c, Z3_ast rm, Z3_ast t, Z3_sort s) {
Z3_TRY;
LOG_Z3_mk_fpa_to_fp_real(c, rm, t, s);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpa_util();
if (!fu.is_rm(to_expr(rm)) ||
!ctx->autil().is_real(to_expr(t)) ||
!fu.is_float(to_sort(s))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_fp_signed(Z3_context c, Z3_ast rm, Z3_ast t, Z3_sort s) {
Z3_TRY;
LOG_Z3_mk_fpa_to_fp_signed(c, rm, t, s);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpa_util();
if (!fu.is_rm(to_expr(rm)) ||
!ctx->bvutil().is_bv(to_expr(t)) ||
!fu.is_float(to_sort(s))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_fp_unsigned(Z3_context c, Z3_ast rm, Z3_ast t, Z3_sort s) {
Z3_TRY;
LOG_Z3_mk_fpa_to_fp_unsigned(c, rm, t, s);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpa_util();
if (!fu.is_rm(to_expr(rm)) ||
!ctx->bvutil().is_bv(to_expr(t)) ||
!fu.is_float(to_sort(s))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
Z3_ast r = of_ast(fu.mk_to_fp_unsigned(to_sort(s), to_expr(rm), to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_ubv(Z3_context c, Z3_ast rm, Z3_ast t, unsigned sz) {
Z3_TRY;
LOG_Z3_mk_fpa_to_ubv(c, rm, t, sz);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_to_ubv(to_expr(rm), to_expr(t), sz));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_sbv(Z3_context c, Z3_ast rm, Z3_ast t, unsigned sz) {
Z3_TRY;
LOG_Z3_mk_fpa_to_sbv(c, rm, t, sz);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_to_sbv(to_expr(rm), to_expr(t), sz));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_real(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_to_real(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_to_real(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
unsigned Z3_API Z3_fpa_get_ebits(Z3_context c, Z3_sort s) {
Z3_TRY;
LOG_Z3_fpa_get_ebits(c, s);
RESET_ERROR_CODE();
CHECK_NON_NULL(s, 0);
return mk_c(c)->fpa_util().get_ebits(to_sort(s));
Z3_CATCH_RETURN(0);
}
unsigned Z3_API Z3_fpa_get_sbits(Z3_context c, Z3_sort s) {
Z3_TRY;
LOG_Z3_fpa_get_ebits(c, s);
RESET_ERROR_CODE();
CHECK_NON_NULL(s, 0);
return mk_c(c)->fpa_util().get_sbits(to_sort(s));
Z3_CATCH_RETURN(0);
}
Z3_bool Z3_API Z3_fpa_get_numeral_sign(Z3_context c, Z3_ast t, int * sgn) {
Z3_TRY;
LOG_Z3_fpa_get_numeral_sign(c, t, sgn);
RESET_ERROR_CODE();
ast_manager & m = mk_c(c)->m();
mpf_manager & mpfm = mk_c(c)->fpa_util().fm();
fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid());
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;
}
*sgn = (mpfm.is_nan(val)) ? 0 : mpfm.sgn(val);
return r;
Z3_CATCH_RETURN(0);
}
Z3_string Z3_API Z3_fpa_get_numeral_significand_string(__in Z3_context c, __in Z3_ast t) {
Z3_TRY;
LOG_Z3_fpa_get_numeral_significand_string(c, t);
RESET_ERROR_CODE();
ast_manager & m = mk_c(c)->m();
mpf_manager & mpfm = mk_c(c)->fpa_util().fm();
unsynch_mpq_manager & mpqm = mpfm.mpq_manager();
fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid());
scoped_mpf val(mpfm);
if (!plugin->is_numeral(to_expr(t), val)) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return "";
}
else if (!mpfm.is_regular(val)) {
SET_ERROR_CODE(Z3_INVALID_ARG)
return "";
}
unsigned sbits = val.get().get_sbits();
scoped_mpq q(mpqm);
mpqm.set(q, mpfm.sig_normalized(val));
mpqm.div(q, mpfm.m_powers2(sbits - 1), q);
std::stringstream ss;
mpqm.display_decimal(ss, q, sbits);
return mk_c(c)->mk_external_string(ss.str());
Z3_CATCH_RETURN("");
}
Z3_string Z3_API Z3_fpa_get_numeral_exponent_string(__in Z3_context c, __in Z3_ast t) {
Z3_TRY;
LOG_Z3_fpa_get_numeral_exponent_string(c, t);
RESET_ERROR_CODE();
ast_manager & m = mk_c(c)->m();
mpf_manager & mpfm = mk_c(c)->fpa_util().fm();
unsynch_mpq_manager & mpqm = mpfm.mpq_manager();
fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid());
scoped_mpf val(mpfm);
bool r = plugin->is_numeral(to_expr(t), val);
if (!r) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return "";
}
else if (!mpfm.is_normal(val) && !mpfm.is_denormal(val)) {
SET_ERROR_CODE(Z3_INVALID_ARG)
return "";
}
mpf_exp_t exp = mpfm.exp_normalized(val);
std::stringstream ss;
ss << exp;
return mk_c(c)->mk_external_string(ss.str());
Z3_CATCH_RETURN("");
}
Z3_bool Z3_API Z3_fpa_get_numeral_exponent_int64(__in Z3_context c, __in Z3_ast t, __out __int64 * n) {
Z3_TRY;
LOG_Z3_fpa_get_numeral_exponent_string(c, t);
RESET_ERROR_CODE();
ast_manager & m = mk_c(c)->m();
mpf_manager & mpfm = mk_c(c)->fpa_util().fm();
unsynch_mpq_manager & mpqm = mpfm.mpq_manager();
fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid());
scoped_mpf val(mpfm);
bool r = plugin->is_numeral(to_expr(t), val);
if (!r) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
*n = mpfm.exp(val);
return 1;
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_to_ieee_bv(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->fpa_util().mk_float_to_ieee_bv(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_fp_real_int(Z3_context c, Z3_ast rm, Z3_ast sig, Z3_ast exp, Z3_sort s) {
Z3_TRY;
LOG_Z3_mk_fpa_to_fp_real_int(c, rm, sig, exp, s);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
fpa_util & fu = ctx->fpa_util();
if (!fu.is_rm(to_expr(rm)) ||
!ctx->autil().is_real(to_expr(sig)) ||
!ctx->autil().is_int(to_expr(exp)) ||
!fu.is_float(to_sort(s))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(sig), to_expr(exp)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
};

View file

@ -23,13 +23,15 @@ Revision History:
#include"arith_decl_plugin.h"
#include"bv_decl_plugin.h"
#include"algebraic_numbers.h"
#include"fpa_decl_plugin.h"
bool is_numeral_sort(Z3_context c, Z3_sort ty) {
sort * _ty = to_sort(ty);
family_id fid = _ty->get_family_id();
if (fid != mk_c(c)->get_arith_fid() &&
fid != mk_c(c)->get_bv_fid() &&
fid != mk_c(c)->get_datalog_fid()) {
fid != mk_c(c)->get_datalog_fid() &&
fid != mk_c(c)->get_fpa_fid()) {
return false;
}
return true;
@ -48,7 +50,7 @@ extern "C" {
Z3_ast Z3_API Z3_mk_numeral(Z3_context c, const char* n, Z3_sort ty) {
Z3_TRY;
LOG_Z3_mk_numeral(c, n, ty);
RESET_ERROR_CODE();
RESET_ERROR_CODE();
if (!check_numeral_sort(c, ty)) {
RETURN_Z3(0);
}
@ -56,40 +58,42 @@ extern "C" {
SET_ERROR_CODE(Z3_INVALID_ARG);
RETURN_Z3(0);
}
sort * _ty = to_sort(ty);
bool is_float = mk_c(c)->fpa_util().is_float(_ty);
std::string fixed_num;
char const* m = n;
while (*m) {
if (!(('0' <= *m && *m <= '9') ||
('/' == *m) || ('-' == *m) ||
(' ' == *m) || ('\n' == *m) ||
('.' == *m) || ('e' == *m) ||
('E' == *m))) {
('/' == *m) || ('-' == *m) ||
(' ' == *m) || ('\n' == *m) ||
('.' == *m) || ('e' == *m) ||
('E' == *m) ||
(('p' == *m) && is_float) ||
(('P' == *m)) && is_float)) {
SET_ERROR_CODE(Z3_PARSER_ERROR);
return 0;
}
++m;
}
ast * a = mk_c(c)->mk_numeral_core(rational(n), to_sort(ty));
ast * a = 0;
if (_ty->get_family_id() == mk_c(c)->get_fpa_fid()) {
// avoid expanding floats into huge rationals.
fpa_util & fu = mk_c(c)->fpa_util();
scoped_mpf t(fu.fm());
fu.fm().set(t, fu.get_ebits(_ty), fu.get_sbits(_ty), MPF_ROUND_TOWARD_ZERO, n);
a = fu.mk_value(t);
mk_c(c)->save_ast_trail(a);
}
else
a = mk_c(c)->mk_numeral_core(rational(n), _ty);
RETURN_Z3(of_ast(a));
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_int(Z3_context c, int value, Z3_sort ty) {
Z3_TRY;
LOG_Z3_mk_int(c, value, ty);
RESET_ERROR_CODE();
if (!check_numeral_sort(c, ty)) {
RETURN_Z3(0);
}
ast * a = mk_c(c)->mk_numeral_core(rational(value), to_sort(ty));
RETURN_Z3(of_ast(a));
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_unsigned_int(Z3_context c, unsigned value, Z3_sort ty) {
Z3_TRY;
LOG_Z3_mk_unsigned_int(c, value, ty);
RESET_ERROR_CODE();
RESET_ERROR_CODE();
if (!check_numeral_sort(c, ty)) {
RETURN_Z3(0);
}
@ -97,11 +101,23 @@ extern "C" {
RETURN_Z3(of_ast(a));
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_unsigned_int(Z3_context c, unsigned value, Z3_sort ty) {
Z3_TRY;
LOG_Z3_mk_unsigned_int(c, value, ty);
RESET_ERROR_CODE();
if (!check_numeral_sort(c, ty)) {
RETURN_Z3(0);
}
ast * a = mk_c(c)->mk_numeral_core(rational(value), to_sort(ty));
RETURN_Z3(of_ast(a));
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_int64(Z3_context c, long long value, Z3_sort ty) {
Z3_TRY;
LOG_Z3_mk_int64(c, value, ty);
RESET_ERROR_CODE();
RESET_ERROR_CODE();
if (!check_numeral_sort(c, ty)) {
RETURN_Z3(0);
}
@ -110,11 +126,11 @@ extern "C" {
RETURN_Z3(of_ast(a));
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_unsigned_int64(Z3_context c, unsigned long long value, Z3_sort ty) {
Z3_TRY;
LOG_Z3_mk_unsigned_int64(c, value, ty);
RESET_ERROR_CODE();
RESET_ERROR_CODE();
if (!check_numeral_sort(c, ty)) {
RETURN_Z3(0);
}
@ -129,9 +145,11 @@ extern "C" {
LOG_Z3_is_numeral_ast(c, a);
RESET_ERROR_CODE();
expr* e = to_expr(a);
return
return
mk_c(c)->autil().is_numeral(e) ||
mk_c(c)->bvutil().is_numeral(e);
mk_c(c)->bvutil().is_numeral(e) ||
mk_c(c)->fpa_util().is_numeral(e) ||
mk_c(c)->fpa_util().is_rm_numeral(e);
Z3_CATCH_RETURN(Z3_FALSE);
}
@ -172,8 +190,37 @@ extern "C" {
return mk_c(c)->mk_external_string(r.to_string());
}
else {
SET_ERROR_CODE(Z3_INVALID_ARG);
return "";
// floats are separated from all others to avoid huge rationals.
fpa_util & fu = mk_c(c)->fpa_util();
scoped_mpf tmp(fu.fm());
mpf_rounding_mode rm;
if (mk_c(c)->fpa_util().is_rm_numeral(to_expr(a), rm)) {
switch (rm) {
case OP_FPA_RM_NEAREST_TIES_TO_EVEN:
return mk_c(c)->mk_external_string("roundNearestTiesToEven");
break;
case OP_FPA_RM_NEAREST_TIES_TO_AWAY:
return mk_c(c)->mk_external_string("roundNearestTiesToAway");
break;
case OP_FPA_RM_TOWARD_POSITIVE:
return mk_c(c)->mk_external_string("roundTowardPositive");
break;
case OP_FPA_RM_TOWARD_NEGATIVE:
return mk_c(c)->mk_external_string("roundTowardNegative");
break;
case OP_FPA_RM_TOWARD_ZERO:
default:
return mk_c(c)->mk_external_string("roundTowardZero");
break;
}
}
else if (mk_c(c)->fpa_util().is_numeral(to_expr(a), tmp)) {
return mk_c(c)->mk_external_string(fu.fm().to_string(tmp));
}
else {
SET_ERROR_CODE(Z3_INVALID_ARG);
return "";
}
}
Z3_CATCH_RETURN("");
}

View file

@ -227,10 +227,8 @@ namespace Microsoft.Z3
internal override void IncRef(IntPtr o)
{
// Console.WriteLine("AST IncRef()");
if (Context == null)
throw new Z3Exception("inc() called on null context");
if (o == IntPtr.Zero)
throw new Z3Exception("inc() called on null AST");
if (Context == null || o == IntPtr.Zero)
return;
Context.AST_DRQ.IncAndClear(Context, o);
base.IncRef(o);
}
@ -238,10 +236,8 @@ namespace Microsoft.Z3
internal override void DecRef(IntPtr o)
{
// Console.WriteLine("AST DecRef()");
if (Context == null)
throw new Z3Exception("dec() called on null context");
if (o == IntPtr.Zero)
throw new Z3Exception("dec() called on null AST");
if (Context == null || o == IntPtr.Zero)
return;
Context.AST_DRQ.Add(o);
base.DecRef(o);
}

View file

@ -32,11 +32,6 @@ namespace Microsoft.Z3
{
#region Internal
/// <summary> Constructor for ArithExpr </summary>
internal protected ArithExpr(Context ctx)
: base(ctx)
{
Contract.Requires(ctx != null);
}
internal ArithExpr(Context ctx, IntPtr obj)
: base(ctx, obj)
{

View file

@ -32,11 +32,6 @@ namespace Microsoft.Z3
{
#region Internal
/// <summary> Constructor for ArrayExpr </summary>
internal protected ArrayExpr(Context ctx)
: base(ctx)
{
Contract.Requires(ctx != null);
}
internal ArrayExpr(Context ctx, IntPtr obj)
: base(ctx, obj)
{

View file

@ -41,7 +41,6 @@ namespace Microsoft.Z3
#region Internal
/// <summary> Constructor for BitVecExpr </summary>
internal protected BitVecExpr(Context ctx) : base(ctx) { Contract.Requires(ctx != null); }
internal BitVecExpr(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); }
#endregion
}

View file

@ -32,8 +32,6 @@ namespace Microsoft.Z3
{
#region Internal
/// <summary> Constructor for BoolExpr </summary>
internal protected BoolExpr(Context ctx) : base(ctx) { Contract.Requires(ctx != null); }
/// <summary> Constructor for BoolExpr </summary>
internal BoolExpr(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); }
#endregion
}

View file

@ -3438,6 +3438,805 @@ namespace Microsoft.Z3
}
#endregion
#region Floating-Point Arithmetic
#region Rounding Modes
#region RoundingMode Sort
/// <summary>
/// Create the floating-point RoundingMode sort.
/// </summary>
public FPRMSort MkFPRoundingModeSort()
{
Contract.Ensures(Contract.Result<FPRMSort>() != null);
return new FPRMSort(this);
}
#endregion
#region Numerals
/// <summary>
/// Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode.
/// </summary>
public FPRMExpr MkFPRoundNearestTiesToEven()
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPRMExpr(this, Native.Z3_mk_fpa_round_nearest_ties_to_even(nCtx));
}
/// <summary>
/// Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode.
/// </summary>
public FPRMNum MkFPRNE()
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPRMNum(this, Native.Z3_mk_fpa_rne(nCtx));
}
/// <summary>
/// Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode.
/// </summary>
public FPRMNum MkFPRoundNearestTiesToAway()
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPRMNum(this, Native.Z3_mk_fpa_round_nearest_ties_to_away(nCtx));
}
/// <summary>
/// Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode.
/// </summary>
public FPRMNum MkFPRNA()
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPRMNum(this, Native.Z3_mk_fpa_rna(nCtx));
}
/// <summary>
/// Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode.
/// </summary>
public FPRMNum MkFPRoundTowardPositive()
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_positive(nCtx));
}
/// <summary>
/// Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode.
/// </summary>
public FPRMNum MkFPRTP()
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPRMNum(this, Native.Z3_mk_fpa_rtp(nCtx));
}
/// <summary>
/// Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode.
/// </summary>
public FPRMNum MkFPRoundTowardNegative()
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_negative(nCtx));
}
/// <summary>
/// Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode.
/// </summary>
public FPRMNum MkFPRTN()
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPRMNum(this, Native.Z3_mk_fpa_rtn(nCtx));
}
/// <summary>
/// Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode.
/// </summary>
public FPRMNum MkFPRoundTowardZero()
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_zero(nCtx));
}
/// <summary>
/// Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode.
/// </summary>
public FPRMNum MkFPRTZ()
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPRMNum(this, Native.Z3_mk_fpa_rtz(nCtx));
}
#endregion
#endregion
#region FloatingPoint Sorts
/// <summary>
/// Create a FloatingPoint sort.
/// </summary>
/// <param name="ebits">exponent bits in the FloatingPoint sort.</param>
/// <param name="sbits">significand bits in the FloatingPoint sort.</param>
public FPSort MkFPSort(uint ebits, uint sbits)
{
Contract.Ensures(Contract.Result<FPSort>() != null);
return new FPSort(this, ebits, sbits);
}
/// <summary>
/// Create the half-precision (16-bit) FloatingPoint sort.
/// </summary>
public FPSort MkFPSortHalf()
{
Contract.Ensures(Contract.Result<FPSort>() != null);
return new FPSort(this, Native.Z3_mk_fpa_sort_half(nCtx));
}
/// <summary>
/// Create the half-precision (16-bit) FloatingPoint sort.
/// </summary>
public FPSort MkFPSort16()
{
Contract.Ensures(Contract.Result<FPSort>() != null);
return new FPSort(this, Native.Z3_mk_fpa_sort_16(nCtx));
}
/// <summary>
/// Create the single-precision (32-bit) FloatingPoint sort.
/// </summary>
public FPSort MkFPSortSingle()
{
Contract.Ensures(Contract.Result<FPSort>() != null);
return new FPSort(this, Native.Z3_mk_fpa_sort_single(nCtx));
}
/// <summary>
/// Create the single-precision (32-bit) FloatingPoint sort.
/// </summary>
public FPSort MkFPSort32()
{
Contract.Ensures(Contract.Result<FPSort>() != null);
return new FPSort(this, Native.Z3_mk_fpa_sort_32(nCtx));
}
/// <summary>
/// Create the double-precision (64-bit) FloatingPoint sort.
/// </summary>
public FPSort MkFPSortDouble()
{
Contract.Ensures(Contract.Result<FPSort>() != null);
return new FPSort(this, Native.Z3_mk_fpa_sort_double(nCtx));
}
/// <summary>
/// Create the double-precision (64-bit) FloatingPoint sort.
/// </summary>
public FPSort MkFPSort64()
{
Contract.Ensures(Contract.Result<FPSort>() != null);
return new FPSort(this, Native.Z3_mk_fpa_sort_64(nCtx));
}
/// <summary>
/// Create the quadruple-precision (128-bit) FloatingPoint sort.
/// </summary>
public FPSort MkFPSortQuadruple()
{
Contract.Ensures(Contract.Result<FPSort>() != null);
return new FPSort(this, Native.Z3_mk_fpa_sort_quadruple(nCtx));
}
/// <summary>
/// Create the quadruple-precision (128-bit) FloatingPoint sort.
/// </summary>
public FPSort MkFPSort128()
{
Contract.Ensures(Contract.Result<FPSort>() != null);
return new FPSort(this, Native.Z3_mk_fpa_sort_128(nCtx));
}
#endregion
#region Numerals
/// <summary>
/// Create a NaN of sort s.
/// </summary>
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFPNaN(FPSort s)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPNum(this, Native.Z3_mk_fpa_nan(nCtx, s.NativeObject));
}
/// <summary>
/// Create a floating-point infinity of sort s.
/// </summary>
/// <param name="s">FloatingPoint sort.</param>
/// <param name="negative">indicates whether the result should be negative.</param>
public FPNum MkFPInf(FPSort s, bool negative)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPNum(this, Native.Z3_mk_fpa_inf(nCtx, s.NativeObject, negative ? 1 : 0));
}
/// <summary>
/// Create a floating-point zero of sort s.
/// </summary>
/// <param name="s">FloatingPoint sort.</param>
/// <param name="negative">indicates whether the result should be negative.</param>
public FPNum MkFPZero(FPSort s, bool negative)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPNum(this, Native.Z3_mk_fpa_zero(nCtx, s.NativeObject, negative ? 1 : 0));
}
/// <summary>
/// Create a numeral of FloatingPoint sort from a float.
/// </summary>
/// <param name="v">numeral value.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFPNumeral(float v, FPSort s)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPNum(this, Native.Z3_mk_fpa_numeral_float(nCtx, v, s.NativeObject));
}
/// <summary>
/// Create a numeral of FloatingPoint sort from a float.
/// </summary>
/// <param name="v">numeral value.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFPNumeral(double v, FPSort s)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPNum(this, Native.Z3_mk_fpa_numeral_double(nCtx, v, s.NativeObject));
}
/// <summary>
/// Create a numeral of FloatingPoint sort from an int.
/// </summary>
/// <param name="v">numeral value.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFPNumeral(int v, FPSort s)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPNum(this, Native.Z3_mk_fpa_numeral_int(nCtx, v, s.NativeObject));
}
/// <summary>
/// Create a numeral of FloatingPoint sort from a sign bit and two integers.
/// </summary>
/// <param name="sgn">the sign.</param>
/// <param name="sig">the significand.</param>
/// <param name="exp">the exponent.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFPNumeral(bool sgn, uint sig, int exp, FPSort s)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPNum(this, Native.Z3_mk_fpa_numeral_uint_int(nCtx, sgn ? 1 : 0, sig, exp, s.NativeObject));
}
/// <summary>
/// Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers.
/// </summary>
/// <param name="sgn">the sign.</param>
/// <param name="sig">the significand.</param>
/// <param name="exp">the exponent.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFPNumeral(bool sgn, UInt64 sig, Int64 exp, FPSort s)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return new FPNum(this, Native.Z3_mk_fpa_numeral_uint64_int64(nCtx, sgn ? 1 : 0, sig, exp, s.NativeObject));
}
/// <summary>
/// Create a numeral of FloatingPoint sort from a float.
/// </summary>
/// <param name="v">numeral value.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFP(float v, FPSort s)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return MkFPNumeral(v, s);
}
/// <summary>
/// Create a numeral of FloatingPoint sort from a float.
/// </summary>
/// <param name="v">numeral value.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFP(double v, FPSort s)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return MkFPNumeral(v, s);
}
/// <summary>
/// Create a numeral of FloatingPoint sort from an int.
/// </summary>
/// <param name="v">numeral value.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFP(int v, FPSort s)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return MkFPNumeral(v, s);
}
/// <summary>
/// Create a numeral of FloatingPoint sort from a sign bit and two integers.
/// </summary>
/// <param name="sgn">the sign.</param>
/// <param name="exp">the exponent.</param>
/// <param name="sig">the significand.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFP(bool sgn, int exp, uint sig, FPSort s)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return MkFPNumeral(sgn, sig, exp, s);
}
/// <summary>
/// Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers.
/// </summary>
/// <param name="sgn">the sign.</param>
/// <param name="exp">the exponent.</param>
/// <param name="sig">the significand.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFP(bool sgn, Int64 exp, UInt64 sig, FPSort s)
{
Contract.Ensures(Contract.Result<FPRMExpr>() != null);
return MkFPNumeral(sgn, sig, exp, s);
}
#endregion
#region Operators
/// <summary>
/// Floating-point absolute value
/// </summary>
/// <param name="t">floating-point term</param>
public FPExpr MkFPAbs(FPExpr t)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_abs(this.nCtx, t.NativeObject));
}
/// <summary>
/// Floating-point negation
/// </summary>
/// <param name="t">floating-point term</param>
public FPExpr MkFPNeg(FPExpr t)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_neg(this.nCtx, t.NativeObject));
}
/// <summary>
/// Floating-point addition
/// </summary>
/// <param name="rm">rounding mode term</param>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public FPExpr MkFPAdd(FPRMExpr rm, FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_add(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Floating-point subtraction
/// </summary>
/// <param name="rm">rounding mode term</param>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public FPExpr MkFPSub(FPRMExpr rm, FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_sub(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Floating-point multiplication
/// </summary>
/// <param name="rm">rounding mode term</param>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public FPExpr MkFPMul(FPRMExpr rm, FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_mul(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Floating-point division
/// </summary>
/// <param name="rm">rounding mode term</param>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public FPExpr MkFPDiv(FPRMExpr rm, FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_div(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Floating-point fused multiply-add
/// </summary>
/// <remarks>
/// The result is round((t1 * t2) + t3)
/// </remarks>
/// <param name="rm">rounding mode term</param>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
/// <param name="t3">floating-point term</param>
public FPExpr MkFPFMA(FPRMExpr rm, FPExpr t1, FPExpr t2, FPExpr t3)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_fma(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject, t3.NativeObject));
}
/// <summary>
/// Floating-point square root
/// </summary>
/// <param name="rm">rounding mode term</param>
/// <param name="t">floating-point term</param>
public FPExpr MkFPSqrt(FPRMExpr rm, FPExpr t)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_sqrt(this.nCtx, rm.NativeObject, t.NativeObject));
}
/// <summary>
/// Floating-point remainder
/// </summary>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public FPExpr MkFPRem(FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_rem(this.nCtx, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Floating-point roundToIntegral. Rounds a floating-point number to
/// the closest integer, again represented as a floating-point number.
/// </summary>
/// <param name="rm">term of RoundingMode sort</param>
/// <param name="t">floating-point term</param>
public FPExpr MkFPRoundToIntegral(FPRMExpr rm, FPExpr t)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_round_to_integral(this.nCtx, rm.NativeObject, t.NativeObject));
}
/// <summary>
/// Minimum of floating-point numbers.
/// </summary>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public FPExpr MkFPMin(FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_min(this.nCtx, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Maximum of floating-point numbers.
/// </summary>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public FPExpr MkFPMax(FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<FPNum>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_max(this.nCtx, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Floating-point less than or equal.
/// </summary>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public BoolExpr MkFPLEq(FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_leq(this.nCtx, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Floating-point less than.
/// </summary>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public BoolExpr MkFPLt(FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_lt(this.nCtx, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Floating-point greater than or equal.
/// </summary>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public BoolExpr MkFPGEq(FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_geq(this.nCtx, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Floating-point greater than.
/// </summary>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public BoolExpr MkFPGt(FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_gt(this.nCtx, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Floating-point equality.
/// </summary>
/// <remarks>
/// Note that this is IEEE 754 equality (as opposed to standard =).
/// </remarks>
/// <param name="t1">floating-point term</param>
/// <param name="t2">floating-point term</param>
public BoolExpr MkFPEq(FPExpr t1, FPExpr t2)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_eq(this.nCtx, t1.NativeObject, t2.NativeObject));
}
/// <summary>
/// Predicate indicating whether t is a normal floating-point number.
/// </summary>
/// <param name="t">floating-point term</param>
public BoolExpr MkFPIsNormal(FPExpr t)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_is_normal(this.nCtx, t.NativeObject));
}
/// <summary>
/// Predicate indicating whether t is a subnormal floating-point number.
/// </summary>
/// <param name="t">floating-point term</param>
public BoolExpr MkFPIsSubnormal(FPExpr t)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_is_subnormal(this.nCtx, t.NativeObject));
}
/// <summary>
/// Predicate indicating whether t is a floating-point number with zero value, i.e., +0 or -0.
/// </summary>
/// <param name="t">floating-point term</param>
public BoolExpr MkFPIsZero(FPExpr t)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_is_zero(this.nCtx, t.NativeObject));
}
/// <summary>
/// Predicate indicating whether t is a floating-point number representing +oo or -oo.
/// </summary>
/// <param name="t">floating-point term</param>
public BoolExpr MkFPIsInfinite(FPExpr t)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_is_infinite(this.nCtx, t.NativeObject));
}
/// <summary>
/// Predicate indicating whether t is a NaN.
/// </summary>
/// <param name="t">floating-point term</param>
public BoolExpr MkFPIsNaN(FPExpr t)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_is_nan(this.nCtx, t.NativeObject));
}
/// <summary>
/// Predicate indicating whether t is a negative floating-point number.
/// </summary>
/// <param name="t">floating-point term</param>
public BoolExpr MkFPIsNegative(FPExpr t)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_is_negative(this.nCtx, t.NativeObject));
}
/// <summary>
/// Predicate indicating whether t is a positive floating-point number.
/// </summary>
/// <param name="t">floating-point term</param>
public BoolExpr MkFPIsPositive(FPExpr t)
{
Contract.Ensures(Contract.Result<BoolExpr>() != null);
return new BoolExpr(this, Native.Z3_mk_fpa_is_positive(this.nCtx, t.NativeObject));
}
#endregion
#region Conversions to FloatingPoint terms
/// <summary>
/// Create an expression of FloatingPoint sort from three bit-vector expressions.
/// </summary>
/// <remarks>
/// This is the operator named `fp' in the SMT FP theory definition.
/// Note that sgn 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
/// of the resulting expression is automatically determined from the bit-vector sizes
/// of the arguments.
/// </remarks>
/// <param name="sgn">bit-vector term (of size 1) representing the sign.</param>
/// <param name="sig">bit-vector term representing the significand.</param>
/// <param name="exp">bit-vector term representing the exponent.</param>
public FPExpr MkFP(BitVecExpr sgn, BitVecExpr sig, BitVecExpr exp)
{
Contract.Ensures(Contract.Result<FPExpr>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_fp(this.nCtx, sgn.NativeObject, sig.NativeObject, exp.NativeObject));
}
/// <summary>
/// Conversion of a single IEEE 754-2008 bit-vector into a floating-point number.
/// </summary>
/// <remarks>
/// Produces a term that represents the conversion of a bit-vector term bv to a
/// floating-point term of sort s. The bit-vector size of bv (m) must be equal
/// to ebits+sbits of s. The format of the bit-vector is as defined by the
/// IEEE 754-2008 interchange format.
/// </remarks>
/// <param name="bv">bit-vector value (of size m).</param>
/// <param name="s">FloatingPoint sort (ebits+sbits == m)</param>
public FPExpr MkFPToFP(BitVecExpr bv, FPSort s)
{
Contract.Ensures(Contract.Result<FPExpr>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_to_fp_bv(this.nCtx, bv.NativeObject, s.NativeObject));
}
/// <summary>
/// Conversion of a FloatingPoint term into another term of different FloatingPoint sort.
/// </summary>
/// <remarks>
/// Produces a term that represents the conversion of a floating-point term t to a
/// floating-point term of sort s. If necessary, the result will be rounded according
/// to rounding mode rm.
/// </remarks>
/// <param name="rm">RoundingMode term.</param>
/// <param name="t">FloatingPoint term.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPExpr MkFPToFP(FPRMExpr rm, FPExpr t, FPSort s)
{
Contract.Ensures(Contract.Result<FPExpr>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_to_fp_float(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject));
}
/// <summary>
/// Conversion of a term of real sort into a term of FloatingPoint sort.
/// </summary>
/// <remarks>
/// Produces a term that represents the conversion of term t of real sort into a
/// floating-point term of sort s. If necessary, the result will be rounded according
/// to rounding mode rm.
/// </remarks>
/// <param name="rm">RoundingMode term.</param>
/// <param name="t">term of Real sort.</param>
/// <param name="s">FloatingPoint sort.</param>
public FPExpr MkFPToFP(FPRMExpr rm, RealExpr t, FPSort s)
{
Contract.Ensures(Contract.Result<FPExpr>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_to_fp_real(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject));
}
/// <summary>
/// Conversion of a 2's complement signed bit-vector term into a term of FloatingPoint sort.
/// </summary>
/// <remarks>
/// Produces a term that represents the conversion of the bit-vector term t into a
/// floating-point term of sort s. The bit-vector t is taken to be in signed
/// 2's complement format (when signed==true, otherwise unsigned). If necessary, the
/// result will be rounded according to rounding mode rm.
/// </remarks>
/// <param name="rm">RoundingMode term.</param>
/// <param name="t">term of bit-vector sort.</param>
/// <param name="s">FloatingPoint sort.</param>
/// <param name="signed">flag indicating whether t is interpreted as signed or unsigned bit-vector.</param>
public FPExpr MkFPToFP(FPRMExpr rm, BitVecExpr t, FPSort s, bool signed)
{
Contract.Ensures(Contract.Result<FPExpr>() != null);
if (signed)
return new FPExpr(this, Native.Z3_mk_fpa_to_fp_signed(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject));
else
return new FPExpr(this, Native.Z3_mk_fpa_to_fp_unsigned(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject));
}
/// <summary>
/// Conversion of a floating-point number to another FloatingPoint sort s.
/// </summary>
/// <remarks>
/// Produces a term that represents the conversion of a floating-point term t to a different
/// FloatingPoint sort s. If necessary, rounding according to rm is applied.
/// </remarks>
/// <param name="s">FloatingPoint sort</param>
/// <param name="rm">floating-point rounding mode term</param>
/// <param name="t">floating-point term</param>
public FPExpr MkFPToFP(FPSort s, FPRMExpr rm, FPExpr t)
{
Contract.Ensures(Contract.Result<FPExpr>() != null);
return new FPExpr(this, Native.Z3_mk_fpa_to_fp_float(this.nCtx, s.NativeObject, rm.NativeObject, t.NativeObject));
}
#endregion
#region Conversions from FloatingPoint terms
/// <summary>
/// Conversion of a floating-point term into a bit-vector.
/// </summary>
/// <remarks>
/// Produces a term that represents the conversion of the floating-poiunt term t into a
/// bit-vector term of size sz in 2's complement format (signed when signed==true). If necessary,
/// the result will be rounded according to rounding mode rm.
/// </remarks>
/// <param name="rm">RoundingMode term.</param>
/// <param name="t">FloatingPoint term</param>
/// <param name="sz">Size of the resulting bit-vector.</param>
/// <param name="signed">Indicates whether the result is a signed or unsigned bit-vector.</param>
public BitVecExpr MkFPToBV(FPRMExpr rm, FPExpr t, uint sz, bool signed)
{
Contract.Ensures(Contract.Result<BitVecExpr>() != null);
if (signed)
return new BitVecExpr(this, Native.Z3_mk_fpa_to_sbv(this.nCtx, rm.NativeObject, t.NativeObject, sz));
else
return new BitVecExpr(this, Native.Z3_mk_fpa_to_ubv(this.nCtx, rm.NativeObject, t.NativeObject, sz));
}
/// <summary>
/// Conversion of a floating-point term into a real-numbered term.
/// </summary>
/// <remarks>
/// Produces a term that represents the conversion of the floating-poiunt term t into a
/// real number. Note that this type of conversion will often result in non-linear
/// constraints over real terms.
/// </remarks>
/// <param name="t">FloatingPoint term</param>
public RealExpr MkFPToReal(FPExpr t)
{
Contract.Ensures(Contract.Result<RealExpr>() != null);
return new RealExpr(this, Native.Z3_mk_fpa_to_real(this.nCtx, t.NativeObject));
}
#endregion
#region Z3-specific extensions
/// <summary>
/// Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format.
/// </summary>
/// <remarks>
/// The size of the resulting bit-vector is automatically determined. Note that
/// IEEE 754-2008 allows multiple different representations of NaN. This conversion
/// knows only one NaN and it will always produce the same bit-vector represenatation of
/// that NaN.
/// </remarks>
/// <param name="t">FloatingPoint term.</param>
public BitVecExpr MkFPToIEEEBV(FPExpr t)
{
Contract.Ensures(Contract.Result<BitVecExpr>() != null);
return new BitVecExpr(this, Native.Z3_mk_fpa_to_ieee_bv(this.nCtx, t.NativeObject));
}
/// <summary>
/// Conversion of a real-sorted significand and an integer-sorted exponent into a term of FloatingPoint sort.
/// </summary>
/// <remarks>
/// Produces a term that represents the conversion of sig * 2^exp into a
/// floating-point term of sort s. If necessary, the result will be rounded
/// according to rounding mode rm.
/// </remarks>
/// <param name="rm">RoundingMode term.</param>
/// <param name="sig">Significand term of Real sort.</param>
/// <param name="exp">Exponent term of Int sort.</param>
/// <param name="s">FloatingPoint sort.</param>
public BitVecExpr MkFPToFP(FPRMExpr rm, RealExpr sig, IntExpr exp, FPSort s)
{
Contract.Ensures(Contract.Result<BitVecExpr>() != null);
return new BitVecExpr(this, Native.Z3_mk_fpa_to_fp_real_int(this.nCtx, rm.NativeObject, sig.NativeObject, exp.NativeObject, s.NativeObject));
}
#endregion
#endregion // Floating-point Arithmetic
#region Miscellaneous
/// <summary>

View file

@ -32,11 +32,6 @@ namespace Microsoft.Z3
{
#region Internal
/// <summary> Constructor for DatatypeExpr </summary>
internal protected DatatypeExpr(Context ctx)
: base(ctx)
{
Contract.Requires(ctx != null);
}
internal DatatypeExpr(Context ctx, IntPtr obj)
: base(ctx, obj)
{

View file

@ -78,7 +78,7 @@ namespace Microsoft.Z3
#region Internal
internal EnumSort(Context ctx, Symbol name, Symbol[] enumNames)
: base(ctx)
: base(ctx, IntPtr.Zero)
{
Contract.Requires(ctx != null);
Contract.Requires(name != null);

View file

@ -1448,6 +1448,281 @@ namespace Microsoft.Z3
/// Indicates whether the term is a less than predicate over a finite domain.
/// </summary>
public bool IsFiniteDomainLT { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FD_LT; } }
#endregion
#region Floating-point terms
/// <summary>
/// Indicates whether the terms is of floating-point sort.
/// </summary>
public bool IsFP
{
get { return Native.Z3_get_sort_kind(Context.nCtx, Native.Z3_get_sort(Context.nCtx, NativeObject)) == (uint)Z3_sort_kind.Z3_FLOATING_POINT_SORT; }
}
/// <summary>
/// Indicates whether the terms is of floating-point rounding mode sort.
/// </summary>
public bool IsFPRM
{
get { return Native.Z3_get_sort_kind(Context.nCtx, Native.Z3_get_sort(Context.nCtx, NativeObject)) == (uint)Z3_sort_kind.Z3_ROUNDING_MODE_SORT; }
}
/// <summary>
/// Indicates whether the term is a floating-point numeral
/// </summary>
public bool IsFPNumeral { get { return IsFP && IsNumeral; } }
/// <summary>
/// Indicates whether the term is a floating-point rounding mode numeral
/// </summary>
public bool IsFPRMNumeral { get { return IsFPRM && IsNumeral; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven
/// </summary>
public bool IsFPRMRoundNearestTiesToEven{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway
/// </summary>
public bool IsFPRMRoundNearestTiesToAway{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardNegative
/// </summary>
public bool IsFPRMRoundTowardNegative{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardPositive
/// </summary>
public bool IsFPRMRoundTowardPositive{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardZero
/// </summary>
public bool IsFPRMRoundTowardZero{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven
/// </summary>
public bool IsFPRMExprRNE{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway
/// </summary>
public bool IsFPRMExprRNA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardNegative
/// </summary>
public bool IsFPRMExprRTN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardPositive
/// </summary>
public bool IsFPRMExprRTP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardZero
/// </summary>
public bool IsFPRMExprRTZ { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } }
/// <summary>
/// Indicates whether the term is a floating-point rounding mode numeral
/// </summary>
public bool IsFPRMExpr {
get {
return IsApp &&
(FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY||
FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN ||
FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE ||
FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE ||
FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO);
}
}
/// <summary>
/// Indicates whether the term is a floating-point +oo
/// </summary>
public bool IsFPPlusInfinity{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_PLUS_INF; } }
/// <summary>
/// Indicates whether the term is a floating-point -oo
/// </summary>
public bool IsFPMinusInfinity{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_MINUS_INF; } }
/// <summary>
/// Indicates whether the term is a floating-point NaN
/// </summary>
public bool IsFPNaN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_NAN; } }
/// <summary>
/// Indicates whether the term is a floating-point +zero
/// </summary>
public bool IsFPPlusZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_PLUS_ZERO; } }
/// <summary>
/// Indicates whether the term is a floating-point -zero
/// </summary>
public bool IsFPMinusZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_MINUS_ZERO; } }
/// <summary>
/// Indicates whether the term is a floating-point addition term
/// </summary>
public bool IsFPAdd { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_ADD; } }
/// <summary>
/// Indicates whether the term is a floating-point subtraction term
/// </summary>
public bool IsFPSub { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_SUB; } }
/// <summary>
/// Indicates whether the term is a floating-point negation term
/// </summary>
public bool IsFPNeg { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_NEG; } }
/// <summary>
/// Indicates whether the term is a floating-point multiplication term
/// </summary>
public bool IsFPMul { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_MUL; } }
/// <summary>
/// Indicates whether the term is a floating-point divison term
/// </summary>
public bool IsFPDiv { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_DIV; } }
/// <summary>
/// Indicates whether the term is a floating-point remainder term
/// </summary>
public bool IsFPRem { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_REM; } }
/// <summary>
/// Indicates whether the term is a floating-point term absolute value term
/// </summary>
public bool IsFPAbs { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_ABS; } }
/// <summary>
/// Indicates whether the term is a floating-point minimum term
/// </summary>
public bool IsFPMin { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_MIN; } }
/// <summary>
/// Indicates whether the term is a floating-point maximum term
/// </summary>
public bool IsFPMax { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_MAX; } }
/// <summary>
/// Indicates whether the term is a floating-point fused multiply-add term
/// </summary>
public bool IsFPFMA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_FMA; } }
/// <summary>
/// Indicates whether the term is a floating-point square root term
/// </summary>
public bool IsFPSqrt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_SQRT; } }
/// <summary>
/// Indicates whether the term is a floating-point roundToIntegral term
/// </summary>
public bool IsFPRoundToIntegral { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_ROUND_TO_INTEGRAL; } }
/// <summary>
/// Indicates whether the term is a floating-point equality term
/// </summary>
public bool IsFPEq { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_EQ; } }
/// <summary>
/// Indicates whether the term is a floating-point less-than term
/// </summary>
public bool IsFPLt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_LT; } }
/// <summary>
/// Indicates whether the term is a floating-point greater-than term
/// </summary>
public bool IsFPGt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_GT; } }
/// <summary>
/// Indicates whether the term is a floating-point less-than or equal term
/// </summary>
public bool IsFPLe { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_LE; } }
/// <summary>
/// Indicates whether the term is a floating-point greater-than or erqual term
/// </summary>
public bool IsFPGe { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_GE; } }
/// <summary>
/// Indicates whether the term is a floating-point isNaN predicate term
/// </summary>
public bool IsFPisNaN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_NAN; } }
/// <summary>
/// Indicates whether the term is a floating-point isInf predicate term
/// </summary>
public bool IsFPisInf { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_INF; } }
/// <summary>
/// Indicates whether the term is a floating-point isZero predicate term
/// </summary>
public bool IsFPisZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_ZERO; } }
/// <summary>
/// Indicates whether the term is a floating-point isNormal term
/// </summary>
public bool IsFPisNormal { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_NORMAL; } }
/// <summary>
/// Indicates whether the term is a floating-point isSubnormal predicate term
/// </summary>
public bool IsFPisSubnormal { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_SUBNORMAL; } }
/// <summary>
/// Indicates whether the term is a floating-point isNegative predicate term
/// </summary>
public bool IsFPisNegative { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_NEGATIVE; } }
/// <summary>
/// Indicates whether the term is a floating-point isPositive predicate term
/// </summary>
public bool IsFPisPositive { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_POSITIVE; } }
/// <summary>
/// Indicates whether the term is a floating-point constructor term
/// </summary>
public bool IsFPFP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_FP; } }
/// <summary>
/// Indicates whether the term is a floating-point conversion term
/// </summary>
public bool IsFPToFp { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_FP; } }
/// <summary>
/// Indicates whether the term is a floating-point conversion from unsigned bit-vector term
/// </summary>
public bool IsFPToFpUnsigned { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_FP_UNSIGNED; } }
/// <summary>
/// Indicates whether the term is a floating-point conversion to unsigned bit-vector term
/// </summary>
public bool IsFPToUBV { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_UBV; } }
/// <summary>
/// Indicates whether the term is a floating-point conversion to signed bit-vector term
/// </summary>
public bool IsFPToSBV { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_SBV; } }
/// <summary>
/// Indicates whether the term is a floating-point conversion to real term
/// </summary>
public bool IsFPToReal { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_REAL; } }
/// <summary>
/// Indicates whether the term is a floating-point conversion to IEEE-754 bit-vector term
/// </summary>
public bool IsFPToIEEEBV { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_IEEE_BV; } }
#endregion
#endregion
@ -1489,10 +1764,6 @@ namespace Microsoft.Z3
/// <summary>
/// Constructor for Expr
/// </summary>
internal protected Expr(Context ctx) : base(ctx) { Contract.Requires(ctx != null); }
/// <summary>
/// Constructor for Expr
/// </summary>
internal protected Expr(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); }
#if DEBUG
@ -1541,7 +1812,9 @@ namespace Microsoft.Z3
{
case Z3_sort_kind.Z3_INT_SORT: return new IntNum(ctx, obj);
case Z3_sort_kind.Z3_REAL_SORT: return new RatNum(ctx, obj);
case Z3_sort_kind.Z3_BV_SORT: return new BitVecNum(ctx, obj);
case Z3_sort_kind.Z3_BV_SORT: return new BitVecNum(ctx, obj);
case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPNum(ctx, obj);
case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMNum(ctx, obj);
}
}
@ -1552,7 +1825,9 @@ namespace Microsoft.Z3
case Z3_sort_kind.Z3_REAL_SORT: return new RealExpr(ctx, obj);
case Z3_sort_kind.Z3_BV_SORT: return new BitVecExpr(ctx, obj);
case Z3_sort_kind.Z3_ARRAY_SORT: return new ArrayExpr(ctx, obj);
case Z3_sort_kind.Z3_DATATYPE_SORT: return new DatatypeExpr(ctx, obj);
case Z3_sort_kind.Z3_DATATYPE_SORT: return new DatatypeExpr(ctx, obj);
case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPExpr(ctx, obj);
case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMExpr(ctx, obj);
}
return new Expr(ctx, obj);

52
src/api/dotnet/FPExpr.cs Normal file
View file

@ -0,0 +1,52 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPExpr.cs
Abstract:
Z3 Managed API: Floating Point Expressions
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;
namespace Microsoft.Z3
{
/// <summary>
/// FloatingPoint Expressions
/// </summary>
public class FPExpr : Expr
{
/// <summary>
/// The number of exponent bits.
/// </summary>
public uint EBits { get { return ((FPSort)Sort).EBits; } }
/// <summary>
/// The number of significand bits.
/// </summary>
public uint SBits { get { return ((FPSort)Sort).EBits; } }
#region Internal
/// <summary> Constructor for FPExpr </summary>
internal FPExpr(Context ctx, IntPtr obj)
: base(ctx, obj)
{
Contract.Requires(ctx != null);
}
#endregion
}
}

103
src/api/dotnet/FPNum.cs Normal file
View file

@ -0,0 +1,103 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPNum.cs
Abstract:
Z3 Managed API: Floating Point Numerals
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
using System;
using System.Diagnostics.Contracts;
namespace Microsoft.Z3
{
/// <summary>
/// FloatiungPoint Numerals
/// </summary>
[ContractVerification(true)]
public class FPNum : FPExpr
{
/// <summary>
/// Retrieves the sign of a floating-point literal
/// </summary>
/// <remarks>
/// Remarks: returns true if the numeral is negative
/// </remarks>
public bool Sign
{
get
{
int res = 0;
if (Native.Z3_fpa_get_numeral_sign(Context.nCtx, NativeObject, ref res) == 0)
throw new Z3Exception("Sign is not a Boolean value");
return res != 0;
}
}
/// <summary>
/// The significand value of a floating-point numeral as a string
/// </summary>
/// <remarks>
/// The significand s is always 0 &lt; s &lt; 2.0; the resulting string is long
/// enough to represent the real significand precisely.
/// </remarks>
public string Significand
{
get
{
return Native.Z3_fpa_get_numeral_significand_string(Context.nCtx, NativeObject);
}
}
/// <summary>
/// Return the exponent value of a floating-point numeral as a string
/// </summary>
public string Exponent
{
get
{
return Native.Z3_fpa_get_numeral_exponent_string(Context.nCtx, NativeObject);
}
}
/// <summary>
/// Return the exponent value of a floating-point numeral as a signed 64-bit integer
/// </summary>
public Int64 ExponentInt64
{
get
{
Int64 result = 0;
if (Native.Z3_fpa_get_numeral_exponent_int64(Context.nCtx, NativeObject, ref result) == 0)
throw new Z3Exception("Exponent is not a 64 bit integer");
return result;
}
}
#region Internal
internal FPNum(Context ctx, IntPtr obj)
: base(ctx, obj)
{
Contract.Requires(ctx != null);
}
#endregion
/// <summary>
/// Returns a string representation of the numeral.
/// </summary>
public override string ToString()
{
return Native.Z3_get_numeral_string(Context.nCtx, NativeObject);
}
}
}

View file

@ -0,0 +1,42 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPRMExpr.cs
Abstract:
Z3 Managed API: Floating Point Expressions over Rounding Modes
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;
namespace Microsoft.Z3
{
/// <summary>
/// FloatingPoint RoundingMode Expressions
/// </summary>
public class FPRMExpr : Expr
{
#region Internal
/// <summary> Constructor for FPRMExpr </summary>
internal FPRMExpr(Context ctx, IntPtr obj)
: base(ctx, obj)
{
Contract.Requires(ctx != null);
}
#endregion
}
}

100
src/api/dotnet/FPRMNum.cs Normal file
View file

@ -0,0 +1,100 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPRMExpr.cs
Abstract:
Z3 Managed API: Floating Point Rounding Mode Numerals
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;
namespace Microsoft.Z3
{
/// <summary>
/// Floating-point rounding mode numerals
/// </summary>
public class FPRMNum : FPRMExpr
{
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven
/// </summary>
public bool isRoundNearestTiesToEven { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven
/// </summary>
public bool isRNE { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway
/// </summary>
public bool isRoundNearestTiesToAway { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway
/// </summary>
public bool isRNA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardPositive
/// </summary>
public bool isRoundTowardPositive { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardPositive
/// </summary>
public bool isRTP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardNegative
/// </summary>
public bool isRoundTowardNegative { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardNegative
/// </summary>
public bool isRTN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardZero
/// </summary>
public bool isRoundTowardZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } }
/// <summary>
/// Indicates whether the term is the floating-point rounding numeral roundTowardZero
/// </summary>
public bool isRTZ { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } }
/// <summary>
/// Returns a string representation of the numeral.
/// </summary>
public override string ToString()
{
return Native.Z3_get_numeral_string(Context.nCtx, NativeObject);
}
#region Internal
/// <summary> Constructor for FPRMNum </summary>
internal FPRMNum(Context ctx, IntPtr obj)
: base(ctx, obj)
{
Contract.Requires(ctx != null);
}
#endregion
}
}

View file

@ -0,0 +1,43 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPRMSort.cs
Abstract:
Z3 Managed API: Rounding Mode Sort
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
using System;
using System.Diagnostics.Contracts;
namespace Microsoft.Z3
{
/// <summary>
/// The FloatingPoint RoundingMode sort
/// </summary>
public class FPRMSort : Sort
{
#region Internal
internal FPRMSort(Context ctx, IntPtr obj)
: base(ctx, obj)
{
Contract.Requires(ctx != null);
}
internal FPRMSort(Context ctx)
: base(ctx, Native.Z3_mk_fpa_rounding_mode_sort(ctx.nCtx))
{
Contract.Requires(ctx != null);
}
#endregion
}
}

52
src/api/dotnet/FPSort.cs Normal file
View file

@ -0,0 +1,52 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPSort.cs
Abstract:
Z3 Managed API: Floating Point Sorts
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
using System;
using System.Diagnostics.Contracts;
namespace Microsoft.Z3
{
/// <summary>
/// FloatingPoint sort
/// </summary>
public class FPSort : Sort
{
/// <summary>
/// The number of exponent bits.
/// </summary>
public uint EBits { get { return Native.Z3_fpa_get_ebits(Context.nCtx, NativeObject); } }
/// <summary>
/// The number of significand bits.
/// </summary>
public uint SBits { get { return Native.Z3_fpa_get_sbits(Context.nCtx, NativeObject); } }
#region Internal
internal FPSort(Context ctx, IntPtr obj)
: base(ctx, obj)
{
Contract.Requires(ctx != null);
}
internal FPSort(Context ctx, uint ebits, uint sbits)
: base(ctx, Native.Z3_mk_fpa_sort(ctx.nCtx, ebits, sbits))
{
Contract.Requires(ctx != null);
}
#endregion
}
}

View file

@ -1,5 +1,5 @@
/*++
Copyright (<c>) 2012 Microsoft Corporation
Copyright (c) 2012 Microsoft Corporation
Module Name:
@ -32,11 +32,6 @@ namespace Microsoft.Z3
{
#region Internal
/// <summary> Constructor for IntExpr </summary>
internal protected IntExpr(Context ctx)
: base(ctx)
{
Contract.Requires(ctx != null);
}
internal IntExpr(Context ctx, IntPtr obj)
: base(ctx, obj)
{

View file

@ -113,9 +113,9 @@ namespace Microsoft.Z3
}
}
#region Internal
#region Internal
internal ListSort(Context ctx, Symbol name, Sort elemSort)
: base(ctx)
: base(ctx, IntPtr.Zero)
{
Contract.Requires(ctx != null);
Contract.Requires(name != null);

View file

@ -342,6 +342,12 @@
<Compile Include="ConstructorList.cs" />
<Compile Include="DatatypeExpr.cs" />
<Compile Include="DatatypeSort.cs" />
<Compile Include="FPExpr.cs" />
<Compile Include="FPNum.cs" />
<Compile Include="FPRMExpr.cs" />
<Compile Include="FPRMNum.cs" />
<Compile Include="FPRMSort.cs" />
<Compile Include="FPSort.cs" />
<Compile Include="Global.cs" />
<Compile Include="IDecRefQueue.cs" />
<Compile Include="Enumerations.cs" />

View file

@ -160,7 +160,7 @@ namespace Microsoft.Z3
#region Internal
[ContractVerification(false)] // F: Clousot ForAll decompilation gets confused below. Setting verification off until I fixed the bug
internal Quantifier(Context ctx, bool isForall, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
: base(ctx)
: base(ctx, IntPtr.Zero)
{
Contract.Requires(ctx != null);
Contract.Requires(sorts != null);
@ -203,7 +203,7 @@ namespace Microsoft.Z3
[ContractVerification(false)] // F: Clousot ForAll decompilation gets confused below. Setting verification off until I fixed the bug
internal Quantifier(Context ctx, bool isForall, Expr[] bound, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
: base(ctx)
: base(ctx, IntPtr.Zero)
{
Contract.Requires(ctx != null);
Contract.Requires(body != null);

View file

@ -32,11 +32,6 @@ namespace Microsoft.Z3
{
#region Internal
/// <summary> Constructor for RealExpr </summary>
internal protected RealExpr(Context ctx)
: base(ctx)
{
Contract.Requires(ctx != null);
}
internal RealExpr(Context ctx, IntPtr obj)
: base(ctx, obj)
{

View file

@ -116,8 +116,7 @@ namespace Microsoft.Z3
#region Internal
/// <summary>
/// Sort constructor
/// </summary>
internal protected Sort(Context ctx) : base(ctx) { Contract.Requires(ctx != null); }
/// </summary>
internal Sort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); }
#if DEBUG
@ -146,6 +145,8 @@ namespace Microsoft.Z3
case Z3_sort_kind.Z3_UNINTERPRETED_SORT: return new UninterpretedSort(ctx, obj);
case Z3_sort_kind.Z3_FINITE_DOMAIN_SORT: return new FiniteDomainSort(ctx, obj);
case Z3_sort_kind.Z3_RELATION_SORT: return new RelationSort(ctx, obj);
case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPSort(ctx, obj);
case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMSort(ctx, obj);
default:
throw new Z3Exception("Unknown sort kind");
}

View file

@ -68,7 +68,7 @@ namespace Microsoft.Z3
#region Internal
internal TupleSort(Context ctx, Symbol name, uint numFields, Symbol[] fieldNames, Sort[] fieldSorts)
: base(ctx)
: base(ctx, IntPtr.Zero)
{
Contract.Requires(ctx != null);
Contract.Requires(name != null);

View file

@ -25,11 +25,6 @@ public class ArithExpr extends Expr
/**
* Constructor for ArithExpr
**/
protected ArithExpr(Context ctx)
{
super(ctx);
}
ArithExpr(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);

View file

@ -26,11 +26,6 @@ public class ArrayExpr extends Expr
/**
* Constructor for ArrayExpr
**/
protected ArrayExpr(Context ctx)
{
super(ctx);
}
ArrayExpr(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);

View file

@ -37,11 +37,6 @@ public class BitVecExpr extends Expr
/**
* Constructor for BitVecExpr
**/
BitVecExpr(Context ctx)
{
super(ctx);
}
BitVecExpr(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);

View file

@ -25,11 +25,6 @@ public class DatatypeExpr extends Expr
/**
* Constructor for DatatypeExpr
**/
protected DatatypeExpr(Context ctx)
{
super(ctx);
}
DatatypeExpr(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);

View file

@ -64,7 +64,7 @@ public class EnumSort extends Sort
EnumSort(Context ctx, Symbol name, Symbol[] enumNames) throws Z3Exception
{
super(ctx);
super(ctx, 0);
int n = enumNames.length;
long[] n_constdecls = new long[n];

41
src/api/java/FPExpr.java Normal file
View file

@ -0,0 +1,41 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPExpr.java
Abstract:
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
package com.microsoft.z3;
/**
* FloatingPoint Expressions
*/
public class FPExpr extends Expr
{
/**
* The number of exponent bits.
* @throws Z3Exception
*/
public int getEBits() throws Z3Exception { return ((FPSort)getSort()).getEBits(); }
/**
* The number of significand bits.
* @throws Z3Exception
*/
public int getSBits() throws Z3Exception { return ((FPSort)getSort()).getSBits(); }
public FPExpr(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);
}
}

86
src/api/java/FPNum.java Normal file
View file

@ -0,0 +1,86 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPNum.java
Abstract:
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
package com.microsoft.z3;
/**
* FloatingPoint Numerals
*/
public class FPNum extends FPExpr
{
/**
* Retrieves the sign of a floating-point literal
* Remarks: returns true if the numeral is negative
* @throws Z3Exception
*/
public boolean getSign() throws Z3Exception {
Native.IntPtr res = new Native.IntPtr();
if (Native.fpaGetNumeralSign(getContext().nCtx(), getNativeObject(), res) ^ true)
throw new Z3Exception("Sign is not a Boolean value");
return res.value != 0;
}
/**
* 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
* enough to represent the real significand precisely.
* @throws Z3Exception
**/
public String getSignificand() throws Z3Exception {
return Native.fpaGetNumeralSignificandString(getContext().nCtx(), getNativeObject());
}
/**
* Return the exponent value of a floating-point numeral as a string
* @throws Z3Exception
*/
public String getExponent() throws Z3Exception {
return Native.fpaGetNumeralExponentString(getContext().nCtx(), getNativeObject());
}
/**
* Return the exponent value of a floating-point numeral as a signed 64-bit integer
* @throws Z3Exception
*/
public long getExponentInt64() throws Z3Exception {
Native.LongPtr res = new Native.LongPtr();
if (Native.fpaGetNumeralExponentInt64(getContext().nCtx(), getNativeObject(), res) ^ true)
throw new Z3Exception("Exponent is not a 64 bit integer");
return res.value;
}
public FPNum(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);
}
/**
* Returns a string representation of the numeral.
*/
public String toString()
{
try
{
return Native.getNumeralString(getContext().nCtx(), getNativeObject());
} catch (Z3Exception e)
{
return "Z3Exception: " + e.getMessage();
}
}
}

View file

@ -0,0 +1,29 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPRMExpr.java
Abstract:
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
package com.microsoft.z3;
/**
* FloatingPoint RoundingMode Expressions
*/
public class FPRMExpr extends Expr
{
public FPRMExpr(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);
}
}

90
src/api/java/FPRMNum.java Normal file
View file

@ -0,0 +1,90 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPRMNum.java
Abstract:
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
package com.microsoft.z3;
import com.microsoft.z3.enumerations.Z3_decl_kind;
/**
* FloatingPoint RoundingMode Numerals
*/
public class FPRMNum extends FPRMExpr {
/**
* Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven
* @throws Z3Exception
* **/
public boolean isRoundNearestTiesToEven() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; }
/**
* Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven
* @throws Z3Exception
*/
public boolean isRNE() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; }
/**
* Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway
* @throws Z3Exception
*/
public boolean isRoundNearestTiesToAway() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; }
/**
* Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway
* @throws Z3Exception
*/
public boolean isRNA() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; }
/**
* Indicates whether the term is the floating-point rounding numeral roundTowardPositive
* @throws Z3Exception
*/
public boolean isRoundTowardPositive() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; }
/**
* Indicates whether the term is the floating-point rounding numeral roundTowardPositive
* @throws Z3Exception
*/
public boolean isRTP() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; }
/**
* Indicates whether the term is the floating-point rounding numeral roundTowardNegative
* @throws Z3Exception
*/
public boolean isRoundTowardNegative() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; }
/**
* Indicates whether the term is the floating-point rounding numeral roundTowardNegative
* @throws Z3Exception
*/
public boolean isRTN() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; }
/**
* Indicates whether the term is the floating-point rounding numeral roundTowardZero
* @throws Z3Exception
*/
public boolean isRoundTowardZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; }
/**
* Indicates whether the term is the floating-point rounding numeral roundTowardZero
* @throws Z3Exception
*/
public boolean isRTZ() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; }
public FPRMNum(Context ctx, long obj) throws Z3Exception {
super(ctx, obj);
}
}

View file

@ -0,0 +1,35 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPRMExpr.java
Abstract:
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
package com.microsoft.z3;
/**
* The FloatingPoint RoundingMode sort
**/
public class FPRMSort extends Sort
{
public FPRMSort(Context ctx) throws Z3Exception
{
super(ctx, Native.mkFpaRoundingModeSort(ctx.nCtx()));
}
public FPRMSort(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);
}
}

49
src/api/java/FPSort.java Normal file
View file

@ -0,0 +1,49 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
FPSort.java
Abstract:
Author:
Christoph Wintersteiger (cwinter) 2013-06-10
Notes:
--*/
package com.microsoft.z3;
/**
* A FloatingPoint sort
**/
public class FPSort extends Sort
{
public FPSort(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);
}
public FPSort(Context ctx, int ebits, int sbits) throws Z3Exception
{
super(ctx, Native.mkFpaSort(ctx.nCtx(), ebits, sbits));
}
/**
* The number of exponent bits.
*/
public int getEBits() throws Z3Exception {
return Native.fpaGetEbits(getContext().nCtx(), getNativeObject());
}
/**
* The number of significand bits.
*/
public int getSBits() throws Z3Exception {
return Native.fpaGetEbits(getContext().nCtx(), getNativeObject());
}
}

View file

@ -26,11 +26,6 @@ public class IntExpr extends ArithExpr
* Constructor for IntExpr
* @throws Z3Exception on error
**/
protected IntExpr(Context ctx) throws Z3Exception
{
super(ctx);
}
IntExpr(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);

View file

@ -88,7 +88,7 @@ public class ListSort extends Sort
ListSort(Context ctx, Symbol name, Sort elemSort) throws Z3Exception
{
super(ctx);
super(ctx, 0);
Native.LongPtr inil = new Native.LongPtr(), iisnil = new Native.LongPtr();
Native.LongPtr icons = new Native.LongPtr(), iiscons = new Native.LongPtr();

View file

@ -149,7 +149,7 @@ public class Quantifier extends BoolExpr
Expr body, int weight, Pattern[] patterns, Expr[] noPatterns,
Symbol quantifierID, Symbol skolemID) throws Z3Exception
{
super(ctx);
super(ctx, 0);
getContext().checkContextMatch(patterns);
getContext().checkContextMatch(noPatterns);
@ -185,7 +185,7 @@ public class Quantifier extends BoolExpr
int weight, Pattern[] patterns, Expr[] noPatterns,
Symbol quantifierID, Symbol skolemID) throws Z3Exception
{
super(ctx);
super(ctx, 0);
getContext().checkContextMatch(noPatterns);
getContext().checkContextMatch(patterns);

View file

@ -25,11 +25,6 @@ public class RealExpr extends ArithExpr
/**
* Constructor for RealExpr
**/
protected RealExpr(Context ctx)
{
super(ctx);
}
RealExpr(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);

View file

@ -98,18 +98,9 @@ public class Sort extends AST
/**
* Sort constructor
**/
protected Sort(Context ctx) throws Z3Exception
{
super(ctx);
{
}
}
Sort(Context ctx, long obj) throws Z3Exception
{
super(ctx, obj);
{
}
}
void checkNativeObject(long obj) throws Z3Exception
@ -143,6 +134,10 @@ public class Sort extends AST
return new FiniteDomainSort(ctx, obj);
case Z3_RELATION_SORT:
return new RelationSort(ctx, obj);
case Z3_FLOATING_POINT_SORT:
return new FPSort(ctx, obj);
case Z3_ROUNDING_MODE_SORT:
return new FPRMSort(ctx, obj);
default:
throw new Z3Exception("Unknown sort kind");
}

View file

@ -59,7 +59,7 @@ public class TupleSort extends Sort
TupleSort(Context ctx, Symbol name, int numFields, Symbol[] fieldNames,
Sort[] fieldSorts) throws Z3Exception
{
super(ctx);
super(ctx, 0);
Native.LongPtr t = new Native.LongPtr();
setNativeObject(Native.mkTupleSort(ctx.nCtx(), name.getNativeObject(),

View file

@ -555,6 +555,10 @@ def _to_sort_ref(s, ctx):
return ArraySortRef(s, ctx)
elif k == Z3_DATATYPE_SORT:
return DatatypeSortRef(s, ctx)
elif k == Z3_FLOATING_POINT_SORT:
return FPSortRef(s, ctx)
elif k == Z3_ROUNDING_MODE_SORT:
return FPRMSortRef(s, ctx)
return SortRef(s, ctx)
def _sort(ctx, a):
@ -899,6 +903,13 @@ def _to_expr_ref(a, ctx):
return ArrayRef(a, ctx)
if sk == Z3_DATATYPE_SORT:
return DatatypeRef(a, ctx)
if sk == Z3_FLOATING_POINT_SORT:
if k == Z3_APP_AST and _is_numeral(ctx, a):
return FPNumRef(a, ctx)
else:
return FPRef(a, ctx)
if sk == Z3_ROUNDING_MODE_SORT:
return FPRMRef(a, ctx)
return ExprRef(a, ctx)
def _coerce_expr_merge(s, a):
@ -7429,3 +7440,901 @@ def sequence_interpolant(v,p=None,ctx=None):
f = And(Interpolant(f),v[i])
return tree_interpolant(f,p,ctx)
#########################################
#
# Floating-Point Arithmetic
#
#########################################
# Global default rounding mode
_dflt_rounding_mode = Z3_OP_FPA_RM_TOWARD_ZERO
_dflt_fpsort_ebits = 11
_dflt_fpsort_sbits = 53
def get_default_rounding_mode(ctx=None):
"""Retrieves the global default rounding mode."""
global _dflt_rounding_mode
if _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_ZERO:
return RTZ(ctx)
elif _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_NEGATIVE:
return RTN(ctx)
elif _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_POSITIVE:
return RTP(ctx)
elif _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN:
return RNE(ctx)
elif _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY:
return RNA(ctx)
def set_default_rounding_mode(rm, ctx=None):
global _dflt_rounding_mode
if is_fprm_value(rm):
_dflt_rounding_mode = rm.decl().kind()
else:
_z3_assert(_dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_ZERO or
_dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_NEGATIVE or
_dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_POSITIVE or
_dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN or
_dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY,
"illegal rounding mode")
_dflt_rounding_mode = rm
def get_default_fp_sort(ctx=None):
return FPSort(_dflt_fpsort_ebits, _dflt_fpsort_sbits, ctx)
def set_default_fp_sort(ebits, sbits, ctx=None):
global _dflt_fpsort_ebits
global _dflt_fpsort_sbits
_dflt_fpsort_ebits = ebits
_dflt_fpsort_sbits = sbits
def _dflt_rm(ctx=None):
return get_default_rounding_mode(ctx)
def _dflt_fps(ctx=None):
return get_default_fp_sort(ctx)
### FP Sorts
class FPSortRef(SortRef):
"""Floating-point sort."""
def ebits(self):
"""Retrieves the number of bits reserved for the exponent in the FloatingPoint sort `self`.
>>> b = FPSort(8, 24)
>>> b.ebits()
8
"""
return int(Z3_fpa_get_ebits(self.ctx_ref(), self.ast))
def sbits(self):
"""Retrieves the number of bits reserved for the exponent in the FloatingPoint sort `self`.
>>> b = FloatingPointSort(8, 24)
>>> b.sbits()
24
"""
return int(Z3_fpa_get_sbits(self.ctx_ref(), self.ast))
def cast(self, val):
"""Try to cast `val` as a Floating-point expression
>>> b = FPSort(8, 24)
>>> b.cast(1.0)
1.0
>>> b.cast(1.0).sexpr()
'1.0'
"""
if is_expr(val):
if __debug__:
_z3_assert(self.ctx == val.ctx, "Context mismatch")
return val
else:
return FPVal(val, None, self, self.ctx)
def Float16(ctx=None):
"""Floating-point 16-bit (half) sort."""
ctx = _get_ctx(ctx)
return FPSortRef(Z3_mk_fpa_sort_16(ctx.ref()), ctx)
def FloatHalf(ctx=None):
"""Floating-point 16-bit (half) sort."""
ctx = _get_ctx(ctx)
return FPSortRef(Z3_mk_fpa_sort_half(ctx.ref()), ctx)
def Float32(ctx=None):
"""Floating-point 32-bit (single) sort."""
ctx = _get_ctx(ctx)
return FPSortRef(Z3_mk_fpa_sort_32(ctx.ref()), ctx)
def FloatSingle(ctx=None):
"""Floating-point 32-bit (single) sort."""
ctx = _get_ctx(ctx)
return FPSortRef(Z3_mk_fpa_sort_single(ctx.ref()), ctx)
def Float64(ctx=None):
"""Floating-point 64-bit (double) sort."""
ctx = _get_ctx(ctx)
return FPSortRef(Z3_mk_fpa_sort_64(ctx.ref()), ctx)
def FloatSingle(ctx=None):
"""Floating-point 64-bit (double) sort."""
ctx = _get_ctx(ctx)
return FPSortRef(Z3_mk_fpa_sort_double(ctx.ref()), ctx)
def Float128(ctx=None):
"""Floating-point 128-bit (quadruple) sort."""
ctx = _get_ctx(ctx)
return FPSortRef(Z3_mk_fpa_sort_128(ctx.ref()), ctx)
def FloatSingle(ctx=None):
"""Floating-point 128-bit (quadruple) sort."""
ctx = _get_ctx(ctx)
return FPSortRef(Z3_mk_fpa_sort_quadruple(ctx.ref()), ctx)
class FPRMSortRef(SortRef):
""""Floating-point rounding mode sort."""
def is_fp_sort(s):
"""Return True if `s` is a Z3 floating-point sort.
>>> is_fp_sort(FloatingPointSort(8, 24))
True
>>> is_fp_sort(IntSort())
False
"""
return isinstance(s, FPSortRef)
def is_fprm_sort(s):
"""Return True if `s` is a Z3 floating-point rounding mode sort.
>>> is_fprm_sort(FPSort(8, 24))
False
>>> is_fprm_sort()
False
"""
return isinstance(s, FPSortRef)
### FP Expressions
class FPRef(ExprRef):
"""Floating-point expressions."""
def sort(self):
"""Return the sort of the floating-point expression `self`.
>>> x = FP('1.0', FPSort(8, 24))
>>> x.sort()
(_ FloatingPoint 8 24)
>>> x.sort() == FloatingPointSort(8, 24)
True
"""
return FPSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx)
def ebits(self):
"""Retrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`.
>>> b = FloatingPointSort(8, 24)
>>> b.ebits()
8
"""
return self.sort().ebits();
def sbits(self):
"""Retrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`.
>>> b = FloatingPointSort(8, 24)
>>> b.sbits()
24
"""
return self.sort().sbits();
def as_string(self):
"""Return a Z3 floating point expression as a Python string."""
return Z3_ast_to_string(self.ctx_ref(), self.as_ast())
def __le__(self, other):
return fpLEQ(self, other)
def __lt__(self, other):
return fpLEQ(self, other)
def __ge__(self, other):
return fpGEQ(self, other)
def __gt__(self, other):
return fpGT(self, other)
def __ne__(self, other):
return fpNEQ(self, other)
def __add__(self, other):
"""Create the Z3 expression `self + other`.
>>> x = FP('x', 8, 24)
>>> y = FP('y', 8, 24)
>>> x + y
x + y
>>> (x + y).sort()
FloatingPoint(8 24)
"""
a, b = z3._coerce_exprs(self, other)
return fpAdd(_dflt_rm(), self, other)
def __radd__(self, other):
"""Create the Z3 expression `other + self`.
>>> x = FP('x', FPSort(8, 24))
>>> 10 + x
10 + x
"""
a, b = _coerce_exprs(self, other)
return fpAdd(_dflt_rm(), other, self)
def __sub__(self, other):
"""Create the Z3 expression `self - other`.
>>> x = FP('x', 8, 24)
>>> y = FP('y', 8, 24)
>>> x - y
x - y
>>> (x - y).sort()
FloatingPoint(8 24)
"""
a, b = z3._coerce_exprs(self, other)
return fpSub(_dflt_rm(), self, other)
def __rsub__(self, other):
"""Create the Z3 expression `other - self`.
>>> x = FP('x', FPSort(8, 24))
>>> 10 - x
10 - x
"""
a, b = _coerce_exprs(self, other)
return fpSub(_dflt_rm(), other, self)
def __mul__(self, other):
"""Create the Z3 expression `self * other`.
>>> x = FP('x', 8, 24)
>>> y = FP('y', 8, 24)
>>> x * y
x * y
>>> (x * y).sort()
FloatingPoint(8 24)
"""
a, b = z3._coerce_exprs(self, other)
return fpMul(_dflt_rm(), self, other)
def __rmul_(self, other):
"""Create the Z3 expression `other * self`.
>>> x = FP('x', FPSort(8, 24))
>>> 10 * x
10 * x
"""
a, b = _coerce_exprs(self, other)
return fpMul(_dflt_rm(), other, self)
def __pos__(self):
"""Create the Z3 expression `+self`."""
return self
def __neg__(self):
"""Create the Z3 expression `-self`."""
return FPRef(fpNeg(self))
def __truediv__(self, other):
"""Create the Z3 expression division `self / other`."""
return self.__div__(other)
def __rtruediv__(self, other):
"""Create the Z3 expression division `other / self`."""
return self.__rdiv__(other)
def __mod__(self, other):
"""Create the Z3 expression mod `self % other`."""
return fpRem(self, other)
def __rmod__(self, other):
"""Create the Z3 expression mod `other % self`."""
return fpRem(other, self)
class FPRMRef(ExprRef):
"""Floating-point rounding mode expressions"""
def as_string(self):
"""Return a Z3 floating point expression as a Python string."""
return Z3_ast_to_string(self.ctx_ref(), self.as_ast())
def RoundNearestTiesToEven(ctx=None):
ctx = _get_ctx(ctx)
return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_even(ctx.ref()), ctx)
def RNE (ctx=None):
ctx = _get_ctx(ctx)
return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_even(ctx.ref()), ctx)
def RoundNearestTiesToAway(ctx=None):
ctx = _get_ctx(ctx)
return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_away(ctx.ref()), ctx)
def RNA (ctx=None):
ctx = _get_ctx(ctx)
return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_away(ctx.ref()), ctx)
def RoundTowardPositive(ctx=None):
ctx = _get_ctx(ctx)
return FPRMRef(Z3_mk_fpa_round_toward_positive(ctx.ref()), ctx)
def RTP(ctx=None):
ctx = _get_ctx(ctx)
return FPRMRef(Z3_mk_fpa_round_toward_positive(ctx.ref()), ctx)
def RoundTowardNegative(ctx=None):
ctx = _get_ctx(ctx)
return FPRMRef(Z3_mk_fpa_round_toward_negative(ctx.ref()), ctx)
def RTN(ctx=None):
ctx = _get_ctx(ctx)
return FPRMRef(Z3_mk_fpa_round_toward_negative(ctx.ref()), ctx)
def RoundTowardZero(ctx=None):
ctx = _get_ctx(ctx)
return FPRMRef(Z3_mk_fpa_round_toward_zero(ctx.ref()), ctx)
def RTZ(ctx=None):
ctx = _get_ctx(ctx)
return FPRMRef(Z3_mk_fpa_round_toward_zero(ctx.ref()), ctx)
def is_fprm(a):
"""Return `True` if `a` is a Z3 floating-point rounding mode expression.
>>> rm = ?
"""
return isinstance(a, FPRMRef)
def is_fprm_value(a):
"""Return `True` if `a` is a Z3 floating-point rounding mode numeral value."""
return is_fprm(a) and _is_numeral(a.ctx, a.ast)
### FP Numerals
class FPNumRef(FPRef):
def isNaN(self):
return self.decl().kind() == Z3_OP_FPA_NAN
def isInf(self):
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.num_args() == 3 and self.arg(0) == BitVecVal(1))
def _to_fpnum(num, ctx=None):
if isinstance(num, FPNum):
return num
else:
return FPNum(num, ctx)
def is_fp(a):
"""Return `True` if `a` is a Z3 floating-point expression.
>>> b = FP('b', FPSort(8, 24))
>>> is_fp(b)
True
>>> is_fp(b + 1.0)
True
>>> is_fp(Int('x'))
False
"""
return isinstance(a, FPRef)
def is_fp_value(a):
"""Return `True` if `a` is a Z3 floating-point numeral value.
>>> b = FP('b', FPSort(8, 24))
>>> is_fp_value(b)
False
>>> b = FPVal(1.0, FPSort(8, 24))
>>> b
1.0p0
>>> is_fp_value(b)
True
"""
return is_fp(a) and _is_numeral(a.ctx, a.ast)
def FPSort(ebits, sbits, ctx=None):
"""Return a Z3 floating-point sort of the given sizes. If `ctx=None`, then the global context is used.
>>> Single = FPSort(8, 24)
>>> Double = FPSort(11, 53)
>>> Single
(_ FloatingPoint 8 24)
>>> x = Const('x', Single)
>>> eq(x, FP('x', 8, 24))
True
"""
ctx = z3._get_ctx(ctx)
return FPSortRef(Z3_mk_fpa_sort(ctx.ref(), ebits, sbits), ctx)
def _to_float_str(val):
if isinstance(val, float):
return str(val)
elif isinstance(val, bool):
if val:
return "1.0"
else:
return "0.0"
elif _is_int(val):
return str(val)
elif isinstance(val, str):
return val
if __debug__:
_z3_assert(False, "Python value cannot be used as a double")
def fpNaN(s):
_z3_assert(isinstance(s, FPSortRef), "sort mismatch")
return FPNumRef(Z3_mk_fpa_nan(s.ctx_ref(), s.ast), s.ctx)
def fpPlusInfinity(s):
_z3_assert(isinstance(s, FPSortRef), "sort mismatch")
return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, False), s.ctx)
def fpMinusInfinity(s):
_z3_assert(isinstance(s, FPSortRef), "sort mismatch")
return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, True), s.ctx)
def fpInfinity(s, negative):
_z3_assert(isinstance(s, FPSortRef), "sort mismatch")
_z3_assert(isinstance(negative, bool), "expected Boolean flag")
return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, negative), s.ctx)
def fpPlusZero(s):
_z3_assert(isinstance(s, FPSortRef), "sort mismatch")
return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, False), s.ctx)
def fpMinusZero(s):
_z3_assert(isinstance(s, FPSortRef), "sort mismatch")
return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, True), s.ctx)
def fpZero(s, negative):
_z3_assert(isinstance(s, FPSortRef), "sort mismatch")
_z3_assert(isinstance(negative, bool), "expected Boolean flag")
return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, negative), s.ctx)
def FPVal(sig, exp=None, fps=None, ctx=None):
"""Return a floating-point value of value `val` and sort `fps`. If `ctx=None`, then the global context is used.
>>> v = FPVal(1.0, FPSort(8, 24)))
>>> v
1.0
>>> print("0x%.8x" % v.as_long())
0x0000000a
"""
ctx = _get_ctx(ctx)
if is_fp_sort(exp):
fps = exp
exp = None
elif fps == None:
fps = _dflt_fps(ctx)
_z3_assert(is_fp_sort(fps), "sort mismatch")
if exp == None:
exp = 0
val = _to_float_str(sig)
val = val + 'p'
val = val + _to_int_str(exp)
return FPNumRef(Z3_mk_numeral(ctx.ref(), val, fps.ast), ctx)
def FP(name, fpsort, ctx=None):
"""Return a floating-point constant named `name`.
`fpsort` is the floating-point sort.
If `ctx=None`, then the global context is used.
>>> x = FP('x', FPSort(8, 24))
>>> is_fp(x)
True
>>> x.ebits()
8
>>> x.sort()
(_ FloatingPoint 8 24)
>>> word = FPSort(8, 24)
>>> x2 = FP('x', word)
>>> eq(x, x2)
True
"""
ctx = fpsort.ctx
return FPRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), fpsort.ast), ctx)
def FPs(names, fpsort, ctx=None):
"""Return an array of floating-point constants.
>>> x, y, z = BitVecs('x y z', 16)
>>> x.size()
16
>>> x.sort()
BitVec(16)
>>> Sum(x, y, z)
0 + x + y + z
>>> Product(x, y, z)
1*x*y*z
>>> simplify(Product(x, y, z))
x*y*z
"""
ctx = z3._get_ctx(ctx)
if isinstance(names, str):
names = names.split(" ")
return [FP(name, fpsort, ctx) for name in names]
def fpAbs(a):
"""Create a Z3 floating-point absolute value expression.
>>> s = FPSort(8, 24)
>>> rm = FPRM.RNE
>>> x = FPVal(1.0, s)
>>> fpAbs(x)
1.0
>>> x = FPVal(-1.0, s)
>>> fpAbs(x)
1.0
>>> fpAbs(x).sort()
FloatingPoint(8, 24)
"""
if __debug__:
_z3_assert(is_fp(a), "First argument must be Z3 floating-point expression")
return FPRef(Z3_mk_fpa_abs(a.ctx_ref(), a.as_ast()), a.ctx)
def fpNeg(a):
"""Create a Z3 floating-point addition expression.
>>> s = FPSort(8, 24)
>>> rm = FPRM.RNE
>>> x = FP('x', s)
>>> y = FP('y', s)
fp.add(rm, x, y)
>>> fp.add(rm, x, y).sort()
FloatingPoint(8, 24)
"""
if __debug__:
_z3_assert(is_fp(a), "First argument must be Z3 floating-point expression")
return FPRef(Z3_mk_fpa_neg(a.ctx_ref(), a.as_ast()), a.ctx)
def fpAdd(rm, a, b):
"""Create a Z3 floating-point addition expression.
>>> s = FPSort(8, 24)
>>> rm = FPRM.RNE
>>> x = FP('x', s)
>>> y = FP('y', s)
fp.add(rm, x, y)
>>> fp.add(rm, x, y).sort()
FloatingPoint(8, 24)
"""
if __debug__:
_z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
_z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_add(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx)
def fpSub(rm, a, b):
"""Create a Z3 floating-point subtraction expression.
>>> s = FPSort(8, 24)
>>> rm = FPRM.RNE
>>> x = FP('x', s)
>>> y = FP('y', s)
fp.add(rm, x, y)
>>> fp.add(rm, x, y).sort()
FloatingPoint(8, 24)
"""
if __debug__:
_z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
_z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_sub(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx)
def fpMul(rm, a, b):
"""Create a Z3 floating-point multiplication expression.
>>> s = FPSort(8, 24)
>>> rm = FPRM.RNE
>>> x = FP('x', s)
>>> y = FP('y', s)
fp.add(rm, x, y)
>>> fp.add(rm, x, y).sort()
FloatingPoint(8, 24)
"""
if __debug__:
_z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
_z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_mul(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx)
def fpDiv(rm, a, b):
"""Create a Z3 floating-point divison expression.
>>> s = FPSort(8, 24)
>>> rm = FPRM.RNE
>>> x = FP('x', s)
>>> y = FP('y', s)
fpAdd(rm, x, y)
>>> fp.add(rm, x, y).sort()
FloatingPoint(8, 24)
"""
if __debug__:
_z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
_z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_div(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx)
def fpRem(a, b):
"""Create a Z3 floating-point remainder expression.
>>> s = FPSort(8, 24)
>>> rm = RNE()
>>> x = FP('x', s)
>>> y = FP('y', s)
fpRem(x, y)
>>> fpRem(rm, x, y).sort()
FloatingPoint(8, 24)
"""
if __debug__:
_z3_assert(is_fp(a) and is_fp(b), "Both arguments must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_rem(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
def fpMin(a, b):
"""Create a Z3 floating-point minimium expression.
>>> s = FPSort(8, 24)
>>> rm = RNE()
>>> x = FP('x', s)
>>> y = FP('y', s)
fpMin(x, y)
>>> fpMin(rm, x, y).sort()
FloatingPoint(8, 24)
"""
if __debug__:
_z3_assert(is_fp(a) and is_fp(b), "Both arguments must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_min(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
def fpMax(a, b):
"""Create a Z3 floating-point maximum expression.
>>> s = FPSort(8, 24)
>>> rm = RNE()
>>> x = FP('x', s)
>>> y = FP('y', s)
fpMin(x, y)
>>> fpMin(rm, x, y).sort()
FloatingPoint(8, 24)
"""
if __debug__:
_z3_assert(is_fp(a) and is_fp(b), "Both arguments must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_max(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
def fpFMA(rm, a, b, c):
"""Create a Z3 floating-point fused multiply-add expression.
"""
if __debug__:
_z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
_z3_assert(is_fp(a) and is_fp(b) and is_fp(c), "Second, third, and fourth argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_fma(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast(), c.as_ast()), rm.ctx)
def fpSqrt(rm, a):
"""Create a Z3 floating-point square root expression.
"""
if __debug__:
_z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
_z3_assert(is_fp(a), "Second argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_sqrt(rm.ctx_ref(), rm.as_ast(), a.as_ast()), rm.ctx)
def fpRoundToIntegral(rm, a):
"""Create a Z3 floating-point roundToIntegral expression.
"""
if __debug__:
_z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
_z3_assert(is_fp(a), "Second argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_round_to_integral(rm.ctx_ref(), rm.as_ast(), a.as_ast()), rm.ctx)
def fpIsNaN(a):
"""Create a Z3 floating-point isNaN expression.
"""
if __debug__:
_z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_is_nan(a.ctx_ref(), a.as_ast()), a.ctx)
def fpIsInfinite(a):
"""Create a Z3 floating-point isNaN expression.
"""
if __debug__:
_z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_is_infinite(a.ctx_ref(), a.as_ast()), a.ctx)
def fpIsZero(a):
"""Create a Z3 floating-point isNaN expression.
"""
if __debug__:
_z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_is_zero(a.ctx_ref(), a.as_ast()), a.ctx)
def fpIsNormal(a):
"""Create a Z3 floating-point isNaN expression.
"""
if __debug__:
_z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_is_normal(a.ctx_ref(), a.as_ast()), a.ctx)
def fpIsSubnormal(a):
"""Create a Z3 floating-point isNaN expression.
"""
if __debug__:
_z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_is_subnormal(a.ctx_ref(), a.as_ast()), a.ctx)
def fpIsNegative(a):
"""Create a Z3 floating-point isNaN expression.
"""
if __debug__:
_z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_is_negative(a.ctx_ref(), a.as_ast()), a.ctx)
def fpIsPositive(a):
"""Create a Z3 floating-point isNaN expression.
"""
if __debug__:
_z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions")
return FPRef(Z3_mk_fpa_is_positive(a.ctx_ref(), a.as_ast()), a.ctx)
def _check_fp_args(a, b):
if __debug__:
_z3_assert(is_fp(a) or is_fp(b), "At least one of the arguments must be a Z3 floating-point expression")
def fpLT(a, b):
"""Create the Z3 floating-point expression `other <= self`.
>>> x, y = FPs('x y', FPSort(8, 24))
>>> fpLT(x, y)
x <= y
>>> (x <= y).sexpr()
'?'
>>> fpLT(x, y).sexpr()
'?'
"""
_check_fp_args(a, b)
a, b = _coerce_exprs(a, b)
return BoolRef(Z3_mk_fpa_lt(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
def fpLEQ(a, b):
"""Create the Z3 floating-point expression `other <= self`.
>>> x, y = FPs('x y', FPSort(8, 24))
>>> fpLEQ(x, y)
x <= y
>>> (x <= y).sexpr()
'?'
>>> fpLEQ(x, y).sexpr()
'?'
"""
_check_fp_args(a, b)
a, b = _coerce_exprs(a, b)
return BoolRef(Z3_mk_fpa_leq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
def fpGT(a, b):
"""Create the Z3 floating-point expression `other <= self`.
>>> x, y = FPs('x y', FPSort(8, 24))
>>> fpGT(x, y)
x <= y
>>> (x <= y).sexpr()
'?'
>>> fpGT(x, y).sexpr()
'?'
"""
_check_fp_args(a, b)
a, b = _coerce_exprs(a, b)
return BoolRef(Z3_mk_fpa_gt(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
def fpGEQ(a, b):
"""Create the Z3 floating-point expression `other <= self`.
>>> x, y = FPs('x y', FPSort(8, 24))
>>> fp_geq(x, y)
x <= y
>>> (x <= y).sexpr()
'?'
>>> fp_geq(x, y).sexpr()
'?'
"""
_check_fp_args(a, b)
a, b = _coerce_exprs(a, b)
return BoolRef(Z3_mk_fpa_geq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
def fpEQ(a, b):
"""Create the Z3 floating-point expression `other <= self`.
>>> x, y = FPs('x y', FPSort(8, 24))
>>> fpEQ(x, y)
x <= y
>>> (x <= y).sexpr()
'?'
>>> fpEQ(x, y).sexpr()
'?'
"""
_check_fp_args(a, b)
a, b = _coerce_exprs(a, b)
return BoolRef(Z3_mk_fpa_eq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
def fpNEQ(a, b):
"""Create the Z3 floating-point expression `other <= self`.
>>> x, y = FPs('x y', FPSort(8, 24))
>>> fpNEQ(x, y)
x <= y
>>> (x <= y).sexpr()
'?'
>>> fpNEQ(x, y).sexpr()
'?'
"""
_check_fp_args(a, b)
a, b = _coerce_exprs(a, b)
return Not(BoolRef(Z3_mk_fpa_eq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx), a.ctx)
def fpFP(sgn, exp, sig):
"""Create the Z3 floating-point value `fpFP(sgn, sig, exp)` from the three bit-vectorssgn, sig, and exp."""
_z3_assert(is_bv(sgn) and is_bv(exp) and is_bv(sig), "sort mismatch")
_z3_assert(sgn.sort().size() == 1, "sort mismatch")
return FPRef(Z3_mk_fpa_fp(sgn.ctx_ref(), sgn.ast, exp.ast, sig.ast), sgn.ctx)
def fpToFP(a1, a2=None, a3=None):
"""Create a Z3 floating-point conversion expression from other terms."""
if is_bv(a1) and is_fp_sort(a2):
return FPRef(Z3_mk_fpa_to_fp_bv(a1.ctx_ref(), a1.ast, a2.ast), a1.ctx)
elif is_fprm(a1) and is_fp(a2) and is_fp_sort(a3):
return FPRef(Z3_mk_fpa_to_fp_float(a1.ctx_ref(), a1.ast, a2.ast, a3.ast), a1.ctx)
elif is_fprm(a1) and is_real(a2) and is_fp_sort(a3):
return FPRef(Z3_mk_fpa_to_fp_real(a1.ctx_ref(), a1.ast, a2.ast, a3.ast), a1.ctx)
elif is_fprm(a1) and is_bv(a2) and is_fp_sort(a3):
return FPRef(Z3_mk_fpa_to_fp_signed(a1.ctx_ref(), a1.ast, a2.ast, a3.ast), a1.ctx)
else:
raise Z3Exception("Unsupported combination of arguments for conversion to floating-point term.")
def fpToFPUnsigned(rm, x, s):
"""Create a Z3 floating-point conversion expression, from unsigned bit-vector to floating-point expression."""
if __debug__:
_z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
_z3_assert(is_bv(x), "Second argument must be a Z3 bit-vector expression")
_z3_assert(is_fp_sort(s), "Third argument must be Z3 floating-point sort")
return FPRef(Z3_mk_fpa_to_fp_unsigned(rm.ctx_ref(), rm.ast, x.ast, s.ast), rm.ctx)
def fpToSBV(rm, x, s):
"""Create a Z3 floating-point conversion expression, from floating-point expression to signed bit-vector."""
if __debug__:
_z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
_z3_assert(is_fp(x), "Second argument must be a Z3 floating-point expression")
_z3_assert(is_bv_sort(s), "Third argument must be Z3 bit-vector sort")
return FPRef(Z3_mk_fpa_to_sbv(rm.ctx_ref(), rm.ast, x.ast, s.size()), rm.ctx)
def fpToUBV(rm, x, s):
"""Create a Z3 floating-point conversion expression, from floating-point expression to unsigned bit-vector."""
if __debug__:
_z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression")
_z3_assert(is_fp(x), "Second argument must be a Z3 floating-point expression")
_z3_assert(is_bv_sort(s), "Third argument must be Z3 bit-vector sort")
return FPRef(Z3_mk_fpa_to_ubv(rm.ctx_ref(), rm.ast, x.ast, s.size()), rm.ctx)
def fpToReal(x):
"""Create a Z3 floating-point conversion expression, from floating-point expression to real."""
if __debug__:
_z3_assert(is_fp(x), "First argument must be a Z3 floating-point expression")
return FPRef(Z3_mk_fpa_to_real(x.ctx_ref(), x.ast), x.ctx)
def fpToIEEEBV(x):
"""Create a Z3 floating-point conversion expression, from floating-point expression to IEEE bit-vector."""
if __debug__:
_z3_assert(is_fp(x), "First argument must be a Z3 floating-point expression")
return FPRef(Z3_mk_fpa_to_ieee_bv(x.ctx_ref(), x.ast), x.ctx)

View file

@ -8,6 +8,7 @@
import sys, io, z3
from z3consts import *
from z3core import *
from ctypes import *
##############################
#
@ -30,7 +31,7 @@ _z3_op_to_str = {
Z3_OP_BASHR : '>>', Z3_OP_BSHL : '<<', Z3_OP_BLSHR : 'LShR',
Z3_OP_CONCAT : 'Concat', Z3_OP_EXTRACT : 'Extract', Z3_OP_BV2INT : 'BV2Int',
Z3_OP_ARRAY_MAP : 'Map', Z3_OP_SELECT : 'Select', Z3_OP_STORE : 'Store',
Z3_OP_CONST_ARRAY : 'K'
Z3_OP_CONST_ARRAY : 'K'
}
# List of infix operators
@ -45,17 +46,64 @@ _z3_unary = [ Z3_OP_UMINUS, Z3_OP_BNOT, Z3_OP_BNEG ]
# Precedence
_z3_precedence = {
Z3_OP_POWER : 0,
Z3_OP_UMINUS : 1, Z3_OP_BNEG : 1, Z3_OP_BNOT : 1,
Z3_OP_UMINUS : 1, Z3_OP_BNEG : 1, Z3_OP_BNOT : 1,
Z3_OP_MUL : 2, Z3_OP_DIV : 2, Z3_OP_IDIV : 2, Z3_OP_MOD : 2, Z3_OP_BMUL : 2, Z3_OP_BSDIV : 2, Z3_OP_BSMOD : 2,
Z3_OP_ADD : 3, Z3_OP_SUB : 3, Z3_OP_BADD : 3, Z3_OP_BSUB : 3,
Z3_OP_ADD : 3, Z3_OP_SUB : 3, Z3_OP_BADD : 3, Z3_OP_BSUB : 3,
Z3_OP_BASHR : 4, Z3_OP_BSHL : 4,
Z3_OP_BAND : 5,
Z3_OP_BXOR : 6,
Z3_OP_BOR : 7,
Z3_OP_LE : 8, Z3_OP_LT : 8, Z3_OP_GE : 8, Z3_OP_GT : 8, Z3_OP_EQ : 8, Z3_OP_SLEQ : 8, Z3_OP_SLT : 8, Z3_OP_SGEQ : 8, Z3_OP_SGT : 8,
Z3_OP_IFF : 8
Z3_OP_IFF : 8,
Z3_OP_FPA_NEG : 1,
Z3_OP_FPA_MUL : 2, Z3_OP_FPA_DIV : 2, Z3_OP_FPA_REM : 2, Z3_OP_FPA_FMA : 2,
Z3_OP_FPA_ADD: 3, Z3_OP_FPA_SUB : 3,
Z3_OP_FPA_LE : 8, Z3_OP_FPA_LT : 8, Z3_OP_FPA_GE : 8, Z3_OP_FPA_GT : 8, Z3_OP_FPA_EQ : 8
}
# FPA operators
_z3_op_to_fpa_normal_str = {
Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN : 'RoundNearestTiesToEven()', Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY : 'RoundNearestTiesToAway()',
Z3_OP_FPA_RM_TOWARD_POSITIVE : 'RoundTowardPositive()', Z3_OP_FPA_RM_TOWARD_NEGATIVE : 'RoundTowardNegative()',
Z3_OP_FPA_RM_TOWARD_ZERO : 'RoundTowardZero()',
Z3_OP_FPA_PLUS_INF : '+oo', Z3_OP_FPA_MINUS_INF : '-oo',
Z3_OP_FPA_NAN : 'NaN', Z3_OP_FPA_PLUS_ZERO : 'PZero', Z3_OP_FPA_MINUS_ZERO : 'NZero',
Z3_OP_FPA_ADD : 'fpAdd', Z3_OP_FPA_SUB : 'fpSub', Z3_OP_FPA_NEG : 'fpNeg', Z3_OP_FPA_MUL : 'fpMul',
Z3_OP_FPA_DIV : 'fpDiv', Z3_OP_FPA_REM : 'fpRem', Z3_OP_FPA_ABS : 'fpAbs',
Z3_OP_FPA_MIN : 'fpMin', Z3_OP_FPA_MAX : 'fpMax',
Z3_OP_FPA_FMA : 'fpFMA', Z3_OP_FPA_SQRT : 'fpSqrt', Z3_OP_FPA_ROUND_TO_INTEGRAL : 'fpRoundToIntegral',
Z3_OP_FPA_EQ : 'fpEQ', Z3_OP_FPA_LT : 'fpLT', Z3_OP_FPA_GT : 'fpGT', Z3_OP_FPA_LE : 'fpLEQ',
Z3_OP_FPA_GE : 'fpGEQ',
Z3_OP_FPA_IS_NAN : 'fpIsNaN', Z3_OP_FPA_IS_INF : 'fpIsInf', Z3_OP_FPA_IS_ZERO : 'fpIsZero',
Z3_OP_FPA_IS_NORMAL : 'fpIsNormal', Z3_OP_FPA_IS_SUBNORMAL : 'fpIsSubnormal',
Z3_OP_FPA_IS_NEGATIVE : 'fpIsNegative', Z3_OP_FPA_IS_POSITIVE : 'fpIsPositive',
Z3_OP_FPA_FP : 'fpFP', Z3_OP_FPA_TO_FP : 'fpToFP', Z3_OP_FPA_TO_FP_UNSIGNED: 'fpToFPUnsigned',
Z3_OP_FPA_TO_UBV : 'fpToUBV', Z3_OP_FPA_TO_SBV : 'fpToSBV', Z3_OP_FPA_TO_REAL: 'fpToReal',
Z3_OP_FPA_TO_IEEE_BV : 'fpToIEEEBV'
}
_z3_op_to_fpa_pretty_str = {
Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN : 'RNE()', Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY : 'RNA()',
Z3_OP_FPA_RM_TOWARD_POSITIVE : 'RTP()', Z3_OP_FPA_RM_TOWARD_NEGATIVE : 'RTN()',
Z3_OP_FPA_RM_TOWARD_ZERO : 'RTZ()',
Z3_OP_FPA_PLUS_INF : '+oo', Z3_OP_FPA_MINUS_INF : '-oo',
Z3_OP_FPA_NAN : 'NaN', Z3_OP_FPA_PLUS_ZERO : '+0.0', Z3_OP_FPA_MINUS_ZERO : '-0.0',
Z3_OP_FPA_ADD : '+', Z3_OP_FPA_SUB : '-', Z3_OP_FPA_MUL : '*', Z3_OP_FPA_DIV : '/',
Z3_OP_FPA_REM : '%', Z3_OP_FPA_NEG : '-',
Z3_OP_FPA_EQ : 'fpEQ', Z3_OP_FPA_LT : '<', Z3_OP_FPA_GT : '>', Z3_OP_FPA_LE : '<=', Z3_OP_FPA_GE : '>='
}
_z3_fpa_infix = [
Z3_OP_FPA_ADD, Z3_OP_FPA_SUB, Z3_OP_FPA_MUL, Z3_OP_FPA_DIV, Z3_OP_FPA_REM,
Z3_OP_FPA_LT, Z3_OP_FPA_GT, Z3_OP_FPA_LE, Z3_OP_FPA_GE
]
def _is_assoc(k):
return k == Z3_OP_BOR or k == Z3_OP_BXOR or k == Z3_OP_BAND or k == Z3_OP_ADD or k == Z3_OP_BADD or k == Z3_OP_MUL or k == Z3_OP_BMUL
@ -134,10 +182,14 @@ _infix_map = {}
_unary_map = {}
_infix_compact_map = {}
for (_k,_v) in _z3_op_to_fpa_normal_str.items():
_z3_op_to_str[_k] = _v
for _k in _z3_infix:
_infix_map[_k] = True
for _k in _z3_unary:
_unary_map[_k] = True
for _k in _z3_infix_compact:
_infix_compact_map[_k] = True
@ -463,6 +515,7 @@ class Formatter:
self.precision = 10
self.ellipses = to_format(_ellipses)
self.max_visited = 10000
self.fpa_pretty = False
def pp_ellipses(self):
return self.ellipses
@ -499,6 +552,8 @@ class Formatter:
return seq1('Array', (self.pp_sort(s.domain()), self.pp_sort(s.range())))
elif isinstance(s, z3.BitVecSortRef):
return seq1('BitVec', (to_format(s.size()), ))
elif isinstance(s, z3.FPSortRef):
return seq1('FPSort', (to_format(s.ebits()), to_format(s.sbits())))
else:
return to_format(s.name())
@ -520,6 +575,123 @@ class Formatter:
def pp_bv(self, a):
return to_format(a.as_string())
def pp_fprm_value(self, a):
z3._z3_assert(z3.is_fprm_value(a), 'expected FPRMNumRef')
if self.fpa_pretty and a.decl().kind() in _z3_op_to_fpa_pretty_str:
return to_format(_z3_op_to_fpa_pretty_str.get(a.decl().kind()))
else:
return to_format(_z3_op_to_fpa_normal_str.get(a.decl().kind()))
def pp_fp_value(self, a):
z3._z3_assert(isinstance(a, z3.FPNumRef), 'type mismatch')
if not self.fpa_pretty:
if (a.isNaN()):
return to_format('NaN')
elif (a.isInf()):
if (a.isNegative()):
return to_format('-oo')
else:
return to_format('+oo')
elif (a.isZero()):
if (a.isNegative()):
return to_format('-zero')
else:
return to_format('+zero')
else:
z3._z3_assert(z3.is_fp_value(a), 'expecting FP num ast')
r = []
sgn = c_long(0)
sgnb = Z3_fpa_get_numeral_sign(a.ctx_ref(), a.ast, byref(sgn))
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('))
if not sgnb and sgn:
r.append(to_format('-'))
r.append(to_format(sig))
r.append(to_format('*(2**'))
r.append(to_format(exp))
r.append(to_format(', '))
r.append(to_format(a.sort()))
r.append(to_format('))'))
return compose(r)
else:
if (a.isNaN()):
return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_FPA_NAN])
elif (a.isInf()):
if (a.isNegative()):
return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_FPA_MINUS_INF])
else:
return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_FPA_PLUS_INF])
elif (a.isZero()):
if (a.isNegative()):
return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_FPA_MINUS_ZERO])
else:
return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_FPA_PLUS_ZERO])
else:
z3._z3_assert(z3.is_fp_value(a), 'expecting FP num ast')
r = []
sgn = c_long(0)
sgnb = Z3_fpa_get_numeral_sign(a.ctx_ref(), a.ast, byref(sgn))
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 not sgnb and sgn != 0:
r.append(to_format('-'))
r.append(to_format(sig))
if (exp != '0'):
r.append(to_format('*(2**'))
r.append(to_format(exp))
r.append(to_format(')'))
return compose(r)
def pp_fp(self, a, d, xs):
z3._z3_assert(isinstance(a, z3.FPRef), "type mismatch")
k = a.decl().kind()
op = '?'
if (self.fpa_pretty and k in _z3_op_to_fpa_pretty_str):
op = _z3_op_to_fpa_pretty_str[k]
elif k in _z3_op_to_fpa_normal_str:
op = _z3_op_to_fpa_normal_str[k]
elif k in _z3_op_to_str:
op = _z3_op_to_str[k]
n = a.num_args()
if self.fpa_pretty:
if self.is_infix(k) and n >= 3:
rm = a.arg(0)
if z3.is_fprm_value(rm) and z3._dflt_rm(a.ctx).eq(rm):
arg1 = to_format(self.pp_expr(a.arg(1), d+1, xs))
arg2 = to_format(self.pp_expr(a.arg(2), d+1, xs))
r = []
r.append(arg1)
r.append(to_format(' '))
r.append(to_format(op))
r.append(to_format(' '))
r.append(arg2)
return compose(r)
elif k == Z3_OP_FPA_NEG:
return compose([to_format('-') , to_format(self.pp_expr(a.arg(0), d+1, xs))])
if k in _z3_op_to_fpa_normal_str:
op = _z3_op_to_fpa_normal_str[k]
r = []
r.append(to_format(op))
if not z3.is_const(a):
r.append(to_format('('))
first = True
for c in a.children():
if first:
first = False
else:
r.append(to_format(', '))
r.append(self.pp_expr(c, d+1, xs))
r.append(to_format(')'))
return compose(r)
else:
return to_format(a.as_string())
def pp_prefix(self, a, d, xs):
r = []
sz = 0
@ -678,9 +850,15 @@ class Formatter:
elif z3.is_rational_value(a):
return self.pp_rational(a)
elif z3.is_algebraic_value(a):
return self.pp_algebraic(a)
return self.pp_algebraic(a)
elif z3.is_bv_value(a):
return self.pp_bv(a)
elif z3.is_fprm_value(a):
return self.pp_fprm_value(a)
elif z3.is_fp_value(a):
return self.pp_fp_value(a)
elif z3.is_fp(a):
return self.pp_fp(a, d, xs)
elif z3.is_const(a):
return self.pp_const(a)
else:
@ -939,6 +1117,12 @@ def set_pp_option(k, v):
else:
set_html_mode(False)
return True
if k == 'fpa_pretty':
if v:
set_fpa_pretty(True)
else:
set_fpa_pretty(False)
return True
val = getattr(_PP, k, None)
if val != None:
z3._z3_assert(type(v) == type(val), "Invalid pretty print option value")
@ -965,6 +1149,23 @@ def set_html_mode(flag=True):
else:
_Formatter = Formatter()
def set_fpa_pretty(flag=True):
global _Formatter
global _z3_op_to_str
_Formatter.fpa_pretty = flag
if flag:
for (_k,_v) in _z3_op_to_fpa_pretty_str.items():
_z3_op_to_str[_k] = _v
for _k in _z3_fpa_infix:
_infix_map[_k] = True
else:
for (_k,_v) in _z3_op_to_fpa_normal_str.items():
_z3_op_to_str[_k] = _v
for _k in _z3_fpa_infix:
_infix_map[_k] = False
def in_html_mode():
return isinstance(_Formatter, HTMLFormatter)

View file

@ -28,6 +28,7 @@ Notes:
#include"z3_polynomial.h"
#include"z3_rcf.h"
#include"z3_interp.h"
#include"z3_fpa.h"
#undef __in
#undef __out

View file

@ -194,6 +194,8 @@ typedef enum
Z3_DATATYPE_SORT,
Z3_RELATION_SORT,
Z3_FINITE_DOMAIN_SORT,
Z3_FLOATING_POINT_SORT,
Z3_ROUNDING_MODE_SORT,
Z3_UNKNOWN_SORT = 1000
} Z3_sort_kind;
@ -875,6 +877,90 @@ typedef enum
- Z3_OP_DT_ACCESSOR: datatype accessor.
- Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN: Floating-point rounding mode RNE
- Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY: Floating-point rounding mode RNA
- Z3_OP_FPA_RM_TOWARD_POSITIVE: Floating-point rounding mode RTP
- Z3_OP_FPA_RM_TOWARD_NEGATIVE: Floating-point rounding mode RTN
- Z3_OP_FPA_RM_TOWARD_ZERO: Floating-point rounding mode RTZ
- Z3_OP_FPA_NUM: Floating-point value
- Z3_OP_FPA_PLUS_INF: Floating-point +oo
- Z3_OP_FPA_MINUS_INF: Floating-point -oo
- Z3_OP_FPA_NAN: Floating-point NaN
- Z3_OP_FPA_PLUS_ZERO: Floating-point +zero
- Z3_OP_FPA_MINUS_ZERO: Floating-point -zero
- Z3_OP_FPA_ADD: Floating-point addition
- Z3_OP_FPA_SUB: Floating-point subtraction
- Z3_OP_FPA_NEG: Floating-point negation
- Z3_OP_FPA_MUL: Floating-point multiplication
- Z3_OP_FPA_DIV: Floating-point division
- Z3_OP_FPA_REM: Floating-point remainder
- Z3_OP_FPA_ABS: Floating-point absolute value
- Z3_OP_FPA_MIN: Floating-point minimum
- Z3_OP_FPA_MAX: Floating-point maximum
- Z3_OP_FPA_FMA: Floating-point fused multiply-add
- Z3_OP_FPA_SQRT: Floating-point square root
- Z3_OP_FPA_ROUND_TO_INTEGRAL: Floating-point round to integral
- Z3_OP_FPA_EQ: Floating-point equality
- Z3_OP_FPA_LT: Floating-point less than
- Z3_OP_FPA_GT: Floating-point greater than
- Z3_OP_FPA_LE: Floating-point less than or equal
- Z3_OP_FPA_GE: Floating-point greater than or equal
- Z3_OP_FPA_IS_NAN: Floating-point isNaN
- Z3_OP_FPA_IS_INF: Floating-point isInfinite
- Z3_OP_FPA_IS_ZERO: Floating-point isZero
- Z3_OP_FPA_IS_NORMAL: Floating-point isNormal
- Z3_OP_FPA_IS_SUBNORMAL: Floating-point isSubnormal
- Z3_OP_FPA_IS_NEGATIVE: Floating-point isNegative
- Z3_OP_FPA_IS_POSITIVE: Floating-point isPositive
- Z3_OP_FPA_FP: Floating-point constructor from 3 bit-vectors
- Z3_OP_FPA_TO_FP: Floating-point conversion (various)
- Z3_OP_FPA_TO_FP_UNSIGNED: Floating-point conversion from unsigend bit-vector
- Z3_OP_FPA_TO_UBV: Floating-point conversion to unsigned bit-vector
- Z3_OP_FPA_TO_SBV: Floating-point conversion to signed bit-vector
- Z3_OP_FPA_TO_REAL: Floating-point conversion to real number
- Z3_OP_FPA_TO_IEEE_BV: Floating-point conversion to IEEE-754 bit-vector
- Z3_OP_UNINTERPRETED: kind used for uninterpreted symbols.
*/
typedef enum {
@ -1056,6 +1142,55 @@ typedef enum {
Z3_OP_DT_RECOGNISER,
Z3_OP_DT_ACCESSOR,
// Floating-Point Arithmetic
Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN,
Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY,
Z3_OP_FPA_RM_TOWARD_POSITIVE,
Z3_OP_FPA_RM_TOWARD_NEGATIVE,
Z3_OP_FPA_RM_TOWARD_ZERO,
Z3_OP_FPA_NUM,
Z3_OP_FPA_PLUS_INF,
Z3_OP_FPA_MINUS_INF,
Z3_OP_FPA_NAN,
Z3_OP_FPA_PLUS_ZERO,
Z3_OP_FPA_MINUS_ZERO,
Z3_OP_FPA_ADD,
Z3_OP_FPA_SUB,
Z3_OP_FPA_NEG,
Z3_OP_FPA_MUL,
Z3_OP_FPA_DIV,
Z3_OP_FPA_REM,
Z3_OP_FPA_ABS,
Z3_OP_FPA_MIN,
Z3_OP_FPA_MAX,
Z3_OP_FPA_FMA,
Z3_OP_FPA_SQRT,
Z3_OP_FPA_ROUND_TO_INTEGRAL,
Z3_OP_FPA_EQ,
Z3_OP_FPA_LT,
Z3_OP_FPA_GT,
Z3_OP_FPA_LE,
Z3_OP_FPA_GE,
Z3_OP_FPA_IS_NAN,
Z3_OP_FPA_IS_INF,
Z3_OP_FPA_IS_ZERO,
Z3_OP_FPA_IS_NORMAL,
Z3_OP_FPA_IS_SUBNORMAL,
Z3_OP_FPA_IS_NEGATIVE,
Z3_OP_FPA_IS_POSITIVE,
Z3_OP_FPA_FP,
Z3_OP_FPA_TO_FP,
Z3_OP_FPA_TO_FP_UNSIGNED,
Z3_OP_FPA_TO_UBV,
Z3_OP_FPA_TO_SBV,
Z3_OP_FPA_TO_REAL,
Z3_OP_FPA_TO_IEEE_BV,
Z3_OP_UNINTERPRETED
} Z3_decl_kind;
@ -1698,8 +1833,7 @@ extern "C" {
/**
\brief Create the real type.
This type is not a floating point number.
Z3 does not have support for floating point numbers yet.
Note that this type is not a floating point number.
def_API('Z3_mk_real_sort', SORT, (_in(CONTEXT), ))
*/

923
src/api/z3_fpa.h Normal file
View file

@ -0,0 +1,923 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
z3_fpa.h
Abstract:
Additional APIs for floating-point arithmetic (FP).
Author:
Christoph M. Wintersteiger (cwinter) 2013-06-05
Notes:
--*/
#ifndef _Z3_FPA_H_
#define _Z3_FPA_H_
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
\defgroup capi C API
*/
/*@{*/
/**
@name Floating-Point API
*/
/*@{*/
/**
\brief Create the RoundingMode sort.
\param c logical context.
def_API('Z3_mk_fpa_rounding_mode_sort', SORT, (_in(CONTEXT),))
*/
Z3_sort Z3_API Z3_mk_fpa_rounding_mode_sort(__in Z3_context c);
/**
\brief Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode.
\param c logical context.
def_API('Z3_mk_fpa_round_nearest_ties_to_even', AST, (_in(CONTEXT),))
*/
Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_even(__in Z3_context c);
/**
\brief Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode.
\param c logical context.
def_API('Z3_mk_fpa_rne', AST, (_in(CONTEXT),))
*/
Z3_ast Z3_API Z3_mk_fpa_rne(__in Z3_context c);
/**
\brief Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode.
\param c logical context.
def_API('Z3_mk_fpa_round_nearest_ties_to_away', AST, (_in(CONTEXT),))
*/
Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_away(__in Z3_context c);
/**
\brief Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode.
\param c logical context.
def_API('Z3_mk_fpa_rna', AST, (_in(CONTEXT),))
*/
Z3_ast Z3_API Z3_mk_fpa_rna(__in Z3_context c);
/**
\brief Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode.
\param c logical context.
def_API('Z3_mk_fpa_round_toward_positive', AST, (_in(CONTEXT),))
*/
Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(__in Z3_context c);
/**
\brief Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode.
\param c logical context.
def_API('Z3_mk_fpa_rtp', AST, (_in(CONTEXT),))
*/
Z3_ast Z3_API Z3_mk_fpa_rtp(__in Z3_context c);
/**
\brief Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode.
\param c logical context.
def_API('Z3_mk_fpa_round_toward_negative', AST, (_in(CONTEXT),))
*/
Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(__in Z3_context c);
/**
\brief Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode.
\param c logical context.
def_API('Z3_mk_fpa_rtn', AST, (_in(CONTEXT),))
*/
Z3_ast Z3_API Z3_mk_fpa_rtn(__in Z3_context c);
/**
\brief Create a numeral of RoundingMode sort which represents the TowardZero rounding mode.
\param c logical context.
def_API('Z3_mk_fpa_round_toward_zero', AST, (_in(CONTEXT),))
*/
Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(__in Z3_context c);
/**
\brief Create a numeral of RoundingMode sort which represents the TowardZero rounding mode.
\param c logical context.
def_API('Z3_mk_fpa_rtz', AST, (_in(CONTEXT),))
*/
Z3_ast Z3_API Z3_mk_fpa_rtz(__in Z3_context c);
/**
\brief Create a FloatingPoint sort.
\param c logical context.
\param ebits number of exponent bits.
\param sbits number of significand bits.
\remark ebits must be larger than 1 and sbits must be larger than 2.
def_API('Z3_mk_fpa_sort', SORT, (_in(CONTEXT), _in(UINT), _in(UINT)))
*/
Z3_sort Z3_API Z3_mk_fpa_sort(__in Z3_context c, __in unsigned ebits, __in unsigned sbits);
/**
\brief Create the half-precision (16-bit) FloatingPoint sort.
\param c logical context.
def_API('Z3_mk_fpa_sort_half', SORT, (_in(CONTEXT),))
*/
Z3_sort Z3_API Z3_mk_fpa_sort_half(__in Z3_context c);
/**
\brief Create the half-precision (16-bit) FloatingPoint sort.
\param c logical context.
def_API('Z3_mk_fpa_sort_16', SORT, (_in(CONTEXT),))
*/
Z3_sort Z3_API Z3_mk_fpa_sort_16(__in Z3_context c);
/**
\brief Create the single-precision (32-bit) FloatingPoint sort.
\param c logical context.
def_API('Z3_mk_fpa_sort_single', SORT, (_in(CONTEXT),))
*/
Z3_sort Z3_API Z3_mk_fpa_sort_single(__in Z3_context c);
/**
\brief Create the single-precision (32-bit) FloatingPoint sort.
\param c logical context.
def_API('Z3_mk_fpa_sort_32', SORT, (_in(CONTEXT),))
*/
Z3_sort Z3_API Z3_mk_fpa_sort_32(__in Z3_context c);
/**
\brief Create the double-precision (64-bit) FloatingPoint sort.
\param c logical context.
def_API('Z3_mk_fpa_sort_double', SORT, (_in(CONTEXT),))
*/
Z3_sort Z3_API Z3_mk_fpa_sort_double(__in Z3_context c);
/**
\brief Create the double-precision (64-bit) FloatingPoint sort.
\param c logical context.
def_API('Z3_mk_fpa_sort_64', SORT, (_in(CONTEXT),))
*/
Z3_sort Z3_API Z3_mk_fpa_sort_64(__in Z3_context c);
/**
\brief Create the quadruple-precision (128-bit) FloatingPoint sort.
\param c logical context.
\param ebits number of exponent bits
\param sbits number of significand bits
\remark ebits must be larger than 1 and sbits must be larger than 2.
def_API('Z3_mk_fpa_sort_quadruple', SORT, (_in(CONTEXT),))
*/
Z3_sort Z3_API Z3_mk_fpa_sort_quadruple(__in Z3_context c);
/**
\brief Create the quadruple-precision (128-bit) FloatingPoint sort.
\param c logical context.
\param ebits number of exponent bits
\param sbits number of significand bits
\remark ebits must be larger than 1 and sbits must be larger than 2.
def_API('Z3_mk_fpa_sort_128', SORT, (_in(CONTEXT),))
*/
Z3_sort Z3_API Z3_mk_fpa_sort_128(__in Z3_context c);
/**
\brief Create a floating-point NaN of sort s.
\param c logical context.
\param s target sort
def_API('Z3_mk_fpa_nan', AST, (_in(CONTEXT),_in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_nan(__in Z3_context c, __in Z3_sort s);
/**
\brief Create a floating-point infinity of sort s.
\param c logical context.
\param s target sort
\param negative indicates whether the result should be negative
When \c negative is true, -oo will be generated instead of +oo.
def_API('Z3_mk_fpa_inf', AST, (_in(CONTEXT),_in(SORT),_in(BOOL)))
*/
Z3_ast Z3_API Z3_mk_fpa_inf(__in Z3_context c, __in Z3_sort s, __in Z3_bool negative);
/**
\brief Create a floating-point zero of sort s.
\param c logical context.
\param s target sort
\param negative indicates whether the result should be negative
When \c negative is true, -zero will be generated instead of +zero.
def_API('Z3_mk_fpa_zero', AST, (_in(CONTEXT),_in(SORT),_in(BOOL)))
*/
Z3_ast Z3_API Z3_mk_fpa_zero(__in Z3_context c, __in Z3_sort s, __in Z3_bool negative);
/**
\brief Create an expression of FloatingPoint sort from three bit-vector expressions.
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
are required to be greater than 1 and 2 respectively. The FloatingPoint sort
of the resulting expression is automatically determined from the bit-vector sizes
of the arguments.
\params c logical context.
\params sgn sign
\params exp exponent
\params sig significand
def_API('Z3_mk_fpa_fp', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_fp(__in Z3_context c, __in Z3_ast sgn, __in Z3_ast exp, __in Z3_ast sig);
/**
\brief Create a numeral of FloatingPoint sort from a float.
This function is used to create numerals that fit in a float value.
It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string.
\params c logical context.
\params v value.
\params ty sort.
ty must be a FloatingPoint sort
\sa Z3_mk_numeral
def_API('Z3_mk_fpa_numeral_float', AST, (_in(CONTEXT), _in(FLOAT), _in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_numeral_float(__in Z3_context c, __in float v, __in Z3_sort ty);
/**
\brief Create a numeral of FloatingPoint sort from a double.
This function is used to create numerals that fit in a double value.
It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string.
\params c logical context.
\params v value.
\params ty sort.
ty must be a FloatingPoint sort
\sa Z3_mk_numeral
def_API('Z3_mk_fpa_numeral_double', AST, (_in(CONTEXT), _in(DOUBLE), _in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_numeral_double(__in Z3_context c, __in double v, __in Z3_sort ty);
/**
\brief Create a numeral of FloatingPoint sort from a signed integer.
\params c logical context.
\params v value.
ty must be a FloatingPoint sort
\sa Z3_mk_numeral
def_API('Z3_mk_fpa_numeral_int', AST, (_in(CONTEXT), _in(INT), _in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_numeral_int(__in Z3_context c, __in signed v, Z3_sort ty);
/**
\brief Create a numeral of FloatingPoint sort from a sign bit and two integers.
\params c logical context.
\params sgn sign bit (true == negative).
\params sig significand.
\params exp exponent.
ty must be a FloatingPoint sort
\sa Z3_mk_numeral
def_API('Z3_mk_fpa_numeral_uint_int', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(INT), _in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_numeral_uint_int(__in Z3_context c, __in Z3_bool sgn, __in unsigned sig, __in signed exp, Z3_sort ty);
/**
\brief Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers.
\params c logical context.
\params sgn sign bit (true == negative).
\params sig significand.
\params exp exponent.
ty must be a FloatingPoint sort
\sa Z3_mk_numeral
def_API('Z3_mk_fpa_numeral_uint64_int64', AST, (_in(CONTEXT), _in(BOOL), _in(UINT64), _in(INT64), _in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_numeral_uint64_int64(__in Z3_context c, __in Z3_bool sgn, __in __uint64 sig, __in __int64 exp, Z3_sort ty);
/**
\brief Floating-point absolute value
\param c logical context.
\param t term of FloatingPoint sort.
def_API('Z3_mk_fpa_abs', AST, (_in(CONTEXT),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_abs(__in Z3_context c, __in Z3_ast t);
/**
\brief Floating-point negation
\param c logical context.
\param t term of FloatingPoint sort.
def_API('Z3_mk_fpa_neg', AST, (_in(CONTEXT),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_neg(__in Z3_context c, __in Z3_ast t);
/**
\brief Floating-point addition
\param c logical context.
\param rm term of RoundingMode sort.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
rm must be of RoundingMode sort, t1 and t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_add', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_add(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Floating-point subtraction
\param c logical context.
\param rm term of RoundingMode sort.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
rm must be of RoundingMode sort, t1 and t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_sub', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_sub(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Floating-point multiplication
\param c logical context.
\param rm term of RoundingMode sort.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
rm must be of RoundingMode sort, t1 and t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_mul', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_mul(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Floating-point division
\param c logical context.
\param rm term of RoundingMode sort.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
The nodes rm must be of RoundingMode sort t1 and t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_div', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_div(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Floating-point fused multiply-add.
\param c logical context.
\param rm term of RoundingMode sort.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
The result is round((t1 * t2) + t3)
rm must be of RoundingMode sort, t1, t2, and t3 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_fma', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_fma(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t1, __in Z3_ast t2, __in Z3_ast t3);
/**
\brief Floating-point square root
\param c logical context.
\param rm term of RoundingMode sort.
\param t term of FloatingPoint sort.
rm must be of RoundingMode sort, t must have FloatingPoint sort.
def_API('Z3_mk_fpa_sqrt', AST, (_in(CONTEXT),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_sqrt(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t);
/**
\brief Floating-point remainder
\param c logical context.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
t1 and t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_rem', AST, (_in(CONTEXT),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_rem(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Floating-point roundToIntegral. Rounds a floating-point number to
the closest integer, again represented as a floating-point number.
\param c logical context.
\param rm term of RoundingMode sort.
\param t term of FloatingPoint sort.
t must be of FloatingPoint sort.
def_API('Z3_mk_fpa_round_to_integral', AST, (_in(CONTEXT),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_round_to_integral(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t);
/**
\brief Minimum of floating-point numbers.
\param c logical context.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
t1, t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_min', AST, (_in(CONTEXT),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_min(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Maximum of floating-point numbers.
\param c logical context.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
t1, t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_max', AST, (_in(CONTEXT),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_max(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Floating-point less than or equal.
\param c logical context.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
t1 and t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_leq', AST, (_in(CONTEXT),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_leq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Floating-point less than.
\param c logical context.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
t1 and t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_lt', AST, (_in(CONTEXT),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_lt(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Floating-point greater than or equal.
\param c logical context.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
t1 and t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_geq', AST, (_in(CONTEXT),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_geq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Floating-point greater than.
\param c logical context.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
t1 and t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_gt', AST, (_in(CONTEXT),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_gt(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Floating-point equality.
\param c logical context.
\param t1 term of FloatingPoint sort.
\param t2 term of FloatingPoint sort.
Note that this is IEEE 754 equality (as opposed to SMT-LIB =).
t1 and t2 must have the same FloatingPoint sort.
def_API('Z3_mk_fpa_eq', AST, (_in(CONTEXT),_in(AST),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_eq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2);
/**
\brief Predicate indicating whether t is a normal floating-point number.
\param c logical context.
\param t term of FloatingPoint sort.
t must have FloatingPoint sort.
def_API('Z3_mk_fpa_is_normal', AST, (_in(CONTEXT),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_is_normal(__in Z3_context c, __in Z3_ast t);
/**
\brief Predicate indicating whether t is a subnormal floating-point number.
\param c logical context.
\param t term of FloatingPoint sort.
t must have FloatingPoint sort.
def_API('Z3_mk_fpa_is_subnormal', AST, (_in(CONTEXT),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_is_subnormal(__in Z3_context c, __in Z3_ast t);
/**
\brief Predicate indicating whether t is a floating-point number with zero value, i.e., +zero or -zero.
\param c logical context.
\param t term of FloatingPoint sort.
t must have FloatingPoint sort.
def_API('Z3_mk_fpa_is_zero', AST, (_in(CONTEXT),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_is_zero(__in Z3_context c, __in Z3_ast t);
/**
\brief Predicate indicating whether t is a floating-point number representing +oo or -oo.
\param c logical context.
\param t term of FloatingPoint sort.
t must have FloatingPoint sort.
def_API('Z3_mk_fpa_is_infinite', AST, (_in(CONTEXT),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_is_infinite(__in Z3_context c, __in Z3_ast t);
/**
\brief Predicate indicating whether t is a NaN.
\param c logical context.
\param t term of FloatingPoint sort.
t must have FloatingPoint sort.
def_API('Z3_mk_fpa_is_nan', AST, (_in(CONTEXT),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_is_nan(__in Z3_context c, __in Z3_ast t);
/**
\brief Predicate indicating whether t is a negative floating-point number.
\param c logical context.
\param t term of FloatingPoint sort.
t must have FloatingPoint sort.
def_API('Z3_mk_fpa_is_negative', AST, (_in(CONTEXT),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_is_negative(__in Z3_context c, __in Z3_ast t);
/**
\brief Predicate indicating whether t is a positive floating-point number.
\param c logical context.
\param t term of FloatingPoint sort.
t must have FloatingPoint sort.
def_API('Z3_mk_fpa_is_positive', AST, (_in(CONTEXT),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_is_positive(__in Z3_context c, __in Z3_ast t);
/**
\brief Conversion of a single IEEE 754-2008 bit-vector into a floating-point number.
Produces a term that represents the conversion of a bit-vector term bv to a
floating-point term of sort s.
\param c logical context.
\param bv a bit-vector term.
\param s floating-point sort.
s must be a FloatingPoint sort, t must be of bit-vector sort, and the bit-vector
size of bv must be equal to ebits+sbits of s. The format of the bit-vector is
as defined by the IEEE 754-2008 interchange format.
def_API('Z3_mk_fpa_to_fp_bv', AST, (_in(CONTEXT),_in(AST),_in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_to_fp_bv(__in Z3_context c, __in Z3_ast bv, __in Z3_sort s);
/**
\brief Conversion of a FloatingPoint term into another term of different FloatingPoint sort.
Produces a term that represents the conversion of a floating-point term t to a
floating-point term of sort s. If necessary, the result will be rounded according
to rounding mode rm.
\param c logical context.
\param rm term of RoundingMode sort.
\param t term of FloatingPoint sort.
\param s floating-point sort.
s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of floating-point sort.
def_API('Z3_mk_fpa_to_fp_float', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_to_fp_float(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in Z3_sort s);
/**
\brief Conversion of a term of real sort into a term of FloatingPoint sort.
Produces a term that represents the conversion of term t of real sort into a
floating-point term of sort s. If necessary, the result will be rounded according
to rounding mode rm.
\param c logical context.
\param rm term of RoundingMode sort.
\param t term of Real sort.
\param s floating-point sort.
s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of real sort.
def_API('Z3_mk_fpa_to_fp_real', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_to_fp_real(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in Z3_sort s);
/**
\brief Conversion of a 2's complement signed bit-vector term into a term of FloatingPoint sort.
Produces a term that represents the conversion of the bit-vector term t into a
floating-point term of sort s. The bit-vector t is taken to be in signed
2's complement format. If necessary, the result will be rounded according
to rounding mode rm.
\param c logical context.
\param rm term of RoundingMode sort.
\param t term of bit-vector sort.
\param s floating-point sort.
s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of bit-vector sort.
def_API('Z3_mk_fpa_to_fp_signed', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_to_fp_signed(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in Z3_sort s);
/**
\brief Conversion of a 2's complement unsigned bit-vector term into a term of FloatingPoint sort.
Produces a term that represents the conversion of the bit-vector term t into a
floating-point term of sort s. The bit-vector t is taken to be in unsigned
2's complement format. If necessary, the result will be rounded according
to rounding mode rm.
\param c logical context.
\param rm term of RoundingMode sort.
\param t term of bit-vector sort.
\param s floating-point sort.
s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of bit-vector sort.
def_API('Z3_mk_fpa_to_fp_unsigned', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_to_fp_unsigned(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in Z3_sort s);
/**
\brief Conversion of a floating-point term into an unsigned bit-vector.
Produces a term that represents the conversion of the floating-poiunt term t into a
bit-vector term of size sz in unsigned 2's complement format. If necessary, the result
will be rounded according to rounding mode rm.
\param c logical context.
\param rm term of RoundingMode sort.
\param t term of FloatingPoint sort.
\param sz size of the resulting bit-vector.
def_API('Z3_mk_fpa_to_ubv', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(UINT)))
*/
Z3_ast Z3_API Z3_mk_fpa_to_ubv(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in unsigned sz);
/**
\brief Conversion of a floating-point term into a signed bit-vector.
Produces a term that represents the conversion of the floating-poiunt term t into a
bit-vector term of size sz in signed 2's complement format. If necessary, the result
will be rounded according to rounding mode rm.
\param c logical context.
\param rm term of RoundingMode sort.
\param t term of FloatingPoint sort.
\param sz size of the resulting bit-vector.
def_API('Z3_mk_fpa_to_sbv', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(UINT)))
*/
Z3_ast Z3_API Z3_mk_fpa_to_sbv(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in unsigned sz);
/**
\brief Conversion of a floating-point term into a real-numbered term.
Produces a term that represents the conversion of the floating-poiunt term t into a
real number. Note that this type of conversion will often result in non-linear
constraints over real terms.
\param c logical context.
\param t term of FloatingPoint sort.
def_API('Z3_mk_fpa_to_real', AST, (_in(CONTEXT),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_to_real(__in Z3_context c, __in Z3_ast t);
/**
@name Z3-specific extensions
*/
/*@{*/
/**
\brief Retrieves the number of bits reserved for the exponent in a FloatingPoint sort.
\param s FloatingPoint sort.
def_API('Z3_fpa_get_ebits', UINT, (_in(CONTEXT),_in(SORT)))
*/
unsigned Z3_API Z3_fpa_get_ebits(__in Z3_context c, __in Z3_sort s);
/**
\brief Retrieves the number of bits reserved for the significand in a FloatingPoint sort.
\param s FloatingPoint sort.
def_API('Z3_fpa_get_sbits', UINT, (_in(CONTEXT),_in(SORT)))
*/
unsigned Z3_API Z3_fpa_get_sbits(__in Z3_context c, __in Z3_sort s);
/**
\brief Retrieves the sign of a floating-point literal
Remarks: sets \c sgn to 0 if the literal is NaN or positive and to 1 otherwise.
\param t a floating-point numeral.
def_API('Z3_fpa_get_numeral_sign', BOOL, (_in(CONTEXT), _in(AST), _out(INT)))
*/
Z3_bool Z3_API Z3_fpa_get_numeral_sign(__in Z3_context c, __in Z3_ast t, __out int * sgn);
/**
\brief Return the significand value of a floating-point numeral as a string
Remarks: The significand s is always 0 < s < 2.0; the resulting string is long
enough to represent the real significand precisely.
\param t a floating-point numeral.
def_API('Z3_fpa_get_numeral_significand_string', STRING, (_in(CONTEXT), _in(AST)))
*/
Z3_string Z3_API Z3_fpa_get_numeral_significand_string(__in Z3_context c, __in Z3_ast t);
/**
\brief Return the exponent value of a floating-point numeral as a string
\param t a floating-point numeral.
def_API('Z3_fpa_get_numeral_exponent_string', STRING, (_in(CONTEXT), _in(AST)))
*/
Z3_string Z3_API Z3_fpa_get_numeral_exponent_string(__in Z3_context c, __in Z3_ast t);
/**
\brief Return the exponent value of a floating-point numeral as a signed 64-bit integer
\param t a floating-point numeral.
def_API('Z3_fpa_get_numeral_exponent_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64)))
*/
Z3_bool Z3_API Z3_fpa_get_numeral_exponent_int64(__in Z3_context c, __in Z3_ast t, __out __int64 * n);
/**
\brief Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format.
\param c logical context.
\param t term of FloatingPoint sort.
t must have FloatingPoint sort. The size of the resulting bit-vector is automatically
determined.
Note that IEEE 754-2008 allows multiple different representations of NaN. This conversion
knows only one NaN and it will always produce the same bit-vector represenatation of
that NaN.
def_API('Z3_mk_fpa_to_ieee_bv', AST, (_in(CONTEXT),_in(AST)))
*/
Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t);
/**
\brief Conversion of a real-sorted significand and an integer-sorted exponent into a term of FloatingPoint sort.
Produces a term that represents the conversion of sig * 2^exp into a
floating-point term of sort s. If necessary, the result will be rounded
according to rounding mode rm.
\param c logical context.
\param rm term of RoundingMode sort.
\param sig significand term of Real sort.
\param exp exponent term of Int sort.
\param s FloatingPoint sort.
s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of real sort.
def_API('Z3_mk_fpa_to_fp_real_int', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST),_in(SORT)))
*/
Z3_ast Z3_API Z3_mk_fpa_to_fp_real_int(__in Z3_context c, __in Z3_ast rm, __in Z3_ast sig, __in Z3_ast exp, __in Z3_sort s);
/*@}*/
/*@}*/
/*@}*/
#ifdef __cplusplus
};
#endif // __cplusplus
#endif

View file

@ -40,11 +40,12 @@ struct z3_replayer::imp {
__int64 m_int64;
__uint64 m_uint64;
double m_double;
float m_float;
size_t m_ptr;
size_t_map<void *> m_heap;
svector<z3_replayer_cmd> m_cmds;
enum value_kind { INT64, UINT64, DOUBLE, STRING, SYMBOL, OBJECT, UINT_ARRAY, SYMBOL_ARRAY, OBJECT_ARRAY };
enum value_kind { INT64, UINT64, DOUBLE, STRING, SYMBOL, OBJECT, UINT_ARRAY, SYMBOL_ARRAY, OBJECT_ARRAY, FLOAT };
struct value {
value_kind m_kind;
@ -54,6 +55,7 @@ struct z3_replayer::imp {
double m_double;
char const * m_str;
void * m_obj;
float m_float;
};
value():m_kind(OBJECT), m_int(0) {}
value(void * obj):m_kind(OBJECT), m_obj(obj) {}
@ -61,6 +63,7 @@ struct z3_replayer::imp {
value(value_kind k, __uint64 u):m_kind(k), m_uint(u) {}
value(value_kind k, __int64 i):m_kind(k), m_int(i) {}
value(value_kind k, double d):m_kind(k), m_double(d) {}
value(value_kind k, float f):m_kind(k), m_float(f) {}
};
svector<value> m_args;
@ -85,9 +88,12 @@ struct z3_replayer::imp {
case UINT64:
out << v.m_uint;
break;
case FLOAT:
out << v.m_float;
break;
case DOUBLE:
out << v.m_double;
break;
break;
case STRING:
out << v.m_str;
break;
@ -219,6 +225,26 @@ struct z3_replayer::imp {
return curr() == '-' || curr() == '.' || ('0' <= curr() && curr() <= '9') || curr() == 'e' || curr() == 'E';
}
#if (!defined(strtof))
float strtof(const char * str, char ** end_ptr) {
// Note: This may introduce a double-rounding problem.
return (float)strtod(str, end_ptr);
}
#endif
void read_float() {
m_string.reset();
while (is_double_char()) {
m_string.push_back(curr());
next();
}
if (m_string.empty())
throw z3_replayer_exception("invalid float");
m_string.push_back(0);
char * ptr;
m_float = strtof(m_string.begin(), &ptr);
}
void read_double() {
m_string.reset();
while (is_double_char()) {
@ -407,12 +433,18 @@ struct z3_replayer::imp {
TRACE("z3_replayer", tout << "[" << m_line << "] " << "U " << m_uint64 << "\n";);
m_args.push_back(value(UINT64, m_uint64));
break;
case 'F':
// push float
next(); skip_blank(); read_float();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "F " << m_float << "\n";);
m_args.push_back(value(FLOAT, m_float));
break;
case 'D':
// push double
next(); skip_blank(); read_double();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "D " << m_double << "\n";);
m_args.push_back(value(DOUBLE, m_double));
break;
break;
case 'p':
case 's':
case 'u':
@ -516,6 +548,12 @@ struct z3_replayer::imp {
return m_args[pos].m_uint;
}
float get_float(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != FLOAT)
throw_invalid_reference();
return m_args[pos].m_float;
}
double get_double(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != DOUBLE)
throw_invalid_reference();
@ -653,6 +691,10 @@ __uint64 z3_replayer::get_uint64(unsigned pos) const {
return m_imp->get_uint64(pos);
}
float z3_replayer::get_float(unsigned pos) const {
return m_imp->get_float(pos);
}
double z3_replayer::get_double(unsigned pos) const {
return m_imp->get_double(pos);
}

View file

@ -42,6 +42,7 @@ public:
unsigned get_uint(unsigned pos) const;
__int64 get_int64(unsigned pos) const;
__uint64 get_uint64(unsigned pos) const;
float get_float(unsigned pos) const;
double get_double(unsigned pos) const;
bool get_bool(unsigned pos) const;
Z3_string get_str(unsigned pos) const;

View file

@ -413,16 +413,16 @@ sort * get_sort(expr const * n) {
//
// -----------------------------------
unsigned get_node_size(ast const * n) {
switch(n->get_kind()) {
case AST_SORT: return to_sort(n)->get_size();
case AST_FUNC_DECL: return to_func_decl(n)->get_size();
case AST_APP: return to_app(n)->get_size();
case AST_VAR: return to_var(n)->get_size();
case AST_QUANTIFIER: return to_quantifier(n)->get_size();
default: UNREACHABLE();
}
return 0;
unsigned get_node_size(ast const * n) {
switch(n->get_kind()) {
case AST_SORT: return to_sort(n)->get_size();
case AST_FUNC_DECL: return to_func_decl(n)->get_size();
case AST_APP: return to_app(n)->get_size();
case AST_VAR: return to_var(n)->get_size();
case AST_QUANTIFIER: return to_quantifier(n)->get_size();
default: UNREACHABLE();
}
return 0;
}
bool compare_nodes(ast const * n1, ast const * n2) {
@ -737,7 +737,7 @@ func_decl * basic_decl_plugin::mk_proof_decl(
for (unsigned i = 0; i < num_parents; i++)
domain.push_back(m_proof_sort);
domain.push_back(m_bool_sort);
func_decl_info info(m_family_id, k, num_parameters, params);
func_decl_info info(m_family_id, k, num_parameters, params);
return m_manager->mk_func_decl(symbol(name), num_parents+1, domain.c_ptr(), m_proof_sort, info);
}
@ -1643,12 +1643,12 @@ ast * ast_manager::register_node_core(ast * n) {
to_func_decl(n)->m_info = alloc(func_decl_info, *(to_func_decl(n)->get_info()));
to_func_decl(n)->m_info->init_eh(*this);
}
inc_array_ref(to_func_decl(n)->get_arity(), to_func_decl(n)->get_domain());
inc_ref(to_func_decl(n)->get_range());
break;
inc_array_ref(to_func_decl(n)->get_arity(), to_func_decl(n)->get_domain());
inc_ref(to_func_decl(n)->get_range());
break;
case AST_APP: {
app * t = to_app(n);
inc_ref(t->get_decl());
inc_ref(t->get_decl());
unsigned num_args = t->get_num_args();
if (num_args > 0) {
app_flags * f = t->flags();
@ -1696,19 +1696,19 @@ ast * ast_manager::register_node_core(ast * n) {
f->m_depth = depth;
SASSERT(t->get_depth() == depth);
}
break;
break;
}
case AST_VAR:
inc_ref(to_var(n)->get_sort());
break;
case AST_QUANTIFIER:
inc_array_ref(to_quantifier(n)->get_num_decls(), to_quantifier(n)->get_decl_sorts());
inc_ref(to_quantifier(n)->get_expr());
inc_array_ref(to_quantifier(n)->get_num_decls(), to_quantifier(n)->get_decl_sorts());
inc_ref(to_quantifier(n)->get_expr());
inc_array_ref(to_quantifier(n)->get_num_patterns(), to_quantifier(n)->get_patterns());
inc_array_ref(to_quantifier(n)->get_num_no_patterns(), to_quantifier(n)->get_no_patterns());
break;
break;
default:
break;
break;
}
return n;
}
@ -1721,7 +1721,7 @@ void ast_manager::delete_node(ast * n) {
while (!worklist.empty()) {
n = worklist.back();
worklist.pop_back();
TRACE("ast", tout << "Deleting object " << n->m_id << " " << n << "\n";);
CTRACE("del_quantifier", is_quantifier(n), tout << "deleting quantifier " << n->m_id << " " << n << "\n";);
TRACE("mk_var_bug", tout << "del_ast: " << n->m_id << "\n";);
@ -1770,8 +1770,8 @@ void ast_manager::delete_node(ast * n) {
dec_array_ref(worklist, to_quantifier(n)->get_num_patterns(), to_quantifier(n)->get_patterns());
dec_array_ref(worklist, to_quantifier(n)->get_num_no_patterns(), to_quantifier(n)->get_no_patterns());
break;
default:
break;
default:
break;
}
if (m_debug_ref_count) {
m_debug_free_indices.insert(n->m_id,0);
@ -2567,9 +2567,9 @@ proof * ast_manager::mk_transitivity(proof * p1, proof * p2) {
(is_eq(get_fact(p2)) || is_oeq(get_fact(p2)))));
CTRACE("mk_transitivity", to_app(get_fact(p1))->get_arg(1) != to_app(get_fact(p2))->get_arg(0),
tout << mk_pp(get_fact(p1), *this) << "\n\n" << mk_pp(get_fact(p2), *this) << "\n";
tout << mk_bounded_pp(p1, *this, 5) << "\n\n";
tout << mk_bounded_pp(p2, *this, 5) << "\n\n";
);
tout << mk_bounded_pp(p1, *this, 5) << "\n\n";
tout << mk_bounded_pp(p2, *this, 5) << "\n\n";
);
SASSERT(to_app(get_fact(p1))->get_arg(1) == to_app(get_fact(p2))->get_arg(0));
if (is_reflexivity(p1))
return p2;
@ -2848,7 +2848,7 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
SASSERT(is_or(f1));
app * cls = to_app(f1);
unsigned cls_sz = cls->get_num_args();
CTRACE("cunit_bug", !(num_proofs == cls_sz || (num_proofs == cls_sz + 1 && is_false(new_fact))),
CTRACE("cunit_bug", !(num_proofs == cls_sz || (num_proofs == cls_sz + 1 && is_false(new_fact))),
for (unsigned i = 0; i < num_proofs; i++) tout << mk_pp(get_fact(proofs[i]), *this) << "\n";
tout << "===>\n";
tout << mk_pp(new_fact, *this) << "\n";);

View file

@ -222,34 +222,65 @@ format * smt2_pp_environment::pp_bv_literal(app * t, bool use_bv_lits, bool bv_n
return vf;
}
format * smt2_pp_environment::pp_float_literal(app * t) {
format * smt2_pp_environment::pp_float_literal(app * t, bool use_bv_lits, bool use_float_real_lits) {
mpf_manager & fm = get_futil().fm();
scoped_mpf v(fm);
ast_manager & m = get_manager();
format * body = 0;
VERIFY(get_futil().is_value(t, v));
string_buffer<> buf;
VERIFY(get_futil().is_numeral(t, v));
if (fm.is_nan(v)) {
body = mk_string(get_manager(), "NaN");
buf << "(_ NaN " << v.get().get_ebits() << " " << v.get().get_sbits() << ")";
return mk_string(m, buf.c_str());
}
else if (fm.is_pinf(v)) {
body = mk_string(get_manager(), "plusInfinity");
buf << "(_ +oo " << v.get().get_ebits() << " " << v.get().get_sbits() << ")";
return mk_string(m, buf.c_str());
}
else if (fm.is_ninf(v)) {
body = mk_string(get_manager(), "minusInfinity");
buf << "(_ -oo " << v.get().get_ebits() << " " << v.get().get_sbits() << ")";
return mk_string(m, buf.c_str());
}
else if (fm.is_pzero(v)) {
// TODO: make it SMT 2.0 compatible
body = mk_string(get_manager(), "+0.0");
else if (fm.is_pzero(v)) {
buf << "(_ +zero " << v.get().get_ebits() << " " << v.get().get_sbits() << ")";
return mk_string(m, buf.c_str());
}
else if (fm.is_nzero(v)) {
// TODO: make it SMT 2.0 compatible
body = mk_string(get_manager(), "-0.0");
buf << "(_ -zero " << v.get().get_ebits() << " " << v.get().get_sbits() << ")";
return mk_string(m, buf.c_str());
}
else if (use_float_real_lits)
{
buf << "((_ to_fp " << v.get().get_ebits() << " " <<
v.get().get_sbits() << ") RTZ " <<
fm.to_string(v).c_str() << ")";
return mk_string(m, buf.c_str());
}
else {
// TODO: make it SMT 2.0 compatible
std::string val = fm.to_string(v);
body = mk_string(get_manager(), val.c_str());
if (use_bv_lits)
buf << "(fp #b" << (fm.sgn(v) ? 1 : 0);
else
buf << "(fp (_ bv" << (fm.sgn(v) ? 1 : 0) << " 1)";
body = mk_string(m, buf.c_str());
body = mk_compose(m, body, mk_string(m, " "));
mpf_exp_t exp = fm.exp(v);
const mpz & bias = fm.m_powers2.m1(v.get().get_ebits() - 1);
mpf_exp_t biased_exp = exp + fm.mpz_manager().get_int64(bias);
app_ref e_biased_exp(m);
e_biased_exp = get_bvutil().mk_numeral(biased_exp, v.get().get_ebits());
body = mk_compose(m, body, pp_bv_literal(e_biased_exp, use_bv_lits, false));
body = mk_compose(m, body, mk_string(m, " "));
scoped_mpz sig(fm.mpz_manager());
sig = fm.sig(v);
app_ref e_sig(m);
e_sig = get_bvutil().mk_numeral(rational(sig), v.get().get_sbits() - 1);
body = mk_compose(m, body, pp_bv_literal(e_sig, use_bv_lits, false));
body = mk_compose(m, body, mk_string(m, ")"));
return body;
}
return pp_as(body, get_manager().get_sort(t));
}
// generate (- f)
@ -365,7 +396,7 @@ format_ns::format * smt2_pp_environment::pp_sort(sort * s) {
unsigned ebits = get_futil().get_ebits(s);
unsigned sbits = get_futil().get_sbits(s);
ptr_buffer<format> fs;
fs.push_back(mk_string(m, "FP"));
fs.push_back(mk_string(m, "FloatingPoint"));
fs.push_back(mk_unsigned(m, ebits));
fs.push_back(mk_unsigned(m, sbits));
return mk_seq1(m, fs.begin(), fs.end(), f2f(), "_");
@ -425,6 +456,7 @@ class smt2_printer {
bool m_pp_decimal;
unsigned m_pp_decimal_precision;
bool m_pp_bv_lits;
bool m_pp_float_real_lits;
bool m_pp_bv_neg;
unsigned m_pp_max_depth;
unsigned m_pp_min_alias_size;
@ -543,8 +575,8 @@ class smt2_printer {
else if (m_env.get_bvutil().is_numeral(c)) {
f = m_env.pp_bv_literal(c, m_pp_bv_lits, m_pp_bv_neg);
}
else if (m_env.get_futil().is_value(c)) {
f = m_env.pp_float_literal(c);
else if (m_env.get_futil().is_numeral(c)) {
f = m_env.pp_float_literal(c, m_pp_bv_lits, m_pp_float_real_lits);
}
else if (m_env.get_dlutil().is_numeral(c)) {
f = m_env.pp_datalog_literal(c);
@ -987,6 +1019,7 @@ public:
m_pp_decimal = p.decimal();
m_pp_decimal_precision = p.decimal_precision();
m_pp_bv_lits = p.bv_literals();
m_pp_float_real_lits = p.fp_real_literals();
m_pp_bv_neg = p.bv_neg();
m_pp_max_depth = p.max_depth();
m_pp_min_alias_size = p.min_alias_size();

View file

@ -27,7 +27,7 @@ Revision History:
#include"arith_decl_plugin.h"
#include"bv_decl_plugin.h"
#include"array_decl_plugin.h"
#include"float_decl_plugin.h"
#include"fpa_decl_plugin.h"
#include"dl_decl_plugin.h"
#include"smt2_util.h"
@ -46,13 +46,13 @@ public:
virtual arith_util & get_autil() = 0;
virtual bv_util & get_bvutil() = 0;
virtual array_util & get_arutil() = 0;
virtual float_util & get_futil() = 0;
virtual fpa_util & get_futil() = 0;
virtual datalog::dl_decl_util& get_dlutil() = 0;
virtual bool uses(symbol const & s) const = 0;
virtual format_ns::format * pp_fdecl(func_decl * f, unsigned & len);
virtual format_ns::format * pp_bv_literal(app * t, bool use_bv_lits, bool bv_neg);
virtual format_ns::format * pp_arith_literal(app * t, bool decimal, unsigned prec);
virtual format_ns::format * pp_float_literal(app * t);
virtual format_ns::format * pp_float_literal(app * t, bool use_bv_lits, bool use_float_real_lits);
virtual format_ns::format * pp_datalog_literal(app * t);
virtual format_ns::format * pp_sort(sort * s);
virtual format_ns::format * pp_fdecl_ref(func_decl * f);
@ -69,7 +69,7 @@ class smt2_pp_environment_dbg : public smt2_pp_environment {
arith_util m_autil;
bv_util m_bvutil;
array_util m_arutil;
float_util m_futil;
fpa_util m_futil;
datalog::dl_decl_util m_dlutil;
public:
smt2_pp_environment_dbg(ast_manager & m):m_manager(m), m_autil(m), m_bvutil(m), m_arutil(m), m_futil(m), m_dlutil(m) {}
@ -77,7 +77,7 @@ public:
virtual arith_util & get_autil() { return m_autil; }
virtual bv_util & get_bvutil() { return m_bvutil; }
virtual array_util & get_arutil() { return m_arutil; }
virtual float_util & get_futil() { return m_futil; }
virtual fpa_util & get_futil() { return m_futil; }
virtual datalog::dl_decl_util& get_dlutil() { return m_dlutil; }
virtual bool uses(symbol const & s) const { return false; }
};

View file

@ -1003,7 +1003,7 @@ public:
visit_sort(d->get_domain(i), true);
}
m_out << ")";
}
}
};

View file

@ -136,7 +136,7 @@ void bv_decl_plugin::finalize() {
for (; it != end; ++it) {
ptr_vector<func_decl> & ds = *it;
DEC_REF(ds);
}
}
DEC_REF(m_mkbv);
}
@ -157,13 +157,13 @@ void bv_decl_plugin::mk_bv_sort(unsigned bv_size) {
}
inline sort * bv_decl_plugin::get_bv_sort(unsigned bv_size) {
if (bv_size < (1 << 12)) {
mk_bv_sort(bv_size);
if (bv_size < (1 << 12)) {
mk_bv_sort(bv_size);
return m_bv_sorts[bv_size];
}
parameter p(bv_size);
sort_size sz(sort_size::mk_very_big());
return m_manager->mk_sort(symbol("bv"), sort_info(m_family_id, BV_SORT, sz, 1, &p));
}
parameter p(bv_size);
sort_size sz(sort_size::mk_very_big());
return m_manager->mk_sort(symbol("bv"), sort_info(m_family_id, BV_SORT, sz, 1, &p));
}
sort * bv_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) {

View file

@ -919,9 +919,9 @@ void datatype_util::display_datatype(sort *s0, std::ostream& strm) {
todo.push_back(s0);
mark.mark(s0, true);
while (!todo.empty()) {
sort* s = todo.back();
sort* s = todo.back();
todo.pop_back();
strm << s->get_name() << " =\n";
strm << s->get_name() << " =\n";
ptr_vector<func_decl> const * cnstrs = get_datatype_constructors(s);
for (unsigned i = 0; i < cnstrs->size(); ++i) {
@ -931,14 +931,14 @@ void datatype_util::display_datatype(sort *s0, std::ostream& strm) {
ptr_vector<func_decl> const * accs = get_constructor_accessors(cns);
for (unsigned j = 0; j < accs->size(); ++j) {
func_decl* acc = (*accs)[j];
sort* s1 = acc->get_range();
sort* s1 = acc->get_range();
strm << "(" << acc->get_name() << ": " << s1->get_name() << ") ";
if (is_datatype(s1) && are_siblings(s1, s0) && !mark.is_marked(s1)) {
mark.mark(s1, true);
todo.push_back(s1);
}
}
strm << "\n";
strm << "\n";
}
}

View file

@ -1,746 +0,0 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
float_decl_plugin.cpp
Abstract:
Floating point decl plugin
Author:
Leonardo de Moura (leonardo) 2012-01-15.
Revision History:
--*/
#include"float_decl_plugin.h"
#include"arith_decl_plugin.h"
#include"bv_decl_plugin.h"
float_decl_plugin::float_decl_plugin():
m_values(m_fm),
m_value_table(mpf_hash_proc(m_values), mpf_eq_proc(m_values)) {
m_real_sort = 0;
m_int_sort = 0;
m_bv_plugin = 0;
}
void float_decl_plugin::set_manager(ast_manager * m, family_id id) {
decl_plugin::set_manager(m, id);
family_id aid = m_manager->mk_family_id("arith");
m_real_sort = m_manager->mk_sort(aid, REAL_SORT);
SASSERT(m_real_sort != 0); // arith_decl_plugin must be installed before float_decl_plugin.
m_manager->inc_ref(m_real_sort);
m_int_sort = m_manager->mk_sort(aid, INT_SORT);
SASSERT(m_int_sort != 0); // arith_decl_plugin must be installed before float_decl_plugin.
m_manager->inc_ref(m_int_sort);
// BV is not optional anymore.
SASSERT(m_manager->has_plugin(symbol("bv")));
m_bv_fid = m_manager->mk_family_id("bv");
m_bv_plugin = static_cast<bv_decl_plugin*>(m_manager->get_plugin(m_bv_fid));
}
float_decl_plugin::~float_decl_plugin() {
}
unsigned float_decl_plugin::mk_id(mpf const & v) {
unsigned new_id = m_id_gen.mk();
m_values.reserve(new_id+1);
m_fm.set(m_values[new_id], v);
unsigned old_id = m_value_table.insert_if_not_there(new_id);
if (old_id != new_id) {
m_id_gen.recycle(new_id);
m_fm.del(m_values[new_id]);
}
return old_id;
}
void float_decl_plugin::recycled_id(unsigned id) {
SASSERT(m_value_table.contains(id));
m_value_table.erase(id);
m_id_gen.recycle(id);
m_fm.del(m_values[id]);
}
func_decl * float_decl_plugin::mk_value_decl(mpf const & v) {
parameter p(mk_id(v), true);
SASSERT(p.is_external());
sort * s = mk_float_sort(v.get_ebits(), v.get_sbits());
return m_manager->mk_const_decl(symbol("float"), s, func_decl_info(m_family_id, OP_FLOAT_VALUE, 1, &p));
}
app * float_decl_plugin::mk_value(mpf const & v) {
return m_manager->mk_const(mk_value_decl(v));
}
bool float_decl_plugin::is_value(expr * n, mpf & val) {
if (is_app_of(n, m_family_id, OP_FLOAT_VALUE)) {
m_fm.set(val, m_values[to_app(n)->get_decl()->get_parameter(0).get_ext_id()]);
return true;
}
else if (is_app_of(n, m_family_id, OP_FLOAT_MINUS_INF)) {
unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
m_fm.mk_ninf(ebits, sbits, val);
return true;
}
else if (is_app_of(n, m_family_id, OP_FLOAT_PLUS_INF)) {
unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
m_fm.mk_pinf(ebits, sbits, val);
return true;
}
else if (is_app_of(n, m_family_id, OP_FLOAT_NAN)) {
unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
m_fm.mk_nan(ebits, sbits, val);
return true;
}
else if (is_app_of(n, m_family_id, OP_FLOAT_PLUS_ZERO)) {
unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
m_fm.mk_pzero(ebits, sbits, val);
return true;
}
else if (is_app_of(n, m_family_id, OP_FLOAT_MINUS_ZERO)) {
unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int();
unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int();
m_fm.mk_nzero(ebits, sbits, val);
return true;
}
return false;
}
bool float_decl_plugin::is_rm_value(expr * n, mpf_rounding_mode & val) {
if (is_app_of(n, m_family_id, OP_RM_NEAREST_TIES_TO_AWAY)) {
val = MPF_ROUND_NEAREST_TAWAY;
return true;
}
else if (is_app_of(n, m_family_id, OP_RM_NEAREST_TIES_TO_EVEN)) {
val = MPF_ROUND_NEAREST_TEVEN;
return true;
}
else if (is_app_of(n, m_family_id, OP_RM_TOWARD_NEGATIVE)) {
val = MPF_ROUND_TOWARD_NEGATIVE;
return true;
}
else if (is_app_of(n, m_family_id, OP_RM_TOWARD_POSITIVE)) {
val = MPF_ROUND_TOWARD_POSITIVE;
return true;
}
else if (is_app_of(n, m_family_id, OP_RM_TOWARD_ZERO)) {
val = MPF_ROUND_TOWARD_ZERO;
return true;
}
return 0;
}
void float_decl_plugin::del(parameter const & p) {
SASSERT(p.is_external());
recycled_id(p.get_ext_id());
}
parameter float_decl_plugin::translate(parameter const & p, decl_plugin & target) {
SASSERT(p.is_external());
float_decl_plugin & _target = static_cast<float_decl_plugin&>(target);
return parameter(_target.mk_id(m_values[p.get_ext_id()]), true);
}
void float_decl_plugin::finalize() {
if (m_real_sort) { m_manager->dec_ref(m_real_sort); }
if (m_int_sort) { m_manager->dec_ref(m_int_sort); }
}
decl_plugin * float_decl_plugin::mk_fresh() {
return alloc(float_decl_plugin);
}
sort * float_decl_plugin::mk_float_sort(unsigned ebits, unsigned sbits) {
parameter p1(ebits), p2(sbits);
parameter ps[2] = { p1, p2 };
sort_size sz;
sz = sort_size::mk_very_big(); // TODO: refine
return m_manager->mk_sort(symbol("FloatingPoint"), sort_info(m_family_id, FLOAT_SORT, sz, 2, ps));
}
sort * float_decl_plugin::mk_rm_sort() {
return m_manager->mk_sort(symbol("RoundingMode"), sort_info(m_family_id, ROUNDING_MODE_SORT));
}
sort * float_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) {
switch (k) {
case FLOAT_SORT:
if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) {
m_manager->raise_exception("expecting two integer parameters to floating point sort");
}
if (parameters[0].get_int() <= 1 || parameters[1].get_int() <= 1)
m_manager->raise_exception("floating point sorts need parameters > 1");
if (parameters[0].get_int() > parameters[1].get_int())
m_manager->raise_exception("floating point sorts with ebits > sbits are currently not supported");
return mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
case ROUNDING_MODE_SORT:
return mk_rm_sort();
case FLOAT16_SORT:
return mk_float_sort(5, 11);
case FLOAT32_SORT:
return mk_float_sort(8, 24);
case FLOAT64_SORT:
return mk_float_sort(11, 53);
case FLOAT128_SORT:
return mk_float_sort(15, 133);
default:
m_manager->raise_exception("unknown floating point theory sort");
return 0;
}
}
func_decl * float_decl_plugin::mk_rm_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (num_parameters != 0)
m_manager->raise_exception("rounding mode constant does not have parameters");
if (arity != 0)
m_manager->raise_exception("rounding mode is a constant");
sort * s = mk_rm_sort();
func_decl_info finfo(m_family_id, k);
switch (k) {
case OP_RM_NEAREST_TIES_TO_EVEN:
return m_manager->mk_const_decl(symbol("roundNearestTiesToEven"), s, finfo);
case OP_RM_NEAREST_TIES_TO_AWAY:
return m_manager->mk_const_decl(symbol("roundNearestTiesToAway"), s, finfo);
case OP_RM_TOWARD_POSITIVE:
return m_manager->mk_const_decl(symbol("roundTowardPositive"), s, finfo);
case OP_RM_TOWARD_NEGATIVE:
return m_manager->mk_const_decl(symbol("roundTowardNegative"), s, finfo);
case OP_RM_TOWARD_ZERO:
return m_manager->mk_const_decl(symbol("roundTowardZero"), s, finfo);
default:
UNREACHABLE();
return 0;
}
}
func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
sort * s;
if (num_parameters == 1 && parameters[0].is_ast() && is_sort(parameters[0].get_ast()) && is_float_sort(to_sort(parameters[0].get_ast()))) {
s = to_sort(parameters[0].get_ast());
}
else if (num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()) {
s = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
}
else if (range != 0 && is_float_sort(range)) {
s = range;
}
else {
m_manager->raise_exception("sort of floating point constant was not specified");
UNREACHABLE();
}
SASSERT(is_sort_of(s, m_family_id, FLOAT_SORT));
unsigned ebits = s->get_parameter(0).get_int();
unsigned sbits = s->get_parameter(1).get_int();
scoped_mpf val(m_fm);
switch (k)
{
case OP_FLOAT_NAN: m_fm.mk_nan(ebits, sbits, val);
SASSERT(m_fm.is_nan(val));
break;
case OP_FLOAT_MINUS_INF: m_fm.mk_ninf(ebits, sbits, val); break;
case OP_FLOAT_PLUS_INF: m_fm.mk_pinf(ebits, sbits, val); break;
case OP_FLOAT_MINUS_ZERO: m_fm.mk_nzero(ebits, sbits, val); break;
case OP_FLOAT_PLUS_ZERO: m_fm.mk_pzero(ebits, sbits, val); break;
}
return mk_value_decl(val);
}
func_decl * float_decl_plugin::mk_bin_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (arity != 2)
m_manager->raise_exception("invalid number of arguments to floating point relation");
if (domain[0] != domain[1] || !is_float_sort(domain[0]))
m_manager->raise_exception("sort mismatch, expected equal FloatingPoint sorts as arguments");
symbol name;
switch (k) {
case OP_FLOAT_EQ: name = "fp.eq"; break;
case OP_FLOAT_LT: name = "fp.lt"; break;
case OP_FLOAT_GT: name = "fp.gt"; break;
case OP_FLOAT_LE: name = "fp.lte"; break;
case OP_FLOAT_GE: name = "fp.gte"; break;
default:
UNREACHABLE();
break;
}
func_decl_info finfo(m_family_id, k);
finfo.set_chainable(true);
return m_manager->mk_func_decl(name, arity, domain, m_manager->mk_bool_sort(), finfo);
}
func_decl * float_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (arity != 1)
m_manager->raise_exception("invalid number of arguments to floating point relation");
if (!is_float_sort(domain[0]))
m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort");
symbol name;
switch (k) {
case OP_FLOAT_IS_ZERO: name = "fp.isZero"; break;
case OP_FLOAT_IS_NZERO: name = "fp.isNZero"; break;
case OP_FLOAT_IS_PZERO: name = "fp.isPZero"; break;
case OP_FLOAT_IS_NEGATIVE: name = "fp.isNegative"; break;
case OP_FLOAT_IS_POSITIVE: name = "fp.isPositive"; break;
case OP_FLOAT_IS_NAN: name = "fp.isNaN"; break;
case OP_FLOAT_IS_INF: name = "fp.isInfinite"; break;
case OP_FLOAT_IS_NORMAL: name = "fp.isNormal"; break;
case OP_FLOAT_IS_SUBNORMAL: name = "fp.isSubnormal"; break;
default:
UNREACHABLE();
break;
}
return m_manager->mk_func_decl(name, arity, domain, m_manager->mk_bool_sort(), func_decl_info(m_family_id, k));
}
func_decl * float_decl_plugin::mk_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (arity != 1)
m_manager->raise_exception("invalid number of arguments to floating point operator");
if (!is_float_sort(domain[0]))
m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort");
symbol name;
switch (k) {
case OP_FLOAT_ABS: name = "fp.abs"; break;
case OP_FLOAT_NEG: name = "fp.neg"; break;
default:
UNREACHABLE();
break;
}
return m_manager->mk_func_decl(name, arity, domain, domain[0], func_decl_info(m_family_id, k));
}
func_decl * float_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (arity != 2)
m_manager->raise_exception("invalid number of arguments to floating point operator");
if (domain[0] != domain[1] || !is_float_sort(domain[0]))
m_manager->raise_exception("sort mismatch, expected arguments of equal FloatingPoint sorts");
symbol name;
switch (k) {
case OP_FLOAT_REM: name = "fp.rem"; break;
case OP_FLOAT_MIN: name = "fp.min"; break;
case OP_FLOAT_MAX: name = "fp.max"; break;
default:
UNREACHABLE();
break;
}
return m_manager->mk_func_decl(name, arity, domain, domain[0], func_decl_info(m_family_id, k));
}
func_decl * float_decl_plugin::mk_rm_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (arity != 3)
m_manager->raise_exception("invalid number of arguments to floating point operator");
if (!is_rm_sort(domain[0]))
m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort");
if (domain[1] != domain[2] || !is_float_sort(domain[1]))
m_manager->raise_exception("sort mismatch, expected arguments 1 and 2 of equal FloatingPoint sorts");
symbol name;
switch (k) {
case OP_FLOAT_ADD: name = "fp.add"; break;
case OP_FLOAT_SUB: name = "fp.sub"; break;
case OP_FLOAT_MUL: name = "fp.mul"; break;
case OP_FLOAT_DIV: name = "fp.div"; break;
default:
UNREACHABLE();
break;
}
return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k));
}
func_decl * float_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (arity != 2)
m_manager->raise_exception("invalid number of arguments to floating point operator");
if (!is_rm_sort(domain[0]))
m_manager->raise_exception("sort mismatch, expected RoundingMode as first argument");
if (!is_float_sort(domain[1]))
m_manager->raise_exception("sort mismatch, expected FloatingPoint as second argument");
symbol name;
switch (k) {
case OP_FLOAT_SQRT: name = "fp.sqrt"; break;
case OP_FLOAT_ROUND_TO_INTEGRAL: name = "fp.roundToIntegral"; break;
default:
UNREACHABLE();
break;
}
return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k));
}
func_decl * float_decl_plugin::mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (arity != 4)
m_manager->raise_exception("invalid number of arguments to fused_ma operator");
if (!is_rm_sort(domain[0]))
m_manager->raise_exception("sort mismatch, expected RoundingMode as first argument");
if (domain[1] != domain[2] || domain[1] != domain[3] || !is_float_sort(domain[1]))
m_manager->raise_exception("sort mismatch, expected arguments 1,2,3 of equal FloatingPoint sort");
symbol name("fp.fma");
return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k));
}
func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (m_bv_plugin && arity == 3 &&
is_sort_of(domain[0], m_bv_fid, BV_SORT) &&
is_sort_of(domain[1], m_bv_fid, BV_SORT) &&
is_sort_of(domain[2], m_bv_fid, BV_SORT)) {
// 3 BVs -> 1 FP
sort * fp = mk_float_sort(domain[2]->get_parameter(0).get_int(), domain[1]->get_parameter(0).get_int()+1);
symbol name("fp");
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
}
else if (m_bv_plugin && arity == 1 && is_sort_of(domain[0], m_bv_fid, BV_SORT)) {
// 1 BV -> 1 FP
if (num_parameters != 2)
m_manager->raise_exception("invalid number of parameters to to_fp");
if (!parameters[0].is_int() || !parameters[1].is_int())
m_manager->raise_exception("invalid parameter type to to_fp");
int ebits = parameters[0].get_int();
int sbits = parameters[1].get_int();
sort * fp = mk_float_sort(ebits, sbits);
symbol name("to_fp");
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
}
else if (m_bv_plugin && arity == 2 &&
is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
is_sort_of(domain[1], m_bv_fid, BV_SORT)) {
// Rounding + 1 BV -> 1 FP
if (num_parameters != 2)
m_manager->raise_exception("invalid number of parameters to to_fp");
if (!parameters[0].is_int() || !parameters[1].is_int())
m_manager->raise_exception("invalid parameter type to to_fp");
int ebits = parameters[0].get_int();
int sbits = parameters[1].get_int();
sort * fp = mk_float_sort(ebits, sbits);
symbol name("to_fp");
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
}
else if (arity == 2 &&
is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
is_sort_of(domain[1], m_family_id, FLOAT_SORT)) {
// Rounding + 1 FP -> 1 FP
if (num_parameters != 2)
m_manager->raise_exception("invalid number of parameters to to_fp");
if (!parameters[0].is_int() || !parameters[1].is_int())
m_manager->raise_exception("invalid parameter type to to_fp");
int ebits = parameters[0].get_int();
int sbits = parameters[1].get_int();
if (!is_rm_sort(domain[0]))
m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort");
if (!is_sort_of(domain[1], m_family_id, FLOAT_SORT))
m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort");
sort * fp = mk_float_sort(ebits, sbits);
symbol name("to_fp");
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
}
else {
// 1 Real -> 1 FP
if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
m_manager->raise_exception("expecting two integer parameters to to_fp");
if (arity != 2 && arity != 3)
m_manager->raise_exception("invalid number of arguments to to_fp operator");
if (arity == 3 && domain[2] != m_int_sort)
m_manager->raise_exception("sort mismatch, expected second argument of Int sort");
if (domain[1] != m_real_sort)
m_manager->raise_exception("sort mismatch, expected second argument of Real sort");
sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
symbol name("to_fp");
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
}
}
func_decl * float_decl_plugin::mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (arity != 1)
m_manager->raise_exception("invalid number of arguments to asIEEEBV");
if (!is_float_sort(domain[0]))
m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort");
unsigned float_sz = domain[0]->get_parameter(0).get_int() + domain[0]->get_parameter(1).get_int();
parameter ps[] = { parameter(float_sz) };
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ps);
symbol name("asIEEEBV");
return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
}
func_decl * float_decl_plugin::mk_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (arity != 3)
m_manager->raise_exception("invalid number of arguments to fp");
if (!is_sort_of(domain[0], m_bv_fid, BV_SORT) ||
!is_sort_of(domain[1], m_bv_fid, BV_SORT) ||
!is_sort_of(domain[2], m_bv_fid, BV_SORT))
m_manager->raise_exception("sort mismatch");
sort * fp = mk_float_sort(domain[1]->get_parameter(0).get_int(), domain[2]->get_parameter(0).get_int() + 1);
symbol name("fp");
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k));
}
func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
if (!m_bv_plugin)
m_manager->raise_exception("to_fp_unsigned unsupported; use a logic with BV support");
if (arity != 2)
m_manager->raise_exception("invalid number of arguments to to_fp_unsigned");
if (is_rm_sort(domain[0]))
m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort");
if (!is_sort_of(domain[1], m_bv_fid, BV_SORT))
m_manager->raise_exception("sort mismatch, expected second argument of BV sort");
sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
symbol name("fp.t_ubv");
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k));
}
func_decl * float_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
NOT_IMPLEMENTED_YET();
}
func_decl * float_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
NOT_IMPLEMENTED_YET();
}
func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) {
switch (k) {
case OP_TO_FLOAT:
return mk_to_float(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_MINUS_INF:
case OP_FLOAT_PLUS_INF:
case OP_FLOAT_NAN:
return mk_float_const_decl(k, num_parameters, parameters, arity, domain, range);
case OP_RM_NEAREST_TIES_TO_EVEN:
case OP_RM_NEAREST_TIES_TO_AWAY:
case OP_RM_TOWARD_POSITIVE:
case OP_RM_TOWARD_NEGATIVE:
case OP_RM_TOWARD_ZERO:
return mk_rm_const_decl(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_EQ:
case OP_FLOAT_LT:
case OP_FLOAT_GT:
case OP_FLOAT_LE:
case OP_FLOAT_GE:
return mk_bin_rel_decl(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_IS_ZERO:
case OP_FLOAT_IS_NZERO:
case OP_FLOAT_IS_PZERO:
case OP_FLOAT_IS_NEGATIVE:
case OP_FLOAT_IS_POSITIVE:
case OP_FLOAT_IS_NAN:
case OP_FLOAT_IS_INF:
case OP_FLOAT_IS_NORMAL:
case OP_FLOAT_IS_SUBNORMAL:
return mk_unary_rel_decl(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_ABS:
case OP_FLOAT_NEG:
return mk_unary_decl(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_REM:
case OP_FLOAT_MIN:
case OP_FLOAT_MAX:
return mk_binary_decl(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_ADD:
case OP_FLOAT_MUL:
case OP_FLOAT_DIV:
return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_SUB:
if (arity == 1)
return mk_unary_decl(OP_FLOAT_NEG, num_parameters, parameters, arity, domain, range);
else
return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_SQRT:
case OP_FLOAT_ROUND_TO_INTEGRAL:
return mk_rm_unary_decl(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_FMA:
return mk_fma(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_TO_IEEE_BV:
return mk_float_to_ieee_bv(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_FP:
return mk_from3bv(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_TO_UBV:
return mk_to_ubv(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_TO_SBV:
return mk_to_sbv(k, num_parameters, parameters, arity, domain, range);
case OP_FLOAT_TO_REAL:
return mk_to_real(k, num_parameters, parameters, arity, domain, range);
default:
m_manager->raise_exception("unsupported floating point operator");
return 0;
}
}
void float_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
// These are the operators from the final draft of the SMT FloatingPoint standard
op_names.push_back(builtin_name("+oo", OP_FLOAT_PLUS_INF));
op_names.push_back(builtin_name("-oo", OP_FLOAT_MINUS_INF));
op_names.push_back(builtin_name("+zero", OP_FLOAT_PLUS_ZERO));
op_names.push_back(builtin_name("-zero", OP_FLOAT_MINUS_ZERO));
op_names.push_back(builtin_name("NaN", OP_FLOAT_NAN));
op_names.push_back(builtin_name("roundNearestTiesToEven", OP_RM_NEAREST_TIES_TO_EVEN));
op_names.push_back(builtin_name("roundNearestTiesToAway", OP_RM_NEAREST_TIES_TO_AWAY));
op_names.push_back(builtin_name("roundTowardPositive", OP_RM_TOWARD_POSITIVE));
op_names.push_back(builtin_name("roundTowardNegative", OP_RM_TOWARD_NEGATIVE));
op_names.push_back(builtin_name("roundTowardZero", OP_RM_TOWARD_ZERO));
op_names.push_back(builtin_name("RNE", OP_RM_NEAREST_TIES_TO_EVEN));
op_names.push_back(builtin_name("RNA", OP_RM_NEAREST_TIES_TO_AWAY));
op_names.push_back(builtin_name("RTP", OP_RM_TOWARD_POSITIVE));
op_names.push_back(builtin_name("RTN", OP_RM_TOWARD_NEGATIVE));
op_names.push_back(builtin_name("RTZ", OP_RM_TOWARD_ZERO));
op_names.push_back(builtin_name("fp.abs", OP_FLOAT_ABS));
op_names.push_back(builtin_name("fp.neg", OP_FLOAT_NEG));
op_names.push_back(builtin_name("fp.add", OP_FLOAT_ADD));
op_names.push_back(builtin_name("fp.sub", OP_FLOAT_SUB));
op_names.push_back(builtin_name("fp.mul", OP_FLOAT_MUL));
op_names.push_back(builtin_name("fp.div", OP_FLOAT_DIV));
op_names.push_back(builtin_name("fp.fma", OP_FLOAT_FMA));
op_names.push_back(builtin_name("fp.sqrt", OP_FLOAT_SQRT));
op_names.push_back(builtin_name("fp.rem", OP_FLOAT_REM));
op_names.push_back(builtin_name("fp.roundToIntegral", OP_FLOAT_ROUND_TO_INTEGRAL));
op_names.push_back(builtin_name("fp.min", OP_FLOAT_MIN));
op_names.push_back(builtin_name("fp.max", OP_FLOAT_MAX));
op_names.push_back(builtin_name("fp.leq", OP_FLOAT_LE));
op_names.push_back(builtin_name("fp.lt", OP_FLOAT_LT));
op_names.push_back(builtin_name("fp.geq", OP_FLOAT_GE));
op_names.push_back(builtin_name("fp.gt", OP_FLOAT_GT));
op_names.push_back(builtin_name("fp.eq", OP_FLOAT_EQ));
op_names.push_back(builtin_name("fp.isNormal", OP_FLOAT_IS_NORMAL));
op_names.push_back(builtin_name("fp.isSubnormal", OP_FLOAT_IS_SUBNORMAL));
op_names.push_back(builtin_name("fp.isZero", OP_FLOAT_IS_ZERO));
op_names.push_back(builtin_name("fp.isInfinite", OP_FLOAT_IS_INF));
op_names.push_back(builtin_name("fp.isNaN", OP_FLOAT_IS_NAN));
op_names.push_back(builtin_name("fp.isNegative", OP_FLOAT_IS_NEGATIVE));
op_names.push_back(builtin_name("fp.isPositive", OP_FLOAT_IS_POSITIVE));
op_names.push_back(builtin_name("fp", OP_FLOAT_FP));
op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV));
op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV));
op_names.push_back(builtin_name("to_fp", OP_TO_FLOAT));
}
void float_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbol const & logic) {
sort_names.push_back(builtin_name("FloatingPoint", FLOAT_SORT));
sort_names.push_back(builtin_name("RoundingMode", ROUNDING_MODE_SORT));
// The final theory supports three common FloatingPoint sorts
sort_names.push_back(builtin_name("Float16", FLOAT16_SORT));
sort_names.push_back(builtin_name("Float32", FLOAT32_SORT));
sort_names.push_back(builtin_name("Float64", FLOAT64_SORT));
sort_names.push_back(builtin_name("Float128", FLOAT128_SORT));
}
expr * float_decl_plugin::get_some_value(sort * s) {
SASSERT(s->is_sort_of(m_family_id, FLOAT_SORT));
mpf tmp;
m_fm.mk_nan(s->get_parameter(0).get_int(), s->get_parameter(1).get_int(), tmp);
expr * res = this->mk_value(tmp);
m_fm.del(tmp);
return res;
}
bool float_decl_plugin::is_value(app * e) const {
if (e->get_family_id() != m_family_id)
return false;
switch (e->get_decl_kind()) {
case OP_RM_NEAREST_TIES_TO_EVEN:
case OP_RM_NEAREST_TIES_TO_AWAY:
case OP_RM_TOWARD_POSITIVE:
case OP_RM_TOWARD_NEGATIVE:
case OP_RM_TOWARD_ZERO:
case OP_FLOAT_VALUE:
case OP_FLOAT_PLUS_INF:
case OP_FLOAT_MINUS_INF:
case OP_FLOAT_PLUS_ZERO:
case OP_FLOAT_MINUS_ZERO:
case OP_FLOAT_NAN:
return true;
case OP_TO_FLOAT:
return m_manager->is_value(e->get_arg(0));
default:
return false;
}
}
float_util::float_util(ast_manager & m):
m_manager(m),
m_fid(m.mk_family_id("float")),
m_a_util(m) {
m_plugin = static_cast<float_decl_plugin*>(m.get_plugin(m_fid));
}
float_util::~float_util() {
}
sort * float_util::mk_float_sort(unsigned ebits, unsigned sbits) {
parameter ps[2] = { parameter(ebits), parameter(sbits) };
return m().mk_sort(m_fid, FLOAT_SORT, 2, ps);
}
unsigned float_util::get_ebits(sort * s) {
SASSERT(is_float(s));
return static_cast<unsigned>(s->get_parameter(0).get_int());
}
unsigned float_util::get_sbits(sort * s) {
SASSERT(is_float(s));
return static_cast<unsigned>(s->get_parameter(1).get_int());
}
app * float_util::mk_nan(unsigned ebits, unsigned sbits) {
scoped_mpf v(fm());
fm().mk_nan(ebits, sbits, v);
return mk_value(v);
}
app * float_util::mk_plus_inf(unsigned ebits, unsigned sbits) {
scoped_mpf v(fm());
fm().mk_pinf(ebits, sbits, v);
return mk_value(v);
}
app * float_util::mk_minus_inf(unsigned ebits, unsigned sbits) {
scoped_mpf v(fm());
fm().mk_ninf(ebits, sbits, v);
return mk_value(v);
}
app * float_util::mk_pzero(unsigned ebits, unsigned sbits) {
scoped_mpf v(fm());
fm().mk_pzero(ebits, sbits, v);
return mk_value(v);
}
app * float_util::mk_nzero(unsigned ebits, unsigned sbits) {
scoped_mpf v(fm());
fm().mk_nzero(ebits, sbits, v);
return mk_value(v);
}

View file

@ -1,284 +0,0 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
float_decl_plugin.h
Abstract:
Floating point decl plugin
Author:
Leonardo de Moura (leonardo) 2012-01-15.
Revision History:
--*/
#ifndef _FLOAT_DECL_PLUGIN_H_
#define _FLOAT_DECL_PLUGIN_H_
#include"ast.h"
#include"id_gen.h"
#include"arith_decl_plugin.h"
#include"bv_decl_plugin.h"
#include"mpf.h"
enum float_sort_kind {
FLOAT_SORT,
ROUNDING_MODE_SORT,
FLOAT16_SORT,
FLOAT32_SORT,
FLOAT64_SORT,
FLOAT128_SORT
};
enum float_op_kind {
OP_RM_NEAREST_TIES_TO_EVEN,
OP_RM_NEAREST_TIES_TO_AWAY,
OP_RM_TOWARD_POSITIVE,
OP_RM_TOWARD_NEGATIVE,
OP_RM_TOWARD_ZERO,
OP_FLOAT_VALUE,
OP_FLOAT_PLUS_INF,
OP_FLOAT_MINUS_INF,
OP_FLOAT_NAN,
OP_FLOAT_PLUS_ZERO,
OP_FLOAT_MINUS_ZERO,
OP_FLOAT_ADD,
OP_FLOAT_SUB,
OP_FLOAT_NEG,
OP_FLOAT_MUL,
OP_FLOAT_DIV,
OP_FLOAT_REM,
OP_FLOAT_ABS,
OP_FLOAT_MIN,
OP_FLOAT_MAX,
OP_FLOAT_FMA, // x*y + z
OP_FLOAT_SQRT,
OP_FLOAT_ROUND_TO_INTEGRAL,
OP_FLOAT_EQ,
OP_FLOAT_LT,
OP_FLOAT_GT,
OP_FLOAT_LE,
OP_FLOAT_GE,
OP_FLOAT_IS_NAN,
OP_FLOAT_IS_INF,
OP_FLOAT_IS_ZERO,
OP_FLOAT_IS_NORMAL,
OP_FLOAT_IS_SUBNORMAL,
OP_FLOAT_IS_PZERO,
OP_FLOAT_IS_NZERO,
OP_FLOAT_IS_NEGATIVE,
OP_FLOAT_IS_POSITIVE,
OP_TO_FLOAT,
OP_FLOAT_TO_IEEE_BV,
OP_FLOAT_FP,
OP_FLOAT_TO_FP,
OP_FLOAT_TO_UBV,
OP_FLOAT_TO_SBV,
OP_FLOAT_TO_REAL,
LAST_FLOAT_OP
};
class float_decl_plugin : public decl_plugin {
struct mpf_hash_proc {
scoped_mpf_vector const & m_values;
mpf_hash_proc(scoped_mpf_vector const & values):m_values(values) {}
unsigned operator()(unsigned id) const { return m_values.m().hash(m_values[id]); }
};
struct mpf_eq_proc {
scoped_mpf_vector const & m_values;
mpf_eq_proc(scoped_mpf_vector const & values):m_values(values) {}
bool operator()(unsigned id1, unsigned id2) const { return m_values.m().eq_core(m_values[id1], m_values[id2]); }
};
typedef chashtable<unsigned, mpf_hash_proc, mpf_eq_proc> value_table;
mpf_manager m_fm;
id_gen m_id_gen;
scoped_mpf_vector m_values;
value_table m_value_table;
sort * m_real_sort;
sort * m_int_sort;
family_id m_bv_fid;
bv_decl_plugin * m_bv_plugin;
sort * mk_float_sort(unsigned ebits, unsigned sbits);
sort * mk_rm_sort();
func_decl * mk_rm_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_float_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_bin_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_unary_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_rm_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_rm_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_to_float(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
virtual void set_manager(ast_manager * m, family_id id);
unsigned mk_id(mpf const & v);
void recycled_id(unsigned id);
public:
float_decl_plugin();
bool is_float_sort(sort * s) const { return is_sort_of(s, m_family_id, FLOAT_SORT); }
bool is_rm_sort(sort * s) const { return is_sort_of(s, m_family_id, ROUNDING_MODE_SORT); }
virtual ~float_decl_plugin();
virtual void finalize();
virtual decl_plugin * mk_fresh();
virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters);
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic);
virtual void get_sort_names(svector<builtin_name> & sort_names, symbol const & logic);
virtual expr * get_some_value(sort * s);
virtual bool is_value(app* e) const;
virtual bool is_unique_value(app* e) const { return is_value(e); }
mpf_manager & fm() { return m_fm; }
func_decl * mk_value_decl(mpf const & v);
app * mk_value(mpf const & v);
bool is_value(expr * n) { return is_app_of(n, m_family_id, OP_FLOAT_VALUE); }
bool is_value(expr * n, mpf & val);
bool is_rm_value(expr * n, mpf_rounding_mode & val);
bool is_rm_value(expr * n) { mpf_rounding_mode t; return is_rm_value(n, t); }
mpf const & get_value(unsigned id) const {
SASSERT(m_value_table.contains(id));
return m_values[id];
}
virtual void del(parameter const & p);
virtual parameter translate(parameter const & p, decl_plugin & target);
};
class float_util {
ast_manager & m_manager;
float_decl_plugin * m_plugin;
family_id m_fid;
arith_util m_a_util;
public:
float_util(ast_manager & m);
~float_util();
ast_manager & m() const { return m_manager; }
mpf_manager & fm() const { return m_plugin->fm(); }
family_id get_fid() const { return m_fid; }
family_id get_family_id() const { return m_fid; }
arith_util & au() { return m_a_util; }
float_decl_plugin & plugin() { return *m_plugin; }
sort * mk_float_sort(unsigned ebits, unsigned sbits);
sort * mk_rm_sort() { return m().mk_sort(m_fid, ROUNDING_MODE_SORT); }
bool is_float(sort * s) { return is_sort_of(s, m_fid, FLOAT_SORT); }
bool is_rm(sort * s) { return is_sort_of(s, m_fid, ROUNDING_MODE_SORT); }
bool is_float(expr * e) { return is_float(m_manager.get_sort(e)); }
bool is_rm(expr * e) { return is_rm(m_manager.get_sort(e)); }
unsigned get_ebits(sort * s);
unsigned get_sbits(sort * s);
app * mk_round_nearest_ties_to_even() { return m().mk_const(m_fid, OP_RM_NEAREST_TIES_TO_EVEN); }
app * mk_round_nearest_ties_to_away() { return m().mk_const(m_fid, OP_RM_NEAREST_TIES_TO_AWAY); }
app * mk_round_toward_positive() { return m().mk_const(m_fid, OP_RM_TOWARD_POSITIVE); }
app * mk_round_toward_negative() { return m().mk_const(m_fid, OP_RM_TOWARD_NEGATIVE); }
app * mk_round_toward_zero() { return m().mk_const(m_fid, OP_RM_TOWARD_ZERO); }
app * mk_nan(unsigned ebits, unsigned sbits);
app * mk_plus_inf(unsigned ebits, unsigned sbits);
app * mk_minus_inf(unsigned ebits, unsigned sbits);
app * mk_nan(sort * s) { return mk_nan(get_ebits(s), get_sbits(s)); }
app * mk_plus_inf(sort * s) { return mk_plus_inf(get_ebits(s), get_sbits(s)); }
app * mk_minus_inf(sort * s) { return mk_minus_inf(get_ebits(s), get_sbits(s)); }
app * mk_value(mpf const & v) { return m_plugin->mk_value(v); }
bool is_value(expr * n) { return m_plugin->is_value(n); }
bool is_value(expr * n, mpf & v) { return m_plugin->is_value(n, v); }
bool is_rm_value(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm_value(n, v); }
app * mk_pzero(unsigned ebits, unsigned sbits);
app * mk_nzero(unsigned ebits, unsigned sbits);
app * mk_pzero(sort * s) { return mk_pzero(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_value(n, v) && fm().is_nan(v); }
bool is_plus_inf(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pinf(v); }
bool is_minus_inf(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_ninf(v); }
bool is_zero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_zero(v); }
bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pzero(v); }
bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nzero(v); }
bool is_to_float(expr * n) { return is_app_of(n, m_fid, OP_TO_FLOAT); }
app * mk_to_float(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_TO_FLOAT, arg1, arg2); }
app * mk_add(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_ADD, arg1, arg2, arg3); }
app * mk_mul(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_MUL, arg1, arg2, arg3); }
app * mk_sub(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_SUB, arg1, arg2, arg3); }
app * mk_div(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_DIV, arg1, arg2, arg3); }
app * mk_neg(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_NEG, arg1); }
app * mk_rem(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_REM, arg1, arg2); }
app * mk_max(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MAX, arg1, arg2); }
app * mk_min(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MIN, arg1, arg2); }
app * mk_abs(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1); }
app * mk_sqrt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_SQRT, arg1, arg2); }
app * mk_round(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ROUND_TO_INTEGRAL, arg1, arg2); }
app * mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) {
expr * args[4] = { arg1, arg2, arg3, arg4 };
return m().mk_app(m_fid, OP_FLOAT_FMA, 4, args);
}
app * mk_float_eq(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_EQ, arg1, arg2); }
app * mk_lt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_LT, arg1, arg2); }
app * mk_gt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_GT, arg1, arg2); }
app * mk_le(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_LE, arg1, arg2); }
app * mk_ge(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_GE, arg1, arg2); }
app * mk_is_nan(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NAN, arg1); }
app * mk_is_inf(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_INF, arg1); }
app * mk_is_zero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_ZERO, arg1); }
app * mk_is_normal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NORMAL, arg1); }
app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SUBNORMAL, arg1); }
app * mk_is_nzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NZERO, arg1); }
app * mk_is_pzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_PZERO, arg1); }
app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); }
app * mk_is_positive(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_POSITIVE, arg1); }
app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); }
bool is_neg(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_NEG); }
app * mk_float_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_TO_IEEE_BV, arg1); }
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -22,11 +22,11 @@ Notes:
#include"ast.h"
#include"obj_hashtable.h"
#include"ref_util.h"
#include"float_decl_plugin.h"
#include"fpa_decl_plugin.h"
#include"bv_decl_plugin.h"
#include"basic_simplifier_plugin.h"
typedef enum { BV_RM_TIES_TO_AWAY=0, BV_RM_TIES_TO_EVEN=1, BV_RM_TO_NEGATIVE=2, BV_RM_TO_POSITIVE=3, BV_RM_TO_ZERO=4 } BV_RM_VAL;
typedef enum { BV_RM_TIES_TO_EVEN, BV_RM_TIES_TO_AWAY, BV_RM_TO_POSITIVE, BV_RM_TO_NEGATIVE, BV_RM_TO_ZERO = 4 } BV_RM_VAL;
struct func_decl_triple {
func_decl_triple () { f_sgn = 0; f_sig = 0; f_exp = 0; }
@ -42,14 +42,16 @@ struct func_decl_triple {
};
class fpa2bv_converter {
protected:
ast_manager & m;
basic_simplifier_plugin m_simp;
float_util m_util;
fpa_util m_util;
bv_util m_bv_util;
arith_util m_arith_util;
mpf_manager & m_mpf_manager;
unsynch_mpz_manager & m_mpz_manager;
float_decl_plugin * m_plugin;
fpa_decl_plugin * m_plugin;
bool m_hi_fp_unspecified;
obj_map<func_decl, expr*> m_const2bv;
obj_map<func_decl, expr*> m_rm_const2bv;
@ -60,8 +62,9 @@ public:
fpa2bv_converter(ast_manager & m);
~fpa2bv_converter();
float_util & fu() { return m_util; }
fpa_util & fu() { return m_util; }
bv_util & bu() { return m_bv_util; }
arith_util & au() { return m_arith_util; }
bool is_float(sort * s) { return m_util.is_float(s); }
bool is_float(expr * e) { return is_app(e) && m_util.is_float(to_app(e)->get_decl()->get_range()); }
@ -69,25 +72,24 @@ public:
bool is_rm(sort * s) { return m_util.is_rm(s); }
bool is_float_family(func_decl * f) { return f->get_family_id() == m_util.get_family_id(); }
void mk_triple(expr * sign, expr * significand, expr * exponent, expr_ref & result) {
SASSERT(m_bv_util.is_bv(sign) && m_bv_util.get_bv_size(sign) == 1);
SASSERT(m_bv_util.is_bv(significand));
SASSERT(m_bv_util.is_bv(exponent));
result = m.mk_app(m_util.get_family_id(), OP_TO_FLOAT, sign, significand, exponent);
}
void mk_fp(expr * sign, expr * exponent, expr * significand, expr_ref & result);
void mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void split_fp(expr * e, expr * & sgn, expr * & exp, expr * & sig) const;
void split_fp(expr * e, expr_ref & sgn, expr_ref & exp, expr_ref & sig) const;
void mk_eq(expr * a, expr * b, expr_ref & result);
void mk_ite(expr * c, expr * t, expr * f, expr_ref & result);
void mk_rounding_mode(func_decl * f, expr_ref & result);
void mk_value(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_const(func_decl * f, expr_ref & result);
void mk_rm_const(func_decl * f, expr_ref & result);
void mk_numeral(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
virtual void mk_const(func_decl * f, expr_ref & result);
virtual void mk_rm_const(func_decl * f, expr_ref & result);
void mk_uninterpreted_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_var(unsigned base_inx, sort * srt, expr_ref & result);
void mk_plus_inf(func_decl * f, expr_ref & result);
void mk_minus_inf(func_decl * f, expr_ref & result);
void mk_pinf(func_decl * f, expr_ref & result);
void mk_ninf(func_decl * f, expr_ref & result);
void mk_nan(func_decl * f, expr_ref & result);
void mk_nzero(func_decl *f, expr_ref & result);
void mk_pzero(func_decl *f, expr_ref & result);
@ -119,28 +121,36 @@ public:
void mk_is_nan(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_is_inf(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_is_normal(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_is_subnormal(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_is_subnormal(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_float(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_fp_float(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result);
void mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result);
void mk_to_fp_real_int(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void set_unspecified_fp_hi(bool v) { m_hi_fp_unspecified = v; }
expr_ref mk_to_ubv_unspecified(unsigned width);
expr_ref mk_to_sbv_unspecified(unsigned width);
expr_ref mk_to_real_unspecified();
obj_map<func_decl, expr*> const & const2bv() const { return m_const2bv; }
obj_map<func_decl, expr*> const & rm_const2bv() const { return m_rm_const2bv; }
obj_map<func_decl, func_decl*> const & uf2bvuf() const { return m_uf2bvuf; }
obj_map<func_decl, func_decl_triple> const & uf23bvuf() const { return m_uf23bvuf; }
void reset(void);
void dbg_decouple(const char * prefix, expr_ref & e);
expr_ref_vector extra_assertions;
expr_ref_vector m_extra_assertions;
protected:
void split(expr * e, expr * & sgn, expr * & sig, expr * & exp) const;
void mk_is_nan(expr * e, expr_ref & result);
void mk_is_inf(expr * e, expr_ref & result);
void mk_is_pinf(expr * e, expr_ref & result);
@ -167,10 +177,13 @@ protected:
void unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & lz, bool normalize);
void round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & result);
expr_ref mk_rounding_decision(expr * rm, expr * sgn, expr * last, expr * round, expr * sticky);
void add_core(unsigned sbits, unsigned ebits, expr_ref & rm,
expr_ref & c_sgn, expr_ref & c_sig, expr_ref & c_exp, expr_ref & d_sgn, expr_ref & d_sig, expr_ref & d_exp,
expr_ref & res_sgn, expr_ref & res_sig, expr_ref & res_exp);
app * mk_fresh_const(char const * prefix, unsigned sz);
};
#endif

View file

@ -24,6 +24,7 @@ Notes:
#include"rewriter_def.h"
#include"bv_decl_plugin.h"
#include"fpa2bv_converter.h"
#include"fpa2bv_rewriter_params.hpp"
struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
ast_manager & m_manager;
@ -36,7 +37,7 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
ast_manager & m() const { return m_manager; }
fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c, params_ref const & p):
fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c, params_ref const & p) :
m_manager(m),
m_out(m),
m_conv(c),
@ -58,9 +59,16 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
void reset() {
}
void updt_local_params(params_ref const & _p) {
fpa2bv_rewriter_params p(_p);
bool v = p.hi_fp_unspecified();
m_conv.set_unspecified_fp_hi(v);
}
void updt_params(params_ref const & p) {
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
m_max_steps = p.get_uint("max_steps", UINT_MAX);
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
m_max_steps = p.get_uint("max_steps", UINT_MAX);
updt_local_params(p);
}
bool max_steps_exceeded(unsigned num_steps) const {
@ -107,49 +115,53 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
if (m_conv.is_float_family(f)) {
switch (f->get_decl_kind()) {
case OP_RM_NEAREST_TIES_TO_AWAY:
case OP_RM_NEAREST_TIES_TO_EVEN:
case OP_RM_TOWARD_NEGATIVE:
case OP_RM_TOWARD_POSITIVE:
case OP_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE;
case OP_FLOAT_VALUE: m_conv.mk_value(f, num, args, result); return BR_DONE;
case OP_FLOAT_PLUS_INF: m_conv.mk_plus_inf(f, result); return BR_DONE;
case OP_FLOAT_MINUS_INF: m_conv.mk_minus_inf(f, result); return BR_DONE;
case OP_FLOAT_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE;
case OP_FLOAT_MINUS_ZERO: m_conv.mk_nzero(f, result); return BR_DONE;
case OP_FLOAT_NAN: m_conv.mk_nan(f, result); return BR_DONE;
case OP_FLOAT_ADD: m_conv.mk_add(f, num, args, result); return BR_DONE;
case OP_FLOAT_SUB: m_conv.mk_sub(f, num, args, result); return BR_DONE;
case OP_FLOAT_NEG: m_conv.mk_neg(f, num, args, result); return BR_DONE;
case OP_FLOAT_MUL: m_conv.mk_mul(f, num, args, result); return BR_DONE;
case OP_FLOAT_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE;
case OP_FLOAT_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE;
case OP_FLOAT_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
case OP_FLOAT_MIN: m_conv.mk_min(f, num, args, result); return BR_DONE;
case OP_FLOAT_MAX: m_conv.mk_max(f, num, args, result); return BR_DONE;
case OP_FLOAT_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE;
case OP_FLOAT_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE;
case OP_FLOAT_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE;
case OP_FLOAT_EQ: m_conv.mk_float_eq(f, num, args, result); return BR_DONE;
case OP_FLOAT_LT: m_conv.mk_float_lt(f, num, args, result); return BR_DONE;
case OP_FLOAT_GT: m_conv.mk_float_gt(f, num, args, result); return BR_DONE;
case OP_FLOAT_LE: m_conv.mk_float_le(f, num, args, result); return BR_DONE;
case OP_FLOAT_GE: m_conv.mk_float_ge(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_NZERO: m_conv.mk_is_nzero(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_PZERO: m_conv.mk_is_pzero(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_NAN: m_conv.mk_is_nan(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE;
case OP_TO_FLOAT: m_conv.mk_to_float(f, num, args, result); return BR_DONE;
case OP_FLOAT_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
case OP_FLOAT_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE;
case OP_FLOAT_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE;
case OP_FLOAT_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE;
case OP_FLOAT_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE;
case OP_FPA_RM_NEAREST_TIES_TO_AWAY:
case OP_FPA_RM_NEAREST_TIES_TO_EVEN:
case OP_FPA_RM_TOWARD_NEGATIVE:
case OP_FPA_RM_TOWARD_POSITIVE:
case OP_FPA_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE;
case OP_FPA_NUM: m_conv.mk_numeral(f, num, args, result); return BR_DONE;
case OP_FPA_PLUS_INF: m_conv.mk_pinf(f, result); return BR_DONE;
case OP_FPA_MINUS_INF: m_conv.mk_ninf(f, result); return BR_DONE;
case OP_FPA_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE;
case OP_FPA_MINUS_ZERO: m_conv.mk_nzero(f, result); return BR_DONE;
case OP_FPA_NAN: m_conv.mk_nan(f, result); return BR_DONE;
case OP_FPA_ADD: m_conv.mk_add(f, num, args, result); return BR_DONE;
case OP_FPA_SUB: m_conv.mk_sub(f, num, args, result); return BR_DONE;
case OP_FPA_NEG: m_conv.mk_neg(f, num, args, result); return BR_DONE;
case OP_FPA_MUL: m_conv.mk_mul(f, num, args, result); return BR_DONE;
case OP_FPA_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE;
case OP_FPA_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE;
case OP_FPA_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_DONE;
case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_DONE;
case OP_FPA_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE;
case OP_FPA_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE;
case OP_FPA_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE;
case OP_FPA_EQ: m_conv.mk_float_eq(f, num, args, result); return BR_DONE;
case OP_FPA_LT: m_conv.mk_float_lt(f, num, args, result); return BR_DONE;
case OP_FPA_GT: m_conv.mk_float_gt(f, num, args, result); return BR_DONE;
case OP_FPA_LE: m_conv.mk_float_le(f, num, args, result); return BR_DONE;
case OP_FPA_GE: m_conv.mk_float_ge(f, num, args, result); return BR_DONE;
case OP_FPA_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE;
case OP_FPA_IS_NAN: m_conv.mk_is_nan(f, num, args, result); return BR_DONE;
case OP_FPA_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE;
case OP_FPA_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE;
case OP_FPA_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE;
case OP_FPA_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE;
case OP_FPA_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE;
case OP_FPA_TO_FP: m_conv.mk_to_fp(f, num, args, result); return BR_DONE;
case OP_FPA_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE;
case OP_FPA_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE;
case OP_FPA_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE;
case OP_FPA_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE;
case OP_FPA_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE;
case OP_FPA_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
case OP_FPA_INTERNAL_BVWRAP:
case OP_FPA_INTERNAL_BVUNWRAP:
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: return BR_FAILED;
default:
TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n";
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;);
@ -247,13 +259,13 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
unsigned ebits = m_conv.fu().get_ebits(s);
unsigned sbits = m_conv.fu().get_sbits(s);
new_var = m().mk_var(t->get_idx(), m_conv.bu().mk_sort(sbits+ebits));
m_conv.mk_triple(m_conv.bu().mk_extract(sbits+ebits-1, sbits+ebits-1, new_var),
m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var),
m_conv.bu().mk_extract(ebits-1, 0, new_var),
new_exp);
m_conv.mk_fp(m_conv.bu().mk_extract(sbits+ebits-1, sbits+ebits-1, new_var),
m_conv.bu().mk_extract(ebits - 1, 0, new_var),
m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var),
new_exp);
}
else
new_exp = m().mk_var(t->get_idx(), s);
new_exp = m().mk_var(t->get_idx(), s);
result = new_exp;
result_pr = 0;

View file

@ -0,0 +1,5 @@
def_module_params(module_name='rewriter',
class_name='fpa2bv_rewriter_params',
export=True,
params=(("hi_fp_unspecified", BOOL, True, "use the 'hardware interpretation' for unspecified values in fp.to_ubv, fp.to_sbv, and fp.to_real)"),
))

1000
src/ast/fpa_decl_plugin.cpp Normal file

File diff suppressed because it is too large Load diff

341
src/ast/fpa_decl_plugin.h Normal file
View file

@ -0,0 +1,341 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
fpa_decl_plugin.h
Abstract:
Floating point decl plugin
Author:
Leonardo de Moura (leonardo) 2012-01-15.
Revision History:
--*/
#ifndef _fpa_decl_plugin_H_
#define _fpa_decl_plugin_H_
#include"ast.h"
#include"id_gen.h"
#include"arith_decl_plugin.h"
#include"bv_decl_plugin.h"
#include"mpf.h"
enum fpa_sort_kind {
FLOATING_POINT_SORT,
ROUNDING_MODE_SORT,
FLOAT16_SORT,
FLOAT32_SORT,
FLOAT64_SORT,
FLOAT128_SORT
};
enum fpa_op_kind {
OP_FPA_RM_NEAREST_TIES_TO_EVEN,
OP_FPA_RM_NEAREST_TIES_TO_AWAY,
OP_FPA_RM_TOWARD_POSITIVE,
OP_FPA_RM_TOWARD_NEGATIVE,
OP_FPA_RM_TOWARD_ZERO,
OP_FPA_NUM,
OP_FPA_PLUS_INF,
OP_FPA_MINUS_INF,
OP_FPA_NAN,
OP_FPA_PLUS_ZERO,
OP_FPA_MINUS_ZERO,
OP_FPA_ADD,
OP_FPA_SUB,
OP_FPA_NEG,
OP_FPA_MUL,
OP_FPA_DIV,
OP_FPA_REM,
OP_FPA_ABS,
OP_FPA_MIN,
OP_FPA_MAX,
OP_FPA_FMA, // x*y + z
OP_FPA_SQRT,
OP_FPA_ROUND_TO_INTEGRAL,
OP_FPA_EQ,
OP_FPA_LT,
OP_FPA_GT,
OP_FPA_LE,
OP_FPA_GE,
OP_FPA_IS_NAN,
OP_FPA_IS_INF,
OP_FPA_IS_ZERO,
OP_FPA_IS_NORMAL,
OP_FPA_IS_SUBNORMAL,
OP_FPA_IS_NEGATIVE,
OP_FPA_IS_POSITIVE,
OP_FPA_FP,
OP_FPA_TO_FP,
OP_FPA_TO_FP_UNSIGNED,
OP_FPA_TO_UBV,
OP_FPA_TO_SBV,
OP_FPA_TO_REAL,
/* Extensions */
OP_FPA_TO_IEEE_BV,
/* Internal use only */
OP_FPA_INTERNAL_BVWRAP,
OP_FPA_INTERNAL_BVUNWRAP,
OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED,
OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED,
OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED,
LAST_FLOAT_OP
};
class fpa_decl_plugin : public decl_plugin {
struct mpf_hash_proc {
scoped_mpf_vector const & m_values;
mpf_hash_proc(scoped_mpf_vector const & values):m_values(values) {}
unsigned operator()(unsigned id) const { return m_values.m().hash(m_values[id]); }
};
struct mpf_eq_proc {
scoped_mpf_vector const & m_values;
mpf_eq_proc(scoped_mpf_vector const & values):m_values(values) {}
bool operator()(unsigned id1, unsigned id2) const { return m_values.m().eq_core(m_values[id1], m_values[id2]); }
};
typedef chashtable<unsigned, mpf_hash_proc, mpf_eq_proc> value_table;
mpf_manager m_fm;
id_gen m_id_gen;
scoped_mpf_vector m_values;
value_table m_value_table;
sort * m_real_sort;
sort * m_int_sort;
family_id m_arith_fid;
family_id m_bv_fid;
bv_decl_plugin * m_bv_plugin;
sort * mk_float_sort(unsigned ebits, unsigned sbits);
sort * mk_rm_sort();
func_decl * mk_rm_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_float_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_bin_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_unary_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_rm_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_rm_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_fp(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_to_fp(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_internal_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_internal_bv_unwrap(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_internal_to_ubv_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_internal_to_sbv_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
func_decl * mk_internal_to_real_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
virtual void set_manager(ast_manager * m, family_id id);
unsigned mk_id(mpf const & v);
void recycled_id(unsigned id);
public:
fpa_decl_plugin();
bool is_float_sort(sort * s) const { return is_sort_of(s, m_family_id, FLOATING_POINT_SORT); }
bool is_rm_sort(sort * s) const { return is_sort_of(s, m_family_id, ROUNDING_MODE_SORT); }
virtual ~fpa_decl_plugin();
virtual void finalize();
virtual decl_plugin * mk_fresh();
virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters);
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range);
virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic);
virtual void get_sort_names(svector<builtin_name> & sort_names, symbol const & logic);
virtual expr * get_some_value(sort * s);
virtual bool is_value(app* e) const;
virtual bool is_unique_value(app* e) const;
mpf_manager & fm() { return m_fm; }
func_decl * mk_numeral_decl(mpf const & v);
app * mk_numeral(mpf const & v);
bool is_numeral(expr * n);
bool is_numeral(expr * n, mpf & val);
bool is_rm_numeral(expr * n, mpf_rounding_mode & val);
bool is_rm_numeral(expr * n);
mpf const & get_value(unsigned id) const {
SASSERT(m_value_table.contains(id));
return m_values[id];
}
virtual void del(parameter const & p);
virtual parameter translate(parameter const & p, decl_plugin & target);
};
class fpa_util {
ast_manager & m_manager;
fpa_decl_plugin * m_plugin;
family_id m_fid;
arith_util m_a_util;
bv_util m_bv_util;
public:
fpa_util(ast_manager & m);
~fpa_util();
ast_manager & m() const { return m_manager; }
mpf_manager & fm() const { return m_plugin->fm(); }
family_id get_fid() const { return m_fid; }
family_id get_family_id() const { return m_fid; }
arith_util & au() { return m_a_util; }
fpa_decl_plugin & plugin() { return *m_plugin; }
sort * mk_float_sort(unsigned ebits, unsigned sbits);
sort * mk_rm_sort() { return m().mk_sort(m_fid, ROUNDING_MODE_SORT); }
bool is_float(sort * s) { return is_sort_of(s, m_fid, FLOATING_POINT_SORT); }
bool is_rm(sort * s) { return is_sort_of(s, m_fid, ROUNDING_MODE_SORT); }
bool is_float(expr * e) { return is_float(m_manager.get_sort(e)); }
bool is_rm(expr * e) { return is_rm(m_manager.get_sort(e)); }
unsigned get_ebits(sort * s);
unsigned get_sbits(sort * s);
app * mk_round_nearest_ties_to_even() { return m().mk_const(m_fid, OP_FPA_RM_NEAREST_TIES_TO_EVEN); }
app * mk_round_nearest_ties_to_away() { return m().mk_const(m_fid, OP_FPA_RM_NEAREST_TIES_TO_AWAY); }
app * mk_round_toward_positive() { return m().mk_const(m_fid, OP_FPA_RM_TOWARD_POSITIVE); }
app * mk_round_toward_negative() { return m().mk_const(m_fid, OP_FPA_RM_TOWARD_NEGATIVE); }
app * mk_round_toward_zero() { return m().mk_const(m_fid, OP_FPA_RM_TOWARD_ZERO); }
app * mk_nan(unsigned ebits, unsigned sbits);
app * mk_pinf(unsigned ebits, unsigned sbits);
app * mk_ninf(unsigned ebits, unsigned sbits);
app * mk_nan(sort * s) { return mk_nan(get_ebits(s), get_sbits(s)); }
app * mk_pinf(sort * s) { return mk_pinf(get_ebits(s), get_sbits(s)); }
app * mk_ninf(sort * s) { return mk_ninf(get_ebits(s), get_sbits(s)); }
app * mk_value(mpf const & v) { return m_plugin->mk_numeral(v); }
bool is_numeral(expr * n) { return m_plugin->is_numeral(n); }
bool is_numeral(expr * n, mpf & v) { return m_plugin->is_numeral(n, v); }
bool is_rm_numeral(expr * n) { return m_plugin->is_rm_numeral(n); }
bool is_rm_numeral(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm_numeral(n, v); }
app * mk_pzero(unsigned ebits, unsigned sbits);
app * mk_nzero(unsigned ebits, unsigned sbits);
app * mk_pzero(sort * s) { return mk_pzero(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_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_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_nzero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_nzero(v); }
app * mk_fp(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_FP, arg1, arg2, arg3); }
app * mk_to_fp(sort * s, expr * bv_t) {
SASSERT(is_float(s) && s->get_num_parameters() == 2);
return m().mk_app(m_fid, OP_FPA_TO_FP, 2, s->get_parameters(), 1, &bv_t);
}
app * mk_to_fp(sort * s, expr * rm, expr * t) {
SASSERT(is_float(s) && s->get_num_parameters() == 2);
expr * args[] = { rm, t };
return m().mk_app(m_fid, OP_FPA_TO_FP, 2, s->get_parameters(), 2, args);
}
app * mk_to_fp(sort * s, expr * rm, expr * sig, expr * exp) {
SASSERT(is_float(s) && s->get_num_parameters() == 2);
expr * args[] = { rm, sig, exp };
return m().mk_app(m_fid, OP_FPA_TO_FP, 2, s->get_parameters(), 3, args);
}
app * mk_to_fp_unsigned(sort * s, expr * rm, expr * t) {
SASSERT(is_float(s) && s->get_num_parameters() == 2);
expr * args[] = { rm, t };
return m().mk_app(m_fid, OP_FPA_TO_FP_UNSIGNED, 2, s->get_parameters(), 2, args);
}
bool is_to_fp(expr * n) { return is_app_of(n, m_fid, OP_FPA_TO_FP); }
app * mk_to_ubv(expr * rm, expr * t, unsigned sz) {
parameter ps[] = { parameter(sz) };
expr * args[] = { rm, t };
return m().mk_app(m_fid, OP_FPA_TO_UBV, 1, ps, 2, args); }
app * mk_to_sbv(expr * rm, expr * t, unsigned sz) {
parameter ps[] = { parameter(sz) };
expr * args[] = { rm, t };
return m().mk_app(m_fid, OP_FPA_TO_SBV, 1, ps, 2, args);
}
app * mk_to_real(expr * t) { return m().mk_app(m_fid, OP_FPA_TO_REAL, t); }
app * mk_add(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_ADD, arg1, arg2, arg3); }
app * mk_mul(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_MUL, arg1, arg2, arg3); }
app * mk_sub(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_SUB, arg1, arg2, arg3); }
app * mk_div(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_DIV, arg1, arg2, arg3); }
app * mk_neg(expr * arg1) { return m().mk_app(m_fid, OP_FPA_NEG, arg1); }
app * mk_rem(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_REM, arg1, arg2); }
app * mk_max(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_MAX, arg1, arg2); }
app * mk_min(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_MIN, arg1, arg2); }
app * mk_abs(expr * arg1) { return m().mk_app(m_fid, OP_FPA_ABS, arg1); }
app * mk_sqrt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_SQRT, arg1, arg2); }
app * mk_round_to_integral(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_ROUND_TO_INTEGRAL, arg1, arg2); }
app * mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) {
expr * args[4] = { arg1, arg2, arg3, arg4 };
return m().mk_app(m_fid, OP_FPA_FMA, 4, args);
}
app * mk_float_eq(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_EQ, arg1, arg2); }
app * mk_lt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_LT, arg1, arg2); }
app * mk_gt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_GT, arg1, arg2); }
app * mk_le(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_LE, arg1, arg2); }
app * mk_ge(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_GE, arg1, arg2); }
app * mk_is_nan(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NAN, arg1); }
app * mk_is_inf(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_INF, arg1); }
app * mk_is_zero(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_ZERO, arg1); }
app * mk_is_normal(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NORMAL, arg1); }
app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_SUBNORMAL, arg1); }
app * mk_is_positive(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_POSITIVE, arg1); }
app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NEGATIVE, arg1); }
bool is_neg(expr * a) { return is_app_of(a, m_fid, OP_FPA_NEG); }
app * mk_float_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FPA_TO_IEEE_BV, arg1); }
app * mk_internal_to_ubv_unspecified(unsigned width);
app * mk_internal_to_sbv_unspecified(unsigned width);
app * mk_internal_to_real_unspecified();
bool is_wrap(expr * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BVWRAP); }
bool is_unwrap(expr * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BVUNWRAP); }
};
#endif

View file

@ -10,6 +10,7 @@ def_module_params('pp',
('decimal', BOOL, False, 'pretty print real numbers using decimal notation (the output may be truncated). Z3 adds a ? if the value is not precise'),
('decimal_precision', UINT, 10, 'maximum number of decimal places to be used when pp.decimal=true'),
('bv_literals', BOOL, True, 'use Bit-Vector literals (e.g, #x0F and #b0101) during pretty printing'),
('fp_real_literals', BOOL, False, 'use real-numbered floating point literals (e.g, +1.0p-1) during pretty printing'),
('bv_neg', BOOL, False, 'use bvneg when displaying Bit-Vector literals where the most significant bit is 1'),
('flat_assoc', BOOL, True, 'flat associative operators (when pretty printing SMT2 terms/formulas)'),
('fixed_indent', BOOL, False, 'use a fixed indentation for applications'),

View file

@ -24,7 +24,7 @@ Revision History:
#include"datatype_decl_plugin.h"
#include"dl_decl_plugin.h"
#include"seq_decl_plugin.h"
#include"float_decl_plugin.h"
#include"fpa_decl_plugin.h"
void reg_decl_plugins(ast_manager & m) {
if (!m.get_plugin(m.mk_family_id(symbol("arith")))) {
@ -45,7 +45,7 @@ void reg_decl_plugins(ast_manager & m) {
if (!m.get_plugin(m.mk_family_id(symbol("seq")))) {
m.register_plugin(symbol("seq"), alloc(seq_decl_plugin));
}
if (!m.get_plugin(m.mk_family_id(symbol("float")))) {
m.register_plugin(symbol("float"), alloc(float_decl_plugin));
if (!m.get_plugin(m.mk_family_id(symbol("fpa")))) {
m.register_plugin(symbol("fpa"), alloc(fpa_decl_plugin));
}
}

View file

@ -24,31 +24,31 @@ Revision History:
ast_manager& m = result.get_manager();
uint64 v1, v2;
switch(f->get_decl_kind()) {
case datalog::OP_DL_LT:
if (m_util.is_numeral_ext(args[0], v1) &&
m_util.is_numeral_ext(args[1], v2)) {
result = (v1 < v2)?m.mk_true():m.mk_false();
return BR_DONE;
}
// x < x <=> false
if (args[0] == args[1]) {
result = m.mk_false();
return BR_DONE;
}
// x < 0 <=> false
if (m_util.is_numeral_ext(args[1], v2) && v2 == 0) {
result = m.mk_false();
return BR_DONE;
}
// 0 < x <=> 0 != x
if (m_util.is_numeral_ext(args[1], v1) && v1 == 0) {
result = m.mk_not(m.mk_eq(args[0], args[1]));
return BR_DONE;
}
break;
case datalog::OP_DL_LT:
if (m_util.is_numeral_ext(args[0], v1) &&
m_util.is_numeral_ext(args[1], v2)) {
result = (v1 < v2)?m.mk_true():m.mk_false();
return BR_DONE;
}
// x < x <=> false
if (args[0] == args[1]) {
result = m.mk_false();
return BR_DONE;
}
// x < 0 <=> false
if (m_util.is_numeral_ext(args[1], v2) && v2 == 0) {
result = m.mk_false();
return BR_DONE;
}
// 0 < x <=> 0 != x
if (m_util.is_numeral_ext(args[1], v1) && v1 == 0) {
result = m.mk_not(m.mk_eq(args[0], args[1]));
return BR_DONE;
}
break;
default:
break;
default:
break;
}
return BR_FAILED;
}

View file

@ -1,556 +0,0 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
float_rewriter.cpp
Abstract:
Basic rewriting rules for floating point numbers.
Author:
Leonardo (leonardo) 2012-02-02
Notes:
--*/
#include"float_rewriter.h"
float_rewriter::float_rewriter(ast_manager & m, params_ref const & p):
m_util(m) {
updt_params(p);
}
float_rewriter::~float_rewriter() {
}
void float_rewriter::updt_params(params_ref const & p) {
}
void float_rewriter::get_param_descrs(param_descrs & r) {
}
br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
br_status st = BR_FAILED;
SASSERT(f->get_family_id() == get_fid());
switch (f->get_decl_kind()) {
case OP_TO_FLOAT: st = mk_to_fp(f, num_args, args, result); break;
case OP_FLOAT_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break;
case OP_FLOAT_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break;
case OP_FLOAT_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break;
case OP_FLOAT_MUL: SASSERT(num_args == 3); st = mk_mul(args[0], args[1], args[2], result); break;
case OP_FLOAT_DIV: SASSERT(num_args == 3); st = mk_div(args[0], args[1], args[2], result); break;
case OP_FLOAT_REM: SASSERT(num_args == 2); st = mk_rem(args[0], args[1], result); break;
case OP_FLOAT_ABS: SASSERT(num_args == 1); st = mk_abs(args[0], result); break;
case OP_FLOAT_MIN: SASSERT(num_args == 2); st = mk_min(args[0], args[1], result); break;
case OP_FLOAT_MAX: SASSERT(num_args == 2); st = mk_max(args[0], args[1], result); break;
case OP_FLOAT_FMA: SASSERT(num_args == 4); st = mk_fma(args[0], args[1], args[2], args[3], result); break;
case OP_FLOAT_SQRT: SASSERT(num_args == 2); st = mk_sqrt(args[0], args[1], result); break;
case OP_FLOAT_ROUND_TO_INTEGRAL: SASSERT(num_args == 2); st = mk_round(args[0], args[1], result); break;
case OP_FLOAT_EQ: SASSERT(num_args == 2); st = mk_float_eq(args[0], args[1], result); break;
case OP_FLOAT_LT: SASSERT(num_args == 2); st = mk_lt(args[0], args[1], result); break;
case OP_FLOAT_GT: SASSERT(num_args == 2); st = mk_gt(args[0], args[1], result); break;
case OP_FLOAT_LE: SASSERT(num_args == 2); st = mk_le(args[0], args[1], result); break;
case OP_FLOAT_GE: SASSERT(num_args == 2); st = mk_ge(args[0], args[1], result); break;
case OP_FLOAT_IS_ZERO: SASSERT(num_args == 1); st = mk_is_zero(args[0], result); break;
case OP_FLOAT_IS_NZERO: SASSERT(num_args == 1); st = mk_is_nzero(args[0], result); break;
case OP_FLOAT_IS_PZERO: SASSERT(num_args == 1); st = mk_is_pzero(args[0], result); break;
case OP_FLOAT_IS_NAN: SASSERT(num_args == 1); st = mk_is_nan(args[0], result); break;
case OP_FLOAT_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break;
case OP_FLOAT_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break;
case OP_FLOAT_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break;
case OP_FLOAT_IS_NEGATIVE: SASSERT(num_args == 1); st = mk_is_negative(args[0], result); break;
case OP_FLOAT_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break;
case OP_FLOAT_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break;
case OP_FLOAT_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break;
case OP_FLOAT_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(args[0], args[1], result); break;
case OP_FLOAT_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(args[0], args[1], result); break;
case OP_FLOAT_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break;
}
return st;
}
br_status float_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
SASSERT(f->get_num_parameters() == 2);
SASSERT(f->get_parameter(0).is_int());
SASSERT(f->get_parameter(1).is_int());
unsigned ebits = f->get_parameter(0).get_int();
unsigned sbits = f->get_parameter(1).get_int();
if (num_args == 2) {
mpf_rounding_mode rm;
if (!m_util.is_rm_value(args[0], rm))
return BR_FAILED;
rational q;
mpf q_mpf;
if (m_util.au().is_numeral(args[1], q)) {
TRACE("fp_rewriter", tout << "q: " << q << std::endl; );
mpf v;
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq());
result = m_util.mk_value(v);
m_util.fm().del(v);
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
return BR_DONE;
}
else if (m_util.is_value(args[1], q_mpf)) {
TRACE("fp_rewriter", tout << "q: " << m_util.fm().to_string(q_mpf) << std::endl; );
mpf v;
m_util.fm().set(v, ebits, sbits, rm, q_mpf);
result = m_util.mk_value(v);
m_util.fm().del(v);
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
return BR_DONE;
}
else
return BR_FAILED;
}
else if (num_args == 3 &&
m_util.is_rm(args[0]) &&
m_util.au().is_real(args[1]) &&
m_util.au().is_int(args[2])) {
mpf_rounding_mode rm;
if (!m_util.is_rm_value(args[0], rm))
return BR_FAILED;
rational q;
if (!m_util.au().is_numeral(args[1], q))
return BR_FAILED;
rational e;
if (!m_util.au().is_numeral(args[2], e))
return BR_FAILED;
TRACE("fp_rewriter", tout << "q: " << q << ", e: " << e << "\n";);
mpf v;
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq(), e.to_mpq().numerator());
result = m_util.mk_value(v);
m_util.fm().del(v);
return BR_DONE;
}
else {
return BR_FAILED;
}
}
br_status float_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_value(arg1, rm)) {
scoped_mpf v2(m_util.fm()), v3(m_util.fm());
if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) {
scoped_mpf t(m_util.fm());
m_util.fm().add(rm, v2, v3, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
br_status float_rewriter::mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
// a - b = a + (-b)
result = m_util.mk_add(arg1, arg2, m_util.mk_neg(arg3));
return BR_REWRITE2;
}
br_status float_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_value(arg1, rm)) {
scoped_mpf v2(m_util.fm()), v3(m_util.fm());
if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) {
scoped_mpf t(m_util.fm());
m_util.fm().mul(rm, v2, v3, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
br_status float_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_value(arg1, rm)) {
scoped_mpf v2(m_util.fm()), v3(m_util.fm());
if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) {
scoped_mpf t(m_util.fm());
m_util.fm().div(rm, v2, v3, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
br_status float_rewriter::mk_neg(expr * arg1, expr_ref & result) {
if (m_util.is_nan(arg1)) {
// -nan --> nan
result = arg1;
return BR_DONE;
}
if (m_util.is_plus_inf(arg1)) {
// - +oo --> -oo
result = m_util.mk_minus_inf(m().get_sort(arg1));
return BR_DONE;
}
if (m_util.is_minus_inf(arg1)) {
// - -oo -> +oo
result = m_util.mk_plus_inf(m().get_sort(arg1));
return BR_DONE;
}
if (m_util.is_neg(arg1)) {
// - - a --> a
result = to_app(arg1)->get_arg(0);
return BR_DONE;
}
scoped_mpf v1(m_util.fm());
if (m_util.is_value(arg1, v1)) {
m_util.fm().neg(v1);
result = m_util.mk_value(v1);
return BR_DONE;
}
// TODO: more simplifications
return BR_FAILED;
}
br_status float_rewriter::mk_rem(expr * arg1, expr * arg2, expr_ref & result) {
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) {
scoped_mpf t(m_util.fm());
m_util.fm().rem(v1, v2, t);
result = m_util.mk_value(t);
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_abs(expr * arg1, expr_ref & result) {
if (m_util.is_nan(arg1)) {
result = arg1;
return BR_DONE;
}
result = m().mk_ite(m_util.mk_is_sign_minus(arg1),
m_util.mk_neg(arg1),
arg1);
return BR_REWRITE2;
}
br_status float_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) {
if (m_util.is_nan(arg1)) {
result = arg2;
return BR_DONE;
}
if (m_util.is_nan(arg2)) {
result = arg1;
return BR_DONE;
}
// expand as using ite's
result = m().mk_ite(m().mk_or(mk_eq_nan(arg1), m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2))),
arg2,
m().mk_ite(mk_eq_nan(arg2),
arg1,
m().mk_ite(m_util.mk_lt(arg1, arg2),
arg1,
arg2)));
return BR_REWRITE_FULL;
}
br_status float_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
if (m_util.is_nan(arg1)) {
result = arg2;
return BR_DONE;
}
if (m_util.is_nan(arg2)) {
result = arg1;
return BR_DONE;
}
// expand as using ite's
result = m().mk_ite(m().mk_or(mk_eq_nan(arg1), m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2))),
arg2,
m().mk_ite(mk_eq_nan(arg2),
arg1,
m().mk_ite(m_util.mk_gt(arg1, arg2),
arg1,
arg2)));
return BR_REWRITE_FULL;
}
br_status float_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_value(arg1, rm)) {
scoped_mpf v2(m_util.fm()), v3(m_util.fm()), v4(m_util.fm());
if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3) && m_util.is_value(arg4, v4)) {
scoped_mpf t(m_util.fm());
m_util.fm().fused_mul_add(rm, v2, v3, v4, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
br_status float_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_value(arg1, rm)) {
scoped_mpf v2(m_util.fm());
if (m_util.is_value(arg2, v2)) {
scoped_mpf t(m_util.fm());
m_util.fm().sqrt(rm, v2, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
br_status float_rewriter::mk_round(expr * arg1, expr * arg2, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_value(arg1, rm)) {
scoped_mpf v2(m_util.fm());
if (m_util.is_value(arg2, v2)) {
scoped_mpf t(m_util.fm());
m_util.fm().round_to_integral(rm, v2, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
// This the floating point theory ==
br_status float_rewriter::mk_float_eq(expr * arg1, expr * arg2, expr_ref & result) {
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) {
result = (m_util.fm().eq(v1, v2)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
// Return (= arg NaN)
app * float_rewriter::mk_eq_nan(expr * arg) {
return m().mk_eq(arg, m_util.mk_nan(m().get_sort(arg)));
}
// Return (not (= arg NaN))
app * float_rewriter::mk_neq_nan(expr * arg) {
return m().mk_not(mk_eq_nan(arg));
}
br_status float_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) {
if (m_util.is_nan(arg1) || m_util.is_nan(arg2)) {
result = m().mk_false();
return BR_DONE;
}
if (m_util.is_minus_inf(arg1)) {
// -oo < arg2 --> not(arg2 = -oo) and not(arg2 = NaN)
result = m().mk_and(m().mk_not(m().mk_eq(arg2, arg1)), mk_neq_nan(arg2));
return BR_REWRITE3;
}
if (m_util.is_minus_inf(arg2)) {
// arg1 < -oo --> false
result = m().mk_false();
return BR_DONE;
}
if (m_util.is_plus_inf(arg1)) {
// +oo < arg2 --> false
result = m().mk_false();
return BR_DONE;
}
if (m_util.is_plus_inf(arg2)) {
// arg1 < +oo --> not(arg1 = +oo) and not(arg1 = NaN)
result = m().mk_and(m().mk_not(m().mk_eq(arg1, arg2)), mk_neq_nan(arg1));
return BR_REWRITE3;
}
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) {
result = (m_util.fm().lt(v1, v2)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
// TODO: more simplifications
return BR_FAILED;
}
br_status float_rewriter::mk_gt(expr * arg1, expr * arg2, expr_ref & result) {
result = m_util.mk_lt(arg2, arg1);
return BR_REWRITE1;
}
br_status float_rewriter::mk_le(expr * arg1, expr * arg2, expr_ref & result) {
if (m_util.is_nan(arg1) || m_util.is_nan(arg2)) {
result = m().mk_false();
return BR_DONE;
}
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) {
result = (m_util.fm().le(v1, v2)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_ge(expr * arg1, expr * arg2, expr_ref & result) {
result = m_util.mk_le(arg2, arg1);
return BR_REWRITE1;
}
br_status float_rewriter::mk_is_zero(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_value(arg1, v)) {
result = (m_util.fm().is_zero(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_is_nzero(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_value(arg1, v)) {
result = (m_util.fm().is_nzero(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_value(arg1, v)) {
result = (m_util.fm().is_pzero(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_is_nan(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_value(arg1, v)) {
result = (m_util.fm().is_nan(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_is_inf(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_value(arg1, v)) {
result = (m_util.fm().is_inf(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_is_normal(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_value(arg1, v)) {
result = (m_util.fm().is_normal(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_value(arg1, v)) {
result = (m_util.fm().is_denormal(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_is_negative(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_value(arg1, v)) {
result = (m_util.fm().is_neg(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_is_positive(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_value(arg1, v)) {
result = (m_util.fm().is_neg(v) || m_util.fm().is_nan(v)) ? m().mk_false() : m().mk_true();
return BR_DONE;
}
return BR_FAILED;
}
// This the SMT =
br_status float_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result) {
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) {
// Note: == is the floats-equality, here we need normal equality.
result = (m_fm.is_nan(v1) && m_fm.is_nan(v2)) ? m().mk_true() :
(m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1)!=m_fm.sgn(v2)) ? m().mk_false() :
(v1 == v2) ? m().mk_true() :
m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_to_ieee_bv(expr * arg1, expr_ref & result) {
return BR_FAILED;
}
br_status float_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
bv_util bu(m());
rational r1, r2, r3;
unsigned bvs1, bvs2, bvs3;
if (bu.is_numeral(arg1, r1, bvs1) && bu.is_numeral(arg2, r2, bvs2) && bu.is_numeral(arg3, r3, bvs3)) {
SASSERT(m_util.fm().mpz_manager().is_one(r2.to_mpq().denominator()));
SASSERT(m_util.fm().mpz_manager().is_one(r3.to_mpq().denominator()));
SASSERT(m_util.fm().mpz_manager().is_int64(r3.to_mpq().numerator()));
scoped_mpf v(m_util.fm());
mpf_exp_t biased_exp = m_util.fm().mpz_manager().get_int64(r2.to_mpq().numerator());
m_util.fm().set(v, bvs2, bvs3 + 1,
r1.is_one(),
r3.to_mpq().numerator(),
m_util.fm().unbias_exp(bvs2, biased_exp));
TRACE("fp_rewriter", tout << "v = " << m_util.fm().to_string(v) << std::endl;);
result = m_util.mk_value(v);
return BR_DONE;
}
return BR_FAILED;
}
br_status float_rewriter::mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result) {
return BR_FAILED;
}
br_status float_rewriter::mk_to_sbv(expr * arg1, expr * arg2, expr_ref & result) {
return BR_FAILED;
}
br_status float_rewriter::mk_to_real(expr * arg1, expr_ref & result) {
return BR_FAILED;
}

View file

@ -0,0 +1,598 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
fpa_rewriter.cpp
Abstract:
Basic rewriting rules for floating point numbers.
Author:
Leonardo (leonardo) 2012-02-02
Notes:
--*/
#include"fpa_rewriter.h"
fpa_rewriter::fpa_rewriter(ast_manager & m, params_ref const & p):
m_util(m) {
updt_params(p);
}
fpa_rewriter::~fpa_rewriter() {
}
void fpa_rewriter::updt_params(params_ref const & p) {
}
void fpa_rewriter::get_param_descrs(param_descrs & r) {
}
br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
br_status st = BR_FAILED;
SASSERT(f->get_family_id() == get_fid());
switch (f->get_decl_kind()) {
case OP_FPA_TO_FP: st = mk_to_fp(f, num_args, args, result); break;
case OP_FPA_TO_FP_UNSIGNED: st = mk_to_fp_unsigned(f, num_args, args, result); break;
case OP_FPA_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break;
case OP_FPA_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break;
case OP_FPA_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break;
case OP_FPA_MUL: SASSERT(num_args == 3); st = mk_mul(args[0], args[1], args[2], result); break;
case OP_FPA_DIV: SASSERT(num_args == 3); st = mk_div(args[0], args[1], args[2], result); break;
case OP_FPA_REM: SASSERT(num_args == 2); st = mk_rem(args[0], args[1], result); break;
case OP_FPA_ABS: SASSERT(num_args == 1); st = mk_abs(args[0], result); break;
case OP_FPA_MIN: SASSERT(num_args == 2); st = mk_min(args[0], args[1], result); break;
case OP_FPA_MAX: SASSERT(num_args == 2); st = mk_max(args[0], args[1], result); break;
case OP_FPA_FMA: SASSERT(num_args == 4); st = mk_fma(args[0], args[1], args[2], args[3], result); break;
case OP_FPA_SQRT: SASSERT(num_args == 2); st = mk_sqrt(args[0], args[1], result); break;
case OP_FPA_ROUND_TO_INTEGRAL: SASSERT(num_args == 2); st = mk_round(args[0], args[1], result); break;
case OP_FPA_EQ: SASSERT(num_args == 2); st = mk_float_eq(args[0], args[1], result); break;
case OP_FPA_LT: SASSERT(num_args == 2); st = mk_lt(args[0], args[1], result); break;
case OP_FPA_GT: SASSERT(num_args == 2); st = mk_gt(args[0], args[1], result); break;
case OP_FPA_LE: SASSERT(num_args == 2); st = mk_le(args[0], args[1], result); break;
case OP_FPA_GE: SASSERT(num_args == 2); st = mk_ge(args[0], args[1], result); break;
case OP_FPA_IS_ZERO: SASSERT(num_args == 1); st = mk_is_zero(args[0], result); break;
case OP_FPA_IS_NAN: SASSERT(num_args == 1); st = mk_is_nan(args[0], result); break;
case OP_FPA_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break;
case OP_FPA_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break;
case OP_FPA_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break;
case OP_FPA_IS_NEGATIVE: SASSERT(num_args == 1); st = mk_is_negative(args[0], result); break;
case OP_FPA_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break;
case OP_FPA_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break;
case OP_FPA_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(args[0], args[1], result); break;
case OP_FPA_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(args[0], args[1], result); break;
case OP_FPA_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break;
case OP_FPA_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break;
}
return st;
}
br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
SASSERT(f->get_num_parameters() == 2);
SASSERT(f->get_parameter(0).is_int());
SASSERT(f->get_parameter(1).is_int());
unsigned ebits = f->get_parameter(0).get_int();
unsigned sbits = f->get_parameter(1).get_int();
if (num_args == 2) {
mpf_rounding_mode rm;
if (!m_util.is_rm_numeral(args[0], rm))
return BR_FAILED;
rational q;
scoped_mpf q_mpf(m_util.fm());
if (m_util.au().is_numeral(args[1], q)) {
TRACE("fp_rewriter", tout << "q: " << q << std::endl; );
scoped_mpf v(m_util.fm());
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq());
result = m_util.mk_value(v);
m_util.fm().del(v);
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
return BR_DONE;
}
else if (m_util.is_numeral(args[1], q_mpf)) {
TRACE("fp_rewriter", tout << "q: " << m_util.fm().to_string(q_mpf) << std::endl; );
scoped_mpf v(m_util.fm());
m_util.fm().set(v, ebits, sbits, rm, q_mpf);
result = m_util.mk_value(v);
m_util.fm().del(v);
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
return BR_DONE;
}
else
return BR_FAILED;
}
else if (num_args == 3) {
bv_util bu(m());
rational r1, r2, r3;
unsigned bvs1, bvs2, bvs3;
if (m_util.is_rm(args[0]) &&
m_util.au().is_real(args[1]) &&
m_util.au().is_int(args[2])) {
mpf_rounding_mode rm;
if (!m_util.is_rm_numeral(args[0], rm))
return BR_FAILED;
rational q;
if (!m_util.au().is_numeral(args[1], q))
return BR_FAILED;
rational e;
if (!m_util.au().is_numeral(args[2], e))
return BR_FAILED;
TRACE("fp_rewriter", tout << "q: " << q << ", e: " << e << "\n";);
scoped_mpf v(m_util.fm());
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq(), e.to_mpq().numerator());
result = m_util.mk_value(v);
m_util.fm().del(v);
return BR_DONE;
}
else if (bu.is_numeral(args[0], r1, bvs1) &&
bu.is_numeral(args[1], r2, bvs2) &&
bu.is_numeral(args[2], r3, bvs3)) {
SASSERT(m_util.fm().mpz_manager().is_one(r2.to_mpq().denominator()));
SASSERT(m_util.fm().mpz_manager().is_one(r3.to_mpq().denominator()));
SASSERT(m_util.fm().mpz_manager().is_int64(r3.to_mpq().numerator()));
scoped_mpf v(m_util.fm());
mpf_exp_t biased_exp = m_util.fm().mpz_manager().get_int64(r2.to_mpq().numerator());
m_util.fm().set(v, bvs2, bvs3 + 1,
r1.is_one(),
r3.to_mpq().numerator(),
m_util.fm().unbias_exp(bvs2, biased_exp));
TRACE("fp_rewriter", tout << "v = " << m_util.fm().to_string(v) << std::endl;);
result = m_util.mk_value(v);
return BR_DONE;
}
else
return BR_FAILED;
}
else
return BR_FAILED;
}
br_status fpa_rewriter::mk_to_fp_unsigned(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
SASSERT(f->get_num_parameters() == 2);
SASSERT(f->get_parameter(0).is_int());
SASSERT(f->get_parameter(1).is_int());
unsigned ebits = f->get_parameter(0).get_int();
unsigned sbits = f->get_parameter(1).get_int();
return BR_FAILED;
}
br_status fpa_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_numeral(arg1, rm)) {
scoped_mpf v2(m_util.fm()), v3(m_util.fm());
if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3)) {
scoped_mpf t(m_util.fm());
m_util.fm().add(rm, v2, v3, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
// a - b = a + (-b)
result = m_util.mk_add(arg1, arg2, m_util.mk_neg(arg3));
return BR_REWRITE2;
}
br_status fpa_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_numeral(arg1, rm)) {
scoped_mpf v2(m_util.fm()), v3(m_util.fm());
if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3)) {
scoped_mpf t(m_util.fm());
m_util.fm().mul(rm, v2, v3, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_numeral(arg1, rm)) {
scoped_mpf v2(m_util.fm()), v3(m_util.fm());
if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3)) {
scoped_mpf t(m_util.fm());
m_util.fm().div(rm, v2, v3, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_neg(expr * arg1, expr_ref & result) {
if (m_util.is_nan(arg1)) {
// -nan --> nan
result = arg1;
return BR_DONE;
}
if (m_util.is_pinf(arg1)) {
// - +oo --> -oo
result = m_util.mk_ninf(m().get_sort(arg1));
return BR_DONE;
}
if (m_util.is_ninf(arg1)) {
// - -oo -> +oo
result = m_util.mk_pinf(m().get_sort(arg1));
return BR_DONE;
}
if (m_util.is_neg(arg1)) {
// - - a --> a
result = to_app(arg1)->get_arg(0);
return BR_DONE;
}
scoped_mpf v1(m_util.fm());
if (m_util.is_numeral(arg1, v1)) {
m_util.fm().neg(v1);
result = m_util.mk_value(v1);
return BR_DONE;
}
// TODO: more simplifications
return BR_FAILED;
}
br_status fpa_rewriter::mk_rem(expr * arg1, expr * arg2, expr_ref & result) {
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
scoped_mpf t(m_util.fm());
m_util.fm().rem(v1, v2, t);
result = m_util.mk_value(t);
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_abs(expr * arg1, expr_ref & result) {
if (m_util.is_nan(arg1)) {
result = arg1;
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) {
if (m_util.is_nan(arg1)) {
result = arg2;
return BR_DONE;
}
if (m_util.is_nan(arg2)) {
result = arg1;
return BR_DONE;
}
// expand as using ite's
result = m().mk_ite(m().mk_or(mk_eq_nan(arg1), m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2))),
arg2,
m().mk_ite(mk_eq_nan(arg2),
arg1,
m().mk_ite(m_util.mk_lt(arg1, arg2),
arg1,
arg2)));
return BR_REWRITE_FULL;
}
br_status fpa_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
if (m_util.is_nan(arg1)) {
result = arg2;
return BR_DONE;
}
if (m_util.is_nan(arg2)) {
result = arg1;
return BR_DONE;
}
// expand as using ite's
result = m().mk_ite(m().mk_or(mk_eq_nan(arg1), m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2))),
arg2,
m().mk_ite(mk_eq_nan(arg2),
arg1,
m().mk_ite(m_util.mk_gt(arg1, arg2),
arg1,
arg2)));
return BR_REWRITE_FULL;
}
br_status fpa_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_numeral(arg1, rm)) {
scoped_mpf v2(m_util.fm()), v3(m_util.fm()), v4(m_util.fm());
if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3) && m_util.is_numeral(arg4, v4)) {
scoped_mpf t(m_util.fm());
m_util.fm().fused_mul_add(rm, v2, v3, v4, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_numeral(arg1, rm)) {
scoped_mpf v2(m_util.fm());
if (m_util.is_numeral(arg2, v2)) {
scoped_mpf t(m_util.fm());
m_util.fm().sqrt(rm, v2, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_round(expr * arg1, expr * arg2, expr_ref & result) {
mpf_rounding_mode rm;
if (m_util.is_rm_numeral(arg1, rm)) {
scoped_mpf v2(m_util.fm());
if (m_util.is_numeral(arg2, v2)) {
scoped_mpf t(m_util.fm());
m_util.fm().round_to_integral(rm, v2, t);
result = m_util.mk_value(t);
return BR_DONE;
}
}
return BR_FAILED;
}
// This the floating point theory ==
br_status fpa_rewriter::mk_float_eq(expr * arg1, expr * arg2, expr_ref & result) {
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
result = (m_util.fm().eq(v1, v2)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
// Return (= arg NaN)
app * fpa_rewriter::mk_eq_nan(expr * arg) {
return m().mk_eq(arg, m_util.mk_nan(m().get_sort(arg)));
}
// Return (not (= arg NaN))
app * fpa_rewriter::mk_neq_nan(expr * arg) {
return m().mk_not(mk_eq_nan(arg));
}
br_status fpa_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) {
if (m_util.is_nan(arg1) || m_util.is_nan(arg2)) {
result = m().mk_false();
return BR_DONE;
}
if (m_util.is_ninf(arg1)) {
// -oo < arg2 --> not(arg2 = -oo) and not(arg2 = NaN)
result = m().mk_and(m().mk_not(m().mk_eq(arg2, arg1)), mk_neq_nan(arg2));
return BR_REWRITE3;
}
if (m_util.is_ninf(arg2)) {
// arg1 < -oo --> false
result = m().mk_false();
return BR_DONE;
}
if (m_util.is_pinf(arg1)) {
// +oo < arg2 --> false
result = m().mk_false();
return BR_DONE;
}
if (m_util.is_pinf(arg2)) {
// arg1 < +oo --> not(arg1 = +oo) and not(arg1 = NaN)
result = m().mk_and(m().mk_not(m().mk_eq(arg1, arg2)), mk_neq_nan(arg1));
return BR_REWRITE3;
}
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
result = (m_util.fm().lt(v1, v2)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
// TODO: more simplifications
return BR_FAILED;
}
br_status fpa_rewriter::mk_gt(expr * arg1, expr * arg2, expr_ref & result) {
result = m_util.mk_lt(arg2, arg1);
return BR_REWRITE1;
}
br_status fpa_rewriter::mk_le(expr * arg1, expr * arg2, expr_ref & result) {
if (m_util.is_nan(arg1) || m_util.is_nan(arg2)) {
result = m().mk_false();
return BR_DONE;
}
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
result = (m_util.fm().le(v1, v2)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_ge(expr * arg1, expr * arg2, expr_ref & result) {
result = m_util.mk_le(arg2, arg1);
return BR_REWRITE1;
}
br_status fpa_rewriter::mk_is_zero(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_numeral(arg1, v)) {
result = (m_util.fm().is_zero(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_is_nzero(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_numeral(arg1, v)) {
result = (m_util.fm().is_nzero(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_numeral(arg1, v)) {
result = (m_util.fm().is_pzero(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_is_nan(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_numeral(arg1, v)) {
result = (m_util.fm().is_nan(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_is_inf(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_numeral(arg1, v)) {
result = (m_util.fm().is_inf(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_is_normal(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_numeral(arg1, v)) {
result = (m_util.fm().is_normal(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_numeral(arg1, v)) {
result = (m_util.fm().is_denormal(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_is_negative(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_numeral(arg1, v)) {
result = (m_util.fm().is_neg(v)) ? m().mk_true() : m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_is_positive(expr * arg1, expr_ref & result) {
scoped_mpf v(m_util.fm());
if (m_util.is_numeral(arg1, v)) {
result = (m_util.fm().is_neg(v) || m_util.fm().is_nan(v)) ? m().mk_false() : m().mk_true();
return BR_DONE;
}
return BR_FAILED;
}
// This the SMT =
br_status fpa_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result) {
scoped_mpf v1(m_util.fm()), v2(m_util.fm());
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
// Note: == is the floats-equality, here we need normal equality.
result = (m_fm.is_nan(v1) && m_fm.is_nan(v2)) ? m().mk_true() :
(m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1)!=m_fm.sgn(v2)) ? m().mk_false() :
(v1 == v2) ? m().mk_true() :
m().mk_false();
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_to_ieee_bv(expr * arg1, expr_ref & result) {
return BR_FAILED;
}
br_status fpa_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
bv_util bu(m());
rational r1, r2, r3;
unsigned bvs1, bvs2, bvs3;
if (bu.is_numeral(arg1, r1, bvs1) && bu.is_numeral(arg2, r2, bvs2) && bu.is_numeral(arg3, r3, bvs3)) {
SASSERT(m_util.fm().mpz_manager().is_one(r2.to_mpq().denominator()));
SASSERT(m_util.fm().mpz_manager().is_one(r3.to_mpq().denominator()));
SASSERT(m_util.fm().mpz_manager().is_int64(r3.to_mpq().numerator()));
scoped_mpf v(m_util.fm());
mpf_exp_t biased_exp = m_util.fm().mpz_manager().get_int64(r2.to_mpq().numerator());
m_util.fm().set(v, bvs2, bvs3 + 1,
r1.is_one(),
r3.to_mpq().numerator(),
m_util.fm().unbias_exp(bvs2, biased_exp));
TRACE("fp_rewriter", tout << "simplified (fp ...) to " << m_util.fm().to_string(v) << std::endl;);
result = m_util.mk_value(v);
return BR_DONE;
}
return BR_FAILED;
}
br_status fpa_rewriter::mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result) {
return BR_FAILED;
}
br_status fpa_rewriter::mk_to_sbv(expr * arg1, expr * arg2, expr_ref & result) {
return BR_FAILED;
}
br_status fpa_rewriter::mk_to_real(expr * arg1, expr_ref & result) {
scoped_mpf fv(m_util.fm());
if (m_util.is_numeral(arg1, fv)) {
if (m_fm.is_nan(fv) || m_fm.is_inf(fv)) {
result = m_util.mk_internal_to_real_unspecified();
}
else {
scoped_mpq r(m_fm.mpq_manager());
m_fm.to_rational(fv, r);
result = m_util.au().mk_numeral(r.get(), false);
}
return BR_DONE;
}
return BR_FAILED;
}

View file

@ -22,19 +22,19 @@ Notes:
#include"ast.h"
#include"rewriter.h"
#include"params.h"
#include"float_decl_plugin.h"
#include"fpa_decl_plugin.h"
#include"mpf.h"
class float_rewriter {
float_util m_util;
class fpa_rewriter {
fpa_util m_util;
mpf_manager m_fm;
app * mk_eq_nan(expr * arg);
app * mk_neq_nan(expr * arg);
public:
float_rewriter(ast_manager & m, params_ref const & p = params_ref());
~float_rewriter();
fpa_rewriter(ast_manager & m, params_ref const & p = params_ref());
~fpa_rewriter();
ast_manager & m() const { return m_util.m(); }
family_id get_fid() const { return m_util.get_fid(); }
@ -75,6 +75,7 @@ public:
br_status mk_to_ieee_bv(expr * arg1, expr_ref & result);
br_status mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
br_status mk_to_fp_unsigned(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
br_status mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result);
br_status mk_to_fp_unsigned(expr * arg1, expr * arg2, expr_ref & result);
br_status mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result);

View file

@ -22,7 +22,7 @@ Notes:
#include"bv_rewriter.h"
#include"datatype_rewriter.h"
#include"array_rewriter.h"
#include"float_rewriter.h"
#include"fpa_rewriter.h"
struct mk_simplified_app::imp {
ast_manager & m;
@ -31,7 +31,7 @@ struct mk_simplified_app::imp {
bv_rewriter m_bv_rw;
array_rewriter m_ar_rw;
datatype_rewriter m_dt_rw;
float_rewriter m_f_rw;
fpa_rewriter m_f_rw;
imp(ast_manager & _m, params_ref const & p):
m(_m),

View file

@ -23,7 +23,7 @@ Notes:
#include"bv_rewriter.h"
#include"datatype_rewriter.h"
#include"array_rewriter.h"
#include"float_rewriter.h"
#include"fpa_rewriter.h"
#include"dl_rewriter.h"
#include"rewriter_def.h"
#include"expr_substitution.h"
@ -39,7 +39,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
bv_rewriter m_bv_rw;
array_rewriter m_ar_rw;
datatype_rewriter m_dt_rw;
float_rewriter m_f_rw;
fpa_rewriter m_f_rw;
dl_rewriter m_dl_rw;
arith_util m_a_util;
bv_util m_bv_util;

View file

@ -148,7 +148,7 @@ void distribute_forall::operator()(expr * f, expr_ref & result) {
while (!m_todo.empty()) {
expr * e = m_todo.back();
if (visit_children(e)) {
if (visit_children(e)) {
m_todo.pop_back();
reduce1(e);
}

View file

@ -0,0 +1,43 @@
/*++
Copyright (c) 2015 Microsoft Corporation
Module Name:
fpa_simplifier_plugin.cpp
Abstract:
Simplifier for the floating-point theory
Author:
Christoph (cwinter) 2015-01-14
--*/
#include"fpa_simplifier_plugin.h"
fpa_simplifier_plugin::fpa_simplifier_plugin(ast_manager & m, basic_simplifier_plugin & b) :
simplifier_plugin(symbol("fpa"), m),
m_util(m),
m_bsimp(b),
m_rw(m) {}
fpa_simplifier_plugin::~fpa_simplifier_plugin() {}
bool fpa_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
set_reduce_invoked();
SASSERT(f->get_family_id() == get_family_id());
/*switch (f->get_decl_kind()) {
case OP_FPA_FP: break;
}*/
return m_rw.mk_app_core(f, num_args, args, result) == BR_DONE;
}
bool fpa_simplifier_plugin::reduce_eq(expr * lhs, expr * rhs, expr_ref & result) {
set_reduce_invoked();
return m_rw.mk_eq_core(lhs, rhs, result) == BR_DONE;
}

View file

@ -0,0 +1,40 @@
/*++
Copyright (c) 2015 Microsoft Corporation
Module Name:
fpa_simplifier_plugin.h
Abstract:
Simplifier for the floating-point theory
Author:
Christoph (cwinter) 2015-01-14
--*/
#ifndef _FPA_SIMPLIFIER_PLUGIN_H_
#define _FPA_SIMPLIFIER_PLUGIN_H_
#include"basic_simplifier_plugin.h"
#include"fpa_decl_plugin.h"
#include"fpa_rewriter.h"
class fpa_simplifier_plugin : public simplifier_plugin {
fpa_util m_util;
basic_simplifier_plugin & m_bsimp;
fpa_rewriter m_rw;
public:
fpa_simplifier_plugin(ast_manager & m, basic_simplifier_plugin & b);
~fpa_simplifier_plugin();
virtual bool reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
virtual bool reduce_eq(expr * lhs, expr * rhs, expr_ref & result);
};
#endif /* _FPA_SIMPLIFIER_PLUGIN_H_ */

View file

@ -255,7 +255,7 @@ protected:
s == m_print_success || s == m_print_warning || s == m_expand_definitions ||
s == m_interactive_mode || s == m_produce_proofs || s == m_produce_unsat_cores ||
s == m_produce_models || s == m_produce_assignments || s == m_produce_interpolants ||
s == m_regular_output_channel || s == m_diagnostic_output_channel ||
s == m_regular_output_channel || s == m_diagnostic_output_channel ||
s == m_random_seed || s == m_verbosity || s == m_global_decls;
}

View file

@ -24,7 +24,7 @@ Notes:
#include"array_decl_plugin.h"
#include"datatype_decl_plugin.h"
#include"seq_decl_plugin.h"
#include"float_decl_plugin.h"
#include"fpa_decl_plugin.h"
#include"ast_pp.h"
#include"var_subst.h"
#include"pp.h"
@ -240,7 +240,7 @@ protected:
arith_util m_autil;
bv_util m_bvutil;
array_util m_arutil;
float_util m_futil;
fpa_util m_futil;
datalog::dl_decl_util m_dlutil;
format_ns::format * pp_fdecl_name(symbol const & s, func_decls const & fs, func_decl * f, unsigned & len) {
@ -267,7 +267,7 @@ public:
virtual arith_util & get_autil() { return m_autil; }
virtual bv_util & get_bvutil() { return m_bvutil; }
virtual array_util & get_arutil() { return m_arutil; }
virtual float_util & get_futil() { return m_futil; }
virtual fpa_util & get_futil() { return m_futil; }
virtual datalog::dl_decl_util& get_dlutil() { return m_dlutil; }
virtual bool uses(symbol const & s) const {
return
@ -512,8 +512,8 @@ bool cmd_context::logic_has_arith_core(symbol const & s) const {
s == "UFNIA" ||
s == "LIA" ||
s == "LRA" ||
s == "QF_FPA" ||
s == "QF_FPABV" ||
s == "QF_FP" ||
s == "QF_FPBV" ||
s == "HORN";
}
@ -532,7 +532,7 @@ bool cmd_context::logic_has_bv_core(symbol const & s) const {
s == "QF_ABV" ||
s == "QF_AUFBV" ||
s == "QF_BVRE" ||
s == "QF_FPABV" ||
s == "QF_FPBV" ||
s == "HORN";
}
@ -556,8 +556,8 @@ bool cmd_context::logic_has_seq() const {
return !has_logic() || logic_has_seq_core(m_logic);
}
bool cmd_context::logic_has_floats() const {
return !has_logic() || m_logic == "QF_FPA" || m_logic == "QF_FPABV";
bool cmd_context::logic_has_fpa() const {
return !has_logic() || m_logic == "QF_FP" || m_logic == "QF_FPBV";
}
bool cmd_context::logic_has_array_core(symbol const & s) const {
@ -601,7 +601,7 @@ void cmd_context::init_manager_core(bool new_manager) {
register_plugin(symbol("array"), alloc(array_decl_plugin), logic_has_array());
register_plugin(symbol("datatype"), alloc(datatype_decl_plugin), logic_has_datatype());
register_plugin(symbol("seq"), alloc(seq_decl_plugin), logic_has_seq());
register_plugin(symbol("float"), alloc(float_decl_plugin), logic_has_floats());
register_plugin(symbol("fpa"), alloc(fpa_decl_plugin), logic_has_fpa());
}
else {
// the manager was created by an external module
@ -614,7 +614,7 @@ void cmd_context::init_manager_core(bool new_manager) {
load_plugin(symbol("array"), logic_has_array(), fids);
load_plugin(symbol("datatype"), logic_has_datatype(), fids);
load_plugin(symbol("seq"), logic_has_seq(), fids);
load_plugin(symbol("float"), logic_has_floats(), fids);
load_plugin(symbol("fpa"), logic_has_fpa(), fids);
svector<family_id>::iterator it = fids.begin();
svector<family_id>::iterator end = fids.end();
@ -668,7 +668,7 @@ bool cmd_context::supported_logic(symbol const & s) const {
logic_has_arith_core(s) || logic_has_bv_core(s) ||
logic_has_array_core(s) || logic_has_seq_core(s) ||
logic_has_horn(s) ||
s == "QF_FPA" || s == "QF_FPABV";
s == "QF_FP" || s == "QF_FPBV";
}
bool cmd_context::set_logic(symbol const & s) {

View file

@ -241,7 +241,7 @@ protected:
bool logic_has_seq() const;
bool logic_has_array() const;
bool logic_has_datatype() const;
bool logic_has_floats() const;
bool logic_has_fpa() const;
bool supported_logic(symbol const & s) const;
void print_unsupported_msg() { regular_stream() << "unsupported" << std::endl; }

View file

@ -124,20 +124,20 @@ namespace Duality {
}
void timer_stop(const char *name){
if(current->name != name || !current->parent){
if (current->name != name || !current->parent) {
#if 0
std::cerr << "imbalanced timer_start and timer_stop";
exit(1);
std::cerr << "imbalanced timer_start and timer_stop";
exit(1);
#endif
// in case we lost a timer stop due to an exception
while(current->name != name && current->parent)
current = current->parent;
if(current->parent){
current->time += (current_time() - current->start_time);
current = current->parent;
// in case we lost a timer stop due to an exception
while (current->name != name && current->parent)
current = current->parent;
if (current->parent) {
current->time += (current_time() - current->start_time);
current = current->parent;
}
return;
}
return;
}
current->time += (current_time() - current->start_time);
current = current->parent;
}

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@ Revision History:
#include"bv_rewriter.h"
#include"datatype_rewriter.h"
#include"array_rewriter.h"
#include"float_rewriter.h"
#include"fpa_rewriter.h"
#include"rewriter_def.h"
#include"cooperate.h"
@ -36,7 +36,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
bv_rewriter m_bv_rw;
array_rewriter m_ar_rw;
datatype_rewriter m_dt_rw;
float_rewriter m_f_rw;
fpa_rewriter m_f_rw;
unsigned long long m_max_memory;
unsigned m_max_steps;
bool m_model_completion;

View file

@ -142,7 +142,7 @@ namespace datalog {
steps.push_back(step());
obj_map<proof, unsigned> index;
index.insert(m_proof, 0);
for (unsigned j = 0; j < rules.size(); ++j) {
proof* p = rules[j];
proof_ref_vector premises(m);

View file

@ -187,10 +187,10 @@ namespace datalog {
if (m_trail.get_num_scopes() == 0) {
throw default_exception("there are no backtracking points to pop to");
}
if(m_engine.get()){
if(get_engine() != DUALITY_ENGINE)
throw default_exception("operation is not supported by engine");
}
if(m_engine.get()){
if(get_engine() != DUALITY_ENGINE)
throw default_exception("operation is not supported by engine");
}
m_trail.pop_scope(1);
}
@ -478,7 +478,7 @@ namespace datalog {
void context::add_rule(expr* rl, symbol const& name, unsigned bound) {
m_rule_fmls.push_back(rl);
m_rule_names.push_back(name);
m_rule_bounds.push_back(bound);
m_rule_bounds.push_back(bound);
}
void context::flush_add_rules() {
@ -706,7 +706,7 @@ namespace datalog {
check_existential_tail(r);
check_positive_predicates(r);
break;
case DUALITY_ENGINE:
case DUALITY_ENGINE:
check_existential_tail(r);
check_positive_predicates(r);
break;
@ -963,12 +963,12 @@ namespace datalog {
// TODO: what?
if(get_engine() != DUALITY_ENGINE) {
new_query();
rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end();
rule_ref r(m_rule_manager);
for (; it != end; ++it) {
rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end();
rule_ref r(m_rule_manager);
for (; it != end; ++it) {
r = *it;
check_rule(r);
}
}
}
#endif
m_mc = mk_skip_model_converter();
@ -985,10 +985,10 @@ namespace datalog {
flush_add_rules();
break;
case DUALITY_ENGINE:
// this lets us use duality with SAS 2013 abstraction
if(quantify_arrays())
flush_add_rules();
break;
// this lets us use duality with SAS 2013 abstraction
if(quantify_arrays())
flush_add_rules();
break;
default:
UNREACHABLE();
}
@ -1109,11 +1109,11 @@ namespace datalog {
void context::get_raw_rule_formulas(expr_ref_vector& rules, svector<symbol>& names, vector<unsigned> &bounds){
for (unsigned i = 0; i < m_rule_fmls.size(); ++i) {
expr_ref r = bind_variables(m_rule_fmls[i].get(), true);
rules.push_back(r.get());
// rules.push_back(m_rule_fmls[i].get());
names.push_back(m_rule_names[i]);
bounds.push_back(m_rule_bounds[i]);
expr_ref r = bind_variables(m_rule_fmls[i].get(), true);
rules.push_back(r.get());
// rules.push_back(m_rule_fmls[i].get());
names.push_back(m_rule_names[i]);
bounds.push_back(m_rule_bounds[i]);
}
}

View file

@ -77,12 +77,12 @@ namespace Duality {
old_rs = 0;
}
~duality_data(){
if(old_rs)
dealloc(old_rs);
if(rpfp)
dealloc(rpfp);
if(ls)
dealloc(ls);
if(old_rs)
dealloc(old_rs);
if(rpfp)
dealloc(rpfp);
if(ls)
(ls);
}
};
@ -171,16 +171,16 @@ lbool dl_interface::query(::expr * query) {
query_ref = m_ctx.get_manager().mk_false();
else {
func_decl_ref query_pred(m_ctx.get_manager());
query_pred = m_ctx.get_rules().get_output_predicate();
ptr_vector<sort> sorts;
unsigned nargs = query_pred.get()->get_arity();
expr_ref_vector vars(m_ctx.get_manager());
for(unsigned i = 0; i < nargs; i++){
::sort *s = query_pred.get()->get_domain(i);
vars.push_back(m_ctx.get_manager().mk_var(nargs-1-i,s));
}
query_ref = m_ctx.get_manager().mk_app(query_pred.get(),nargs,vars.c_ptr());
query = query_ref.get();
query_pred = m_ctx.get_rules().get_output_predicate();
ptr_vector<sort> sorts;
unsigned nargs = query_pred.get()->get_arity();
expr_ref_vector vars(m_ctx.get_manager());
for(unsigned i = 0; i < nargs; i++){
::sort *s = query_pred.get()->get_domain(i);
vars.push_back(m_ctx.get_manager().mk_var(nargs-1-i,s));
}
query_ref = m_ctx.get_manager().mk_app(query_pred.get(),nargs,vars.c_ptr());
query = query_ref.get();
}
unsigned nrules = rs.get_num_rules();
for(unsigned i = 0; i < nrules; i++){
@ -250,16 +250,16 @@ lbool dl_interface::query(::expr * query) {
while(true){
if(cl.is_app()){
decl_kind k = cl.decl().get_decl_kind();
if(k == Implies)
cl = cl.arg(1);
else {
heads.insert(cl.decl());
break;
}
decl_kind k = cl.decl().get_decl_kind();
if(k == Implies)
cl = cl.arg(1);
else {
heads.insert(cl.decl());
break;
}
}
else if(cl.is_quantifier())
cl = cl.body();
cl = cl.body();
else break;
}
}
@ -268,18 +268,18 @@ lbool dl_interface::query(::expr * query) {
::ast *fa = pinned[i];
if(is_func_decl(fa)){
::func_decl *fd = to_func_decl(fa);
if(m_ctx.is_predicate(fd)) {
func_decl f(_d->ctx,fd);
if(!heads.contains(fd)){
int arity = f.arity();
std::vector<expr> args;
for(int j = 0; j < arity; j++)
args.push_back(_d->ctx.fresh_func_decl("X",f.domain(j))());
expr c = implies(_d->ctx.bool_val(false),f(args));
c = _d->ctx.make_quant(Forall,args,c);
clauses.push_back(c);
bounds.push_back(UINT_MAX);
}
if (m_ctx.is_predicate(fd)) {
func_decl f(_d->ctx, fd);
if (!heads.contains(fd)) {
int arity = f.arity();
std::vector<expr> args;
for (int j = 0; j < arity; j++)
args.push_back(_d->ctx.fresh_func_decl("X", f.domain(j))());
expr c = implies(_d->ctx.bool_val(false), f(args));
c = _d->ctx.make_quant(Forall, args, c);
clauses.push_back(c);
bounds.push_back(UINT_MAX);
}
}
}
}
@ -483,17 +483,17 @@ void dl_interface::display_certificate_non_const(std::ostream& out) {
model orig_model = _d->cex.get_tree()->dualModel;
for(unsigned i = 0; i < orig_model.num_consts(); i++){
func_decl cnst = orig_model.get_const_decl(i);
if(locals.find(cnst) == locals.end()){
expr thing = orig_model.get_const_interp(cnst);
mod.register_decl(to_func_decl(cnst.raw()),to_expr(thing.raw()));
if (locals.find(cnst) == locals.end()) {
expr thing = orig_model.get_const_interp(cnst);
mod.register_decl(to_func_decl(cnst.raw()), to_expr(thing.raw()));
}
}
for(unsigned i = 0; i < orig_model.num_funcs(); i++){
func_decl cnst = orig_model.get_func_decl(i);
if(locals.find(cnst) == locals.end()){
func_interp thing = orig_model.get_func_interp(cnst);
::func_interp *thing_raw = thing;
mod.register_decl(to_func_decl(cnst.raw()),thing_raw->copy());
if (locals.find(cnst) == locals.end()) {
func_interp thing = orig_model.get_func_interp(cnst);
::func_interp *thing_raw = thing;
mod.register_decl(to_func_decl(cnst.raw()), thing_raw->copy());
}
}
model_v2_pp(out,mod);

View file

@ -110,7 +110,7 @@ struct dl_context {
m_trail.push(push_back_vector<dl_context, svector<symbol> >(m_collected_cmds->m_names));
}
else {
m_context->add_rule(rule, name, bound);
m_context->add_rule(rule, name, bound);
}
}
@ -260,11 +260,11 @@ public:
print_certificate(ctx);
break;
case l_undef:
if(dlctx.get_status() == datalog::BOUNDED){
ctx.regular_stream() << "bounded\n";
print_certificate(ctx);
break;
}
if(dlctx.get_status() == datalog::BOUNDED){
ctx.regular_stream() << "bounded\n";
print_certificate(ctx);
break;
}
ctx.regular_stream() << "unknown\n";
switch(dlctx.get_status()) {
case datalog::INPUT_ERROR:

View file

@ -219,7 +219,7 @@ namespace datalog {
class mk_bit_blast::impl {
context & m_context;
context & m_context;
ast_manager & m;
params_ref m_params;
mk_interp_tail_simplifier m_simplifier;

View file

@ -72,7 +72,7 @@ namespace datalog {
transf.register_plugin(alloc(datalog::mk_bit_blast, ctx, 35000));
if (!ctx.get_params().quantify_arrays())
transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 36000));
transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 36000));
transf.register_plugin(alloc(datalog::mk_karr_invariants, ctx, 36010));
if (ctx.get_params().magic()) {
transf.register_plugin(alloc(datalog::mk_magic_symbolic, ctx, 36020));

View file

@ -1492,11 +1492,11 @@ namespace nlarith {
}
fml = mk_and(equivs.size(), equivs.c_ptr());
}
void mk_plus_inf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) {
void mk_pinf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) {
plus_inf_subst sub(*this);
mk_inf_sign(sub, literals, fml, new_atoms);
}
void mk_minus_inf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) {
void mk_ninf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) {
minus_inf_subst sub(*this);
mk_inf_sign(sub, literals, fml, new_atoms);
}
@ -1704,10 +1704,10 @@ namespace nlarith {
app_ref fml(m());
app_ref_vector new_atoms(m());
if (is_pos) {
mk_plus_inf_sign(literals, fml, new_atoms);
mk_pinf_sign(literals, fml, new_atoms);
}
else {
mk_minus_inf_sign(literals, fml, new_atoms);
mk_ninf_sign(literals, fml, new_atoms);
}
simple_branch* br = alloc(simple_branch, m(), fml);
swap_atoms(br, literals.lits(), new_atoms);

View file

@ -22,6 +22,7 @@ Revision History:
#include"arith_simplifier_plugin.h"
#include"array_simplifier_plugin.h"
#include"datatype_simplifier_plugin.h"
#include"fpa_simplifier_plugin.h"
#include"bv_simplifier_plugin.h"
#include"for_each_expr.h"
#include"well_sorted.h"
@ -96,7 +97,8 @@ void asserted_formulas::setup_simplifier_plugins(simplifier & s, basic_simplifie
s.register_plugin(alloc(array_simplifier_plugin, m_manager, *bsimp, s, m_params));
bvsimp = alloc(bv_simplifier_plugin, m_manager, *bsimp, m_params);
s.register_plugin(bvsimp);
s.register_plugin(alloc(datatype_simplifier_plugin, m_manager, *bsimp));
s.register_plugin(alloc(datatype_simplifier_plugin, m_manager, *bsimp));
s.register_plugin(alloc(fpa_simplifier_plugin, m_manager, *bsimp));
}
void asserted_formulas::init(unsigned num_formulas, expr * const * formulas, proof * const * prs) {

View file

@ -30,6 +30,7 @@ Revision History:
#include"theory_dummy.h"
#include"theory_dl.h"
#include"theory_seq_empty.h"
#include"theory_fpa.h"
namespace smt {
@ -679,6 +680,15 @@ namespace smt {
setup_mi_arith();
}
void setup::setup_QF_FP() {
m_context.register_plugin(alloc(smt::theory_fpa, m_manager));
}
void setup::setup_QF_FPBV() {
setup_QF_BV();
m_context.register_plugin(alloc(smt::theory_fpa, m_manager));
}
bool is_arith(static_features const & st) {
return st.m_num_arith_ineqs > 0 || st.m_num_arith_terms > 0 || st.m_num_arith_eqs > 0;
}
@ -780,6 +790,10 @@ namespace smt {
m_context.register_plugin(alloc(theory_seq_empty, m_manager));
}
void setup::setup_fpa() {
m_context.register_plugin(alloc(theory_fpa, m_manager));
}
void setup::setup_unknown() {
setup_arith();
setup_arrays();
@ -787,6 +801,7 @@ namespace smt {
setup_datatypes();
setup_dl();
setup_seq();
setup_fpa();
}
void setup::setup_unknown(static_features & st) {
@ -798,6 +813,7 @@ namespace smt {
setup_AUFLIA(false);
setup_datatypes();
setup_bv();
setup_fpa();
return;
}

View file

@ -75,6 +75,8 @@ namespace smt {
void setup_QF_AX(static_features const & st);
void setup_QF_AUFLIA();
void setup_QF_AUFLIA(static_features const & st);
void setup_QF_FP();
void setup_QF_FPBV();
void setup_LRA();
void setup_AUFLIA(bool simple_array = true);
void setup_AUFLIA(static_features const & st);
@ -91,10 +93,12 @@ namespace smt {
void setup_bv();
void setup_arith();
void setup_dl();
void setup_seq();
void setup_seq();
void setup_instgen();
void setup_i_arith();
void setup_mi_arith();
void setup_fpa();
public:
setup(context & c, smt_params & params);
void mark_already_configured() { m_already_configured = true; }

View file

@ -17,30 +17,816 @@ Revision History:
--*/
#include"ast_smt2_pp.h"
#include"smt_context.h"
#include"theory_fpa.h"
#include"theory_bv.h"
#include"smt_model_generator.h"
namespace smt {
class fpa2bv_conversion_trail_elem : public trail<theory_fpa> {
ast_manager & m;
obj_map<expr, expr*> & m_conversions;
expr * m_e;
public:
fpa2bv_conversion_trail_elem(ast_manager & m, obj_map<expr, expr*> & c, expr * e) :
m(m), m_conversions(c), m_e(e) {}
virtual ~fpa2bv_conversion_trail_elem() {}
virtual void undo(theory_fpa & th) {
expr * v = m_conversions.find(m_e);
m_conversions.remove(m_e);
m.dec_ref(v);
}
};
void theory_fpa::fpa2bv_converter_wrapped::mk_const(func_decl * f, expr_ref & result) {
SASSERT(f->get_family_id() == null_family_id);
SASSERT(f->get_arity() == 0);
expr * r;
if (m_const2bv.find(f, r)) {
result = r;
}
else {
sort * s = f->get_range();
expr_ref bv(m);
bv = m_th.wrap(m.mk_const(f));
unsigned bv_sz = m_th.m_bv_util.get_bv_size(bv);
unsigned ebits = m_th.m_fpa_util.get_ebits(s);
unsigned sbits = m_th.m_fpa_util.get_sbits(s);
SASSERT(bv_sz == ebits + sbits);
m_th.m_converter.mk_fp(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv),
m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv),
m_bv_util.mk_extract(sbits - 2, 0, bv),
result);
SASSERT(m_th.m_fpa_util.is_float(result));
m_const2bv.insert(f, result);
m.inc_ref(f);
m.inc_ref(result);
}
}
void theory_fpa::fpa2bv_converter_wrapped::mk_rm_const(func_decl * f, expr_ref & result) {
SASSERT(f->get_family_id() == null_family_id);
SASSERT(f->get_arity() == 0);
expr * r;
if (m_rm_const2bv.find(f, r)) {
result = r;
}
else {
SASSERT(is_rm(f->get_range()));
result = m_th.wrap(m.mk_const(f));
m_rm_const2bv.insert(f, result);
m.inc_ref(f);
m.inc_ref(result);
}
}
theory_fpa::theory_fpa(ast_manager & m) :
theory(m.mk_family_id("fpa")),
m_converter(m, this),
m_rw(m, m_converter, params_ref()),
m_th_rw(m),
m_trail_stack(*this),
m_fpa_util(m_converter.fu()),
m_bv_util(m_converter.bu()),
m_arith_util(m_converter.au())
{
params_ref p;
p.set_bool("arith_lhs", true);
m_th_rw.updt_params(p);
}
theory_fpa::~theory_fpa()
{
ast_manager & m = get_manager();
dec_ref_map_values(m, m_conversions);
dec_ref_map_values(m, m_wraps);
dec_ref_map_values(m, m_unwraps);
}
app * theory_fpa::fpa_value_proc::mk_value(model_generator & mg, ptr_vector<expr> & values) {
ast_manager & m = m_th.get_manager();
TRACE("t_fpa_detail", for (unsigned i = 0; i < values.size(); i++)
tout << "value[" << i << "] = " << mk_ismt2_pp(values[i], m) << std::endl;);
mpf_manager & mpfm = m_fu.fm();
unsynch_mpq_manager & mpqm = mpfm.mpq_manager();
unsynch_mpz_manager & mpzm = mpfm.mpz_manager();
app * result;
scoped_mpz bias(mpzm);
mpzm.power(mpz(2), m_ebits - 1, bias);
mpzm.dec(bias);
scoped_mpz sgn_z(mpzm), sig_z(mpzm), exp_z(mpzm);
unsigned bv_sz;
if (values.size() == 1) {
SASSERT(m_bu.is_bv(values[0]));
SASSERT(m_bu.get_bv_size(values[0]) == (m_ebits + m_sbits));
rational all_r(0);
scoped_mpz all_z(mpzm);
bool r = m_bu.is_numeral(values[0], all_r, bv_sz);
SASSERT(r);
SASSERT(bv_sz == (m_ebits + m_sbits));
SASSERT(all_r.is_int());
mpzm.set(all_z, all_r.to_mpq().numerator());
mpzm.machine_div2k(all_z, m_ebits + m_sbits - 1, sgn_z);
mpzm.mod(all_z, mpfm.m_powers2(m_ebits + m_sbits - 1), all_z);
mpzm.machine_div2k(all_z, m_sbits - 1, exp_z);
mpzm.mod(all_z, mpfm.m_powers2(m_sbits - 1), all_z);
mpzm.set(sig_z, all_z);
}
else if (values.size() == 3) {
rational sgn_r(0), exp_r(0), sig_r(0);
bool r = m_bu.is_numeral(values[0], sgn_r, bv_sz);
SASSERT(r && bv_sz == 1);
r = m_bu.is_numeral(values[1], exp_r, bv_sz);
SASSERT(r && bv_sz == m_ebits);
r = m_bu.is_numeral(values[2], sig_r, bv_sz);
SASSERT(r && bv_sz == m_sbits - 1);
SASSERT(sgn_r.to_mpq().denominator() == mpz(1));
SASSERT(exp_r.to_mpq().denominator() == mpz(1));
SASSERT(sig_r.to_mpq().denominator() == mpz(1));
mpzm.set(sgn_z, sgn_r.to_mpq().numerator());
mpzm.set(exp_z, exp_r.to_mpq().numerator());
mpzm.set(sig_z, sig_r.to_mpq().numerator());
}
else
UNREACHABLE();
scoped_mpz exp_u = exp_z - bias;
SASSERT(mpzm.is_int64(exp_u));
scoped_mpf f(mpfm);
mpfm.set(f, m_ebits, m_sbits, mpzm.is_one(sgn_z), sig_z, mpzm.get_int64(exp_u));
result = m_fu.mk_value(f);
TRACE("t_fpa", tout << "fpa_value_proc::mk_value [" <<
mpzm.to_string(sgn_z) << "," <<
mpzm.to_string(exp_z) << "," <<
mpzm.to_string(sig_z) << "] --> " <<
mk_ismt2_pp(result, m_th.get_manager()) << "\n";);
return result;
}
app * theory_fpa::fpa_rm_value_proc::mk_value(model_generator & mg, ptr_vector<expr> & values) {
SASSERT(values.size() == 1);
ast_manager & m = m_th.get_manager();
TRACE("t_fpa_detail", for (unsigned i = 0; i < values.size(); i++)
tout << "value[" << i << "] = " << mk_ismt2_pp(values[i], m) << std::endl;);
app * result = 0;
sort * s = m.get_sort(values[0]);
unsigned bv_sz;
rational val(0);
bool r = m_bu.is_numeral(values[0], val, bv_sz);
SASSERT(r);
SASSERT(bv_sz == 3);
switch (val.get_uint64())
{
case BV_RM_TIES_TO_AWAY: result = m_fu.mk_round_nearest_ties_to_away(); break;
case BV_RM_TIES_TO_EVEN: result = m_fu.mk_round_nearest_ties_to_even(); break;
case BV_RM_TO_NEGATIVE: result = m_fu.mk_round_toward_negative(); break;
case BV_RM_TO_POSITIVE: result = m_fu.mk_round_toward_positive(); break;
case BV_RM_TO_ZERO:
default: result = m_fu.mk_round_toward_zero();
}
TRACE("t_fpa", tout << "fpa_rm_value_proc::mk_value result: " <<
mk_ismt2_pp(result, m_th.get_manager()) << "\n";);
return result;
}
app_ref theory_fpa::wrap(expr * e) {
SASSERT(!m_fpa_util.is_wrap(e));
ast_manager & m = get_manager();
context & ctx = get_context();
sort * e_srt = m.get_sort(e);
func_decl *w;
if (!m_wraps.find(e_srt, w)) {
SASSERT(!m_wraps.contains(e_srt));
sort * bv_srt;
if (m_converter.is_rm(e_srt))
bv_srt = m_bv_util.mk_sort(3);
else {
SASSERT(m_converter.is_float(e_srt));
unsigned ebits = m_fpa_util.get_ebits(e_srt);
unsigned sbits = m_fpa_util.get_sbits(e_srt);
bv_srt = m_bv_util.mk_sort(ebits + sbits);
}
w = m.mk_func_decl(get_family_id(), OP_FPA_INTERNAL_BVWRAP, 0, 0, 1, &e_srt, bv_srt);
m_wraps.insert(e_srt, w);
m.inc_ref(w);
}
app_ref res(m);
res = m.mk_app(w, e);
return res;
}
app_ref theory_fpa::unwrap(expr * e, sort * s) {
SASSERT(!m_fpa_util.is_unwrap(e));
ast_manager & m = get_manager();
context & ctx = get_context();
sort * bv_srt = m.get_sort(e);
func_decl *u;
if (!m_unwraps.find(bv_srt, u)) {
SASSERT(!m_unwraps.contains(bv_srt));
u = m.mk_func_decl(get_family_id(), OP_FPA_INTERNAL_BVUNWRAP, 0, 0, 1, &bv_srt, s);
m_unwraps.insert(bv_srt, u);
m.inc_ref(u);
}
app_ref res(m);
res = m.mk_app(u, e);
return res;
}
expr_ref theory_fpa::convert_atom(expr * e) {
ast_manager & m = get_manager();
expr_ref res(m);
proof_ref pr(m);
m_rw(e, res);
m_th_rw(res, res);
SASSERT(is_app(res));
SASSERT(m.is_bool(res));
return res;
}
expr_ref theory_fpa::convert_term(expr * e) {
ast_manager & m = get_manager();
context & ctx = get_context();
expr_ref e_conv(m), res(m);
proof_ref pr(m);
m_rw(e, e_conv);
if (m_fpa_util.is_rm(e)) {
SASSERT(is_sort_of(m.get_sort(e_conv), m_bv_util.get_family_id(), BV_SORT));
SASSERT(m_bv_util.get_bv_size(e_conv) == 3);
m_th_rw(e_conv, res);
}
else if (m_fpa_util.is_float(e)) {
expr_ref sgn(m), sig(m), exp(m);
m_converter.split_fp(e_conv, sgn, exp, sig);
m_th_rw(sgn);
m_th_rw(exp);
m_th_rw(sig);
m_converter.mk_fp(sgn, exp, sig, res);
}
else
UNREACHABLE();
SASSERT(res.get() != 0);
return res;
}
expr_ref theory_fpa::convert_conversion_term(expr * e) {
/* This is for the conversion functions fp.to_* */
ast_manager & m = get_manager();
context & ctx = get_context();
expr_ref res(m);
proof_ref pr(m);
SASSERT(m_arith_util.is_real(e) || m_bv_util.is_bv(e));
m_rw(e, res);
m_th_rw(res, res);
return res;
}
expr_ref theory_fpa::convert_unwrap(expr * e) {
SASSERT(m_fpa_util.is_unwrap(e));
ast_manager & m = get_manager();
sort * srt = m.get_sort(e);
expr_ref res(m);
if (m_fpa_util.is_rm(srt)) {
res = to_app(e)->get_arg(0);
}
else {
SASSERT(m_fpa_util.is_float(srt));
unsigned ebits = m_fpa_util.get_ebits(srt);
unsigned sbits = m_fpa_util.get_sbits(srt);
expr_ref bv(m);
bv = to_app(e)->get_arg(0);
unsigned bv_sz = m_bv_util.get_bv_size(bv);
m_converter.mk_fp(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv),
m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv),
m_bv_util.mk_extract(sbits - 2, 0, bv),
res);
}
return res;
}
expr_ref theory_fpa::convert(expr * e)
{
ast_manager & m = get_manager();
context & ctx = get_context();
expr_ref res(m);
if (m_conversions.contains(e)) {
res = m_conversions.find(e);
TRACE("t_fpa_detail", tout << "cached:" << std::endl;
tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl <<
mk_ismt2_pp(res, m) << std::endl;);
return res;
}
else {
if (m_fpa_util.is_unwrap(e))
res = convert_unwrap(e);
else if (m.is_bool(e))
res = convert_atom(e);
else if (m_fpa_util.is_float(e) || m_fpa_util.is_rm(e))
res = convert_term(e);
else if (m_arith_util.is_real(e) || m_bv_util.is_bv(e))
res = convert_conversion_term(e);
else
UNREACHABLE();
TRACE("t_fpa_detail", tout << "converted; caching:" << std::endl;
tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl <<
mk_ismt2_pp(res, m) << std::endl;);
m_conversions.insert(e, res);
m.inc_ref(res);
m_trail_stack.push(fpa2bv_conversion_trail_elem(m, m_conversions, e));
}
return res;
}
expr_ref theory_fpa::mk_side_conditions()
{
ast_manager & m = get_manager();
context & ctx = get_context();
simplifier & simp = ctx.get_simplifier();
expr_ref res(m), t(m);
proof_ref t_pr(m);
res = m.mk_true();
expr_ref_vector::iterator it = m_converter.m_extra_assertions.begin();
expr_ref_vector::iterator end = m_converter.m_extra_assertions.end();
for (; it != end; it++) {
simp(*it, t, t_pr);
res = m.mk_and(res, t);
}
m_converter.m_extra_assertions.reset();
m_th_rw(res);
CTRACE("t_fpa", !m.is_true(res), tout << "side condition: " << mk_ismt2_pp(res, m) << "\n";);
return res;
}
void theory_fpa::assert_cnstr(expr * e) {
if (get_manager().is_true(e)) return;
TRACE("t_fpa_detail", tout << "asserting " << mk_ismt2_pp(e, get_manager()) << "\n";);
context & ctx = get_context();
ctx.internalize(e, false);
literal lit(ctx.get_literal(e));
ctx.mark_as_relevant(lit);
ctx.mk_th_axiom(get_id(), 1, &lit);
TRACE("t_fpa_detail", tout << "done asserting " << mk_ismt2_pp(e, get_manager()) << "\n";);
}
void theory_fpa::attach_new_th_var(enode * n) {
context & ctx = get_context();
theory_var v = mk_var(n);
ctx.attach_th_var(n, this, v);
TRACE("t_fpa_detail", tout << "new theory var: " << mk_ismt2_pp(n->get_owner(), get_manager()) << " := " << v << "\n";);
}
bool theory_fpa::internalize_atom(app * atom, bool gate_ctx) {
TRACE("bv", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";);
TRACE("t_fpa", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";);
SASSERT(atom->get_family_id() == get_family_id());
NOT_IMPLEMENTED_YET();
ast_manager & m = get_manager();
context & ctx = get_context();
if (ctx.b_internalized(atom))
return true;
unsigned num_args = atom->get_num_args();
for (unsigned i = 0; i < num_args; i++)
ctx.internalize(atom->get_arg(i), false);
literal l(ctx.mk_bool_var(atom));
ctx.set_var_theory(l.var(), get_id());
expr_ref bv_atom(m);
bv_atom = convert_atom(atom);
SASSERT(is_app(bv_atom) && m.is_bool(bv_atom));
bv_atom = m.mk_and(bv_atom, mk_side_conditions());
assert_cnstr(m.mk_iff(atom, bv_atom));
return true;
}
void theory_fpa::new_eq_eh(theory_var, theory_var) {
NOT_IMPLEMENTED_YET();
bool theory_fpa::internalize_term(app * term) {
ast_manager & m = get_manager();
context & ctx = get_context();
TRACE("t_fpa", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << "\n";);
SASSERT(term->get_family_id() == get_family_id());
SASSERT(!ctx.e_internalized(term));
unsigned num_args = term->get_num_args();
for (unsigned i = 0; i < num_args; i++)
ctx.internalize(term->get_arg(i), false);
enode * e = (ctx.e_internalized(term)) ? ctx.get_enode(term) :
ctx.mk_enode(term, false, false, true);
if (is_attached_to_var(e))
return false;
attach_new_th_var(e);
// The conversion operators fp.to_* appear in non-FP constraints.
// The corresponding constraints will not be translated and added
// via convert(...) and assert_cnstr(...) in initialize_atom(...).
// Therefore, we translate and assert them here.
fpa_op_kind k = (fpa_op_kind)term->get_decl_kind();
switch (k) {
case OP_FPA_TO_UBV:
case OP_FPA_TO_SBV:
case OP_FPA_TO_REAL: {
expr_ref conv(m);
conv = convert(term);
assert_cnstr(m.mk_eq(term, conv));
assert_cnstr(mk_side_conditions());
break;
}
default: /* ignore */;
}
return true;
}
void theory_fpa::apply_sort_cnstr(enode * n, sort * s) {
TRACE("t_fpa", tout << "apply sort cnstr for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << "\n";);
SASSERT(n->get_owner()->get_family_id() == get_family_id() ||
n->get_owner()->get_family_id() == null_theory_id);
SASSERT(s->get_family_id() == get_family_id());
if (!is_attached_to_var(n)) {
attach_new_th_var(n);
ast_manager & m = get_manager();
context & ctx = get_context();
app_ref owner(m);
sort_ref owner_sort(m);
owner = n->get_owner();
owner_sort = m.get_sort(owner);
if (m_fpa_util.is_rm(owner_sort)) {
// For every RM term, we need to make sure that it's
// associated bit-vector is within the valid range.
if (!m_fpa_util.is_unwrap(owner)) {
expr_ref valid(m), limit(m);
limit = m_bv_util.mk_numeral(4, 3);
valid = m_bv_util.mk_ule(wrap(owner), limit);
assert_cnstr(valid);
}
}
if (!ctx.relevancy() && !m_fpa_util.is_unwrap(owner))
assert_cnstr(m.mk_eq(unwrap(wrap(owner), owner_sort), owner));
}
}
void theory_fpa::new_diseq_eh(theory_var, theory_var) {
NOT_IMPLEMENTED_YET();
void theory_fpa::new_eq_eh(theory_var x, theory_var y) {
ast_manager & m = get_manager();
TRACE("t_fpa", tout << "new eq: " << x << " = " << y << std::endl;);
TRACE("t_fpa_detail", tout << mk_ismt2_pp(get_enode(x)->get_owner(), m) << " = " <<
mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl;);
context & ctx = get_context();
fpa_util & fu = m_fpa_util;
bv_util & bu = m_bv_util;
mpf_manager & mpfm = fu.fm();
expr_ref xe(m), ye(m);
xe = get_enode(x)->get_owner();
ye = get_enode(y)->get_owner();
if ((m.is_bool(xe) && m.is_bool(ye)) ||
(m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye))) {
SASSERT(to_app(xe)->get_decl()->get_family_id() == get_family_id());
return;
}
expr_ref xc(m), yc(m);
xc = convert(xe);
yc = convert(ye);
TRACE("t_fpa_detail", tout << "xc=" << mk_ismt2_pp(xc, m) << std::endl;
tout << "yc=" << mk_ismt2_pp(yc, m) << std::endl;);
expr_ref c(m);
if (fu.is_float(xe) && fu.is_float(ye))
{
expr *x_sgn, *x_sig, *x_exp;
m_converter.split_fp(xc, x_sgn, x_exp, x_sig);
expr *y_sgn, *y_sig, *y_exp;
m_converter.split_fp(yc, y_sgn, y_exp, y_sig);
c = m.mk_eq(m_bv_util.mk_concat(m_bv_util.mk_concat(x_sgn, x_exp), x_sig),
m_bv_util.mk_concat(m_bv_util.mk_concat(y_sgn, y_exp), y_sig));
}
else
c = m.mk_eq(xc, yc);
m_th_rw(c);
assert_cnstr(m.mk_iff(m.mk_eq(xe, ye), c));
assert_cnstr(mk_side_conditions());
return;
}
void theory_fpa::new_diseq_eh(theory_var x, theory_var y) {
ast_manager & m = get_manager();
TRACE("t_fpa", tout << "new diseq: " << x << " != " << y << std::endl;);
TRACE("t_fpa_detail", tout << mk_ismt2_pp(get_enode(x)->get_owner(), m) << " != " <<
mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl;);
context & ctx = get_context();
mpf_manager & mpfm = m_fpa_util.fm();
expr_ref xe(m), ye(m);
xe = get_enode(x)->get_owner();
ye = get_enode(y)->get_owner();
if ((m.is_bool(xe) && m.is_bool(ye)) ||
(m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye))) {
SASSERT(to_app(xe)->get_decl()->get_family_id() == get_family_id());
return;
}
expr_ref xc(m), yc(m);
xc = convert(xe);
yc = convert(ye);
expr_ref c(m);
if (m_fpa_util.is_float(xe) && m_fpa_util.is_float(ye))
{
expr *x_sgn, *x_sig, *x_exp;
m_converter.split_fp(xc, x_sgn, x_exp, x_sig);
expr *y_sgn, *y_sig, *y_exp;
m_converter.split_fp(yc, y_sgn, y_exp, y_sig);
c = m.mk_not(m.mk_eq(m_bv_util.mk_concat(m_bv_util.mk_concat(x_sgn, x_exp), x_sig),
m_bv_util.mk_concat(m_bv_util.mk_concat(y_sgn, y_exp), y_sig)));
}
else
c = m.mk_not(m.mk_eq(xc, yc));
m_th_rw(c);
assert_cnstr(m.mk_iff(m.mk_not(m.mk_eq(xe, ye)), c));
assert_cnstr(mk_side_conditions());
return;
}
void theory_fpa::push_scope_eh() {
NOT_IMPLEMENTED_YET();
theory::push_scope_eh();
m_trail_stack.push_scope();
}
void theory_fpa::pop_scope_eh(unsigned num_scopes) {
NOT_IMPLEMENTED_YET();
void theory_fpa::pop_scope_eh(unsigned num_scopes) {
m_trail_stack.pop_scope(num_scopes);
TRACE("t_fpa", tout << "pop " << num_scopes << "; now " << m_trail_stack.get_num_scopes() << "\n";);
// unsigned num_old_vars = get_old_num_vars(num_scopes);
theory::pop_scope_eh(num_scopes);
}
void theory_fpa::assign_eh(bool_var v, bool is_true) {
ast_manager & m = get_manager();
context & ctx = get_context();
expr * e = ctx.bool_var2expr(v);
TRACE("t_fpa", tout << "assign_eh for: " << v << " (" << is_true << "):\n" << mk_ismt2_pp(e, m) << "\n";);
expr_ref converted(m);
converted = m.mk_and(convert(e), mk_side_conditions());
if (is_true)
assert_cnstr(m.mk_implies(e, converted));
else
assert_cnstr(m.mk_implies(m.mk_not(e), m.mk_not(converted)));
}
void theory_fpa::relevant_eh(app * n) {
ast_manager & m = get_manager();
TRACE("t_fpa", tout << "relevant_eh for: " << mk_ismt2_pp(n, m) << "\n";);
mpf_manager & mpfm = m_fpa_util.fm();
unsynch_mpq_manager & mpqm = mpfm.mpq_manager();
if (m_fpa_util.is_float(n) || m_fpa_util.is_rm(n)) {
sort * s = m.get_sort(n);
if (!m_fpa_util.is_unwrap(n)) {
expr_ref wrapped(m), c(m);
wrapped = wrap(n);
mpf_rounding_mode rm;
scoped_mpf val(mpfm);
if (m_fpa_util.is_rm_numeral(n, rm)) {
c = m.mk_eq(wrapped, m_bv_util.mk_numeral(rm, 3));
assert_cnstr(c);
}
else if (m_fpa_util.is_numeral(n, val)) {
unsigned sz = val.get().get_ebits() + val.get().get_sbits();
expr_ref bv_val_e(m);
bv_val_e = convert(n);
SASSERT(is_app(bv_val_e));
SASSERT(to_app(bv_val_e)->get_num_args() == 3);
app_ref bv_val_a(to_app(bv_val_e.get()), m);
expr * args[] = { bv_val_a->get_arg(0), bv_val_a->get_arg(1), bv_val_a->get_arg(2) };
c = m.mk_eq(wrapped, m_bv_util.mk_concat(3, args));
c = m.mk_and(c, mk_side_conditions());
assert_cnstr(c);
}
else {
c = m.mk_eq(unwrap(wrapped, m.get_sort(n)), n);
assert_cnstr(c);
}
}
}
else if (n->get_family_id() == get_family_id()) {
// These are the conversion functions fp.to_* */
SASSERT(!m_fpa_util.is_float(n) && !m_fpa_util.is_rm(n));
}
else
UNREACHABLE();
}
void theory_fpa::reset_eh() {
TRACE("t_fpa", tout << "reset_eh\n";);
pop_scope_eh(m_trail_stack.get_num_scopes());
m_converter.reset();
m_rw.reset();
m_th_rw.reset();
m_trail_stack.pop_scope(m_trail_stack.get_num_scopes());
if (m_factory) dealloc(m_factory); m_factory = 0;
ast_manager & m = get_manager();
dec_ref_map_values(m, m_conversions);
dec_ref_map_values(m, m_wraps);
dec_ref_map_values(m, m_unwraps);
theory::reset_eh();
}
final_check_status theory_fpa::final_check_eh() {
TRACE("t_fpa", tout << "final_check_eh\n";);
SASSERT(m_converter.m_extra_assertions.empty());
return FC_DONE;
}
void theory_fpa::init_model(model_generator & mg) {
TRACE("t_fpa", tout << "initializing model" << std::endl; display(tout););
m_factory = alloc(fpa_value_factory, get_manager(), get_family_id());
mg.register_factory(m_factory);
}
model_value_proc * theory_fpa::mk_value(enode * n, model_generator & mg) {
TRACE("t_fpa", tout << "mk_value for: " << mk_ismt2_pp(n->get_owner(), get_manager()) <<
" (sort " << mk_ismt2_pp(get_manager().get_sort(n->get_owner()), get_manager()) << ")\n";);
ast_manager & m = get_manager();
context & ctx = get_context();
app_ref owner(m);
owner = n->get_owner();
// If the owner is not internalized, it doesn't have an enode associated.
SASSERT(ctx.e_internalized(owner));
if (m_fpa_util.is_rm_numeral(owner) ||
m_fpa_util.is_numeral(owner)) {
return alloc(expr_wrapper_proc, owner);
}
model_value_proc * res = 0;
app_ref wrapped(m);
wrapped = wrap(owner);
SASSERT(m_bv_util.is_bv(wrapped));
CTRACE("t_fpa_detail", !ctx.e_internalized(wrapped),
tout << "Model dependency not internalized: " <<
mk_ismt2_pp(wrapped, m) <<
" (owner " << (!ctx.e_internalized(owner) ? "not" : "is") <<
" internalized)" << std::endl;);
if (is_app_of(owner, get_family_id(), OP_FPA_FP)) {
SASSERT(to_app(owner)->get_num_args() == 3);
app_ref a0(m), a1(m), a2(m);
a0 = to_app(owner->get_arg(0));
a1 = to_app(owner->get_arg(1));
a2 = to_app(owner->get_arg(2));
unsigned ebits = m_fpa_util.get_ebits(m.get_sort(owner));
unsigned sbits = m_fpa_util.get_sbits(m.get_sort(owner));
fpa_value_proc * vp = alloc(fpa_value_proc, this, ebits, sbits);
vp->add_dependency(ctx.get_enode(a0));
vp->add_dependency(ctx.get_enode(a1));
vp->add_dependency(ctx.get_enode(a2));
TRACE("t_fpa_detail", tout << "Depends on: " <<
mk_ismt2_pp(a0, m) << " eq. cls. #" << get_enode(a0)->get_root()->get_owner()->get_id() << std::endl <<
mk_ismt2_pp(a1, m) << " eq. cls. #" << get_enode(a1)->get_root()->get_owner()->get_id() << std::endl <<
mk_ismt2_pp(a2, m) << " eq. cls. #" << get_enode(a2)->get_root()->get_owner()->get_id() << std::endl;);
res = vp;
}
else if (ctx.e_internalized(wrapped)) {
if (m_fpa_util.is_rm(owner)) {
fpa_rm_value_proc * vp = alloc(fpa_rm_value_proc, this);
vp->add_dependency(ctx.get_enode(wrapped));
res = vp;
}
else if (m_fpa_util.is_float(owner)) {
unsigned ebits = m_fpa_util.get_ebits(m.get_sort(owner));
unsigned sbits = m_fpa_util.get_sbits(m.get_sort(owner));
fpa_value_proc * vp = alloc(fpa_value_proc, this, ebits, sbits);
enode * en = ctx.get_enode(wrapped);
vp->add_dependency(en);
TRACE("t_fpa_detail", tout << "Depends on: " << mk_ismt2_pp(wrapped, m) << " eq. cls. #" << en->get_root()->get_owner()->get_id() << std::endl;);
res = vp;
}
}
else {
unsigned ebits = m_fpa_util.get_ebits(m.get_sort(owner));
unsigned sbits = m_fpa_util.get_sbits(m.get_sort(owner));
return alloc(expr_wrapper_proc, m_fpa_util.mk_pzero(ebits, sbits));
}
SASSERT(res != 0);
return res;
}
void theory_fpa::finalize_model(model_generator & mg) {}
void theory_fpa::display(std::ostream & out) const
{
ast_manager & m = get_manager();
context & ctx = get_context();
out << "fpa theory variables:" << std::endl;
ptr_vector<enode>::const_iterator it = ctx.begin_enodes();
ptr_vector<enode>::const_iterator end = ctx.end_enodes();
for (; it != end; it++) {
theory_var v = (*it)->get_th_var(get_family_id());
if (v != -1) out << v << " -> " <<
mk_ismt2_pp((*it)->get_owner(), m) << std::endl;
}
out << "bv theory variables:" << std::endl;
it = ctx.begin_enodes();
end = ctx.end_enodes();
for (; it != end; it++) {
theory_var v = (*it)->get_th_var(m_bv_util.get_family_id());
if (v != -1) out << v << " -> " <<
mk_ismt2_pp((*it)->get_owner(), m) << std::endl;
}
out << "arith theory variables:" << std::endl;
it = ctx.begin_enodes();
end = ctx.end_enodes();
for (; it != end; it++) {
theory_var v = (*it)->get_th_var(m_arith_util.get_family_id());
if (v != -1) out << v << " -> " <<
mk_ismt2_pp((*it)->get_owner(), m) << std::endl;
}
out << "equivalence classes:\n";
it = ctx.begin_enodes();
end = ctx.end_enodes();
for (; it != end; ++it) {
expr * n = (*it)->get_owner();
expr * r = (*it)->get_root()->get_owner();
out << r->get_id() << " --> " << mk_ismt2_pp(n, m) << std::endl;
}
}
};

View file

@ -20,26 +20,173 @@ Revision History:
#define _THEORY_FPA_H_
#include"smt_theory.h"
#include"trail.h"
#include"fpa2bv_converter.h"
#include"fpa2bv_rewriter.h"
#include"th_rewriter.h"
#include"value_factory.h"
#include"smt_model_generator.h"
namespace smt {
class theory_fpa : public theory {
fpa2bv_converter m_converter;
virtual final_check_status final_check_eh() { return FC_DONE; }
virtual bool internalize_atom(app*, bool);
virtual bool internalize_term(app*) { return internalize_atom(0, false); }
class fpa_value_factory : public value_factory {
fpa_util m_util;
virtual app * mk_value_core(mpf const & val, sort * s) {
SASSERT(m_util.get_ebits(s) == val.get_ebits());
SASSERT(m_util.get_sbits(s) == val.get_sbits());
return m_util.mk_value(val);
}
public:
fpa_value_factory(ast_manager & m, family_id fid) :
value_factory(m, fid),
m_util(m) {}
virtual ~fpa_value_factory() {}
virtual expr * get_some_value(sort * s) {
mpf_manager & mpfm = m_util.fm();
scoped_mpf q(mpfm);
mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 0);
return m_util.mk_value(q);
}
virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
mpf_manager & mpfm = m_util.fm();
scoped_mpf q(mpfm);
mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 0);
v1 = m_util.mk_value(q);
mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 1);
v2 = m_util.mk_value(q);
return true;
}
virtual expr * get_fresh_value(sort * s) { NOT_IMPLEMENTED_YET(); }
virtual void register_value(expr * n) { /* Ignore */ }
app * mk_value(mpf const & x) {
return m_util.mk_value(x);
}
};
class theory_fpa : public theory {
protected:
typedef trail_stack<theory_fpa> th_trail_stack;
class fpa2bv_converter_wrapped : public fpa2bv_converter {
public:
theory_fpa & m_th;
fpa2bv_converter_wrapped(ast_manager & m, theory_fpa * th) :
fpa2bv_converter(m),
m_th(*th) {}
virtual ~fpa2bv_converter_wrapped() {}
virtual void mk_const(func_decl * f, expr_ref & result);
virtual void mk_rm_const(func_decl * f, expr_ref & result);
};
class fpa_value_proc : public model_value_proc {
protected:
theory_fpa & m_th;
ast_manager & m;
fpa_util & m_fu;
bv_util & m_bu;
buffer<model_value_dependency> m_deps;
unsigned m_ebits;
unsigned m_sbits;
public:
fpa_value_proc(theory_fpa * th, unsigned ebits, unsigned sbits) :
m_th(*th), m_fu(th->m_fpa_util), m_bu(th->m_bv_util), m(th->get_manager()),
m_ebits(ebits), m_sbits(sbits) {}
virtual ~fpa_value_proc() {}
void add_dependency(enode * e) { m_deps.push_back(model_value_dependency(e)); }
virtual void get_dependencies(buffer<model_value_dependency> & result) {
result.append(m_deps);
}
virtual app * mk_value(model_generator & mg, ptr_vector<expr> & values);
};
class fpa_rm_value_proc : public model_value_proc {
theory_fpa & m_th;
ast_manager & m;
fpa_util & m_fu;
bv_util & m_bu;
buffer<model_value_dependency> m_deps;
public:
fpa_rm_value_proc(theory_fpa * th) :
m_th(*th), m_fu(th->m_fpa_util), m_bu(th->m_bv_util), m(th->get_manager()) {}
void add_dependency(enode * e) { m_deps.push_back(model_value_dependency(e)); }
virtual void get_dependencies(buffer<model_value_dependency> & result) {
result.append(m_deps);
}
virtual ~fpa_rm_value_proc() {}
virtual app * mk_value(model_generator & mg, ptr_vector<expr> & values);
};
protected:
fpa2bv_converter_wrapped m_converter;
fpa2bv_rewriter m_rw;
th_rewriter m_th_rw;
th_trail_stack m_trail_stack;
fpa_value_factory * m_factory;
fpa_util & m_fpa_util;
bv_util & m_bv_util;
arith_util & m_arith_util;
obj_map<sort, func_decl*> m_wraps;
obj_map<sort, func_decl*> m_unwraps;
obj_map<expr, expr*> m_conversions;
virtual final_check_status final_check_eh();
virtual bool internalize_atom(app * atom, bool gate_ctx);
virtual bool internalize_term(app * term);
virtual void apply_sort_cnstr(enode * n, sort * s);
virtual void new_eq_eh(theory_var, theory_var);
virtual void new_diseq_eh(theory_var, theory_var);
virtual void push_scope_eh();
virtual void pop_scope_eh(unsigned num_scopes);
virtual void reset_eh();
virtual theory* mk_fresh(context*) { return alloc(theory_fpa, get_manager()); }
virtual char const * get_name() const { return "fpa"; }
virtual char const * get_name() const { return "fpa"; }
virtual model_value_proc * mk_value(enode * n, model_generator & mg);
void assign_eh(bool_var v, bool is_true);
virtual void relevant_eh(app * n);
virtual void init_model(model_generator & m);
virtual void finalize_model(model_generator & mg);
public:
theory_fpa(ast_manager& m) : theory(m.mk_family_id("fpa")), m_converter(m) {}
theory_fpa(ast_manager& m);
virtual ~theory_fpa();
virtual void display(std::ostream & out) const;
protected:
expr_ref mk_side_conditions();
expr_ref convert(expr * e);
expr_ref convert_atom(expr * e);
expr_ref convert_term(expr * e);
expr_ref convert_conversion_term(expr * e);
expr_ref convert_unwrap(expr * e);
void add_trail(ast * a);
void attach_new_th_var(enode * n);
void assert_cnstr(expr * e);
app_ref wrap(expr * e);
app_ref unwrap(expr * e, sort * s);
};
};
#endif /* _THEORY_FPA_H_ */

View file

@ -27,7 +27,7 @@ Notes:
struct aig;
class aig_lit {
friend class aig_ref;
friend class aig_ref;
aig * m_ref;
public:
aig_lit(aig * n = 0):m_ref(n) {}
@ -1508,10 +1508,10 @@ public:
template<typename S>
aig_lit mk_aig(S const & s) {
aig_lit r;
r = m_true;
inc_ref(r);
r = m_true;
inc_ref(r);
try {
expr2aig proc(*this);
expr2aig proc(*this);
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++) {
SASSERT(ref_count(r) >= 1);
@ -1528,10 +1528,10 @@ public:
}
SASSERT(ref_count(r) >= 1);
}
catch (aig_exception ex) {
dec_ref(r);
throw ex;
}
catch (aig_exception ex) {
dec_ref(r);
throw ex;
}
dec_ref_result(r);
return r;
}

Some files were not shown because too many files have changed in this diff Show more