diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index f3a3e9238..55adc8370 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -482,12 +482,12 @@ namespace smt { template void theory_arith::mk_idiv_mod_axioms(expr * dividend, expr * divisor) { + th_rewriter & s = get_context().get_rewriter(); if (!m_util.is_zero(divisor)) { ast_manager & m = get_manager(); // if divisor is zero, then idiv and mod are uninterpreted functions. expr_ref div(m), mod(m), zero(m), abs_divisor(m), one(m); expr_ref eqz(m), eq(m), lower(m), upper(m); - th_rewriter & s = get_context().get_rewriter(); div = m_util.mk_idiv(dividend, divisor); mod = m_util.mk_mod(dividend, divisor); zero = m_util.mk_int(0); @@ -508,6 +508,17 @@ namespace smt { mk_axiom(eqz, upper, !m_util.is_numeral(abs_divisor)); rational k; context& ctx = get_context(); + + if (!m_util.is_numeral(divisor)) { + // (=> (> y 0) (<= (* y (div x y)) x)) + // (=> (< y 0) ???) + expr_ref div_ge(m), div_non_pos(m); + div_ge = m_util.mk_ge(m_util.mk_sub(dividend, m_util.mk_mul(divisor, div)), zero); + s(div_ge); + div_non_pos = m_util.mk_le(divisor, zero); + mk_axiom(div_non_pos, div_ge, false); + } + (void)ctx; if (m_params.m_arith_enum_const_mod && m_util.is_numeral(divisor, k) && k.is_pos() && k < rational(8)) { @@ -542,6 +553,7 @@ namespace smt { } #endif } + #if 0 // e-matching is too restrictive for multiplication. // also suffers from use-after free so formulas have to be pinned in solver. diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index 936953d0a..10b2992fe 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -251,7 +251,7 @@ void theory_seq::init(context* ctx) { m_arith_value.init(ctx); } -#define TRACEFIN(s) { TRACE("seq", tout << ">>" << s << "\n";); IF_VERBOSE(10, verbose_stream() << s << "\n"); } +#define TRACEFIN(s) { TRACE("seq", tout << ">>" << s << "\n";); IF_VERBOSE(11, verbose_stream() << s << "\n"); } final_check_status theory_seq::final_check_eh() {