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:
commit
d56d63e3e8
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
793
src/api/api_fpa.cpp
Normal 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);
|
||||
}
|
||||
|
||||
};
|
|
@ -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("");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
52
src/api/dotnet/FPExpr.cs
Normal 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
103
src/api/dotnet/FPNum.cs
Normal 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 < s < 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);
|
||||
}
|
||||
}
|
||||
}
|
42
src/api/dotnet/FPRMExpr.cs
Normal file
42
src/api/dotnet/FPRMExpr.cs
Normal 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
100
src/api/dotnet/FPRMNum.cs
Normal 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
|
||||
}
|
||||
}
|
43
src/api/dotnet/FPRMSort.cs
Normal file
43
src/api/dotnet/FPRMSort.cs
Normal 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
52
src/api/dotnet/FPSort.cs
Normal 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
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
41
src/api/java/FPExpr.java
Normal 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
86
src/api/java/FPNum.java
Normal 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 < s < 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
29
src/api/java/FPRMExpr.java
Normal file
29
src/api/java/FPRMExpr.java
Normal 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
90
src/api/java/FPRMNum.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
35
src/api/java/FPRMSort.java
Normal file
35
src/api/java/FPRMSort.java
Normal 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
49
src/api/java/FPSort.java
Normal 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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
138
src/api/z3_api.h
138
src/api/z3_api.h
|
@ -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
923
src/api/z3_fpa.h
Normal 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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
|
|
@ -1003,7 +1003,7 @@ public:
|
|||
visit_sort(d->get_domain(i), true);
|
||||
}
|
||||
m_out << ")";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
5
src/ast/fpa/fpa2bv_rewriter_params.pyg
Normal file
5
src/ast/fpa/fpa2bv_rewriter_params.pyg
Normal 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
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
341
src/ast/fpa_decl_plugin.h
Normal 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
|
|
@ -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'),
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
598
src/ast/rewriter/fpa_rewriter.cpp
Normal file
598
src/ast/rewriter/fpa_rewriter.cpp
Normal 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;
|
||||
}
|
|
@ -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);
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
43
src/ast/simplifier/fpa_simplifier_plugin.cpp
Normal file
43
src/ast/simplifier/fpa_simplifier_plugin.cpp
Normal 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;
|
||||
}
|
||||
|
40
src/ast/simplifier/fpa_simplifier_plugin.h
Normal file
40
src/ast/simplifier/fpa_simplifier_plugin.h
Normal 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_ */
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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_ */
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue