mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
pull unstable
Signed-off-by: Nikolaj Bjorner <nbjorner@hotmail.com>
This commit is contained in:
commit
52619b9dbb
337 changed files with 24943 additions and 30606 deletions
|
@ -25,13 +25,12 @@ Revision History:
|
|||
#define MK_MASK(_num_bits_) ((1U << _num_bits_) - 1)
|
||||
|
||||
void bit_vector::expand_to(unsigned new_capacity) {
|
||||
unsigned * new_data = alloc_svect(unsigned, new_capacity);
|
||||
memset(new_data, 0, new_capacity * sizeof(unsigned));
|
||||
if (m_capacity > 0) {
|
||||
memcpy(new_data, m_data, m_capacity * sizeof(unsigned));
|
||||
dealloc_svect(m_data);
|
||||
if (m_data) {
|
||||
m_data = (unsigned*)memory::reallocate(m_data, new_capacity * sizeof(unsigned));
|
||||
} else {
|
||||
m_data = alloc_svect(unsigned, new_capacity);
|
||||
}
|
||||
m_data = new_data;
|
||||
memset(m_data + m_capacity, 0, (new_capacity - m_capacity) * sizeof(unsigned));
|
||||
m_capacity = new_capacity;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,9 +87,7 @@ public:
|
|||
}
|
||||
|
||||
~bit_vector() {
|
||||
if (m_data) {
|
||||
dealloc_svect(m_data);
|
||||
}
|
||||
dealloc_svect(m_data);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
|
|
|
@ -31,18 +31,18 @@ protected:
|
|||
char m_initial_buffer[INITIAL_SIZE * sizeof(T)];
|
||||
|
||||
void free_memory() {
|
||||
if (m_buffer != reinterpret_cast<T*>(m_initial_buffer)) {
|
||||
memory::deallocate(m_buffer);
|
||||
}
|
||||
if (m_buffer != reinterpret_cast<T*>(m_initial_buffer)) {
|
||||
memory::deallocate(m_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void expand() {
|
||||
unsigned new_capacity = m_capacity << 1;
|
||||
T * new_buffer = reinterpret_cast<T*>(memory::allocate(sizeof(T) * new_capacity));
|
||||
memcpy(new_buffer, m_buffer, m_pos * sizeof(T));
|
||||
free_memory();
|
||||
m_buffer = new_buffer;
|
||||
m_capacity = new_capacity;
|
||||
unsigned new_capacity = m_capacity << 1;
|
||||
T * new_buffer = reinterpret_cast<T*>(memory::allocate(sizeof(T) * new_capacity));
|
||||
memcpy(new_buffer, m_buffer, m_pos * sizeof(T));
|
||||
free_memory();
|
||||
m_buffer = new_buffer;
|
||||
m_capacity = new_capacity;
|
||||
}
|
||||
|
||||
void destroy_elements() {
|
||||
|
@ -50,14 +50,14 @@ protected:
|
|||
iterator e = end();
|
||||
for (; it != e; ++it) {
|
||||
it->~T();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
if (CallDestructors) {
|
||||
destroy_elements();
|
||||
}
|
||||
free_memory();
|
||||
if (CallDestructors) {
|
||||
destroy_elements();
|
||||
}
|
||||
free_memory();
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -66,15 +66,15 @@ public:
|
|||
typedef const T * const_iterator;
|
||||
|
||||
buffer():
|
||||
m_buffer(reinterpret_cast<T *>(m_initial_buffer)),
|
||||
m_pos(0),
|
||||
m_capacity(INITIAL_SIZE) {
|
||||
m_buffer(reinterpret_cast<T *>(m_initial_buffer)),
|
||||
m_pos(0),
|
||||
m_capacity(INITIAL_SIZE) {
|
||||
}
|
||||
|
||||
buffer(const buffer & source):
|
||||
m_buffer(reinterpret_cast<T *>(m_initial_buffer)),
|
||||
m_pos(0),
|
||||
m_capacity(INITIAL_SIZE) {
|
||||
m_buffer(reinterpret_cast<T *>(m_initial_buffer)),
|
||||
m_pos(0),
|
||||
m_capacity(INITIAL_SIZE) {
|
||||
unsigned sz = source.size();
|
||||
for(unsigned i = 0; i < sz; i++) {
|
||||
push_back(source.m_buffer[i]);
|
||||
|
@ -82,9 +82,9 @@ public:
|
|||
}
|
||||
|
||||
buffer(unsigned sz, const T & elem):
|
||||
m_buffer(reinterpret_cast<T *>(m_initial_buffer)),
|
||||
m_pos(0),
|
||||
m_capacity(INITIAL_SIZE) {
|
||||
m_buffer(reinterpret_cast<T *>(m_initial_buffer)),
|
||||
m_pos(0),
|
||||
m_capacity(INITIAL_SIZE) {
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
push_back(elem);
|
||||
}
|
||||
|
@ -96,10 +96,10 @@ public:
|
|||
}
|
||||
|
||||
void reset() {
|
||||
if (CallDestructors) {
|
||||
destroy_elements();
|
||||
}
|
||||
m_pos = 0;
|
||||
if (CallDestructors) {
|
||||
destroy_elements();
|
||||
}
|
||||
m_pos = 0;
|
||||
}
|
||||
|
||||
void finalize() {
|
||||
|
@ -110,11 +110,11 @@ public:
|
|||
}
|
||||
|
||||
unsigned size() const {
|
||||
return m_pos;
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return m_pos == 0;
|
||||
return m_pos == 0;
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
|
@ -126,13 +126,13 @@ public:
|
|||
}
|
||||
|
||||
void set_end(iterator it) {
|
||||
m_pos = static_cast<unsigned>(it - m_buffer);
|
||||
if (CallDestructors) {
|
||||
iterator e = end();
|
||||
for (; it != e; ++it) {
|
||||
it->~T();
|
||||
}
|
||||
}
|
||||
m_pos = static_cast<unsigned>(it - m_buffer);
|
||||
if (CallDestructors) {
|
||||
iterator e = end();
|
||||
for (; it != e; ++it) {
|
||||
it->~T();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
|
@ -144,33 +144,33 @@ public:
|
|||
}
|
||||
|
||||
void push_back(const T & elem) {
|
||||
if (m_pos >= m_capacity)
|
||||
expand();
|
||||
new (m_buffer + m_pos) T(elem);
|
||||
m_pos++;
|
||||
if (m_pos >= m_capacity)
|
||||
expand();
|
||||
new (m_buffer + m_pos) T(elem);
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
if (CallDestructors) {
|
||||
back().~T();
|
||||
}
|
||||
}
|
||||
m_pos--;
|
||||
}
|
||||
|
||||
const T & back() const {
|
||||
SASSERT(!empty());
|
||||
SASSERT(m_pos > 0);
|
||||
SASSERT(m_pos > 0);
|
||||
return m_buffer[m_pos - 1];
|
||||
}
|
||||
|
||||
T & back() {
|
||||
SASSERT(!empty());
|
||||
SASSERT(m_pos > 0);
|
||||
SASSERT(m_pos > 0);
|
||||
return m_buffer[m_pos - 1];
|
||||
}
|
||||
|
||||
T * c_ptr() const {
|
||||
return m_buffer;
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
void append(unsigned n, T const * elems) {
|
||||
|
|
|
@ -76,7 +76,8 @@ void invoke_gdb() {
|
|||
for (;;) {
|
||||
std::cerr << "(C)ontinue, (A)bort, (S)top, (T)hrow exception, Invoke (G)DB\n";
|
||||
char result;
|
||||
std::cin >> result;
|
||||
bool ok = (std::cin >> result);
|
||||
if (!ok) exit(ERR_INTERNAL_FATAL); // happens if std::cin is eof or unattached.
|
||||
switch(result) {
|
||||
case 'C':
|
||||
case 'c':
|
||||
|
|
|
@ -60,7 +60,7 @@ static void throw_out_of_memory() {
|
|||
}
|
||||
|
||||
#ifdef PROFILE_MEMORY
|
||||
unsigned g_synch_counter = 0;
|
||||
static unsigned g_synch_counter = 0;
|
||||
class mem_usage_report {
|
||||
public:
|
||||
~mem_usage_report() {
|
||||
|
@ -173,6 +173,7 @@ void memory::display_i_max_usage(std::ostream & os) {
|
|||
<< "\n";
|
||||
}
|
||||
|
||||
#if _DEBUG
|
||||
void memory::deallocate(char const * file, int line, void * p) {
|
||||
deallocate(p);
|
||||
TRACE_CODE(if (!g_finalizing) TRACE("memory", tout << "dealloc " << std::hex << p << std::dec << " " << file << ":" << line << "\n";););
|
||||
|
@ -183,6 +184,7 @@ void * memory::allocate(char const* file, int line, char const* obj, size_t s) {
|
|||
TRACE("memory", tout << "alloc " << std::hex << r << std::dec << " " << file << ":" << line << " " << obj << " " << s << "\n";);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_WINDOWS) || defined(_USE_THREAD_LOCAL)
|
||||
// ==================================
|
||||
|
@ -250,6 +252,24 @@ void * memory::allocate(size_t s) {
|
|||
return static_cast<size_t*>(r) + 1; // we return a pointer to the location after the extra field
|
||||
}
|
||||
|
||||
void* memory::reallocate(void *p, size_t s) {
|
||||
size_t *sz_p = reinterpret_cast<size_t*>(p)-1;
|
||||
size_t sz = *sz_p;
|
||||
void *real_p = reinterpret_cast<void*>(sz_p);
|
||||
s = s + sizeof(size_t); // we allocate an extra field!
|
||||
|
||||
g_memory_thread_alloc_size += s - sz;
|
||||
if (g_memory_thread_alloc_size > SYNCH_THRESHOLD) {
|
||||
synchronize_counters(true);
|
||||
}
|
||||
|
||||
void *r = realloc(real_p, s);
|
||||
if (r == 0)
|
||||
throw_out_of_memory();
|
||||
*(static_cast<size_t*>(r)) = s;
|
||||
return static_cast<size_t*>(r) + 1; // we return a pointer to the location after the extra field
|
||||
}
|
||||
|
||||
#else
|
||||
// ==================================
|
||||
// ==================================
|
||||
|
@ -290,5 +310,29 @@ void * memory::allocate(size_t s) {
|
|||
*(static_cast<size_t*>(r)) = s;
|
||||
return static_cast<size_t*>(r) + 1; // we return a pointer to the location after the extra field
|
||||
}
|
||||
|
||||
void* memory::reallocate(void *p, size_t s) {
|
||||
size_t * sz_p = reinterpret_cast<size_t*>(p) - 1;
|
||||
size_t sz = *sz_p;
|
||||
void * real_p = reinterpret_cast<void*>(sz_p);
|
||||
s = s + sizeof(size_t); // we allocate an extra field!
|
||||
bool out_of_mem = false;
|
||||
#pragma omp critical (z3_memory_manager)
|
||||
{
|
||||
g_memory_alloc_size += s - sz;
|
||||
if (g_memory_alloc_size > g_memory_max_used_size)
|
||||
g_memory_max_used_size = g_memory_alloc_size;
|
||||
if (g_memory_max_size != 0 && g_memory_alloc_size > g_memory_max_size)
|
||||
out_of_mem = true;
|
||||
}
|
||||
if (out_of_mem)
|
||||
throw_out_of_memory();
|
||||
|
||||
void *r = realloc(real_p, s);
|
||||
if (r == 0)
|
||||
throw_out_of_memory();
|
||||
*(static_cast<size_t*>(r)) = s;
|
||||
return static_cast<size_t*>(r) + 1; // we return a pointer to the location after the extra field
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,24 @@ Revision History:
|
|||
#include<ostream>
|
||||
#include"z3_exception.h"
|
||||
|
||||
#ifndef __has_builtin
|
||||
# define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 || __has_builtin(returns_nonnull)
|
||||
# define GCC_RET_NON_NULL __attribute__((returns_nonnull))
|
||||
# else
|
||||
# define GCC_RET_NON_NULL
|
||||
# endif
|
||||
# define ALLOC_ATTR __attribute__((malloc)) GCC_RET_NON_NULL
|
||||
#elif defined(_WINDOWS)
|
||||
# define ALLOC_ATTR __declspec(restrict)
|
||||
#else
|
||||
# define ALLOC_ATTR
|
||||
#endif
|
||||
|
||||
|
||||
class out_of_memory_error : public z3_error {
|
||||
public:
|
||||
out_of_memory_error();
|
||||
|
@ -39,9 +57,12 @@ public:
|
|||
static void display_max_usage(std::ostream& os);
|
||||
static void display_i_max_usage(std::ostream& os);
|
||||
static void deallocate(void* p);
|
||||
static void* allocate(size_t s);
|
||||
static ALLOC_ATTR void* allocate(size_t s);
|
||||
static ALLOC_ATTR void* reallocate(void *p, size_t s);
|
||||
#if _DEBUG
|
||||
static void deallocate(char const* file, int line, void* p);
|
||||
static void* allocate(char const* file, int line, char const* obj, size_t s);
|
||||
static ALLOC_ATTR void* allocate(char const* file, int line, char const* obj, size_t s);
|
||||
#endif
|
||||
static unsigned long long get_allocation_size();
|
||||
static unsigned long long get_max_used_memory();
|
||||
// temporary hack to avoid out-of-memory crash in z3.exe
|
||||
|
@ -74,6 +95,9 @@ void dealloc(T * ptr) {
|
|||
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
ALLOC_ATTR T * alloc_vect(unsigned sz);
|
||||
|
||||
template<typename T>
|
||||
T * alloc_vect(unsigned sz) {
|
||||
T * r = static_cast<T*>(memory::allocate(sizeof(T) * sz));
|
||||
|
|
131
src/util/mpf.cpp
131
src/util/mpf.cpp
|
@ -190,47 +190,9 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, float value) {
|
|||
|
||||
void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpq const & value) {
|
||||
TRACE("mpf_dbg", tout << "set: " << m_mpq_manager.to_string(value) << " [" << ebits << "/" << sbits << "]"<< std::endl;);
|
||||
|
||||
if (m_mpq_manager.is_zero(value))
|
||||
mk_pzero(ebits, sbits, o);
|
||||
else {
|
||||
o.ebits = ebits;
|
||||
o.sbits = sbits;
|
||||
o.sign = m_mpq_manager.is_neg(value);
|
||||
|
||||
m_mpz_manager.set(o.significand, 0);
|
||||
const mpz & p = m_powers2(sbits+2);
|
||||
signed lz = 0;
|
||||
|
||||
o.exponent = sbits+2;
|
||||
|
||||
// CMW: This could be optimized considerably.
|
||||
scoped_mpz t(m_mpz_manager);
|
||||
retry:
|
||||
m_mpz_manager.mul2k(value.numerator(), lz, t);
|
||||
m_mpz_manager.machine_div(t, value.denominator(), o.significand);
|
||||
m_mpz_manager.abs(o.significand);
|
||||
if (m_mpz_manager.lt(o.significand, p)) {
|
||||
lz++;
|
||||
goto retry;
|
||||
}
|
||||
o.exponent -= lz;
|
||||
|
||||
bool sticky = false;
|
||||
while (m_mpz_manager.ge(o.significand, m_powers2(sbits+3))) {
|
||||
sticky = sticky || !m_mpz_manager.is_even(o.significand);
|
||||
m_mpz_manager.machine_div2k(o.significand, 1);
|
||||
o.exponent++;
|
||||
}
|
||||
if (sticky && m_mpz_manager.is_even(o.significand))
|
||||
m_mpz_manager.inc(o.significand);
|
||||
|
||||
TRACE("mpf_dbg", tout << "QUOTIENT = " << m_mpz_manager.to_string(o.significand) << " shift=" << lz << std::endl;);
|
||||
|
||||
SASSERT(m_mpz_manager.ge(o.significand, m_powers2(sbits+2)));
|
||||
round(rm, o);
|
||||
}
|
||||
|
||||
scoped_mpz exp(m_mpz_manager);
|
||||
m_mpz_manager.set(exp, 0);
|
||||
set(o, ebits, sbits, rm, value, exp);
|
||||
TRACE("mpf_dbg", tout << "set: res = " << to_string(o) << std::endl;);
|
||||
}
|
||||
|
||||
|
@ -253,7 +215,6 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode
|
|||
|
||||
TRACE("mpf_dbg", tout << " f = " << f << " e = " << e << std::endl;);
|
||||
|
||||
// [Leo]: potential memory leak. moving q and ex to scoped versions
|
||||
scoped_mpq q(m_mpq_manager);
|
||||
m_mpq_manager.set(q, f.c_str());
|
||||
|
||||
|
@ -276,9 +237,6 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode
|
|||
if (m_mpq_manager.is_zero(significand))
|
||||
mk_zero(ebits, sbits, o.sign, o);
|
||||
else {
|
||||
// [Leo]: The following two lines may produce a memory leak. Moving to scoped version
|
||||
// mpq sig;
|
||||
// mpz exp;
|
||||
scoped_mpq sig(m_mpq_manager);
|
||||
scoped_mpz exp(m_mpq_manager);
|
||||
|
||||
|
@ -296,34 +254,42 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode
|
|||
m_mpq_manager.mul(sig, 2, sig);
|
||||
m_mpz_manager.dec(exp);
|
||||
}
|
||||
|
||||
|
||||
// 1.0 <= sig < 2.0
|
||||
SASSERT((m_mpq_manager.le(1, sig) && m_mpq_manager.lt(sig, 2)));
|
||||
|
||||
TRACE("mpf_dbg", tout << "sig = " << m_mpq_manager.to_string(sig) << " exp = " << m_mpz_manager.to_string(exp) << std::endl;);
|
||||
|
||||
TRACE("mpf_dbg", tout << "sig = " << m_mpq_manager.to_string(sig) <<
|
||||
" exp = " << m_mpz_manager.to_string(exp) << std::endl;);
|
||||
|
||||
m_mpz_manager.set(o.significand, 0);
|
||||
for (unsigned i = 0; i < (sbits+3); i++) {
|
||||
m_mpz_manager.mul2k(o.significand, 1);
|
||||
if (!m_mpq_manager.lt(sig, 1)) {
|
||||
m_mpz_manager.inc(o.significand);
|
||||
if (m_mpq_manager.ge(sig, 1)) {
|
||||
m_mpz_manager.inc(o.significand);
|
||||
m_mpq_manager.dec(sig);
|
||||
}
|
||||
m_mpq_manager.mul(sig, 2, sig);
|
||||
m_mpq_manager.mul(sig, mpq(2), sig);
|
||||
}
|
||||
|
||||
// sticky
|
||||
if (!m_mpq_manager.is_zero(sig) && m_mpz_manager.is_even(o.significand))
|
||||
m_mpz_manager.inc(o.significand);
|
||||
|
||||
TRACE("mpf_dbg", tout << "sig = " << m_mpz_manager.to_string(o.significand) <<
|
||||
" exp = " << o.exponent << std::endl;);
|
||||
|
||||
if (m_mpz_manager.is_small(exp)) {
|
||||
o.exponent = m_mpz_manager.get_int64(exp);
|
||||
round(rm, o);
|
||||
}
|
||||
else
|
||||
mk_inf(ebits, sbits, o.sign, o); // CMW: output warning message? throw exception?
|
||||
mk_inf(ebits, sbits, o.sign, o);
|
||||
}
|
||||
|
||||
TRACE("mpf_dbg", tout << "set: res = " << to_string(o) << std::endl;);
|
||||
}
|
||||
|
||||
void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, bool sign, uint64 significand, int exponent) {
|
||||
void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, bool sign, uint64 significand, mpf_exp_t exponent) {
|
||||
// Assumption: this represents (sign * -1) * (significand/2^sbits) * 2^exponent.
|
||||
o.ebits = ebits;
|
||||
o.sbits = sbits;
|
||||
|
@ -1082,6 +1048,45 @@ void mpf_manager::to_mpz(mpf const & x, unsynch_mpz_manager & zm, mpz & o) {
|
|||
zm.mul2k(o, e);
|
||||
}
|
||||
|
||||
void mpf_manager::to_sbv_mpq(mpf_rounding_mode rm, const mpf & x, scoped_mpq & o) {
|
||||
SASSERT(!is_nan(x) && !is_inf(x));
|
||||
|
||||
scoped_mpf t(*this);
|
||||
scoped_mpz z(m_mpz_manager);
|
||||
|
||||
set(t, x);
|
||||
unpack(t, true);
|
||||
|
||||
SASSERT(t.exponent() < INT_MAX);
|
||||
|
||||
m_mpz_manager.set(z, t.significand());
|
||||
mpf_exp_t e = (mpf_exp_t)t.exponent() - t.sbits() + 1;
|
||||
if (e < 0) {
|
||||
bool last = false, round = false, sticky = m_mpz_manager.is_odd(z);
|
||||
for (; e != 0; e++) {
|
||||
m_mpz_manager.machine_div2k(z, 1);
|
||||
sticky |= round;
|
||||
round = last;
|
||||
last = m_mpz_manager.is_odd(z);
|
||||
}
|
||||
bool inc = false;
|
||||
switch (rm) {
|
||||
case MPF_ROUND_NEAREST_TEVEN: inc = round && (last || sticky); break;
|
||||
case MPF_ROUND_NEAREST_TAWAY: inc = round && (!last || sticky); break; // CMW: Check!
|
||||
case MPF_ROUND_TOWARD_POSITIVE: inc = (!x.sign && (round || sticky)); break;
|
||||
case MPF_ROUND_TOWARD_NEGATIVE: inc = (x.sign && (round || sticky)); break;
|
||||
case MPF_ROUND_TOWARD_ZERO: inc = false; break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
if (inc) m_mpz_manager.inc(z);
|
||||
}
|
||||
else
|
||||
m_mpz_manager.mul2k(z, (unsigned) e);
|
||||
|
||||
m_mpq_manager.set(o, z);
|
||||
if (x.sign) m_mpq_manager.neg(o);
|
||||
}
|
||||
|
||||
void mpf_manager::rem(mpf const & x, mpf const & y, mpf & o) {
|
||||
SASSERT(x.sbits == y.sbits && x.ebits == y.ebits);
|
||||
|
||||
|
@ -1168,14 +1173,13 @@ std::string mpf_manager::to_string(mpf const & x) {
|
|||
|
||||
if (is_nan(x))
|
||||
res = "NaN";
|
||||
else {
|
||||
res = sgn(x) ? "-" : "+";
|
||||
|
||||
else {
|
||||
if (is_inf(x))
|
||||
res += "INF";
|
||||
res = sgn(x) ? "-oo" : "+oo";
|
||||
else if (is_zero(x))
|
||||
res += "0";
|
||||
res = sgn(x) ? "-zero" : "+zero";
|
||||
else {
|
||||
res = sgn(x) ? "-" : "";
|
||||
scoped_mpz num(m_mpq_manager), denom(m_mpq_manager);
|
||||
num = 0;
|
||||
denom = 1;
|
||||
|
@ -1203,7 +1207,9 @@ std::string mpf_manager::to_string(mpf const & x) {
|
|||
|
||||
std::stringstream ss;
|
||||
m_mpq_manager.display_decimal(ss, r, x.sbits);
|
||||
ss << "p" << exponent; // "p" means 2^exp
|
||||
if (m_mpq_manager.is_int(r))
|
||||
ss << ".0";
|
||||
ss << " " << exponent;
|
||||
res += ss.str();
|
||||
}
|
||||
}
|
||||
|
@ -1344,11 +1350,11 @@ bool mpf_manager::is_ninf(mpf const & x) {
|
|||
}
|
||||
|
||||
bool mpf_manager::is_normal(mpf const & x) {
|
||||
return !has_bot_exp(x) && !has_top_exp(x);
|
||||
return !(has_top_exp(x) || is_denormal(x));
|
||||
}
|
||||
|
||||
bool mpf_manager::is_denormal(mpf const & x) {
|
||||
return has_bot_exp(x);
|
||||
return !is_zero(x) && has_bot_exp(x);
|
||||
}
|
||||
|
||||
bool mpf_manager::is_int(mpf const & x) {
|
||||
|
@ -1645,7 +1651,8 @@ void mpf_manager::round(mpf_rounding_mode rm, mpf & o) {
|
|||
bool inc = false;
|
||||
switch (rm) {
|
||||
case MPF_ROUND_NEAREST_TEVEN: inc = round && (last || sticky); break;
|
||||
case MPF_ROUND_NEAREST_TAWAY: inc = round; break; // CMW: Check this.
|
||||
// case MPF_ROUND_NEAREST_TAWAY: inc = round; break; // CMW: Check
|
||||
case MPF_ROUND_NEAREST_TAWAY: inc = round && (!last || sticky); break; // CMW: Fix ok?
|
||||
case MPF_ROUND_TOWARD_POSITIVE: inc = (!o.sign && (round || sticky)); break;
|
||||
case MPF_ROUND_TOWARD_NEGATIVE: inc = (o.sign && (round || sticky)); break;
|
||||
case MPF_ROUND_TOWARD_ZERO: inc = false; break;
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpq const & value);
|
||||
void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, char const * value);
|
||||
void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpq const & significand, mpz const & exponent);
|
||||
void set(mpf & o, unsigned ebits, unsigned sbits, bool sign, uint64 significand, int exponent);
|
||||
void set(mpf & o, unsigned ebits, unsigned sbits, bool sign, uint64 significand, mpf_exp_t exponent);
|
||||
void set(mpf & o, unsigned ebits, unsigned sbits, bool sign, mpz const & significand, mpf_exp_t exponent);
|
||||
void set(mpf & o, mpf const & x);
|
||||
void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpf const & x);
|
||||
|
@ -146,7 +146,22 @@ public:
|
|||
|
||||
bool sgn(mpf const & x) const { return x.sign; }
|
||||
const mpz & sig(mpf const & x) const { return x.significand; }
|
||||
void sig_normalized(mpf const & x, mpz & res) {
|
||||
mpf t;
|
||||
set(t, x);
|
||||
unpack(t, true);
|
||||
mpz_manager().set(res, t.significand);
|
||||
del(t);
|
||||
}
|
||||
const mpf_exp_t & exp(mpf const & x) const { return x.exponent; }
|
||||
mpf_exp_t exp_normalized(mpf const & x) {
|
||||
mpf t;
|
||||
set(t, x);
|
||||
unpack(t, true);
|
||||
mpf_exp_t r = t.exponent;
|
||||
del(t);
|
||||
return r;
|
||||
}
|
||||
|
||||
bool is_nan(mpf const & x);
|
||||
bool is_inf(mpf const & x);
|
||||
|
@ -191,6 +206,8 @@ public:
|
|||
*/
|
||||
unsigned prev_power_of_two(mpf const & a);
|
||||
|
||||
void to_sbv_mpq(mpf_rounding_mode rm, const mpf & x, scoped_mpq & o);
|
||||
|
||||
protected:
|
||||
bool has_bot_exp(mpf const & x);
|
||||
bool has_top_exp(mpf const & x);
|
||||
|
@ -203,8 +220,8 @@ protected:
|
|||
void mk_round_inf(mpf_rounding_mode rm, mpf & o);
|
||||
|
||||
// Convert x into a mpz numeral. zm is the manager that owns o.
|
||||
void to_mpz(mpf const & x, unsynch_mpz_manager & zm, mpz & o);
|
||||
void to_mpz(mpf const & x, scoped_mpz & o) { to_mpz(x, o.m(), o); }
|
||||
void to_mpz(mpf const & x, unsynch_mpz_manager & zm, mpz & o);
|
||||
void to_mpz(mpf const & x, scoped_mpz & o) { to_mpz(x, o.m(), o); }
|
||||
|
||||
class powers2 {
|
||||
unsynch_mpz_manager & m;
|
||||
|
|
|
@ -700,7 +700,7 @@ void mpff_manager::add_sub(bool is_sub, mpff const & a, mpff const & b, mpff & c
|
|||
c.m_sign = sgn_a;
|
||||
unsigned * sig_r = m_buffers[1].c_ptr();
|
||||
size_t r_sz;
|
||||
add_full(sig_a, m_precision, n_sig_b, m_precision, sig_r, m_precision + 1, &r_sz, 0);
|
||||
m_mpn_manager.add(sig_a, m_precision, n_sig_b, m_precision, sig_r, m_precision + 1, &r_sz);
|
||||
SASSERT(r_sz <= m_precision + 1);
|
||||
unsigned num_leading_zeros = nlz(m_precision + 1, sig_r);
|
||||
SASSERT(num_leading_zeros >= sizeof(unsigned) * 8 - 1); // num_leading_zeros >= 31
|
||||
|
@ -740,11 +740,11 @@ void mpff_manager::add_sub(bool is_sub, mpff const & a, mpff const & b, mpff & c
|
|||
unsigned * sig_c = sig(c);
|
||||
if (::lt(m_precision, sig_a, n_sig_b)) {
|
||||
c.m_sign = sgn_b;
|
||||
sub_diff(n_sig_b, m_precision, sig_a, m_precision, sig_c, &borrow, 0);
|
||||
m_mpn_manager.sub(n_sig_b, m_precision, sig_a, m_precision, sig_c, &borrow);
|
||||
}
|
||||
else {
|
||||
c.m_sign = sgn_a;
|
||||
sub_diff(sig_a, m_precision, n_sig_b, m_precision, sig_c, &borrow, 0);
|
||||
m_mpn_manager.sub(sig_a, m_precision, n_sig_b, m_precision, sig_c, &borrow);
|
||||
}
|
||||
SASSERT(borrow == 0);
|
||||
unsigned num_leading_zeros = nlz(m_precision, sig_c);
|
||||
|
@ -793,7 +793,7 @@ void mpff_manager::mul(mpff const & a, mpff const & b, mpff & c) {
|
|||
int64 exp_c = exp_a + exp_b;
|
||||
// store result in m_buffers[0]
|
||||
unsigned * r = m_buffers[0].c_ptr();
|
||||
multiply(sig(a), m_precision, sig(b), m_precision, r, 0);
|
||||
m_mpn_manager.mul(sig(a), m_precision, sig(b), m_precision, r);
|
||||
// r has 2*m_precision_bits bits
|
||||
unsigned num_leading_zeros = nlz(m_precision*2, r);
|
||||
SASSERT(num_leading_zeros <= m_precision_bits);
|
||||
|
@ -864,12 +864,10 @@ void mpff_manager::div(mpff const & a, mpff const & b, mpff & c) {
|
|||
// a is at least 2^(2*m_precision_bits - 1)
|
||||
// Thus the quotient of a/b cannot be zero
|
||||
// Actually, quotient of a/b must be >= 2^(2*m_precision_bits - 1)/(2^m_precision_bits - 1)
|
||||
divide(_a, 2*m_precision,
|
||||
sig(b), m_precision,
|
||||
reciprocal_1_NULL,
|
||||
q,
|
||||
r,
|
||||
0);
|
||||
m_mpn_manager.div(_a, 2 * m_precision,
|
||||
sig(b), m_precision,
|
||||
q,
|
||||
r);
|
||||
TRACE("mpff_div",
|
||||
unsigned j = q_sz;
|
||||
while (j > 0) { --j; tout << std::hex << std::setfill('0') << std::setw(2*sizeof(unsigned)) << q[j]; tout << " "; }
|
||||
|
@ -1193,7 +1191,7 @@ void mpff_manager::display(std::ostream & out, mpff const & n) const {
|
|||
if (shift > 0)
|
||||
shr(m_precision, u_buffer.c_ptr(), shift, u_buffer.c_ptr());
|
||||
sbuffer<char, 1024> str_buffer(11*m_precision, 0);
|
||||
out << mp_decimal(u_buffer.c_ptr(), m_precision, str_buffer.begin(), str_buffer.size(), 0);
|
||||
out << m_mpn_manager.to_string(u_buffer.c_ptr(), m_precision, str_buffer.begin(), str_buffer.size());
|
||||
if (exp > 0) {
|
||||
if (exp <= 63) {
|
||||
uint64 _exp = 1;
|
||||
|
@ -1225,7 +1223,7 @@ void mpff_manager::display(std::ostream & out, mpff const & n) const {
|
|||
}
|
||||
}
|
||||
|
||||
void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned prec, unsigned min_exponent) const {
|
||||
void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned prec, unsigned min_exponent) {
|
||||
// The result in scientific notation when n.m_exponent >= min_exponent or n.m_exponent <= - min_exponent - m_precision_bits
|
||||
int64 exp = n.m_exponent;
|
||||
if (exp >= min_exponent || exp <= -static_cast<int64>(min_exponent) - m_precision_bits || is_int(n)) {
|
||||
|
@ -1246,7 +1244,7 @@ void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned
|
|||
buffer.push_back(s[i]);
|
||||
shr(buffer.size(), buffer.c_ptr(), shift, buffer.size(), buffer.c_ptr());
|
||||
sbuffer<char, 1024> str_buffer(11*buffer.size(), 0);
|
||||
out << mp_decimal(buffer.c_ptr(), buffer.size(), str_buffer.begin(), str_buffer.size(), 0);
|
||||
out << m_mpn_manager.to_string(buffer.c_ptr(), buffer.size(), str_buffer.begin(), str_buffer.size());
|
||||
}
|
||||
else {
|
||||
sbuffer<unsigned, 1024> buffer1, buffer2;
|
||||
|
@ -1274,14 +1272,12 @@ void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned
|
|||
out << "0";
|
||||
}
|
||||
else {
|
||||
divide(buffer1.c_ptr(), m_precision,
|
||||
pw_buffer.c_ptr(), num_words,
|
||||
reciprocal_1_NULL,
|
||||
buffer3.c_ptr(),
|
||||
buffer2.c_ptr(),
|
||||
0);
|
||||
m_mpn_manager.div(buffer1.c_ptr(), m_precision,
|
||||
pw_buffer.c_ptr(), num_words,
|
||||
buffer3.c_ptr(),
|
||||
buffer2.c_ptr());
|
||||
sbuffer<char, 1024> str_buffer(11*buffer3.size(), 0);
|
||||
out << mp_decimal(buffer3.c_ptr(), buffer3.size(), str_buffer.begin(), str_buffer.size(), 0);
|
||||
out << m_mpn_manager.to_string(buffer3.c_ptr(), buffer3.size(), str_buffer.begin(), str_buffer.size());
|
||||
SASSERT(!::is_zero(buffer2.size(), buffer2.c_ptr())); // otherwise n is an integer
|
||||
::copy(buffer2.size(), buffer2.c_ptr(), buffer1.size(), buffer1.c_ptr());
|
||||
}
|
||||
|
@ -1298,7 +1294,7 @@ void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned
|
|||
return;
|
||||
}
|
||||
i = i + 1;
|
||||
multiply(buffer1.c_ptr(), sz1, &ten, 1, buffer2.c_ptr(), 0);
|
||||
m_mpn_manager.mul(buffer1.c_ptr(), sz1, &ten, 1, buffer2.c_ptr());
|
||||
unsigned sz2 = sz1 + 1;
|
||||
while (sz2 > 0 && buffer2[sz2-1] == 0)
|
||||
--sz2;
|
||||
|
@ -1310,12 +1306,10 @@ void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned
|
|||
SASSERT(sz1 == 0 || !::is_zero(sz1, buffer1.c_ptr()));
|
||||
}
|
||||
else {
|
||||
divide(buffer2.c_ptr(), sz2,
|
||||
pw_buffer.c_ptr(), num_words,
|
||||
reciprocal_1_NULL,
|
||||
buffer3.c_ptr(),
|
||||
buffer1.c_ptr(),
|
||||
0);
|
||||
m_mpn_manager.div(buffer2.c_ptr(), sz2,
|
||||
pw_buffer.c_ptr(), num_words,
|
||||
buffer3.c_ptr(),
|
||||
buffer1.c_ptr());
|
||||
out << buffer3[0];
|
||||
sz1 = num_words;
|
||||
while (sz1 > 0 && buffer1[sz1-1] == 0)
|
||||
|
@ -1353,7 +1347,7 @@ void mpff_manager::display_smt2(std::ostream & out, mpff const & n, bool decimal
|
|||
out << "(/ ";
|
||||
|
||||
sbuffer<char, 1024> str_buffer(11*m_precision, 0);
|
||||
out << mp_decimal(u_buffer.c_ptr(), m_precision, str_buffer.begin(), str_buffer.size(), 0);
|
||||
out << m_mpn_manager.to_string(u_buffer.c_ptr(), m_precision, str_buffer.begin(), str_buffer.size());
|
||||
if (decimal) out << ".0";
|
||||
|
||||
if (exp != 0) {
|
||||
|
|
|
@ -29,6 +29,7 @@ Revision History:
|
|||
#include"z3_exception.h"
|
||||
#include"scoped_numeral.h"
|
||||
#include"scoped_numeral_vector.h"
|
||||
#include"mpn.h"
|
||||
|
||||
class mpff_manager;
|
||||
|
||||
|
@ -115,6 +116,7 @@ class mpff_manager {
|
|||
svector<unsigned> m_buffers[MPFF_NUM_BUFFERS];
|
||||
svector<unsigned> m_set_buffer;
|
||||
mpff m_one;
|
||||
mpn_manager m_mpn_manager;
|
||||
|
||||
unsigned * sig(mpff const & n) const { return m_significands.c_ptr() + (n.m_sig_idx * m_precision); }
|
||||
|
||||
|
@ -465,7 +467,7 @@ public:
|
|||
void display_raw(std::ostream & out, mpff const & n) const;
|
||||
void display(std::ostream & out, mpff const & n) const;
|
||||
void display_pp(std::ostream & out, mpff const & n) const { display(out, n); }
|
||||
void display_decimal(std::ostream & out, mpff const & n, unsigned prec=32, unsigned max_power=128) const;
|
||||
void display_decimal(std::ostream & out, mpff const & n, unsigned prec=32, unsigned max_power=128);
|
||||
void display_smt2(std::ostream & out, mpff const & n, bool decimal=true) const;
|
||||
|
||||
std::string to_string(mpff const & a) const;
|
||||
|
|
|
@ -387,12 +387,12 @@ void mpfx_manager::add_sub(bool is_sub, mpfx const & a, mpfx const & b, mpfx & c
|
|||
SASSERT(sgn_a != sgn_b);
|
||||
if (::lt(m_total_sz, w_a, w_b)) {
|
||||
c.m_sign = sgn_b;
|
||||
sub_diff(w_b, m_total_sz, w_a, m_total_sz, w_c, &borrow, 0);
|
||||
m_mpn_manager.sub(w_b, m_total_sz, w_a, m_total_sz, w_c, &borrow);
|
||||
SASSERT(!::is_zero(m_total_sz, w_c));
|
||||
}
|
||||
else {
|
||||
c.m_sign = sgn_a;
|
||||
sub_diff(w_a, m_total_sz, w_b, m_total_sz, w_c, &borrow, 0);
|
||||
m_mpn_manager.sub(w_a, m_total_sz, w_b, m_total_sz, w_c, &borrow);
|
||||
if (::is_zero(m_total_sz, w_c))
|
||||
reset(c);
|
||||
}
|
||||
|
@ -423,7 +423,7 @@ void mpfx_manager::mul(mpfx const & a, mpfx const & b, mpfx & c) {
|
|||
allocate_if_needed(c);
|
||||
c.m_sign = a.m_sign ^ b.m_sign;
|
||||
unsigned * r = m_buffer0.c_ptr();
|
||||
multiply(words(a), m_total_sz, words(b), m_total_sz, r, 0);
|
||||
m_mpn_manager.mul(words(a), m_total_sz, words(b), m_total_sz, r);
|
||||
// round result
|
||||
unsigned * _r = r + m_frac_part_sz;
|
||||
if ((c.m_sign == 1) != m_to_plus_inf && !::is_zero(m_frac_part_sz, r)) {
|
||||
|
@ -473,12 +473,10 @@ void mpfx_manager::div(mpfx const & a, mpfx const & b, mpfx & c) {
|
|||
unsigned q_sz = a_shft_sz - b_sz + 1;
|
||||
unsigned * w_r = m_buffer2.c_ptr();
|
||||
unsigned r_sz = b_sz;
|
||||
divide(w_a_shft, a_shft_sz,
|
||||
w_b, b_sz,
|
||||
reciprocal_1_NULL,
|
||||
w_q,
|
||||
w_r,
|
||||
0);
|
||||
m_mpn_manager.div(w_a_shft, a_shft_sz,
|
||||
w_b, b_sz,
|
||||
w_q,
|
||||
w_r);
|
||||
for (unsigned i = m_total_sz; i < q_sz; i++)
|
||||
if (w_q[i] != 0)
|
||||
throw overflow_exception();
|
||||
|
@ -769,7 +767,7 @@ void mpfx_manager::display(std::ostream & out, mpfx const & n) const {
|
|||
}
|
||||
|
||||
sbuffer<char, 1024> str_buffer(11*sz, 0);
|
||||
out << mp_decimal(w, sz, str_buffer.begin(), str_buffer.size(), 0);
|
||||
out << m_mpn_manager.to_string(w, sz, str_buffer.begin(), str_buffer.size());
|
||||
if (!is_int(n)) {
|
||||
SASSERT(shift != UINT_MAX);
|
||||
// reverse effect of shr
|
||||
|
@ -796,7 +794,7 @@ void mpfx_manager::display_smt2(std::ostream & out, mpfx const & n) const {
|
|||
out << "(/ ";
|
||||
}
|
||||
sbuffer<char, 1024> str_buffer(11*sz, 0);
|
||||
out << mp_decimal(w, sz, str_buffer.begin(), str_buffer.size(), 0);
|
||||
out << m_mpn_manager.to_string(w, sz, str_buffer.begin(), str_buffer.size());
|
||||
if (!is_int(n)) {
|
||||
out << " ";
|
||||
unsigned * w = m_buffer0.c_ptr();
|
||||
|
@ -804,7 +802,7 @@ void mpfx_manager::display_smt2(std::ostream & out, mpfx const & n) const {
|
|||
w[i] = 0;
|
||||
w[m_frac_part_sz] = 1;
|
||||
sbuffer<char, 1024> str_buffer2(11*(m_frac_part_sz+1), 0);
|
||||
out << mp_decimal(w, m_frac_part_sz+1, str_buffer2.begin(), str_buffer2.size(), 0);
|
||||
out << m_mpn_manager.to_string(w, m_frac_part_sz + 1, str_buffer2.begin(), str_buffer2.size());
|
||||
out << ")";
|
||||
}
|
||||
if (is_neg(n))
|
||||
|
@ -816,7 +814,7 @@ void mpfx_manager::display_decimal(std::ostream & out, mpfx const & n, unsigned
|
|||
out << "-";
|
||||
unsigned * w = words(n);
|
||||
sbuffer<char, 1024> str_buffer(11*m_int_part_sz, 0);
|
||||
out << mp_decimal(w + m_frac_part_sz, m_int_part_sz, str_buffer.begin(), str_buffer.size(), 0);
|
||||
out << m_mpn_manager.to_string(w + m_frac_part_sz, m_int_part_sz, str_buffer.begin(), str_buffer.size());
|
||||
if (!is_int(n)) {
|
||||
out << ".";
|
||||
unsigned * frac = m_buffer0.c_ptr();
|
||||
|
@ -830,7 +828,7 @@ void mpfx_manager::display_decimal(std::ostream & out, mpfx const & n, unsigned
|
|||
out << "?";
|
||||
return;
|
||||
}
|
||||
multiply(frac, m_frac_part_sz, &ten, 1, n_frac, 0);
|
||||
m_mpn_manager.mul(frac, m_frac_part_sz, &ten, 1, n_frac);
|
||||
frac_is_zero = ::is_zero(m_frac_part_sz, n_frac);
|
||||
SASSERT(n_frac[m_frac_part_sz] <= 9);
|
||||
if (!frac_is_zero || n_frac[m_frac_part_sz] != 0)
|
||||
|
|
|
@ -25,6 +25,7 @@ Revision History:
|
|||
#include"z3_exception.h"
|
||||
#include"scoped_numeral.h"
|
||||
#include"scoped_numeral_vector.h"
|
||||
#include"mpn.h"
|
||||
|
||||
class mpfx_manager;
|
||||
|
||||
|
@ -83,6 +84,7 @@ class mpfx_manager {
|
|||
unsigned_vector m_buffer0, m_buffer1, m_buffer2;
|
||||
unsigned_vector m_tmp_digits;
|
||||
mpfx m_one;
|
||||
mpn_manager m_mpn_manager;
|
||||
|
||||
unsigned * words(mpfx const & n) const { return m_words.c_ptr() + (n.m_sig_idx * m_total_sz); }
|
||||
unsigned sz(unsigned * ws) const;
|
||||
|
|
107
src/util/mpn.cpp
107
src/util/mpn.cpp
|
@ -26,28 +26,20 @@ Revision History:
|
|||
typedef uint64 mpn_double_digit;
|
||||
COMPILE_TIME_ASSERT(sizeof(mpn_double_digit) == 2 * sizeof(mpn_digit));
|
||||
|
||||
mpn_manager static_mpn_manager;
|
||||
|
||||
const mpn_digit mpn_manager::zero = 0;
|
||||
|
||||
mpn_manager::mpn_manager() {
|
||||
#ifdef Z3DEBUG
|
||||
trace_enabled=true;
|
||||
#endif
|
||||
omp_init_nest_lock(&m_lock);
|
||||
}
|
||||
|
||||
mpn_manager::~mpn_manager() {
|
||||
omp_destroy_nest_lock(&m_lock);
|
||||
}
|
||||
|
||||
int mpn_manager::compare(mpn_digit const * a, size_t const lnga,
|
||||
mpn_digit const * b, size_t const lngb) const {
|
||||
int res = 0;
|
||||
|
||||
#ifdef Z3DEBUG
|
||||
if (trace_enabled)
|
||||
STRACE("mpn", tout << "[mpn] "; );
|
||||
#endif
|
||||
|
||||
trace(a, lnga);
|
||||
|
||||
size_t j = max(lnga, lngb) - 1;
|
||||
|
@ -60,10 +52,7 @@ int mpn_manager::compare(mpn_digit const * a, size_t const lnga,
|
|||
res = -1;
|
||||
}
|
||||
|
||||
#ifdef Z3DEBUG
|
||||
if (trace_enabled)
|
||||
STRACE("mpn", tout << ((res == 1) ? " > " : (res == -1) ? " < " : " == "); );
|
||||
#endif
|
||||
TRACE("mpn", tout << ((res == 1) ? " > " : (res == -1) ? " < " : " == "); );
|
||||
|
||||
trace_nl(b, lngb);
|
||||
return res;
|
||||
|
@ -92,7 +81,7 @@ bool mpn_manager::add(mpn_digit const * a, size_t const lnga,
|
|||
for (os = len+1; os > 1 && c[os-1] == 0; ) os--;
|
||||
SASSERT(os > 0 && os <= len+1);
|
||||
trace_nl(c, os);
|
||||
return true; // return k != 0? What would MSBignum return?
|
||||
return true; // return k != 0?
|
||||
}
|
||||
|
||||
bool mpn_manager::sub(mpn_digit const * a, size_t const lnga,
|
||||
|
@ -164,6 +153,7 @@ bool mpn_manager::div(mpn_digit const * numer, size_t const lnum,
|
|||
mpn_digit const * denom, size_t const lden,
|
||||
mpn_digit * quot,
|
||||
mpn_digit * rem) {
|
||||
MPN_BEGIN_CRITICAL();
|
||||
trace(numer, lnum, denom, lden, "/");
|
||||
bool res = false;
|
||||
|
||||
|
@ -172,6 +162,7 @@ bool mpn_manager::div(mpn_digit const * numer, size_t const lnum,
|
|||
quot[i] = 0;
|
||||
for (size_t i = 0; i < lden; i++)
|
||||
rem[i] = (i < lnum) ? numer[i] : 0;
|
||||
MPN_END_CRITICAL();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -180,8 +171,8 @@ bool mpn_manager::div(mpn_digit const * numer, size_t const lnum,
|
|||
if (denom[i] != zero) all_zero = false;
|
||||
|
||||
if (all_zero) {
|
||||
// Division by 0. What would the MSBignum divide function do?
|
||||
UNREACHABLE();
|
||||
MPN_END_CRITICAL();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -201,12 +192,12 @@ bool mpn_manager::div(mpn_digit const * numer, size_t const lnum,
|
|||
if (lden == 1)
|
||||
res = div_1(u, v[0], quot);
|
||||
else
|
||||
res = div_n(u, v, quot, rem);
|
||||
res = div_n(u, v, quot, rem, t_ms, t_ab);
|
||||
div_unnormalize(u, v, d, rem);
|
||||
}
|
||||
|
||||
// STRACE("mpn_dbg", display_raw(tout, quot, lnum - lden + 1); tout << ", ";
|
||||
// display_raw(tout, rem, lden); tout << std::endl; );
|
||||
// TRACE("mpn_dbg", display_raw(tout, quot, lnum - lden + 1); tout << ", ";
|
||||
// display_raw(tout, rem, lden); tout << std::endl; );
|
||||
trace_nl(quot, lnum-lden+1);
|
||||
|
||||
trace(numer, lnum, denom, lden, "%");
|
||||
|
@ -225,6 +216,7 @@ bool mpn_manager::div(mpn_digit const * numer, size_t const lnum,
|
|||
SASSERT(ok);
|
||||
#endif
|
||||
|
||||
MPN_END_CRITICAL();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -232,7 +224,7 @@ size_t mpn_manager::div_normalize(mpn_digit const * numer, size_t const lnum,
|
|||
mpn_digit const * denom, size_t const lden,
|
||||
mpn_sbuffer & n_numer,
|
||||
mpn_sbuffer & n_denom) const
|
||||
{
|
||||
{
|
||||
size_t d = 0;
|
||||
while (((denom[lden-1] << d) & MASK_FIRST) == 0) d++;
|
||||
SASSERT(d < DIGIT_BITS);
|
||||
|
@ -258,9 +250,8 @@ size_t mpn_manager::div_normalize(mpn_digit const * numer, size_t const lnum,
|
|||
n_denom[0] = denom[0] << d;
|
||||
}
|
||||
|
||||
STRACE("mpn_norm", tout << "Normalized: n_numer="; display_raw(tout, n_numer.c_ptr(), n_numer.size());
|
||||
tout << " n_denom="; display_raw(tout, n_denom.c_ptr(), n_denom.size()); tout << std::endl; );
|
||||
|
||||
TRACE("mpn_norm", tout << "Normalized: n_numer="; display_raw(tout, n_numer.c_ptr(), n_numer.size());
|
||||
tout << " n_denom="; display_raw(tout, n_denom.c_ptr(), n_denom.size()); tout << std::endl; );
|
||||
return d;
|
||||
}
|
||||
|
||||
|
@ -278,8 +269,7 @@ void mpn_manager::div_unnormalize(mpn_sbuffer & numer, mpn_sbuffer & denom,
|
|||
}
|
||||
|
||||
bool mpn_manager::div_1(mpn_sbuffer & numer, mpn_digit const denom,
|
||||
mpn_digit * quot) const
|
||||
{
|
||||
mpn_digit * quot) const {
|
||||
mpn_double_digit q_hat, temp, r_hat, ms;
|
||||
mpn_digit borrow;
|
||||
|
||||
|
@ -300,18 +290,19 @@ bool mpn_manager::div_1(mpn_sbuffer & numer, mpn_digit const denom,
|
|||
quot[j-1]--;
|
||||
numer[j] = numer[j-1] + denom;
|
||||
}
|
||||
STRACE("mpn_div1", tout << "j=" << j << " q_hat=" << q_hat << " r_hat=" << r_hat;
|
||||
tout << " ms=" << ms;
|
||||
tout << " new numer="; display_raw(tout, numer.c_ptr(), numer.size());
|
||||
tout << " borrow=" << borrow;
|
||||
tout << std::endl; );
|
||||
TRACE("mpn_div1", tout << "j=" << j << " q_hat=" << q_hat << " r_hat=" << r_hat;
|
||||
tout << " ms=" << ms;
|
||||
tout << " new numer="; display_raw(tout, numer.c_ptr(), numer.size());
|
||||
tout << " borrow=" << borrow;
|
||||
tout << std::endl; );
|
||||
}
|
||||
|
||||
return true; // return rem != 0 or something like that?
|
||||
return true; // return rem != 0?
|
||||
}
|
||||
|
||||
bool mpn_manager::div_n(mpn_sbuffer & numer, mpn_sbuffer const & denom,
|
||||
mpn_digit * quot, mpn_digit * rem) {
|
||||
mpn_digit * quot, mpn_digit * rem,
|
||||
mpn_sbuffer & ms, mpn_sbuffer & ab) const {
|
||||
SASSERT(denom.size() > 1);
|
||||
|
||||
// This is essentially Knuth's Algorithm D.
|
||||
|
@ -320,7 +311,7 @@ bool mpn_manager::div_n(mpn_sbuffer & numer, mpn_sbuffer const & denom,
|
|||
|
||||
SASSERT(numer.size() == m+n);
|
||||
|
||||
t_ms.resize(n+1);
|
||||
ms.resize(n+1);
|
||||
|
||||
mpn_double_digit q_hat, temp, r_hat;
|
||||
mpn_digit borrow;
|
||||
|
@ -340,36 +331,30 @@ bool mpn_manager::div_n(mpn_sbuffer & numer, mpn_sbuffer const & denom,
|
|||
// Replace numer[j+n]...numer[j] with
|
||||
// numer[j+n]...numer[j] - q * (denom[n-1]...denom[0])
|
||||
mpn_digit q_hat_small = (mpn_digit)q_hat;
|
||||
#ifdef Z3DEBUG
|
||||
trace_enabled = false;
|
||||
#endif
|
||||
mul(&q_hat_small, 1, denom.c_ptr(), n, t_ms.c_ptr());
|
||||
sub(&numer[j], n+1, t_ms.c_ptr(), n+1, &numer[j], &borrow);
|
||||
mul(&q_hat_small, 1, denom.c_ptr(), n, ms.c_ptr());
|
||||
sub(&numer[j], n+1, ms.c_ptr(), n+1, &numer[j], &borrow);
|
||||
quot[j] = q_hat_small;
|
||||
if (borrow) {
|
||||
quot[j]--;
|
||||
t_ab.resize(n+2);
|
||||
ab.resize(n+2);
|
||||
size_t real_size;
|
||||
add(denom.c_ptr(), n, &numer[j], n+1, t_ab.c_ptr(), n+2, &real_size);
|
||||
add(denom.c_ptr(), n, &numer[j], n+1, ab.c_ptr(), n+2, &real_size);
|
||||
for (size_t i = 0; i < n+1; i++)
|
||||
numer[j+i] = t_ab[i];
|
||||
numer[j+i] = ab[i];
|
||||
}
|
||||
#ifdef Z3DEBUG
|
||||
trace_enabled = true;
|
||||
#endif
|
||||
STRACE("mpn_div", tout << "q_hat=" << q_hat << " r_hat=" << r_hat;
|
||||
tout << " t_ms="; display_raw(tout, t_ms.c_ptr(), n);
|
||||
tout << " new numer="; display_raw(tout, numer.c_ptr(), m+n+1);
|
||||
tout << " borrow=" << borrow;
|
||||
tout << std::endl; );
|
||||
TRACE("mpn_div", tout << "q_hat=" << q_hat << " r_hat=" << r_hat;
|
||||
tout << " ms="; display_raw(tout, ms.c_ptr(), n);
|
||||
tout << " new numer="; display_raw(tout, numer.c_ptr(), m+n+1);
|
||||
tout << " borrow=" << borrow;
|
||||
tout << std::endl; );
|
||||
}
|
||||
|
||||
return true; // return rem != 0 or something like that?
|
||||
|
||||
return true; // return rem != 0?
|
||||
}
|
||||
|
||||
char * mpn_manager::to_string(mpn_digit const * a, size_t const lng, char * buf, size_t const lbuf) const {
|
||||
SASSERT(buf && lbuf > 0);
|
||||
STRACE("mpn_to_string", tout << "[mpn] to_string "; display_raw(tout, a, lng); tout << " == "; );
|
||||
TRACE("mpn_to_string", tout << "[mpn] to_string "; display_raw(tout, a, lng); tout << " == "; );
|
||||
|
||||
if (lng == 1) {
|
||||
#ifdef _WINDOWS
|
||||
|
@ -402,7 +387,7 @@ char * mpn_manager::to_string(mpn_digit const * a, size_t const lng, char * buf,
|
|||
std::swap(buf[i], buf[j-i]);
|
||||
}
|
||||
|
||||
STRACE("mpn_to_string", tout << buf << std::endl; );
|
||||
TRACE("mpn_to_string", tout << buf << std::endl; );
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -417,23 +402,23 @@ void mpn_manager::trace(mpn_digit const * a, size_t const lnga,
|
|||
mpn_digit const * b, size_t const lngb,
|
||||
const char * op) const {
|
||||
#ifdef Z3DEBUG
|
||||
if (trace_enabled)
|
||||
STRACE("mpn", tout << "[mpn] " << to_string(a, lnga, char_buf, sizeof(char_buf));
|
||||
tout << " " << op << " " << to_string(b, lngb, char_buf, sizeof(char_buf));
|
||||
tout << " == "; );
|
||||
char char_buf[4096];
|
||||
TRACE("mpn", tout << "[mpn] " << to_string(a, lnga, char_buf, sizeof(char_buf));
|
||||
tout << " " << op << " " << to_string(b, lngb, char_buf, sizeof(char_buf));
|
||||
tout << " == "; );
|
||||
#endif
|
||||
}
|
||||
|
||||
void mpn_manager::trace(mpn_digit const * a, size_t const lnga) const {
|
||||
#ifdef Z3DEBUG
|
||||
if (trace_enabled)
|
||||
STRACE("mpn", tout << to_string(a, lnga, char_buf, sizeof(char_buf)); );
|
||||
char char_buf[4096];
|
||||
TRACE("mpn", tout << to_string(a, lnga, char_buf, sizeof(char_buf)); );
|
||||
#endif
|
||||
}
|
||||
|
||||
void mpn_manager::trace_nl(mpn_digit const * a, size_t const lnga) const {
|
||||
#ifdef Z3DEBUG
|
||||
if (trace_enabled)
|
||||
STRACE("mpn", tout << to_string(a, lnga, char_buf, sizeof(char_buf)) << std::endl; );
|
||||
char char_buf[4096];
|
||||
TRACE("mpn", tout << to_string(a, lnga, char_buf, sizeof(char_buf)) << std::endl; );
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -22,13 +22,15 @@ Revision History:
|
|||
#include<ostream>
|
||||
#include"util.h"
|
||||
#include"buffer.h"
|
||||
|
||||
// we supply a definition of a basic max because mpz relies on it.
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#include"z3_omp.h"
|
||||
|
||||
typedef unsigned int mpn_digit;
|
||||
|
||||
class mpn_manager {
|
||||
omp_nest_lock_t m_lock;
|
||||
#define MPN_BEGIN_CRITICAL() omp_set_nest_lock(&m_lock);
|
||||
#define MPN_END_CRITICAL() omp_unset_nest_lock(&m_lock);
|
||||
|
||||
public:
|
||||
mpn_manager();
|
||||
~mpn_manager();
|
||||
|
@ -56,7 +58,6 @@ public:
|
|||
|
||||
char * to_string(mpn_digit const * a, size_t const lng,
|
||||
char * buf, size_t const lbuf) const;
|
||||
|
||||
private:
|
||||
#ifdef _AMD64_
|
||||
class mpn_sbuffer : public sbuffer<mpn_digit> {
|
||||
|
@ -99,12 +100,8 @@ private:
|
|||
mpn_digit * quot) const;
|
||||
|
||||
bool div_n(mpn_sbuffer & numer, mpn_sbuffer const & denom,
|
||||
mpn_digit * quot, mpn_digit * rem);
|
||||
|
||||
#ifdef Z3DEBUG
|
||||
mutable char char_buf[4096];
|
||||
bool trace_enabled;
|
||||
#endif
|
||||
mpn_digit * quot, mpn_digit * rem,
|
||||
mpn_sbuffer & ms, mpn_sbuffer & ab) const;
|
||||
|
||||
void trace(mpn_digit const * a, size_t const lnga,
|
||||
mpn_digit const * b, size_t const lngb,
|
||||
|
@ -112,85 +109,6 @@ private:
|
|||
|
||||
void trace(mpn_digit const * a, size_t const lnga) const;
|
||||
void trace_nl(mpn_digit const * a, size_t const lnga) const;
|
||||
|
||||
public:
|
||||
// This function is needed because of the static_mpn_manager global variable.
|
||||
// It must be invoked by the memory_manager during finalization.
|
||||
// After we remove MSBignum from the code base, the global variable will
|
||||
// not be needed anymore, and we will be able to eliminate this function.
|
||||
void finalize() {
|
||||
u.finalize();
|
||||
v.finalize();
|
||||
t_ms.finalize();
|
||||
t_ab.finalize();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// MSBignum compatible interface
|
||||
// Note: The `owner' parameter is ignored. We use separate mpn_manager objects for the
|
||||
// same purpose. Multiple owners are not supported in these compatibility functions,
|
||||
// instead a static mpn_manager is used.
|
||||
|
||||
extern mpn_manager static_mpn_manager;
|
||||
|
||||
typedef unsigned int digit_t;
|
||||
|
||||
typedef struct {
|
||||
mpn_digit multiplier;
|
||||
size_t shiftamt;
|
||||
} reciprocal_1_t;
|
||||
|
||||
#define reciprocal_1_NULL ((reciprocal_1_t*)0)
|
||||
|
||||
inline int compare_diff(digit_t const * a, size_t const lnga,
|
||||
digit_t const * b, size_t const lngb)
|
||||
{
|
||||
return static_mpn_manager.compare(a, lnga, b, lngb);
|
||||
}
|
||||
|
||||
inline char * mp_decimal(digit_t const * a, size_t const lng, // Number to be converted and its length
|
||||
char * buf, size_t const lbuf, // output buffer and its length
|
||||
int owner)
|
||||
{
|
||||
return static_mpn_manager.to_string(a, lng, buf, lbuf);
|
||||
}
|
||||
|
||||
inline bool add_full(digit_t const * a, size_t const lnga,
|
||||
digit_t const * b, size_t const lngb,
|
||||
digit_t *c, size_t const lngc_alloc,
|
||||
size_t * plngc,
|
||||
int owner)
|
||||
{
|
||||
return static_mpn_manager.add(a, lnga, b, lngb, c, lngc_alloc, plngc);
|
||||
}
|
||||
|
||||
inline bool sub_diff(digit_t const * a, size_t const lnga,
|
||||
digit_t const * b, size_t const lngb,
|
||||
digit_t * c, digit_t * pborrow,
|
||||
int owner)
|
||||
{
|
||||
return static_mpn_manager.sub(a, lnga, b, lngb, c, pborrow);
|
||||
}
|
||||
|
||||
inline bool multiply(digit_t const * a, size_t const lnga,
|
||||
digit_t const * b, size_t const lngb,
|
||||
digit_t * c,
|
||||
int owner)
|
||||
{
|
||||
return static_mpn_manager.mul(a, lnga, b, lngb, c);
|
||||
}
|
||||
|
||||
inline bool divide(digit_t const * numer, size_t const lnum,
|
||||
digit_t const * denom, size_t const lden,
|
||||
reciprocal_1_t const * supplied_reciprocal, /* reciprocal_t struct for this denominator,
|
||||
or reciprocal_1_NULL
|
||||
if not previously precomputed */
|
||||
digit_t * quot, /* Quotient -- length MAX(lnum - lden + 1, 0) */
|
||||
digit_t * rem, /* Remainder -- length lden */
|
||||
int owner)
|
||||
{
|
||||
return static_mpn_manager.div(numer, lnum, denom, lden, quot, rem);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,7 +37,7 @@ Revision History:
|
|||
// #define LS_BINARY_GCD
|
||||
// #define LEHMER_GCD
|
||||
|
||||
#if defined(_MP_GMP) || (defined(_MP_MSBIGNUM) && defined(_AMD64_))
|
||||
#if defined(_MP_GMP)
|
||||
// Use LEHMER only if not using GMP
|
||||
// LEHMER assumes 32-bit digits, so it cannot be used with MSBIGNUM library + 64-bit binary
|
||||
#define EUCLID_GCD
|
||||
|
@ -365,25 +365,18 @@ void mpz_manager<SYNCH>::big_add_sub(mpz const & a, mpz const & b, mpz & c) {
|
|||
sign_b = -sign_b;
|
||||
size_t real_sz;
|
||||
if (sign_a == sign_b) {
|
||||
unsigned sz = max(cell_a->m_size, cell_b->m_size)+1;
|
||||
unsigned sz = std::max(cell_a->m_size, cell_b->m_size)+1;
|
||||
ensure_tmp_capacity<0>(sz);
|
||||
add_full(cell_a->m_digits,
|
||||
cell_a->m_size,
|
||||
cell_b->m_digits,
|
||||
cell_b->m_size,
|
||||
m_tmp[0]->m_digits,
|
||||
sz,
|
||||
&real_sz,
|
||||
0);
|
||||
m_mpn_manager.add(cell_a->m_digits, cell_a->m_size,
|
||||
cell_b->m_digits, cell_b->m_size,
|
||||
m_tmp[0]->m_digits, sz, &real_sz);
|
||||
SASSERT(real_sz <= sz);
|
||||
set<0>(c, sign_a, static_cast<unsigned>(real_sz));
|
||||
}
|
||||
else {
|
||||
digit_t borrow;
|
||||
int r = compare_diff(cell_a->m_digits,
|
||||
cell_a->m_size,
|
||||
cell_b->m_digits,
|
||||
cell_b->m_size);
|
||||
int r = m_mpn_manager.compare(cell_a->m_digits, cell_a->m_size,
|
||||
cell_b->m_digits, cell_b->m_size);
|
||||
if (r == 0) {
|
||||
reset(c);
|
||||
}
|
||||
|
@ -391,13 +384,12 @@ void mpz_manager<SYNCH>::big_add_sub(mpz const & a, mpz const & b, mpz & c) {
|
|||
// a < b
|
||||
unsigned sz = cell_b->m_size;
|
||||
ensure_tmp_capacity<0>(sz);
|
||||
sub_diff(cell_b->m_digits,
|
||||
cell_b->m_size,
|
||||
cell_a->m_digits,
|
||||
cell_a->m_size,
|
||||
m_tmp[0]->m_digits,
|
||||
&borrow,
|
||||
0);
|
||||
m_mpn_manager.sub(cell_b->m_digits,
|
||||
cell_b->m_size,
|
||||
cell_a->m_digits,
|
||||
cell_a->m_size,
|
||||
m_tmp[0]->m_digits,
|
||||
&borrow);
|
||||
SASSERT(borrow == 0);
|
||||
set<0>(c, sign_b, sz);
|
||||
}
|
||||
|
@ -405,13 +397,12 @@ void mpz_manager<SYNCH>::big_add_sub(mpz const & a, mpz const & b, mpz & c) {
|
|||
// a > b
|
||||
unsigned sz = cell_a->m_size;
|
||||
ensure_tmp_capacity<0>(sz);
|
||||
sub_diff(cell_a->m_digits,
|
||||
cell_a->m_size,
|
||||
cell_b->m_digits,
|
||||
cell_b->m_size,
|
||||
m_tmp[0]->m_digits,
|
||||
&borrow,
|
||||
0);
|
||||
m_mpn_manager.sub(cell_a->m_digits,
|
||||
cell_a->m_size,
|
||||
cell_b->m_digits,
|
||||
cell_b->m_size,
|
||||
m_tmp[0]->m_digits,
|
||||
&borrow);
|
||||
SASSERT(borrow == 0);
|
||||
set<0>(c, sign_a, sz);
|
||||
}
|
||||
|
@ -460,12 +451,11 @@ void mpz_manager<SYNCH>::big_mul(mpz const & a, mpz const & b, mpz & c) {
|
|||
get_sign_cell<1>(b, sign_b, cell_b);
|
||||
unsigned sz = cell_a->m_size + cell_b->m_size;
|
||||
ensure_tmp_capacity<0>(sz);
|
||||
multiply(cell_a->m_digits,
|
||||
cell_a->m_size,
|
||||
cell_b->m_digits,
|
||||
cell_b->m_size,
|
||||
m_tmp[0]->m_digits,
|
||||
0);
|
||||
m_mpn_manager.mul(cell_a->m_digits,
|
||||
cell_a->m_size,
|
||||
cell_b->m_digits,
|
||||
cell_b->m_size,
|
||||
m_tmp[0]->m_digits);
|
||||
set<0>(c, sign_a == sign_b ? 1 : -1, sz);
|
||||
#else
|
||||
// GMP version
|
||||
|
@ -505,14 +495,10 @@ void mpz_manager<SYNCH>::quot_rem_core(mpz const & a, mpz const & b, mpz & q, mp
|
|||
unsigned r_sz = cell_b->m_size;
|
||||
ensure_tmp_capacity<0>(q_sz);
|
||||
ensure_tmp_capacity<1>(r_sz);
|
||||
divide(cell_a->m_digits,
|
||||
cell_a->m_size,
|
||||
cell_b->m_digits,
|
||||
cell_b->m_size,
|
||||
reciprocal_1_NULL,
|
||||
m_tmp[0]->m_digits,
|
||||
m_tmp[1]->m_digits,
|
||||
0);
|
||||
m_mpn_manager.div(cell_a->m_digits, cell_a->m_size,
|
||||
cell_b->m_digits, cell_b->m_size,
|
||||
m_tmp[0]->m_digits,
|
||||
m_tmp[1]->m_digits);
|
||||
if (MODE == QUOT_ONLY || MODE == QUOT_AND_REM)
|
||||
set<0>(q, sign_a == sign_b ? 1 : -1, q_sz);
|
||||
if (MODE == REM_ONLY || MODE == QUOT_AND_REM)
|
||||
|
@ -606,7 +592,7 @@ void mpz_manager<SYNCH>::gcd(mpz const & a, mpz const & b, mpz & c) {
|
|||
// Binary GCD for big numbers
|
||||
// - It doesn't use division
|
||||
// - The initial experiments, don't show any performance improvement
|
||||
// - It only works with _MP_INTERNAL and _MP_MSBIGNUM
|
||||
// - It only works with _MP_INTERNAL
|
||||
mpz u, v, diff;
|
||||
set(u, a);
|
||||
set(v, b);
|
||||
|
@ -1243,10 +1229,8 @@ int mpz_manager<SYNCH>::big_compare(mpz const & a, mpz const & b) {
|
|||
// a is positive
|
||||
if (sign_b > 0) {
|
||||
// a & b are positive
|
||||
return compare_diff(cell_a->m_digits,
|
||||
cell_a->m_size,
|
||||
cell_b->m_digits,
|
||||
cell_b->m_size);
|
||||
return m_mpn_manager.compare(cell_a->m_digits, cell_a->m_size,
|
||||
cell_b->m_digits, cell_b->m_size);
|
||||
}
|
||||
else {
|
||||
// b is negative
|
||||
|
@ -1261,10 +1245,8 @@ int mpz_manager<SYNCH>::big_compare(mpz const & a, mpz const & b) {
|
|||
}
|
||||
else {
|
||||
// a & b are negative
|
||||
return compare_diff(cell_b->m_digits,
|
||||
cell_b->m_size,
|
||||
cell_a->m_digits,
|
||||
cell_a->m_size);
|
||||
return m_mpn_manager.compare(cell_b->m_digits, cell_b->m_size,
|
||||
cell_a->m_digits, cell_a->m_size);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -1411,11 +1393,11 @@ void mpz_manager<SYNCH>::display(std::ostream & out, mpz const & a) const {
|
|||
out << "-";
|
||||
if (sizeof(digit_t) == 4) {
|
||||
sbuffer<char, 1024> buffer(11*size(a), 0);
|
||||
out << mp_decimal(digits(a), size(a), buffer.begin(), buffer.size(), 0);
|
||||
out << m_mpn_manager.to_string(digits(a), size(a), buffer.begin(), buffer.size());
|
||||
}
|
||||
else {
|
||||
sbuffer<char, 1024> buffer(21*size(a), 0);
|
||||
out << mp_decimal(digits(a), size(a), buffer.begin(), buffer.size(), 0);
|
||||
out << m_mpn_manager.to_string(digits(a), size(a), buffer.begin(), buffer.size());
|
||||
}
|
||||
#else
|
||||
// GMP version
|
||||
|
|
|
@ -27,6 +27,7 @@ Revision History:
|
|||
#include"scoped_numeral.h"
|
||||
#include"scoped_numeral_vector.h"
|
||||
#include"z3_omp.h"
|
||||
#include"mpn.h"
|
||||
|
||||
unsigned u_gcd(unsigned u, unsigned v);
|
||||
uint64 u64_gcd(uint64 u, uint64 v);
|
||||
|
@ -37,7 +38,7 @@ typedef unsigned digit_t;
|
|||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4200)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template<bool SYNCH> class mpz_manager;
|
||||
template<bool SYNCH> class mpq_manager;
|
||||
|
@ -107,6 +108,7 @@ class mpz_manager {
|
|||
omp_nest_lock_t m_lock;
|
||||
#define MPZ_BEGIN_CRITICAL() if (SYNCH) omp_set_nest_lock(&m_lock);
|
||||
#define MPZ_END_CRITICAL() if (SYNCH) omp_unset_nest_lock(&m_lock);
|
||||
mpn_manager m_mpn_manager;
|
||||
|
||||
#ifndef _MP_GMP
|
||||
unsigned m_init_cell_capacity;
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
|
||||
#include"util.h"
|
||||
|
||||
unsigned g_verbosity_level = 0;
|
||||
static unsigned g_verbosity_level = 0;
|
||||
|
||||
void set_verbosity_level(unsigned lvl) {
|
||||
g_verbosity_level = lvl;
|
||||
|
@ -40,7 +40,7 @@ std::ostream& verbose_stream() {
|
|||
}
|
||||
|
||||
|
||||
void (*g_fatal_error_handler)(int) = 0;
|
||||
static void (*g_fatal_error_handler)(int) = 0;
|
||||
|
||||
void fatal_error(int error_code) {
|
||||
if (g_fatal_error_handler) {
|
||||
|
|
|
@ -71,18 +71,12 @@ class vector {
|
|||
SZ old_capacity_T = sizeof(T) * old_capacity + sizeof(SZ) * 2;
|
||||
SZ new_capacity = (3 * old_capacity + 1) >> 1;
|
||||
SZ new_capacity_T = sizeof(T) * new_capacity + sizeof(SZ) * 2;
|
||||
SZ size = reinterpret_cast<SZ *>(m_data)[SIZE_IDX];
|
||||
if (new_capacity <= old_capacity || new_capacity_T <= old_capacity_T) {
|
||||
throw default_exception("Overflow encountered when expanding vector");
|
||||
}
|
||||
SZ * mem = reinterpret_cast<SZ*>(memory::allocate(new_capacity_T));
|
||||
*mem = new_capacity;
|
||||
mem ++;
|
||||
*mem = size;
|
||||
mem++;
|
||||
memcpy(mem, m_data, size * sizeof(T));
|
||||
free_memory();
|
||||
m_data = reinterpret_cast<T *>(mem);
|
||||
SZ *mem = (SZ*)memory::reallocate(reinterpret_cast<SZ*>(m_data)-2, new_capacity_T);
|
||||
*mem = new_capacity;
|
||||
m_data = reinterpret_cast<T *>(mem + 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue