3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-12-21 03:33:43 +00:00

FPA theory and API overhaul

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
This commit is contained in:
Christoph M. Wintersteiger 2015-01-01 18:44:41 +00:00
parent a28454d95e
commit 09247d2e29
9 changed files with 944 additions and 331 deletions

View file

@ -7,6 +7,7 @@ Module Name:
Abstract:
Additional APIs for floating-point arithmetic (FP).
Author:
@ -31,7 +32,7 @@ extern "C" {
Z3_sort r = of_sort(ctx->float_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)
{
@ -44,10 +45,20 @@ extern "C" {
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->float_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_even(c);
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->float_util().mk_round_nearest_ties_to_away());
@ -55,10 +66,20 @@ extern "C" {
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->float_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_nearest_ties_to_even(c);
LOG_Z3_mk_fpa_round_toward_positive(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->float_util().mk_round_toward_positive());
@ -66,10 +87,20 @@ extern "C" {
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->float_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_nearest_ties_to_even(c);
LOG_Z3_mk_fpa_round_toward_negative(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->float_util().mk_round_toward_negative());
@ -77,10 +108,20 @@ extern "C" {
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->float_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_nearest_ties_to_even(c);
LOG_Z3_mk_fpa_round_toward_zero(c);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->float_util().mk_round_toward_zero());
@ -88,6 +129,16 @@ extern "C" {
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->float_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;
@ -102,35 +153,35 @@ extern "C" {
Z3_CATCH_RETURN(0);
}
Z3_sort Z3_API Z3_mk_fpa_sort_half(__in Z3_context c) {
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(__in Z3_context c) {
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(__in Z3_context c) {
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(__in Z3_context c) {
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(__in Z3_context c) {
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(__in Z3_context c) {
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(__in Z3_context c) {
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(__in Z3_context c) {
Z3_sort Z3_API Z3_mk_fpa_sort_128(Z3_context c) {
return Z3_mk_fpa_sort(c, 15, 113);
}
@ -164,6 +215,28 @@ extern "C" {
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_fp(Z3_context c, Z3_ast sgn, Z3_ast sig, Z3_ast exp) {
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->float_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->float_util().fm());
ctx->float_util().fm().set(tmp, ctx->float_util().get_ebits(to_sort(ty)), ctx->float_util().get_sbits(to_sort(ty)), v);
Z3_ast r = of_ast(ctx->float_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);
@ -175,6 +248,51 @@ extern "C" {
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->float_util().fm());
ctx->float_util().fm().set(tmp,
ctx->float_util().get_ebits(to_sort(ty)),
ctx->float_util().get_sbits(to_sort(ty)),
v);
Z3_ast r = of_ast(ctx->float_util().mk_value(tmp));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_numeral_uint_int(Z3_context c, 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->float_util().fm());
ctx->float_util().fm().set(tmp,
ctx->float_util().get_ebits(to_sort(ty)),
ctx->float_util().get_sbits(to_sort(ty)),
sgn, sig, exp);
Z3_ast r = of_ast(ctx->float_util().mk_value(tmp));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_numeral_uint64_int64(Z3_context c, 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->float_util().fm());
ctx->float_util().fm().set(tmp,
ctx->float_util().get_ebits(to_sort(ty)),
ctx->float_util().get_sbits(to_sort(ty)),
sgn, sig, exp);
Z3_ast r = of_ast(ctx->float_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;
@ -265,20 +383,40 @@ extern "C" {
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_ast Z3_API Z3_mk_fpa_round_to_integral(Z3_context c, Z3_ast rm, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_eq(c, t1, t2);
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->float_util().mk_float_eq(to_expr(t1), to_expr(t2)));
Z3_ast r = of_ast(ctx->float_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->float_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->float_util().mk_max(to_expr(t1), to_expr(t2)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_le(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_ast Z3_API Z3_mk_fpa_leq(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_le(c, t1, t2);
LOG_Z3_mk_fpa_leq(c, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->float_util().mk_le(to_expr(t1), to_expr(t2)));
@ -296,9 +434,9 @@ extern "C" {
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_ge(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_ast Z3_API Z3_mk_fpa_geq(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_TRY;
LOG_Z3_mk_fpa_ge(c, t1, t2);
LOG_Z3_mk_fpa_geq(c, t1, t2);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->float_util().mk_ge(to_expr(t1), to_expr(t2)));
@ -315,6 +453,16 @@ extern "C" {
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->float_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;
@ -346,9 +494,9 @@ extern "C" {
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_is_inf(Z3_context c, Z3_ast t) {
Z3_ast Z3_API Z3_mk_fpa_is_infinite(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_is_inf(c, t);
LOG_Z3_mk_fpa_is_infinite(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->float_util().mk_is_inf(to_expr(t)));
@ -366,40 +514,142 @@ extern "C" {
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_min(Z3_context c, Z3_ast t1, Z3_ast t2) {
Z3_ast Z3_API Z3_mk_fpa_is_negative(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_min(c, t1, t2);
LOG_Z3_mk_fpa_is_negative(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
Z3_ast r = of_ast(ctx->float_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->float_util().mk_max(to_expr(t1), to_expr(t2)));
Z3_ast r = of_ast(ctx->float_util().mk_is_negative(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_convert(Z3_context c, Z3_sort s, Z3_ast rm, Z3_ast t) {
Z3_ast Z3_API Z3_mk_fpa_is_positive(Z3_context c, Z3_ast t) {
Z3_TRY;
LOG_Z3_mk_fpa_convert(c, s, rm, t);
LOG_Z3_mk_fpa_is_positive(c, t);
RESET_ERROR_CODE();
api::context * ctx = mk_c(c);
expr * args [2] = { to_expr(rm), to_expr(t) };
Z3_ast r = of_ast(ctx->m().mk_app(ctx->float_util().get_family_id(), OP_FLOAT_TO_FP,
to_sort(s)->get_num_parameters(), to_sort(s)->get_parameters(),
2, args));
Z3_ast r = of_ast(ctx->float_util().mk_is_positive(to_expr(t)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t) {
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);
float_util & fu = ctx->float_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);
float_util & fu = ctx->float_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);
float_util & fu = ctx->float_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);
float_util & fu = ctx->float_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);
float_util & fu = ctx->float_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->float_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->float_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->float_util().mk_to_real(to_expr(t)));
RETURN_Z3(r);
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();
@ -409,4 +659,22 @@ extern "C" {
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);
float_util & fu = ctx->float_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);
}
};