From f747bde54895c3a1ba74a528a6bdfee646a19852 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura <leonardo@microsoft.com> Date: Sat, 12 Jan 2013 21:59:41 -0800 Subject: [PATCH] Add restore_interval for extensions Signed-off-by: Leonardo de Moura <leonardo@microsoft.com> --- src/math/realclosure/realclosure.cpp | 58 ++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/src/math/realclosure/realclosure.cpp b/src/math/realclosure/realclosure.cpp index 246f61b90..09e722f23 100644 --- a/src/math/realclosure/realclosure.cpp +++ b/src/math/realclosure/realclosure.cpp @@ -217,8 +217,9 @@ namespace realclosure { unsigned m_kind:2; unsigned m_idx:30; mpbqi m_interval; + mpbqi * m_old_interval; - extension(kind k, unsigned idx):m_ref_count(0), m_kind(k), m_idx(idx) {} + extension(kind k, unsigned idx):m_ref_count(0), m_kind(k), m_idx(idx), m_old_interval(0) {} unsigned idx() const { return m_idx; } kind knd() const { return static_cast<kind>(m_kind); } @@ -365,6 +366,7 @@ namespace realclosure { mk_e_interval m_mk_e_interval; value * m_e; ptr_vector<value> m_to_restore; //!< Set of values v s.t. v->m_old_interval != 0 + ptr_vector<extension> m_ex_to_restore; // Parameters bool m_use_prem; //!< use pseudo-remainder when computing sturm sequences @@ -627,39 +629,59 @@ namespace realclosure { } /** - \brief Save the current interval (i.e., approximation) of the given value. + \brief Save the current interval (i.e., approximation) of the given value or extension. */ - void save_interval(value * v) { + template<typename T> + void save_interval(T * v, ptr_vector<T> & to_restore) { if (v->m_old_interval != 0) return; // interval was already saved. - m_to_restore.push_back(v); + to_restore.push_back(v); inc_ref(v); v->m_old_interval = new (allocator()) mpbqi(); set_interval(*(v->m_old_interval), v->m_interval); } + void save_interval(value * v) { + save_interval(v, m_to_restore); + } + void save_interval(extension * x) { + save_interval(x, m_ex_to_restore); + } /** - \brief Save the current interval (i.e., approximation) of the given value IF it is too small (i.e., too_small(v) == True). + \brief Save the current interval (i.e., approximation) of the given value IF it is too small. */ - void save_interval_if_too_small(value * v) { - if (too_small(v->m_interval)) + void save_interval_if_too_small(value * v, unsigned new_prec) { + if (new_prec > m_max_precision && !contains_zero(interval(v))) save_interval(v); } /** - \brief Restore the saved intervals (approximations) of RCF values. + \brief Save the current interval (i.e., approximation) of the given value IF it is too small. */ - void restore_saved_intervals() { - unsigned sz = m_to_restore.size(); + void save_interval_if_too_small(extension * x, unsigned new_prec) { + if (new_prec > m_max_precision && !contains_zero(x->m_interval)) + save_interval(x); + } + + /** + \brief Restore the saved intervals (approximations) of RCF values and extensions + */ + template<typename T> + void restore_saved_intervals(ptr_vector<T> & to_restore) { + unsigned sz = to_restore.size(); for (unsigned i = 0; i < sz; i++) { - value * v = m_to_restore[i]; + T * v = to_restore[i]; set_interval(v->m_interval, *(v->m_old_interval)); bqim().del(*(v->m_old_interval)); allocator().deallocate(sizeof(mpbqi), v->m_old_interval); v->m_old_interval = 0; dec_ref(v); } - m_to_restore.reset(); + to_restore.reset(); + } + void restore_saved_intervals() { + restore_saved_intervals(m_to_restore); + restore_saved_intervals(m_ex_to_restore); } void cleanup(extension::kind k) { @@ -720,7 +742,7 @@ namespace realclosure { bqim().del(v->m_interval); reset_p(v->num()); reset_p(v->den()); - dec_ref_ext(v->ext()); + dec_ref(v->ext()); allocator().deallocate(sizeof(rational_function_value), v); } @@ -797,12 +819,12 @@ namespace realclosure { allocator().deallocate(sizeof(infinitesimal), i); } - void inc_ref_ext(extension * ext) { + void inc_ref(extension * ext) { SASSERT(ext != 0); ext->m_ref_count++; } - void dec_ref_ext(extension * ext) { + void dec_ref(extension * ext) { SASSERT(m_extensions[ext->knd()][ext->idx()] == ext); SASSERT(ext->m_ref_count > 0); ext->m_ref_count--; @@ -1188,7 +1210,7 @@ namespace realclosure { */ rational_function_value * mk_rational_function_value_core(extension * ext, unsigned num_sz, value * const * num, unsigned den_sz, value * const * den) { rational_function_value * r = alloc(rational_function_value, ext); - inc_ref_ext(ext); + inc_ref(ext); set_p(r->num(), num_sz, num); set_p(r->den(), den_sz, den); r->set_depends_on_infinitesimals(depends_on_infinitesimals(ext) || depends_on_infinitesimals(num_sz, num) || depends_on_infinitesimals(den_sz, den)); @@ -1256,6 +1278,7 @@ namespace realclosure { while (!check_precision(t->interval(), prec)) { TRACE("rcf_transcendental", tout << "refine_transcendental_interval: " << magnitude(t->interval()) << std::endl;); checkpoint(); + save_interval_if_too_small(t, prec); refine_transcendental_interval(t); } } @@ -4106,6 +4129,7 @@ namespace realclosure { } bool refine_algebraic_interval(algebraic * a, unsigned prec) { + save_interval_if_too_small(a, prec); if (a->sdt() != 0) { // we can't bisect the interval, since it contains more than one root. return false; @@ -4178,7 +4202,7 @@ namespace realclosure { int m = magnitude(interval(v)); if (m == INT_MIN || (m < 0 && static_cast<unsigned>(-m) > prec)) return true; - save_interval_if_too_small(v); + save_interval_if_too_small(v, prec); if (is_nz_rational(v)) { refine_rational_interval(to_nz_rational(v), prec); return true;