From f0737bdf7f7fccdc575f425215cf52fc03dbea43 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura <leonardo@microsoft.com> Date: Mon, 14 Jan 2013 18:30:36 -0800 Subject: [PATCH] Replace expensive_eval_sign_at with version that does not generate rational numbers Signed-off-by: Leonardo de Moura <leonardo@microsoft.com> --- src/math/realclosure/realclosure.cpp | 39 +++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/math/realclosure/realclosure.cpp b/src/math/realclosure/realclosure.cpp index d9892e689..7982e28b4 100644 --- a/src/math/realclosure/realclosure.cpp +++ b/src/math/realclosure/realclosure.cpp @@ -3784,13 +3784,40 @@ namespace realclosure { \brief Evaluate the sign of p(b) by computing a value object. */ int expensive_eval_sign_at(unsigned n, value * const * p, mpbq const & b) { - SASSERT(n > 0); + SASSERT(n > 1); SASSERT(p[n - 1] != 0); - value_ref _b(*this); - _b = mk_rational(b); - value_ref pb(*this); - mk_polynomial_value(n, p, _b, pb); - return sign(pb); + // Actually, given b = c/2^k, we compute the sign of (2^k)^n*p(c) + // Original Horner Sequence + // ((a_n * b + a_{n-1})*b + a_{n-2})*b + a_{n-3} ... + // Variation of the Horner Sequence for (2^k)^n*p(b) + // ((a_n * c + a_{n-1}*2_k)*c + a_{n-2}*(2_k)^2)*c + a_{n-3}*(2_k)^3 ... + a_0*(2_k)^n + scoped_mpz mpz_twok(qm()); + qm().mul2k(mpz(1), b.k(), mpz_twok); + value_ref twok(*this), twok_i(*this); + twok = mk_rational(mpz_twok); + twok_i = twok; + value_ref c(*this); + c = mk_rational(b.numerator()); + + value_ref r(*this), ak(*this), rc(*this); + + r = p[n-1]; + unsigned i = n-1; + while (i > 0) { + --i; + if (is_zero(p[i])) { + mul(r, c, r); + } + else { + // ak <- a_i * (2^k)^(n-i) + mul(p[i], twok_i, ak); + // r <- r * c + a_i * (2^k)^(n-i) + mul(r, c, rc); + add(ak, rc, r); + } + mul(twok_i, twok, twok_i); + } + return sign(r); } /**