mirror of
https://github.com/Z3Prover/z3
synced 2025-06-19 20:33:38 +00:00
Merge branch 'unstable' of https://git01.codeplex.com/z3 into unstable
This commit is contained in:
commit
a318b0f104
8 changed files with 195 additions and 167 deletions
|
@ -319,8 +319,8 @@ static void get_file_params(const char *filename, hash_map<std::string,std::stri
|
||||||
tokenize(first_line.substr(2,first_line.size()-2),tokens);
|
tokenize(first_line.substr(2,first_line.size()-2),tokens);
|
||||||
for(unsigned i = 0; i < tokens.size(); i++){
|
for(unsigned i = 0; i < tokens.size(); i++){
|
||||||
std::string &tok = tokens[i];
|
std::string &tok = tokens[i];
|
||||||
int eqpos = tok.find('=');
|
size_t eqpos = tok.find('=');
|
||||||
if(eqpos >= 0 && eqpos < (int)tok.size()){
|
if(eqpos >= 0 && eqpos < tok.size()){
|
||||||
std::string left = tok.substr(0,eqpos);
|
std::string left = tok.substr(0,eqpos);
|
||||||
std::string right = tok.substr(eqpos+1,tok.size()-eqpos-1);
|
std::string right = tok.substr(eqpos+1,tok.size()-eqpos-1);
|
||||||
params[left] = right;
|
params[left] = right;
|
||||||
|
@ -377,8 +377,8 @@ extern "C" {
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
||||||
static Z3_ast and_vec(Z3_context ctx,std::vector<Z3_ast> &c){
|
static Z3_ast and_vec(Z3_context ctx,svector<Z3_ast> &c){
|
||||||
return (c.size() > 1) ? Z3_mk_and(ctx,c.size(),&c[0]) : c[0];
|
return (c.size() > 1) ? Z3_mk_and(ctx,c.size(),&c[0]) : c[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Z3_ast parents_vector_to_tree(Z3_context ctx, int num, Z3_ast *cnsts, int *parents){
|
static Z3_ast parents_vector_to_tree(Z3_context ctx, int num, Z3_ast *cnsts, int *parents){
|
||||||
|
@ -395,15 +395,15 @@ extern "C" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::vector<std::vector<Z3_ast> > chs(num);
|
std::vector<svector<Z3_ast> > chs(num);
|
||||||
for(int i = 0; i < num-1; i++){
|
for(int i = 0; i < num-1; i++){
|
||||||
std::vector<Z3_ast> &c = chs[i];
|
svector<Z3_ast> &c = chs[i];
|
||||||
c.push_back(cnsts[i]);
|
c.push_back(cnsts[i]);
|
||||||
Z3_ast foo = Z3_mk_interp(ctx,and_vec(ctx,c));
|
Z3_ast foo = Z3_mk_interp(ctx,and_vec(ctx,c));
|
||||||
chs[parents[i]].push_back(foo);
|
chs[parents[i]].push_back(foo);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<Z3_ast> &c = chs[num-1];
|
svector<Z3_ast> &c = chs[num-1];
|
||||||
c.push_back(cnsts[num-1]);
|
c.push_back(cnsts[num-1]);
|
||||||
res = and_vec(ctx,c);
|
res = and_vec(ctx,c);
|
||||||
}
|
}
|
||||||
|
@ -468,7 +468,7 @@ extern "C" {
|
||||||
static std::string read_msg;
|
static std::string read_msg;
|
||||||
static std::vector<Z3_ast> read_theory;
|
static std::vector<Z3_ast> read_theory;
|
||||||
|
|
||||||
static bool iZ3_parse(Z3_context ctx, const char *filename, const char **error, std::vector<Z3_ast> &assertions){
|
static bool iZ3_parse(Z3_context ctx, const char *filename, const char **error, svector<Z3_ast> &assertions){
|
||||||
read_error.clear();
|
read_error.clear();
|
||||||
try {
|
try {
|
||||||
std::string foo(filename);
|
std::string foo(filename);
|
||||||
|
@ -510,26 +510,26 @@ extern "C" {
|
||||||
|
|
||||||
hash_map<std::string,std::string> file_params;
|
hash_map<std::string,std::string> file_params;
|
||||||
get_file_params(filename,file_params);
|
get_file_params(filename,file_params);
|
||||||
|
|
||||||
int num_theory = 0;
|
unsigned num_theory = 0;
|
||||||
if(file_params.find("THEORY") != file_params.end())
|
if(file_params.find("THEORY") != file_params.end())
|
||||||
num_theory = atoi(file_params["THEORY"].c_str());
|
num_theory = atoi(file_params["THEORY"].c_str());
|
||||||
|
|
||||||
std::vector<Z3_ast> assertions;
|
svector<Z3_ast> assertions;
|
||||||
if(!iZ3_parse(ctx,filename,error,assertions))
|
if(!iZ3_parse(ctx,filename,error,assertions))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(num_theory > (int)assertions.size())
|
if(num_theory > assertions.size())
|
||||||
num_theory = assertions.size();
|
num_theory = assertions.size();
|
||||||
int num = assertions.size() - num_theory;
|
unsigned num = assertions.size() - num_theory;
|
||||||
|
|
||||||
read_cnsts.resize(num);
|
read_cnsts.resize(num);
|
||||||
read_parents.resize(num);
|
read_parents.resize(num);
|
||||||
read_theory.resize(num_theory);
|
read_theory.resize(num_theory);
|
||||||
|
|
||||||
for(int j = 0; j < num_theory; j++)
|
for(unsigned j = 0; j < num_theory; j++)
|
||||||
read_theory[j] = assertions[j];
|
read_theory[j] = assertions[j];
|
||||||
for(int j = 0; j < num; j++)
|
for(unsigned j = 0; j < num; j++)
|
||||||
read_cnsts[j] = assertions[j+num_theory];
|
read_cnsts[j] = assertions[j+num_theory];
|
||||||
|
|
||||||
if(ret_num_theory)
|
if(ret_num_theory)
|
||||||
|
@ -543,12 +543,12 @@ extern "C" {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int j = 0; j < num; j++)
|
for(unsigned j = 0; j < num; j++)
|
||||||
read_parents[j] = SHRT_MAX;
|
read_parents[j] = SHRT_MAX;
|
||||||
|
|
||||||
hash_map<Z3_ast,int> pred_map;
|
hash_map<Z3_ast,int> pred_map;
|
||||||
|
|
||||||
for(int j = 0; j < num; j++){
|
for(unsigned j = 0; j < num; j++){
|
||||||
Z3_ast lhs = 0, rhs = read_cnsts[j];
|
Z3_ast lhs = 0, rhs = read_cnsts[j];
|
||||||
|
|
||||||
if(Z3_get_decl_kind(ctx,Z3_get_app_decl(ctx,Z3_to_app(ctx,rhs))) == Z3_OP_IMPLIES){
|
if(Z3_get_decl_kind(ctx,Z3_get_app_decl(ctx,Z3_to_app(ctx,rhs))) == Z3_OP_IMPLIES){
|
||||||
|
@ -602,7 +602,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int j = 0; j < num-1; j++)
|
for(unsigned j = 0; j < num-1; j++)
|
||||||
if(read_parents[j] == SHRT_MIN){
|
if(read_parents[j] == SHRT_MIN){
|
||||||
read_error << "formula " << j+1 << ": unreferenced";
|
read_error << "formula " << j+1 << ": unreferenced";
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class BitVecNum extends BitVecExpr
|
||||||
{
|
{
|
||||||
Native.LongPtr res = new Native.LongPtr();
|
Native.LongPtr res = new Native.LongPtr();
|
||||||
if (Native.getNumeralInt64(getContext().nCtx(), getNativeObject(), res) ^ true)
|
if (Native.getNumeralInt64(getContext().nCtx(), getNativeObject(), res) ^ true)
|
||||||
throw new Z3Exception("Numeral is not an int64");
|
throw new Z3Exception("Numeral is not a long");
|
||||||
return res.value;
|
return res.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6424,7 +6424,7 @@ class Tactic:
|
||||||
_z3_assert(isinstance(goal, Goal) or isinstance(goal, BoolRef), "Z3 Goal or Boolean expressions expected")
|
_z3_assert(isinstance(goal, Goal) or isinstance(goal, BoolRef), "Z3 Goal or Boolean expressions expected")
|
||||||
goal = _to_goal(goal)
|
goal = _to_goal(goal)
|
||||||
if len(arguments) > 0 or len(keywords) > 0:
|
if len(arguments) > 0 or len(keywords) > 0:
|
||||||
p = args2params(arguments, keywords, a.ctx)
|
p = args2params(arguments, keywords, self.ctx)
|
||||||
return ApplyResult(Z3_tactic_apply_ex(self.ctx.ref(), self.tactic, goal.goal, p.params), self.ctx)
|
return ApplyResult(Z3_tactic_apply_ex(self.ctx.ref(), self.tactic, goal.goal, p.params), self.ctx)
|
||||||
else:
|
else:
|
||||||
return ApplyResult(Z3_tactic_apply(self.ctx.ref(), self.tactic, goal.goal), self.ctx)
|
return ApplyResult(Z3_tactic_apply(self.ctx.ref(), self.tactic, goal.goal), self.ctx)
|
||||||
|
|
|
@ -479,7 +479,7 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
||||||
// otherwise t2 is also a quantifier.
|
// otherwise t2 is also a quantifier.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
IF_VERBOSE(0, verbose_stream() << "does not match last rule: " << mk_pp(p, m) << "\n";);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case PR_DER: {
|
case PR_DER: {
|
||||||
|
@ -488,13 +488,12 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
||||||
match_fact(p, fact) &&
|
match_fact(p, fact) &&
|
||||||
match_iff(fact.get(), t1, t2) &&
|
match_iff(fact.get(), t1, t2) &&
|
||||||
match_quantifier(t1, is_forall, decls1, body1) &&
|
match_quantifier(t1, is_forall, decls1, body1) &&
|
||||||
is_forall &&
|
is_forall) {
|
||||||
match_or(body1.get(), terms1)) {
|
|
||||||
// TBD: check that terms are set of equalities.
|
// TBD: check that terms are set of equalities.
|
||||||
// t2 is an instance of a predicate in terms1
|
// t2 is an instance of a predicate in terms1
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
IF_VERBOSE(0, verbose_stream() << "does not match last rule: " << mk_pp(p, m) << "\n";);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case PR_HYPOTHESIS: {
|
case PR_HYPOTHESIS: {
|
||||||
|
@ -832,7 +831,7 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
IF_VERBOSE(0, verbose_stream() << "Could not establish complementarity for:\n" <<
|
IF_VERBOSE(0, verbose_stream() << "Could not establish complementarity for:\n" <<
|
||||||
mk_pp(lit1, m) << "\n" << mk_pp(lit2, m) << "\n";);
|
mk_pp(lit1, m) << "\n" << mk_pp(lit2, m) << "\n" << mk_pp(p, m) << "\n";);
|
||||||
}
|
}
|
||||||
fmls[i] = premise1;
|
fmls[i] = premise1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
|
||||||
#include "iz3translate.h"
|
#include "iz3translate.h"
|
||||||
#include "iz3proof.h"
|
#include "iz3proof.h"
|
||||||
#include "iz3profiling.h"
|
#include "iz3profiling.h"
|
||||||
|
|
|
@ -475,10 +475,11 @@ namespace smt {
|
||||||
bool theory_arith<Ext>::all_coeff_int(row const & r) const {
|
bool theory_arith<Ext>::all_coeff_int(row const & r) const {
|
||||||
typename vector<row_entry>::const_iterator it = r.begin_entries();
|
typename vector<row_entry>::const_iterator it = r.begin_entries();
|
||||||
typename vector<row_entry>::const_iterator end = r.end_entries();
|
typename vector<row_entry>::const_iterator end = r.end_entries();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
if (!it->is_dead() && !it->m_coeff.is_int())
|
if (!it->is_dead() && !it->m_coeff.is_int()) {
|
||||||
TRACE("gomory_cut", display_row(tout, r, true););
|
TRACE("gomory_cut", display_row(tout, r, true););
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1588,8 +1588,7 @@ void fpa2bv_converter::mk_round_to_integral(func_decl * f, unsigned num, expr *
|
||||||
v2 = x;
|
v2 = x;
|
||||||
|
|
||||||
unsigned ebits = m_util.get_ebits(f->get_range());
|
unsigned ebits = m_util.get_ebits(f->get_range());
|
||||||
unsigned sbits = m_util.get_sbits(f->get_range());
|
unsigned sbits = m_util.get_sbits(f->get_range());
|
||||||
SASSERT(ebits < sbits);
|
|
||||||
|
|
||||||
expr_ref a_sgn(m), a_sig(m), a_exp(m), a_lz(m);
|
expr_ref a_sgn(m), a_sig(m), a_exp(m), a_lz(m);
|
||||||
unpack(x, a_sgn, a_sig, a_exp, a_lz, true);
|
unpack(x, a_sgn, a_sig, a_exp, a_lz, true);
|
||||||
|
@ -1619,9 +1618,22 @@ void fpa2bv_converter::mk_round_to_integral(func_decl * f, unsigned num, expr *
|
||||||
expr_ref shift(m), r_shifted(m), l_shifted(m);
|
expr_ref shift(m), r_shifted(m), l_shifted(m);
|
||||||
shift = m_bv_util.mk_bv_sub(m_bv_util.mk_numeral(sbits-1, ebits+1),
|
shift = m_bv_util.mk_bv_sub(m_bv_util.mk_numeral(sbits-1, ebits+1),
|
||||||
m_bv_util.mk_sign_extend(1, a_exp));
|
m_bv_util.mk_sign_extend(1, a_exp));
|
||||||
r_shifted = m_bv_util.mk_bv_lshr(a_sig, m_bv_util.mk_zero_extend(sbits-ebits-1, shift));
|
if (sbits > (ebits+1))
|
||||||
|
r_shifted = m_bv_util.mk_bv_lshr(a_sig, m_bv_util.mk_zero_extend(sbits-(ebits+1), shift));
|
||||||
|
else if (sbits < (ebits+1))
|
||||||
|
r_shifted = m_bv_util.mk_extract(ebits, ebits-sbits+1, m_bv_util.mk_bv_lshr(m_bv_util.mk_zero_extend(ebits+1-sbits, a_sig), shift));
|
||||||
|
else // sbits == ebits+1
|
||||||
|
r_shifted = m_bv_util.mk_bv_lshr(a_sig, shift);
|
||||||
|
SASSERT(is_well_sorted(m, r_shifted));
|
||||||
SASSERT(m_bv_util.get_bv_size(r_shifted) == sbits);
|
SASSERT(m_bv_util.get_bv_size(r_shifted) == sbits);
|
||||||
l_shifted = m_bv_util.mk_bv_shl(r_shifted, m_bv_util.mk_zero_extend(sbits-ebits-1, shift));
|
|
||||||
|
if (sbits > (ebits+1))
|
||||||
|
l_shifted = m_bv_util.mk_bv_shl(r_shifted, m_bv_util.mk_zero_extend(sbits-(ebits+1), shift));
|
||||||
|
else if (sbits < (ebits+1))
|
||||||
|
l_shifted = m_bv_util.mk_extract(ebits, ebits-sbits+1, m_bv_util.mk_bv_shl(m_bv_util.mk_zero_extend(ebits+1-sbits, r_shifted), shift));
|
||||||
|
else // sbits == ebits+1
|
||||||
|
l_shifted = m_bv_util.mk_bv_shl(r_shifted, shift);
|
||||||
|
SASSERT(is_well_sorted(m, l_shifted));
|
||||||
SASSERT(m_bv_util.get_bv_size(l_shifted) == sbits);
|
SASSERT(m_bv_util.get_bv_size(l_shifted) == sbits);
|
||||||
|
|
||||||
res_sig = m_bv_util.mk_concat(m_bv_util.mk_numeral(0, 1),
|
res_sig = m_bv_util.mk_concat(m_bv_util.mk_numeral(0, 1),
|
||||||
|
@ -1825,146 +1837,158 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a
|
||||||
mk_triple(args[0], args[1], args[2], result);
|
mk_triple(args[0], args[1], args[2], result);
|
||||||
}
|
}
|
||||||
else if (num == 2 && is_app(args[1]) && m_util.is_float(m.get_sort(args[1]))) {
|
else if (num == 2 && is_app(args[1]) && m_util.is_float(m.get_sort(args[1]))) {
|
||||||
// We also support float to float conversion
|
// We also support float to float conversion
|
||||||
|
sort * s = f->get_range();
|
||||||
expr_ref rm(m), x(m);
|
expr_ref rm(m), x(m);
|
||||||
rm = args[0];
|
rm = args[0];
|
||||||
x = args[1];
|
x = args[1];
|
||||||
|
|
||||||
expr_ref c1(m), c2(m), c3(m), c4(m), c5(m);
|
|
||||||
expr_ref v1(m), v2(m), v3(m), v4(m), v5(m), v6(m);
|
|
||||||
expr_ref one1(m);
|
|
||||||
|
|
||||||
one1 = m_bv_util.mk_numeral(1, 1);
|
unsigned from_sbits = m_util.get_sbits(m.get_sort(x));
|
||||||
expr_ref ninf(m), pinf(m);
|
unsigned from_ebits = m_util.get_ebits(m.get_sort(x));
|
||||||
mk_plus_inf(f, pinf);
|
|
||||||
mk_minus_inf(f, ninf);
|
|
||||||
|
|
||||||
// NaN -> NaN
|
|
||||||
mk_is_nan(x, c1);
|
|
||||||
mk_nan(f, v1);
|
|
||||||
|
|
||||||
// +0 -> +0
|
|
||||||
mk_is_pzero(x, c2);
|
|
||||||
mk_pzero(f, v2);
|
|
||||||
|
|
||||||
// -0 -> -0
|
|
||||||
mk_is_nzero(x, c3);
|
|
||||||
mk_nzero(f, v3);
|
|
||||||
|
|
||||||
// +oo -> +oo
|
|
||||||
mk_is_pinf(x, c4);
|
|
||||||
v4 = pinf;
|
|
||||||
|
|
||||||
// -oo -> -oo
|
|
||||||
mk_is_ninf(x, c5);
|
|
||||||
v5 = ninf;
|
|
||||||
|
|
||||||
// otherwise: the actual conversion with rounding.
|
|
||||||
sort * s = f->get_range();
|
|
||||||
expr_ref sgn(m), sig(m), exp(m), lz(m);
|
|
||||||
unpack(x, sgn, sig, exp, lz, true);
|
|
||||||
|
|
||||||
dbg_decouple("fpa2bv_to_float_x_sig", sig);
|
|
||||||
dbg_decouple("fpa2bv_to_float_x_exp", exp);
|
|
||||||
dbg_decouple("fpa2bv_to_float_lz", lz);
|
|
||||||
|
|
||||||
expr_ref res_sgn(m), res_sig(m), res_exp(m);
|
|
||||||
|
|
||||||
res_sgn = sgn;
|
|
||||||
|
|
||||||
unsigned from_sbits = m_util.get_sbits(m.get_sort(args[1]));
|
|
||||||
unsigned from_ebits = m_util.get_ebits(m.get_sort(args[1]));
|
|
||||||
unsigned to_sbits = m_util.get_sbits(s);
|
unsigned to_sbits = m_util.get_sbits(s);
|
||||||
unsigned to_ebits = m_util.get_ebits(s);
|
unsigned to_ebits = m_util.get_ebits(s);
|
||||||
|
|
||||||
SASSERT(m_bv_util.get_bv_size(sgn) == 1);
|
if (from_sbits == to_sbits && from_ebits == to_ebits)
|
||||||
SASSERT(m_bv_util.get_bv_size(sig) == from_sbits);
|
result = x;
|
||||||
SASSERT(m_bv_util.get_bv_size(exp) == from_ebits);
|
else {
|
||||||
SASSERT(m_bv_util.get_bv_size(lz) == from_ebits);
|
expr_ref c1(m), c2(m), c3(m), c4(m), c5(m);
|
||||||
|
expr_ref v1(m), v2(m), v3(m), v4(m), v5(m), v6(m);
|
||||||
|
expr_ref one1(m);
|
||||||
|
|
||||||
if (from_sbits < (to_sbits + 3))
|
one1 = m_bv_util.mk_numeral(1, 1);
|
||||||
{
|
expr_ref ninf(m), pinf(m);
|
||||||
// make sure that sig has at least to_sbits + 3
|
mk_plus_inf(f, pinf);
|
||||||
res_sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, to_sbits+3-from_sbits));
|
mk_minus_inf(f, ninf);
|
||||||
}
|
|
||||||
else if (from_sbits > (to_sbits + 3))
|
|
||||||
{
|
|
||||||
// collapse the extra bits into a sticky bit.
|
|
||||||
expr_ref sticky(m), low(m), high(m);
|
|
||||||
low = m_bv_util.mk_extract(from_sbits - to_sbits - 3, 0, sig);
|
|
||||||
high = m_bv_util.mk_extract(from_sbits - 1, from_sbits - to_sbits - 2, sig);
|
|
||||||
sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, low.get());
|
|
||||||
res_sig = m_bv_util.mk_concat(high, sticky);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
res_sig = sig;
|
|
||||||
|
|
||||||
res_sig = m_bv_util.mk_zero_extend(1, res_sig); // extra zero in the front for the rounder.
|
// NaN -> NaN
|
||||||
unsigned sig_sz = m_bv_util.get_bv_size(res_sig);
|
mk_is_nan(x, c1);
|
||||||
SASSERT(sig_sz == to_sbits+4);
|
mk_nan(f, v1);
|
||||||
|
|
||||||
expr_ref exponent_overflow(m);
|
// +0 -> +0
|
||||||
exponent_overflow = m.mk_false();
|
mk_is_pzero(x, c2);
|
||||||
|
mk_pzero(f, v2);
|
||||||
|
|
||||||
if (from_ebits < (to_ebits + 2))
|
// -0 -> -0
|
||||||
{
|
mk_is_nzero(x, c3);
|
||||||
res_exp = m_bv_util.mk_sign_extend(to_ebits-from_ebits+2, exp);
|
mk_nzero(f, v3);
|
||||||
}
|
|
||||||
else if (from_ebits > (to_ebits + 2))
|
// +oo -> +oo
|
||||||
{
|
mk_is_pinf(x, c4);
|
||||||
expr_ref high(m), low(m), lows(m), high_red_or(m), high_red_and(m), h_or_eq(m), h_and_eq(m);
|
v4 = pinf;
|
||||||
expr_ref no_ovf(m), zero1(m), s_is_one(m), s_is_zero(m);
|
|
||||||
high = m_bv_util.mk_extract(from_ebits - 1, to_ebits + 2, exp);
|
// -oo -> -oo
|
||||||
low = m_bv_util.mk_extract(to_ebits+1, 0, exp);
|
mk_is_ninf(x, c5);
|
||||||
lows = m_bv_util.mk_extract(to_ebits+1, to_ebits+1, low);
|
v5 = ninf;
|
||||||
|
|
||||||
high_red_or = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, high.get());
|
// otherwise: the actual conversion with rounding.
|
||||||
high_red_and = m.mk_app(m_bv_util.get_fid(), OP_BREDAND, high.get());
|
expr_ref sgn(m), sig(m), exp(m), lz(m);
|
||||||
|
unpack(x, sgn, sig, exp, lz, true);
|
||||||
|
|
||||||
zero1 = m_bv_util.mk_numeral(0, 1);
|
dbg_decouple("fpa2bv_to_float_x_sig", sig);
|
||||||
m_simp.mk_eq(high_red_and, one1, h_and_eq);
|
dbg_decouple("fpa2bv_to_float_x_exp", exp);
|
||||||
m_simp.mk_eq(high_red_or, zero1, h_or_eq);
|
dbg_decouple("fpa2bv_to_float_lz", lz);
|
||||||
m_simp.mk_eq(lows, zero1, s_is_zero);
|
|
||||||
m_simp.mk_eq(lows, one1, s_is_one);
|
expr_ref res_sgn(m), res_sig(m), res_exp(m);
|
||||||
|
|
||||||
|
res_sgn = sgn;
|
||||||
|
|
||||||
|
SASSERT(m_bv_util.get_bv_size(sgn) == 1);
|
||||||
|
SASSERT(m_bv_util.get_bv_size(sig) == from_sbits);
|
||||||
|
SASSERT(m_bv_util.get_bv_size(exp) == from_ebits);
|
||||||
|
SASSERT(m_bv_util.get_bv_size(lz) == from_ebits);
|
||||||
|
|
||||||
|
if (from_sbits < (to_sbits + 3))
|
||||||
|
{
|
||||||
|
// make sure that sig has at least to_sbits + 3
|
||||||
|
res_sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, to_sbits+3-from_sbits));
|
||||||
|
}
|
||||||
|
else if (from_sbits > (to_sbits + 3))
|
||||||
|
{
|
||||||
|
// collapse the extra bits into a sticky bit.
|
||||||
|
expr_ref sticky(m), low(m), high(m);
|
||||||
|
low = m_bv_util.mk_extract(from_sbits - to_sbits - 3, 0, sig);
|
||||||
|
high = m_bv_util.mk_extract(from_sbits - 1, from_sbits - to_sbits - 2, sig);
|
||||||
|
sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, low.get());
|
||||||
|
res_sig = m_bv_util.mk_concat(high, sticky);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res_sig = sig;
|
||||||
|
|
||||||
|
res_sig = m_bv_util.mk_zero_extend(1, res_sig); // extra zero in the front for the rounder.
|
||||||
|
unsigned sig_sz = m_bv_util.get_bv_size(res_sig);
|
||||||
|
SASSERT(sig_sz == to_sbits+4);
|
||||||
|
|
||||||
|
expr_ref exponent_overflow(m);
|
||||||
|
exponent_overflow = m.mk_false();
|
||||||
|
|
||||||
|
if (from_ebits < (to_ebits + 2))
|
||||||
|
{
|
||||||
|
res_exp = m_bv_util.mk_sign_extend(to_ebits-from_ebits+2, exp);
|
||||||
|
|
||||||
|
// subtract lz for subnormal numbers.
|
||||||
|
expr_ref lz_ext(m);
|
||||||
|
lz_ext = m_bv_util.mk_zero_extend(to_ebits-from_ebits+2, lz);
|
||||||
|
res_exp = m_bv_util.mk_bv_sub(res_exp, lz_ext);
|
||||||
|
}
|
||||||
|
else if (from_ebits > (to_ebits + 2))
|
||||||
|
{
|
||||||
|
expr_ref high(m), low(m), lows(m), high_red_or(m), high_red_and(m), h_or_eq(m), h_and_eq(m);
|
||||||
|
expr_ref no_ovf(m), zero1(m), s_is_one(m), s_is_zero(m);
|
||||||
|
high = m_bv_util.mk_extract(from_ebits - 1, to_ebits + 2, exp);
|
||||||
|
low = m_bv_util.mk_extract(to_ebits+1, 0, exp);
|
||||||
|
lows = m_bv_util.mk_extract(to_ebits+1, to_ebits+1, low);
|
||||||
|
|
||||||
expr_ref c2(m);
|
high_red_or = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, high.get());
|
||||||
m_simp.mk_ite(h_or_eq, s_is_one, m.mk_false(), c2);
|
high_red_and = m.mk_app(m_bv_util.get_fid(), OP_BREDAND, high.get());
|
||||||
m_simp.mk_ite(h_and_eq, s_is_zero, c2, exponent_overflow);
|
|
||||||
|
zero1 = m_bv_util.mk_numeral(0, 1);
|
||||||
|
m_simp.mk_eq(high_red_and, one1, h_and_eq);
|
||||||
|
m_simp.mk_eq(high_red_or, zero1, h_or_eq);
|
||||||
|
m_simp.mk_eq(lows, zero1, s_is_zero);
|
||||||
|
m_simp.mk_eq(lows, one1, s_is_one);
|
||||||
|
|
||||||
// Note: Upon overflow, we _could_ try to shift the significand around...
|
expr_ref c2(m);
|
||||||
|
m_simp.mk_ite(h_or_eq, s_is_one, m.mk_false(), c2);
|
||||||
|
m_simp.mk_ite(h_and_eq, s_is_zero, c2, exponent_overflow);
|
||||||
|
|
||||||
|
// Note: Upon overflow, we _could_ try to shift the significand around...
|
||||||
|
|
||||||
res_exp = low;
|
// subtract lz for subnormal numbers.
|
||||||
}
|
expr_ref lz_ext(m), lz_rest(m), lz_redor(m), lz_redor_bool(m);
|
||||||
else
|
lz_ext = m_bv_util.mk_extract(to_ebits+1, 0, lz);
|
||||||
res_exp = exp;
|
lz_rest = m_bv_util.mk_extract(from_ebits-1, to_ebits+2, lz);
|
||||||
|
lz_redor = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, lz_rest.get());
|
||||||
|
m_simp.mk_eq(lz_redor, one1, lz_redor_bool);
|
||||||
|
m_simp.mk_or(exponent_overflow, lz_redor_bool, exponent_overflow);
|
||||||
|
|
||||||
// subtract lz for subnormal numbers.
|
res_exp = m_bv_util.mk_bv_sub(low, lz_ext);
|
||||||
expr_ref lz_ext(m);
|
}
|
||||||
lz_ext = m_bv_util.mk_zero_extend(to_ebits-from_ebits+2, lz);
|
else // from_ebits == (to_ebits + 2)
|
||||||
res_exp = m_bv_util.mk_bv_sub(res_exp, lz_ext);
|
res_exp = m_bv_util.mk_bv_sub(exp, lz);
|
||||||
SASSERT(m_bv_util.get_bv_size(res_exp) == to_ebits+2);
|
|
||||||
|
|
||||||
dbg_decouple("fpa2bv_to_float_res_sig", res_sig);
|
SASSERT(m_bv_util.get_bv_size(res_exp) == to_ebits+2);
|
||||||
dbg_decouple("fpa2bv_to_float_res_exp", res_exp);
|
SASSERT(is_well_sorted(m, res_exp));
|
||||||
|
|
||||||
expr_ref rounded(m);
|
dbg_decouple("fpa2bv_to_float_res_sig", res_sig);
|
||||||
round(s, rm, res_sgn, res_sig, res_exp, rounded);
|
dbg_decouple("fpa2bv_to_float_res_exp", res_exp);
|
||||||
|
|
||||||
|
|
||||||
expr_ref is_neg(m), sig_inf(m);
|
expr_ref rounded(m);
|
||||||
m_simp.mk_eq(sgn, one1, is_neg);
|
round(s, rm, res_sgn, res_sig, res_exp, rounded);
|
||||||
mk_ite(is_neg, ninf, pinf, sig_inf);
|
|
||||||
|
expr_ref is_neg(m), sig_inf(m);
|
||||||
|
m_simp.mk_eq(sgn, one1, is_neg);
|
||||||
|
mk_ite(is_neg, ninf, pinf, sig_inf);
|
||||||
|
|
||||||
dbg_decouple("fpa2bv_to_float_exp_ovf", exponent_overflow);
|
dbg_decouple("fpa2bv_to_float_exp_ovf", exponent_overflow);
|
||||||
|
mk_ite(exponent_overflow, sig_inf, rounded, v6);
|
||||||
|
|
||||||
mk_ite(exponent_overflow, sig_inf, rounded, v6);
|
// And finally, we tie them together.
|
||||||
|
mk_ite(c5, v5, v6, result);
|
||||||
// And finally, we tie them together.
|
mk_ite(c4, v4, result, result);
|
||||||
mk_ite(c5, v5, v6, result);
|
mk_ite(c3, v3, result, result);
|
||||||
mk_ite(c4, v4, result, result);
|
mk_ite(c2, v2, result, result);
|
||||||
mk_ite(c3, v3, result, result);
|
mk_ite(c1, v1, result, result);
|
||||||
mk_ite(c2, v2, result, result);
|
}
|
||||||
mk_ite(c1, v1, result, result);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// .. other than that, we only support rationals for asFloat
|
// .. other than that, we only support rationals for asFloat
|
||||||
|
@ -2167,14 +2191,14 @@ void fpa2bv_converter::mk_bot_exp(unsigned sz, expr_ref & result) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpa2bv_converter::mk_min_exp(unsigned ebits, expr_ref & result) {
|
void fpa2bv_converter::mk_min_exp(unsigned ebits, expr_ref & result) {
|
||||||
SASSERT(ebits > 0);
|
SASSERT(ebits >= 2);
|
||||||
const mpz & z = m_mpf_manager.m_powers2.m1(ebits-1, true);
|
const mpz & z = m_mpf_manager.m_powers2.m1(ebits-1, true);
|
||||||
result = m_bv_util.mk_numeral(z + mpz(1), ebits);
|
result = m_bv_util.mk_numeral(z + mpz(1), ebits);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpa2bv_converter::mk_max_exp(unsigned ebits, expr_ref & result) {
|
void fpa2bv_converter::mk_max_exp(unsigned ebits, expr_ref & result) {
|
||||||
SASSERT(ebits > 0);
|
SASSERT(ebits >= 2);
|
||||||
result = m_bv_util.mk_numeral(m_mpf_manager.m_powers2.m1(ebits-1, false), ebits);
|
result = m_bv_util.mk_numeral(m_mpf_manager.m_powers2.m1(ebits-1, false), ebits);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpa2bv_converter::mk_leading_zeros(expr * e, unsigned max_bits, expr_ref & result) {
|
void fpa2bv_converter::mk_leading_zeros(expr * e, unsigned max_bits, expr_ref & result) {
|
||||||
|
@ -2220,14 +2244,14 @@ void fpa2bv_converter::mk_bias(expr * e, expr_ref & result) {
|
||||||
unsigned ebits = m_bv_util.get_bv_size(e);
|
unsigned ebits = m_bv_util.get_bv_size(e);
|
||||||
SASSERT(ebits >= 2);
|
SASSERT(ebits >= 2);
|
||||||
|
|
||||||
expr_ref mask(m);
|
expr_ref bias(m);
|
||||||
mask = m_bv_util.mk_numeral(fu().fm().m_powers2.m1(ebits-1), ebits);
|
bias = m_bv_util.mk_numeral(fu().fm().m_powers2.m1(ebits-1), ebits);
|
||||||
result = m_bv_util.mk_bv_add(e, mask);
|
result = m_bv_util.mk_bv_add(e, bias);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpa2bv_converter::mk_unbias(expr * e, expr_ref & result) {
|
void fpa2bv_converter::mk_unbias(expr * e, expr_ref & result) {
|
||||||
unsigned ebits = m_bv_util.get_bv_size(e);
|
unsigned ebits = m_bv_util.get_bv_size(e);
|
||||||
SASSERT(ebits >= 2);
|
SASSERT(ebits >= 3);
|
||||||
|
|
||||||
expr_ref e_plus_one(m);
|
expr_ref e_plus_one(m);
|
||||||
e_plus_one = m_bv_util.mk_bv_add(e, m_bv_util.mk_numeral(1, ebits));
|
e_plus_one = m_bv_util.mk_bv_add(e, m_bv_util.mk_numeral(1, ebits));
|
||||||
|
@ -2263,6 +2287,7 @@ void fpa2bv_converter::unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref
|
||||||
|
|
||||||
expr_ref denormal_sig(m), denormal_exp(m);
|
expr_ref denormal_sig(m), denormal_exp(m);
|
||||||
denormal_sig = m_bv_util.mk_zero_extend(1, sig);
|
denormal_sig = m_bv_util.mk_zero_extend(1, sig);
|
||||||
|
SASSERT(ebits >= 3); // Note: when ebits=2 there is no 1-exponent, so mk_unbias will produce a 0.
|
||||||
denormal_exp = m_bv_util.mk_numeral(1, ebits);
|
denormal_exp = m_bv_util.mk_numeral(1, ebits);
|
||||||
mk_unbias(denormal_exp, denormal_exp);
|
mk_unbias(denormal_exp, denormal_exp);
|
||||||
dbg_decouple("fpa2bv_unpack_denormal_exp", denormal_exp);
|
dbg_decouple("fpa2bv_unpack_denormal_exp", denormal_exp);
|
||||||
|
@ -2436,13 +2461,12 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref &
|
||||||
t = m_bv_util.mk_bv_add(exp, m_bv_util.mk_numeral(1, ebits+2));
|
t = m_bv_util.mk_bv_add(exp, m_bv_util.mk_numeral(1, ebits+2));
|
||||||
t = m_bv_util.mk_bv_sub(t, lz);
|
t = m_bv_util.mk_bv_sub(t, lz);
|
||||||
t = m_bv_util.mk_bv_sub(t, m_bv_util.mk_sign_extend(2, e_min));
|
t = m_bv_util.mk_bv_sub(t, m_bv_util.mk_sign_extend(2, e_min));
|
||||||
expr_ref TINY(m);
|
dbg_decouple("fpa2bv_rnd_t", t);
|
||||||
|
expr_ref TINY(m);
|
||||||
TINY = m_bv_util.mk_sle(t, m_bv_util.mk_numeral((unsigned)-1, ebits+2));
|
TINY = m_bv_util.mk_sle(t, m_bv_util.mk_numeral((unsigned)-1, ebits+2));
|
||||||
|
|
||||||
TRACE("fpa2bv_dbg", tout << "TINY = " << mk_ismt2_pp(TINY, m) << std::endl;);
|
|
||||||
SASSERT(is_well_sorted(m, TINY));
|
|
||||||
|
|
||||||
dbg_decouple("fpa2bv_rnd_TINY", TINY);
|
dbg_decouple("fpa2bv_rnd_TINY", TINY);
|
||||||
|
TRACE("fpa2bv_dbg", tout << "TINY = " << mk_ismt2_pp(TINY, m) << std::endl;);
|
||||||
|
SASSERT(is_well_sorted(m, TINY));
|
||||||
|
|
||||||
expr_ref beta(m);
|
expr_ref beta(m);
|
||||||
beta = m_bv_util.mk_bv_add(m_bv_util.mk_bv_sub(exp, lz), m_bv_util.mk_numeral(1, ebits+2));
|
beta = m_bv_util.mk_bv_add(m_bv_util.mk_bv_sub(exp, lz), m_bv_util.mk_numeral(1, ebits+2));
|
||||||
|
@ -2455,7 +2479,7 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref &
|
||||||
dbg_decouple("fpa2bv_rnd_e_min", e_min);
|
dbg_decouple("fpa2bv_rnd_e_min", e_min);
|
||||||
dbg_decouple("fpa2bv_rnd_e_max", e_max);
|
dbg_decouple("fpa2bv_rnd_e_max", e_max);
|
||||||
|
|
||||||
expr_ref sigma(m), sigma_add(m), e_min_p2(m);
|
expr_ref sigma(m), sigma_add(m);
|
||||||
sigma_add = m_bv_util.mk_bv_sub(exp, m_bv_util.mk_sign_extend(2, e_min));
|
sigma_add = m_bv_util.mk_bv_sub(exp, m_bv_util.mk_sign_extend(2, e_min));
|
||||||
sigma_add = m_bv_util.mk_bv_add(sigma_add, m_bv_util.mk_numeral(1, ebits+2));
|
sigma_add = m_bv_util.mk_bv_add(sigma_add, m_bv_util.mk_numeral(1, ebits+2));
|
||||||
m_simp.mk_ite(TINY, sigma_add, lz, sigma);
|
m_simp.mk_ite(TINY, sigma_add, lz, sigma);
|
||||||
|
@ -2477,9 +2501,10 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref &
|
||||||
rs_sig(m), ls_sig(m), big_sh_sig(m), sigma_le_cap(m);
|
rs_sig(m), ls_sig(m), big_sh_sig(m), sigma_le_cap(m);
|
||||||
sigma_neg = m_bv_util.mk_bv_neg(sigma);
|
sigma_neg = m_bv_util.mk_bv_neg(sigma);
|
||||||
sigma_cap = m_bv_util.mk_numeral(sbits+2, sigma_size);
|
sigma_cap = m_bv_util.mk_numeral(sbits+2, sigma_size);
|
||||||
sigma_le_cap = m_bv_util.mk_sle(sigma_neg, sigma_cap);
|
sigma_le_cap = m_bv_util.mk_ule(sigma_neg, sigma_cap);
|
||||||
m_simp.mk_ite(sigma_le_cap, sigma_neg, sigma_cap, sigma_neg_capped);
|
m_simp.mk_ite(sigma_le_cap, sigma_neg, sigma_cap, sigma_neg_capped);
|
||||||
dbg_decouple("fpa2bv_rnd_sigma_neg", sigma_neg);
|
dbg_decouple("fpa2bv_rnd_sigma_neg", sigma_neg);
|
||||||
|
dbg_decouple("fpa2bv_rnd_sigma_cap", sigma_cap);
|
||||||
dbg_decouple("fpa2bv_rnd_sigma_neg_capped", sigma_neg_capped);
|
dbg_decouple("fpa2bv_rnd_sigma_neg_capped", sigma_neg_capped);
|
||||||
sigma_lt_zero = m_bv_util.mk_sle(sigma, m_bv_util.mk_numeral((unsigned)-1, sigma_size));
|
sigma_lt_zero = m_bv_util.mk_sle(sigma, m_bv_util.mk_numeral((unsigned)-1, sigma_size));
|
||||||
dbg_decouple("fpa2bv_rnd_sigma_lt_zero", sigma_lt_zero);
|
dbg_decouple("fpa2bv_rnd_sigma_lt_zero", sigma_lt_zero);
|
||||||
|
|
|
@ -360,6 +360,8 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode
|
||||||
mk_inf(ebits, sbits, x.sign, o);
|
mk_inf(ebits, sbits, x.sign, o);
|
||||||
else if (is_zero(x))
|
else if (is_zero(x))
|
||||||
mk_zero(ebits, sbits, x.sign, o);
|
mk_zero(ebits, sbits, x.sign, o);
|
||||||
|
else if (x.ebits == ebits && x.sbits == sbits)
|
||||||
|
set(o, x);
|
||||||
else {
|
else {
|
||||||
set(o, x);
|
set(o, x);
|
||||||
unpack(o, true);
|
unpack(o, true);
|
||||||
|
@ -1378,12 +1380,12 @@ bool mpf_manager::has_top_exp(mpf const & x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mpf_exp_t mpf_manager::mk_bot_exp(unsigned ebits) {
|
mpf_exp_t mpf_manager::mk_bot_exp(unsigned ebits) {
|
||||||
SASSERT(ebits > 0);
|
SASSERT(ebits >= 2);
|
||||||
return m_mpz_manager.get_int64(m_powers2.m1(ebits-1, true));
|
return m_mpz_manager.get_int64(m_powers2.m1(ebits-1, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
mpf_exp_t mpf_manager::mk_top_exp(unsigned ebits) {
|
mpf_exp_t mpf_manager::mk_top_exp(unsigned ebits) {
|
||||||
SASSERT(ebits > 0);
|
SASSERT(ebits >= 2);
|
||||||
return m_mpz_manager.get_int64(m_powers2(ebits-1));
|
return m_mpz_manager.get_int64(m_powers2(ebits-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue