mirror of
https://github.com/Z3Prover/z3
synced 2025-04-04 16:44:07 +00:00
* reorg sls * sls * na * split into base and plugin * move sat_params to params directory, add op_def repair options * move sat_ddfw to sls, initiate sls-bv-plugin * porting bv-sls * adding basic plugin * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add sls-sms solver * bv updates * updated dependencies Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * updated dependencies Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use portable ptr-initializer Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * move definitions to cpp Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use template<> syntax Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix compiler errors for gcc Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Bump docker/build-push-action from 6.0.0 to 6.1.0 (#7265) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.0.0 to 6.1.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.0.0...v6.1.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * set clean shutdown for local search and re-enable local search when it parallelizes with PB solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Bump docker/build-push-action from 6.1.0 to 6.2.0 (#7269) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.1.0 to 6.2.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.1.0...v6.2.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix a comment for Z3_solver_from_string (#7271) Z3_solver_from_string accepts a string buffer with solver assertions, not a string buffer with filename. * trigger the build with a comment change Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * remove macro distinction #7270 * fix #7268 * kludge to address #7232, probably superseeded by planned revision to setup/pypi Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add new ema invariant (#7288) * Bump docker/build-push-action from 6.2.0 to 6.3.0 (#7280) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.2.0 to 6.3.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.2.0...v6.3.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * merge Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix unit test build Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove shared attribute Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove stale files Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix build of unit test Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixes and rename sls-cc to sls-euf-plugin Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * testing / debugging arithmetic * updates to repair logic, mainly arithmetic * fixes to sls * evolve sls arith * bugfixes in sls-arith * fix typo Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * bug fixes * Update sls_test.cpp * fixes * fixes Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix build Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * refactor basic plugin and clause generation Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixes to ite and other Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * updates * update Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix division by 0 Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * disable fail restart Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * disable tabu when using reset moves Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * update sls_test Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add factoring Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixes to semantics Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * re-add tabu override Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * generalize factoring Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix bug Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove restart Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * disable tabu in fallback modes Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * localize impact of factoring Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * delay factoring Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * flatten products Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * perform lookahead update + nested mul Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * disable nested mul Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * disable nested mul, use non-lookahead Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * make reset updates recursive Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * include linear moves Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * include 5% reset probability Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * separate linear update Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * separate linear update remove 20% threshold Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove linear opt Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * enable multiplier expansion, enable linear move Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use unit coefficients for muls Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * disable non-tabu version of find_nl_moves Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove coefficient from multiplication definition Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * reorg monomials Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add smt params to path Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * avoid negative reward Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use reward as proxy for score Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use reward as proxy for score Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use exponential decay with breaks Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use std::pow Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixes to bv Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixes to fixed Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixup repairs Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * reserve for multiplication Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixing repair Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * include bounds checks in set random * na * fixes to mul Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix mul inverse Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixes to handling signed operators Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * logging and fixes Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * gcm Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * peli Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Add .env to gitignore to prevent environment files from being tracked * Add m_num_pelis counter to stats in sls_context * Remove m_num_pelis member from stats struct in sls_context * Enhance bv_sls_eval with improved repair and logging, refine is_bv_predicate in sls_bv_plugin * Remove verbose logging in register_term function of sls_basic_plugin and fix formatting in sls_context * Rename source files for consistency in `src/ast/sls` directory * Refactor bv_sls files to sls_bv with namespace and class name adjustments * Remove typename from member declarations in bv_fixed class * fixing conca Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Add initial implementation of bit-vector SLS evaluation module in bv_sls_eval.cpp * Remove bv_sls_eval.cpp as part of code cleanup and refactoring * Refactor alignment of member variables in bv_plugin of sls namespace * Rename SLS engine related files to reflect their specific use for bit-vectors * Refactor SLS engine and evaluator components for bit-vector specifics and adjust memory manager alignment * Enhance bv_eval with use_current, lookahead strategies, and randomization improvements in SLS module * Refactor verbose logging and fix logic in range adjustment functions in sls bv modules * Remove commented verbose output in sls_bv_plugin.cpp during repair process * Add early return after setting fixed subterms in sls_bv_fixed.cpp * Remove redundant return statement in sls_bv_fixed.cpp * fixes to new value propagation Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Refactor sls bv evaluation and fix logic checks for bit operations * Add array plugin support and update bv_eval in ast_sls module * Add array, model value, and user sort plugins to SLS module with enhancements in array propagation logic * Refactor array_plugin in sls to improve handling of select expressions with multiple arguments * Enhance array plugin with early termination and propagation verification, and improve euf and user sort plugins with propagation adjustments and debugging enhancements * Add support for handling 'distinct' expressions in SLS context and user sort plugin * Remove model value and user sort plugins from SLS theory * replace user plugin by euf plugin Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove extra file Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Refactor handling of term registration and enhance distinct handling in sls_euf_plugin * Add TODO list for enhancements in sls_euf_plugin.cpp * add incremental mode * updated package * fix sls build Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * break sls build Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix build * break build again * fix build Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixes Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixing incremental Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * avoid units Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixup handling of disequality propagation Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fx Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * recover shift-weight loop Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * alternate Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * throttle save model Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * allow for alternating Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix test for new signature of flip Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * bug fixes Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * restore use of value_hash Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixes Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding dt plugin Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adt Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * dt updates Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * added cycle detection Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * updated sls-datatype Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Refactor context management, improve datatype handling, and enhance logging in sls plugins. * axiomatize dt Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add missing factory plugins to model Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixup finite domain search Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixup finite domain search Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixes Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * redo dfs Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixing model construction for underspecified operators Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixes to occurs check Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixup interpretation building Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * saturate worklist Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * delay distinct axiom Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding model-based sls for datatatypes * update the interface in sls_solver to transfer phase between SAT and SLS * add value transfer option Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * rename aux functions * Track shared variables using a unit set * debugging parallel integration * fix dirty flag setting * update log level * add plugin to smt_context, factor out sls_smt_plugin functionality. * bug fixes * fixes * use common infrastructure for sls-smt * fix build Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix build Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove declaration of context Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add virtual destructor Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * build warnings Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * reorder inclusion order to define smt_context before theory_sls Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * change namespace for single threaded Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * check delayed eqs before nla Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use independent completion flag for sls to avoid conflating with genuine cancelation * validate sls-arith lemmas Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * bugfixes Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add intblast to legacy SMT solver * fixup model generation for theory_intblast Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * mk_value needs to accept more cases where integer expression doesn't evalate Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use th-axioms to track origins of assertions Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add missing operator handling for bitwise operators Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add missing operator handling for bitwise operators Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * normalizing inequality Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add virtual destructor Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * rework elim_unconstrained * fix non-termination Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use glue as computed without adjustment * update model generation to fix model bug Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fixes to model construction * remove package and package lock Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix build warning Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use original gai Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> --------- Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: Lev Nachmanson <levnach@hotmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sergey Bronnikov <estetus@gmail.com> Co-authored-by: Lev Nachmanson <levnach@hotmail.com> Co-authored-by: LiviaSun <33578456+ChuyueSun@users.noreply.github.com>
694 lines
21 KiB
C++
694 lines
21 KiB
C++
/*++
|
|
Copyright (c) 2020 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
bv2int_translator
|
|
|
|
Author:
|
|
|
|
Nikolaj Bjorner (nbjorner) 2024-10-27
|
|
|
|
--*/
|
|
|
|
#include "ast/ast.h"
|
|
#include "ast/arith_decl_plugin.h"
|
|
#include "ast/bv_decl_plugin.h"
|
|
#include "ast/rewriter/bv2int_translator.h"
|
|
#include "ast/ast_ll_pp.h"
|
|
#include "ast/ast_pp.h"
|
|
|
|
bv2int_translator::bv2int_translator(ast_manager& m, bv2int_translator_trail& ctx) :
|
|
m(m),
|
|
ctx(ctx),
|
|
bv(m),
|
|
a(m),
|
|
m_translate(m),
|
|
m_args(m),
|
|
m_pinned(m),
|
|
m_vars(m),
|
|
m_preds(m)
|
|
{}
|
|
|
|
void bv2int_translator::reset(bool is_plugin) {
|
|
m_vars.reset();
|
|
m_preds.reset();
|
|
for (unsigned i = m_translate.size(); i-- > 0; )
|
|
m_translate[i] = nullptr;
|
|
m_is_plugin = is_plugin;
|
|
}
|
|
|
|
|
|
void bv2int_translator::set_translated(expr* e, expr* r) {
|
|
SASSERT(r);
|
|
SASSERT(!is_translated(e));
|
|
m_translate.setx(e->get_id(), r);
|
|
ctx.push_idx(set_vector_idx_trail(m_translate, e->get_id()));
|
|
}
|
|
|
|
void bv2int_translator::internalize_bv(app* e) {
|
|
ensure_translated(e);
|
|
if (m.is_bool(e)) {
|
|
m_preds.push_back(e);
|
|
ctx.push(push_back_vector(m_preds));
|
|
}
|
|
}
|
|
|
|
void bv2int_translator::ensure_translated(expr* e) {
|
|
if (m_translate.get(e->get_id(), nullptr))
|
|
return;
|
|
ptr_vector<expr> todo;
|
|
ast_fast_mark1 visited;
|
|
todo.push_back(e);
|
|
visited.mark(e);
|
|
for (unsigned i = 0; i < todo.size(); ++i) {
|
|
expr* e = todo[i];
|
|
if (!is_app(e))
|
|
continue;
|
|
app* a = to_app(e);
|
|
if (m.is_bool(e) && a->get_family_id() != bv.get_family_id())
|
|
continue;
|
|
for (auto arg : *a)
|
|
if (!visited.is_marked(arg) && !m_translate.get(arg->get_id(), nullptr)) {
|
|
visited.mark(arg);
|
|
todo.push_back(arg);
|
|
}
|
|
}
|
|
std::stable_sort(todo.begin(), todo.end(), [&](expr* a, expr* b) { return get_depth(a) < get_depth(b); });
|
|
for (expr* e : todo)
|
|
translate_expr(e);
|
|
}
|
|
|
|
rational bv2int_translator::bv_size(expr* bv_expr) {
|
|
return rational::power_of_two(bv.get_bv_size(bv_expr->get_sort()));
|
|
}
|
|
|
|
void bv2int_translator::translate_expr(expr* e) {
|
|
if (is_quantifier(e))
|
|
translate_quantifier(to_quantifier(e));
|
|
else if (is_var(e))
|
|
translate_var(to_var(e));
|
|
else {
|
|
app* ap = to_app(e);
|
|
if (m_is_plugin && ap->get_family_id() == basic_family_id && m.is_bool(ap)) {
|
|
set_translated(e, e);
|
|
return;
|
|
}
|
|
m_args.reset();
|
|
for (auto arg : *ap)
|
|
m_args.push_back(translated(arg));
|
|
|
|
if (ap->get_family_id() == basic_family_id)
|
|
translate_basic(ap);
|
|
else if (ap->get_family_id() == bv.get_family_id())
|
|
translate_bv(ap);
|
|
else
|
|
translate_app(ap);
|
|
}
|
|
}
|
|
|
|
void bv2int_translator::translate_quantifier(quantifier* q) {
|
|
if (m_is_plugin) {
|
|
set_translated(q, q);
|
|
return;
|
|
}
|
|
if (is_lambda(q))
|
|
throw default_exception("lambdas are not supported in intblaster");
|
|
expr* b = q->get_expr();
|
|
unsigned nd = q->get_num_decls();
|
|
ptr_vector<sort> sorts;
|
|
for (unsigned i = 0; i < nd; ++i) {
|
|
auto s = q->get_decl_sort(i);
|
|
if (bv.is_bv_sort(s)) {
|
|
NOT_IMPLEMENTED_YET();
|
|
sorts.push_back(a.mk_int());
|
|
}
|
|
else
|
|
sorts.push_back(s);
|
|
}
|
|
b = translated(b);
|
|
// TODO if sorts contain integer, then created bounds variables.
|
|
set_translated(q, m.update_quantifier(q, b));
|
|
}
|
|
|
|
void bv2int_translator::translate_var(var* v) {
|
|
if (bv.is_bv_sort(v->get_sort()))
|
|
set_translated(v, m.mk_var(v->get_idx(), a.mk_int()));
|
|
else
|
|
set_translated(v, v);
|
|
}
|
|
|
|
// Translate functions that are not built-in or bit-vectors.
|
|
// Base method uses fresh functions.
|
|
// Other method could use bv2int, int2bv axioms and coercions.
|
|
// f(args) = bv2int(f(int2bv(args'))
|
|
//
|
|
|
|
void bv2int_translator::translate_app(app* e) {
|
|
|
|
if (m_is_plugin && m.is_bool(e)) {
|
|
set_translated(e, e);
|
|
return;
|
|
}
|
|
|
|
bool has_bv_sort = bv.is_bv(e);
|
|
func_decl* f = e->get_decl();
|
|
|
|
for (unsigned i = 0; i < m_args.size(); ++i)
|
|
if (bv.is_bv(e->get_arg(i)))
|
|
m_args[i] = bv.mk_int2bv(bv.get_bv_size(e->get_arg(i)), m_args.get(i));
|
|
|
|
if (has_bv_sort)
|
|
m_vars.push_back(e);
|
|
if (m_is_plugin) {
|
|
expr* r = m.mk_app(f, m_args);
|
|
if (has_bv_sort) {
|
|
ctx.push(push_back_vector(m_vars));
|
|
r = bv.mk_bv2int(r);
|
|
}
|
|
set_translated(e, r);
|
|
return;
|
|
}
|
|
else if (has_bv_sort) {
|
|
if (f->get_family_id() != null_family_id)
|
|
throw default_exception("conversion for interpreted functions is not supported by intblast solver");
|
|
func_decl* g = nullptr;
|
|
if (!m_new_funs.find(f, g)) {
|
|
g = m.mk_fresh_func_decl(e->get_decl()->get_name(), symbol("bv"), f->get_arity(), f->get_domain(), a.mk_int());
|
|
m_new_funs.insert(f, g);
|
|
}
|
|
f = g;
|
|
m_pinned.push_back(f);
|
|
}
|
|
set_translated(e, m.mk_app(f, m_args));
|
|
}
|
|
|
|
expr_ref bv2int_translator::mk_le(expr* x, expr* y) {
|
|
if (a.is_numeral(y))
|
|
return expr_ref(a.mk_le(x, y), m);
|
|
if (a.is_numeral(x))
|
|
return expr_ref(a.mk_ge(y, x), m);
|
|
return expr_ref(a.mk_le(a.mk_sub(x, y), a.mk_numeral(rational(0), x->get_sort())), m);
|
|
}
|
|
|
|
expr_ref bv2int_translator::mk_lt(expr* x, expr* y) {
|
|
return expr_ref(m.mk_not(mk_le(y, x)), m);
|
|
}
|
|
|
|
|
|
|
|
void bv2int_translator::translate_bv(app* e) {
|
|
|
|
auto bnot = [&](expr* e) {
|
|
return a.mk_sub(a.mk_int(-1), e);
|
|
};
|
|
|
|
auto band = [&](expr_ref_vector const& args) {
|
|
expr* r = arg(0);
|
|
for (unsigned i = 1; i < args.size(); ++i)
|
|
r = a.mk_band(bv.get_bv_size(e), r, arg(i));
|
|
return r;
|
|
};
|
|
|
|
auto rotate_left = [&](unsigned n) {
|
|
auto sz = bv.get_bv_size(e);
|
|
n = n % sz;
|
|
expr* r = arg(0);
|
|
if (n != 0 && sz != 1) {
|
|
// r[sz - n - 1 : 0] ++ r[sz - 1 : sz - n]
|
|
// r * 2^(sz - n) + (r div 2^n) mod 2^(sz - n)???
|
|
// r * A + (r div B) mod A
|
|
auto N = bv_size(e);
|
|
auto A = rational::power_of_two(sz - n);
|
|
auto B = rational::power_of_two(n);
|
|
auto hi = mul(r, a.mk_int(A));
|
|
auto lo = amod(e, a.mk_idiv(umod(e, 0), a.mk_int(B)), A);
|
|
r = add(hi, lo);
|
|
}
|
|
return r;
|
|
};
|
|
|
|
expr* bv_expr = e;
|
|
expr_ref r(m);
|
|
auto const& args = m_args;
|
|
switch (e->get_decl_kind()) {
|
|
case OP_BADD:
|
|
r = a.mk_add(args);
|
|
break;
|
|
case OP_BSUB:
|
|
r = a.mk_sub(args.size(), args.data());
|
|
break;
|
|
case OP_BMUL:
|
|
r = a.mk_mul(args);
|
|
break;
|
|
case OP_ULEQ:
|
|
bv_expr = e->get_arg(0);
|
|
r = mk_le(umod(bv_expr, 0), umod(bv_expr, 1));
|
|
break;
|
|
case OP_UGEQ:
|
|
bv_expr = e->get_arg(0);
|
|
r = mk_ge(umod(bv_expr, 0), umod(bv_expr, 1));
|
|
break;
|
|
case OP_ULT:
|
|
bv_expr = e->get_arg(0);
|
|
r = mk_lt(umod(bv_expr, 0), umod(bv_expr, 1));
|
|
break;
|
|
case OP_UGT:
|
|
bv_expr = e->get_arg(0);
|
|
r = mk_gt(umod(bv_expr, 0), umod(bv_expr, 1));
|
|
break;
|
|
case OP_SLEQ:
|
|
bv_expr = e->get_arg(0);
|
|
r = mk_le(smod(bv_expr, 0), smod(bv_expr, 1));
|
|
break;
|
|
case OP_SGEQ:
|
|
bv_expr = e->get_arg(0);
|
|
r = mk_ge(smod(bv_expr, 0), smod(bv_expr, 1));
|
|
break;
|
|
case OP_SLT:
|
|
bv_expr = e->get_arg(0);
|
|
r = mk_lt(smod(bv_expr, 0), smod(bv_expr, 1));
|
|
break;
|
|
case OP_SGT:
|
|
bv_expr = e->get_arg(0);
|
|
r = mk_gt(smod(bv_expr, 0), smod(bv_expr, 1));
|
|
break;
|
|
case OP_BNEG:
|
|
r = a.mk_uminus(arg(0));
|
|
break;
|
|
case OP_CONCAT: {
|
|
unsigned sz = 0;
|
|
expr_ref new_arg(m);
|
|
for (unsigned i = args.size(); i-- > 0;) {
|
|
expr* old_arg = e->get_arg(i);
|
|
new_arg = umod(old_arg, i);
|
|
if (sz > 0) {
|
|
new_arg = mul(new_arg, a.mk_int(rational::power_of_two(sz)));
|
|
r = add(r, new_arg);
|
|
}
|
|
else
|
|
r = new_arg;
|
|
sz += bv.get_bv_size(old_arg->get_sort());
|
|
}
|
|
break;
|
|
}
|
|
case OP_EXTRACT: {
|
|
unsigned lo, hi;
|
|
expr* old_arg;
|
|
VERIFY(bv.is_extract(e, lo, hi, old_arg));
|
|
r = arg(0);
|
|
if (lo > 0)
|
|
r = a.mk_idiv(r, a.mk_int(rational::power_of_two(lo)));
|
|
break;
|
|
}
|
|
case OP_BV_NUM: {
|
|
rational val;
|
|
unsigned sz;
|
|
VERIFY(bv.is_numeral(e, val, sz));
|
|
r = a.mk_int(val);
|
|
break;
|
|
}
|
|
case OP_BUREM:
|
|
case OP_BUREM_I: {
|
|
expr* x = umod(e, 0), * y = umod(e, 1);
|
|
r = if_eq(y, 0, x, a.mk_mod(x, y));
|
|
break;
|
|
}
|
|
case OP_BUDIV:
|
|
case OP_BUDIV_I: {
|
|
expr* x = umod(e, 0), * y = umod(e, 1);
|
|
r = if_eq(y, 0, a.mk_int(-1), a.mk_idiv(x, y));
|
|
break;
|
|
}
|
|
case OP_BUMUL_NO_OVFL: {
|
|
bv_expr = e->get_arg(0);
|
|
r = mk_lt(mul(umod(bv_expr, 0), umod(bv_expr, 1)), a.mk_int(bv_size(bv_expr)));
|
|
break;
|
|
}
|
|
case OP_BSHL: {
|
|
if (!a.is_numeral(arg(0)) && !a.is_numeral(arg(1)))
|
|
r = a.mk_shl(bv.get_bv_size(e), arg(0), arg(1));
|
|
else {
|
|
expr* x = arg(0), * y = umod(e, 1);
|
|
r = a.mk_int(0);
|
|
for (unsigned i = 0; i < bv.get_bv_size(e); ++i)
|
|
r = if_eq(y, i, mul(x, a.mk_int(rational::power_of_two(i))), r);
|
|
}
|
|
break;
|
|
}
|
|
case OP_BNOT:
|
|
r = bnot(arg(0));
|
|
break;
|
|
case OP_BLSHR:
|
|
if (!a.is_numeral(arg(0)) && !a.is_numeral(arg(1)))
|
|
r = a.mk_lshr(bv.get_bv_size(e), arg(0), arg(1));
|
|
else {
|
|
expr* x = arg(0), * y = umod(e, 1);
|
|
r = a.mk_int(0);
|
|
IF_VERBOSE(4, verbose_stream() << "lshr " << mk_bounded_pp(e, m) << " " << bv.get_bv_size(e) << "\n");
|
|
for (unsigned i = 0; i < bv.get_bv_size(e); ++i)
|
|
r = if_eq(y, i, a.mk_idiv(x, a.mk_int(rational::power_of_two(i))), r);
|
|
}
|
|
break;
|
|
case OP_BASHR:
|
|
if (!a.is_numeral(arg(1)))
|
|
r = a.mk_ashr(bv.get_bv_size(e), arg(0), arg(1));
|
|
else {
|
|
|
|
//
|
|
// ashr(x, y)
|
|
// if y = k & x >= 0 -> x / 2^k
|
|
// if y = k & x < 0 -> (x / 2^k) - 2^{N-k}
|
|
//
|
|
unsigned sz = bv.get_bv_size(e);
|
|
rational N = bv_size(e);
|
|
expr* x = umod(e, 0), * y = umod(e, 1);
|
|
expr* signx = a.mk_ge(x, a.mk_int(N / 2));
|
|
r = m.mk_ite(signx, a.mk_int(-1), a.mk_int(0));
|
|
IF_VERBOSE(4, verbose_stream() << "ashr " << mk_bounded_pp(e, m) << " " << bv.get_bv_size(e) << "\n");
|
|
for (unsigned i = 0; i < sz; ++i) {
|
|
expr* d = a.mk_idiv(x, a.mk_int(rational::power_of_two(i)));
|
|
r = if_eq(y, i,
|
|
m.mk_ite(signx, add(d, a.mk_int(-rational::power_of_two(sz - i))), d),
|
|
r);
|
|
}
|
|
}
|
|
break;
|
|
case OP_BOR:
|
|
// p | q := (p + q) - band(p, q)
|
|
IF_VERBOSE(4, verbose_stream() << "bor " << mk_bounded_pp(e, m) << " " << bv.get_bv_size(e) << "\n");
|
|
r = arg(0);
|
|
for (unsigned i = 1; i < args.size(); ++i)
|
|
r = a.mk_sub(add(r, arg(i)), a.mk_band(bv.get_bv_size(e), r, arg(i)));
|
|
break;
|
|
case OP_BNAND:
|
|
r = bnot(band(args));
|
|
break;
|
|
case OP_BAND:
|
|
IF_VERBOSE(4, verbose_stream() << "band " << mk_bounded_pp(e, m) << " " << bv.get_bv_size(e) << "\n");
|
|
r = band(args);
|
|
break;
|
|
case OP_BXNOR:
|
|
case OP_BXOR: {
|
|
// p ^ q := (p + q) - 2*band(p, q);
|
|
unsigned sz = bv.get_bv_size(e);
|
|
IF_VERBOSE(4, verbose_stream() << "bxor " << bv.get_bv_size(e) << "\n");
|
|
r = arg(0);
|
|
for (unsigned i = 1; i < args.size(); ++i) {
|
|
expr* q = arg(i);
|
|
r = a.mk_sub(add(r, q), mul(a.mk_int(2), a.mk_band(sz, r, q)));
|
|
}
|
|
if (e->get_decl_kind() == OP_BXNOR)
|
|
r = bnot(r);
|
|
break;
|
|
}
|
|
case OP_ZERO_EXT:
|
|
bv_expr = e->get_arg(0);
|
|
r = umod(bv_expr, 0);
|
|
SASSERT(bv.get_bv_size(e) >= bv.get_bv_size(bv_expr));
|
|
break;
|
|
case OP_SIGN_EXT: {
|
|
bv_expr = e->get_arg(0);
|
|
r = umod(bv_expr, 0);
|
|
SASSERT(bv.get_bv_size(e) >= bv.get_bv_size(bv_expr));
|
|
unsigned arg_sz = bv.get_bv_size(bv_expr);
|
|
//unsigned sz = bv.get_bv_size(e);
|
|
// rational N = rational::power_of_two(sz);
|
|
rational M = rational::power_of_two(arg_sz);
|
|
expr* signbit = a.mk_ge(r, a.mk_int(M / 2));
|
|
r = m.mk_ite(signbit, a.mk_sub(r, a.mk_int(M)), r);
|
|
break;
|
|
}
|
|
case OP_INT2BV:
|
|
m_int2bv.push_back(e);
|
|
ctx.push(push_back_vector(m_int2bv));
|
|
r = arg(0);
|
|
break;
|
|
case OP_BV2INT:
|
|
m_bv2int.push_back(e);
|
|
ctx.push(push_back_vector(m_bv2int));
|
|
r = umod(e->get_arg(0), 0);
|
|
break;
|
|
case OP_BCOMP:
|
|
bv_expr = e->get_arg(0);
|
|
r = m.mk_ite(m.mk_eq(umod(bv_expr, 0), umod(bv_expr, 1)), a.mk_int(1), a.mk_int(0));
|
|
break;
|
|
case OP_BSMOD_I:
|
|
case OP_BSMOD: {
|
|
expr* x = umod(e, 0), * y = umod(e, 1);
|
|
rational N = bv_size(e);
|
|
expr* signx = a.mk_ge(x, a.mk_int(N / 2));
|
|
expr* signy = a.mk_ge(y, a.mk_int(N / 2));
|
|
expr* u = a.mk_mod(x, y);
|
|
// u = 0 -> 0
|
|
// y = 0 -> x
|
|
// x < 0, y < 0 -> -u
|
|
// x < 0, y >= 0 -> y - u
|
|
// x >= 0, y < 0 -> y + u
|
|
// x >= 0, y >= 0 -> u
|
|
r = a.mk_uminus(u);
|
|
r = m.mk_ite(m.mk_and(m.mk_not(signx), signy), add(u, y), r);
|
|
r = m.mk_ite(m.mk_and(signx, m.mk_not(signy)), a.mk_sub(y, u), r);
|
|
r = m.mk_ite(m.mk_and(m.mk_not(signx), m.mk_not(signy)), u, r);
|
|
r = if_eq(u, 0, a.mk_int(0), r);
|
|
r = if_eq(y, 0, x, r);
|
|
break;
|
|
}
|
|
case OP_BSDIV_I:
|
|
case OP_BSDIV: {
|
|
// d = udiv(abs(x), abs(y))
|
|
// y = 0, x > 0 -> 1
|
|
// y = 0, x <= 0 -> -1
|
|
// x = 0, y != 0 -> 0
|
|
// x > 0, y < 0 -> -d
|
|
// x < 0, y > 0 -> -d
|
|
// x > 0, y > 0 -> d
|
|
// x < 0, y < 0 -> d
|
|
expr* x = umod(e, 0), * y = umod(e, 1);
|
|
rational N = bv_size(e);
|
|
expr* signx = a.mk_ge(x, a.mk_int(N / 2));
|
|
expr* signy = a.mk_ge(y, a.mk_int(N / 2));
|
|
x = m.mk_ite(signx, a.mk_sub(a.mk_int(N), x), x);
|
|
y = m.mk_ite(signy, a.mk_sub(a.mk_int(N), y), y);
|
|
expr* d = a.mk_idiv(x, y);
|
|
r = m.mk_ite(m.mk_iff(signx, signy), d, a.mk_uminus(d));
|
|
r = if_eq(y, 0, m.mk_ite(signx, a.mk_int(1), a.mk_int(-1)), r);
|
|
break;
|
|
}
|
|
case OP_BSREM_I:
|
|
case OP_BSREM: {
|
|
// y = 0 -> x
|
|
// else x - sdiv(x, y) * y
|
|
expr* x = umod(e, 0), * y = umod(e, 1);
|
|
rational N = bv_size(e);
|
|
expr* signx = a.mk_ge(x, a.mk_int(N / 2));
|
|
expr* signy = a.mk_ge(y, a.mk_int(N / 2));
|
|
expr* absx = m.mk_ite(signx, a.mk_sub(a.mk_int(N), x), x);
|
|
expr* absy = m.mk_ite(signy, a.mk_sub(a.mk_int(N), y), y);
|
|
expr* d = a.mk_idiv(absx, absy);
|
|
d = m.mk_ite(m.mk_iff(signx, signy), d, a.mk_uminus(d));
|
|
r = a.mk_sub(x, mul(d, y));
|
|
r = if_eq(y, 0, x, r);
|
|
break;
|
|
}
|
|
case OP_ROTATE_LEFT: {
|
|
auto n = e->get_parameter(0).get_int();
|
|
r = rotate_left(n);
|
|
break;
|
|
}
|
|
case OP_ROTATE_RIGHT: {
|
|
unsigned sz = bv.get_bv_size(e);
|
|
auto n = e->get_parameter(0).get_int();
|
|
r = rotate_left(sz - n);
|
|
break;
|
|
}
|
|
case OP_EXT_ROTATE_LEFT: {
|
|
unsigned sz = bv.get_bv_size(e);
|
|
expr* y = umod(e, 1);
|
|
r = a.mk_int(0);
|
|
for (unsigned i = 0; i < sz; ++i)
|
|
r = if_eq(y, i, rotate_left(i), r);
|
|
break;
|
|
}
|
|
case OP_EXT_ROTATE_RIGHT: {
|
|
unsigned sz = bv.get_bv_size(e);
|
|
expr* y = umod(e, 1);
|
|
r = a.mk_int(0);
|
|
for (unsigned i = 0; i < sz; ++i)
|
|
r = if_eq(y, i, rotate_left(sz - i), r);
|
|
break;
|
|
}
|
|
case OP_REPEAT: {
|
|
unsigned n = e->get_parameter(0).get_int();
|
|
expr* x = umod(e->get_arg(0), 0);
|
|
r = x;
|
|
rational N = bv_size(e->get_arg(0));
|
|
rational N0 = N;
|
|
for (unsigned i = 1; i < n; ++i)
|
|
r = add(mul(a.mk_int(N), x), r), N *= N0;
|
|
break;
|
|
}
|
|
case OP_BREDOR: {
|
|
r = umod(e->get_arg(0), 0);
|
|
r = m.mk_not(m.mk_eq(r, a.mk_int(0)));
|
|
break;
|
|
}
|
|
case OP_BREDAND: {
|
|
rational N = bv_size(e->get_arg(0));
|
|
r = umod(e->get_arg(0), 0);
|
|
r = m.mk_not(m.mk_eq(r, a.mk_int(N - 1)));
|
|
break;
|
|
}
|
|
default:
|
|
verbose_stream() << mk_pp(e, m) << "\n";
|
|
NOT_IMPLEMENTED_YET();
|
|
}
|
|
set_translated(e, r);
|
|
}
|
|
|
|
expr_ref bv2int_translator::if_eq(expr* n, unsigned k, expr* th, expr* el) {
|
|
rational r;
|
|
expr_ref _th(th, m), _el(el, m);
|
|
if (bv.is_numeral(n, r)) {
|
|
if (r == k)
|
|
return expr_ref(th, m);
|
|
else
|
|
return expr_ref(el, m);
|
|
}
|
|
return expr_ref(m.mk_ite(m.mk_eq(n, a.mk_int(k)), th, el), m);
|
|
}
|
|
|
|
void bv2int_translator::translate_basic(app* e) {
|
|
if (m.is_eq(e)) {
|
|
bool has_bv_arg = any_of(*e, [&](expr* arg) { return bv.is_bv(arg); });
|
|
if (has_bv_arg) {
|
|
expr* bv_expr = e->get_arg(0);
|
|
rational N = rational::power_of_two(bv.get_bv_size(bv_expr));
|
|
if (a.is_numeral(arg(0)) || a.is_numeral(arg(1)) ||
|
|
is_bounded(arg(0), N) || is_bounded(arg(1), N)) {
|
|
set_translated(e, m.mk_eq(umod(bv_expr, 0), umod(bv_expr, 1)));
|
|
}
|
|
else {
|
|
m_args[0] = a.mk_sub(arg(0), arg(1));
|
|
set_translated(e, m.mk_eq(umod(bv_expr, 0), a.mk_int(0)));
|
|
}
|
|
}
|
|
else
|
|
set_translated(e, m.mk_eq(arg(0), arg(1)));
|
|
}
|
|
else if (m.is_ite(e))
|
|
set_translated(e, m.mk_ite(arg(0), arg(1), arg(2)));
|
|
else if (m_is_plugin)
|
|
set_translated(e, e);
|
|
else
|
|
set_translated(e, m.mk_app(e->get_decl(), m_args));
|
|
}
|
|
|
|
bool bv2int_translator::is_bounded(expr* x, rational const& N) {
|
|
return any_of(m_vars, [&](expr* v) {
|
|
return is_translated(v) && translated(v) == x && bv_size(v) <= N;
|
|
});
|
|
}
|
|
|
|
bool bv2int_translator::is_non_negative(expr* bv_expr, expr* e) {
|
|
auto N = rational::power_of_two(bv.get_bv_size(bv_expr));
|
|
rational r;
|
|
if (a.is_numeral(e, r))
|
|
return r >= 0;
|
|
if (is_bounded(e, N))
|
|
return true;
|
|
expr* x = nullptr, * y = nullptr;
|
|
if (a.is_mul(e, x, y))
|
|
return is_non_negative(bv_expr, x) && is_non_negative(bv_expr, y);
|
|
if (a.is_add(e, x, y))
|
|
return is_non_negative(bv_expr, x) && is_non_negative(bv_expr, y);
|
|
return false;
|
|
}
|
|
|
|
expr* bv2int_translator::umod(expr* bv_expr, unsigned i) {
|
|
expr* x = arg(i);
|
|
rational N = bv_size(bv_expr);
|
|
return amod(bv_expr, x, N);
|
|
}
|
|
|
|
expr* bv2int_translator::smod(expr* bv_expr, unsigned i) {
|
|
expr* x = arg(i);
|
|
auto N = bv_size(bv_expr);
|
|
auto shift = N / 2;
|
|
rational r;
|
|
if (a.is_numeral(x, r))
|
|
return a.mk_int(mod(r + shift, N));
|
|
return amod(bv_expr, add(x, a.mk_int(shift)), N);
|
|
}
|
|
|
|
expr_ref bv2int_translator::mul(expr* x, expr* y) {
|
|
expr_ref _x(x, m), _y(y, m);
|
|
if (a.is_zero(x))
|
|
return _x;
|
|
if (a.is_zero(y))
|
|
return _y;
|
|
if (a.is_one(x))
|
|
return _y;
|
|
if (a.is_one(y))
|
|
return _x;
|
|
rational v1, v2;
|
|
if (a.is_numeral(x, v1) && a.is_numeral(y, v2))
|
|
return expr_ref(a.mk_int(v1 * v2), m);
|
|
_x = a.mk_mul(x, y);
|
|
return _x;
|
|
}
|
|
|
|
expr_ref bv2int_translator::add(expr* x, expr* y) {
|
|
expr_ref _x(x, m), _y(y, m);
|
|
if (a.is_zero(x))
|
|
return _y;
|
|
if (a.is_zero(y))
|
|
return _x;
|
|
rational v1, v2;
|
|
if (a.is_numeral(x, v1) && a.is_numeral(y, v2))
|
|
return expr_ref(a.mk_int(v1 + v2), m);
|
|
_x = a.mk_add(x, y);
|
|
return _x;
|
|
}
|
|
|
|
/*
|
|
* Perform simplifications that are claimed sound when the bit-vector interpretations of
|
|
* mod/div always guard the mod and dividend to be non-zero.
|
|
* Potentially shady area is for arithmetic expressions created by int2bv.
|
|
* They will be guarded by a modulus which does not disappear.
|
|
*/
|
|
expr* bv2int_translator::amod(expr* bv_expr, expr* x, rational const& N) {
|
|
rational v;
|
|
expr* r = nullptr, * c = nullptr, * t = nullptr, * e = nullptr;
|
|
if (m.is_ite(x, c, t, e))
|
|
r = m.mk_ite(c, amod(bv_expr, t, N), amod(bv_expr, e, N));
|
|
else if (a.is_idiv(x, t, e) && a.is_numeral(t, v) && 0 <= v && v < N && is_non_negative(bv_expr, e))
|
|
r = x;
|
|
else if (a.is_mod(x, t, e) && a.is_numeral(t, v) && 0 <= v && v < N)
|
|
r = x;
|
|
else if (a.is_numeral(x, v))
|
|
r = a.mk_int(mod(v, N));
|
|
else if (is_bounded(x, N))
|
|
r = x;
|
|
else
|
|
r = a.mk_mod(x, a.mk_int(N));
|
|
return r;
|
|
}
|
|
|
|
void bv2int_translator::translate_eq(expr* e) {
|
|
expr* x = nullptr, * y = nullptr;
|
|
VERIFY(m.is_eq(e, x, y));
|
|
SASSERT(bv.is_bv(x));
|
|
if (!is_translated(e)) {
|
|
ensure_translated(x);
|
|
ensure_translated(y);
|
|
m_args.reset();
|
|
m_args.push_back(a.mk_sub(translated(x), translated(y)));
|
|
set_translated(e, m.mk_eq(umod(x, 0), a.mk_int(0)));
|
|
}
|
|
m_preds.push_back(e);
|
|
TRACE("bv", tout << mk_pp(e, m) << " " << mk_pp(translated(e), m) << "\n");
|
|
ctx.push(push_back_vector(m_preds));
|
|
|
|
}
|