mirror of
https://github.com/Z3Prover/z3
synced 2026-03-07 22:04:53 +00:00
fixes
This commit is contained in:
parent
1a189ebdd7
commit
fa73827d98
3 changed files with 51 additions and 78 deletions
|
|
@ -39,7 +39,7 @@ static void hit_me(char const* wm) {
|
|||
Z3_mk_bv_sort(ctx,i);
|
||||
|
||||
}
|
||||
catch (std::bad_alloc) {
|
||||
catch (std::bad_alloc&) {
|
||||
std::cout << "caught\n";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
--*/
|
||||
#include <cstring>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include "util/mpz.h"
|
||||
|
|
@ -25,6 +26,22 @@ Revision History:
|
|||
#include "util/hash.h"
|
||||
#include "util/bit_util.h"
|
||||
|
||||
static bool mul_overflows(int64_t a, int64_t b, int64_t & result) {
|
||||
#if __STDC_VERSION_STDCKDINT_H__ >= 202311L
|
||||
return std::ckd_mul(&result, a, b);
|
||||
#elif defined(__GNUC__)
|
||||
return __builtin_mul_overflow(a, b, &result);
|
||||
#elif defined(_MSC_VER)
|
||||
// MSVC _mul128 intrinsic
|
||||
__int64 high;
|
||||
result = _mul128(a, b, &high);
|
||||
// Overflow if high bits are not the sign extension of result
|
||||
return high != 0 && high != -1;
|
||||
#else
|
||||
static_assert(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_MP_INTERNAL)
|
||||
#include "util/mpn.h"
|
||||
#elif defined(_MP_GMP)
|
||||
|
|
@ -111,22 +128,6 @@ unsigned u_gcd(unsigned u, unsigned v) {
|
|||
return u << shift;
|
||||
}
|
||||
|
||||
uint64_t u64_gcd(uint64_t u, uint64_t v) {
|
||||
if (u == 0) return v;
|
||||
if (v == 0) return u;
|
||||
if (u == 1 || v == 1) return 1;
|
||||
auto shift = _trailing_zeros64(u | v);
|
||||
u >>= _trailing_zeros64(u);
|
||||
do {
|
||||
v >>= _trailing_zeros64(v);
|
||||
if (u > v) std::swap(u, v);
|
||||
v -= u;
|
||||
}
|
||||
while (v != 0);
|
||||
return u << shift;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<bool SYNCH>
|
||||
mpz_manager<SYNCH>::mpz_manager():
|
||||
|
|
@ -375,9 +376,9 @@ void mpz_manager<SYNCH>::set(mpz_cell& src, mpz & a, int sign, unsigned sz) {
|
|||
}
|
||||
|
||||
unsigned d = src.m_digits[0];
|
||||
if (i == 1 && d <= mpz::SMALL_INT_MAX) {
|
||||
// src fits in small integer range
|
||||
a.set(sign < 0 ? -static_cast<int64_t>(d) : static_cast<int64_t>(d));
|
||||
int64_t val = sign < 0 ? -static_cast<int64_t>(d) : static_cast<int64_t>(d);
|
||||
if (i == 1 && mpz::fits_in_small(val) && a.is_small()) {
|
||||
a.set(val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -425,6 +426,7 @@ void mpz_manager<SYNCH>::set_digits(mpz & target, unsigned sz, digit_t const * d
|
|||
#ifndef _MP_GMP
|
||||
allocate_if_needed(target, sz);
|
||||
memcpy(target.ptr()->m_digits, digits, sizeof(digit_t) * sz);
|
||||
target.ptr()->m_size = sz;
|
||||
target.set_sign(1);
|
||||
#else
|
||||
mk_big(target);
|
||||
|
|
@ -446,9 +448,10 @@ void mpz_manager<SYNCH>::set_digits(mpz & target, unsigned sz, digit_t const * d
|
|||
|
||||
template<bool SYNCH>
|
||||
void mpz_manager<SYNCH>::mul(mpz const & a, mpz const & b, mpz & c) {
|
||||
STRACE(mpz, tout << "[mpz] " << to_string(a) << " * " << to_string(b) << " == ";);
|
||||
if (is_small(a) && is_small(b)) {
|
||||
set(c, a.value() * b.value());
|
||||
STRACE(mpz, tout << "[mpz] " << to_string(a) << " * " << to_string(b) << " == ";);
|
||||
int64_t result;
|
||||
if (is_small(a) && is_small(b) && !mul_overflows(a.value(), b.value(), result)) {
|
||||
set(c, result);
|
||||
}
|
||||
else {
|
||||
big_mul(a, b, c);
|
||||
|
|
@ -510,7 +513,7 @@ void mpz_manager<SYNCH>::machine_div_rem(mpz const & a, mpz const & b, mpz & q,
|
|||
template<bool SYNCH>
|
||||
void mpz_manager<SYNCH>::machine_div(mpz const & a, mpz const & b, mpz & c) {
|
||||
STRACE(mpz, tout << "[mpz-ext] machine-div(" << to_string(a) << ", " << to_string(b) << ") == ";);
|
||||
if (is_small(b) && b.value() == 0)
|
||||
if (is_zero(b))
|
||||
throw default_exception("division by 0");
|
||||
|
||||
if (is_small(a) && is_small(b))
|
||||
|
|
@ -890,12 +893,7 @@ template<bool SYNCH>
|
|||
void mpz_manager<SYNCH>::gcd(mpz const & a, mpz const & b, mpz & c) {
|
||||
static_assert(sizeof(mpz) <= 16, "mpz size overflow");
|
||||
if (is_small(a) && is_small(b)) {
|
||||
int64_t _a = a.value();
|
||||
int64_t _b = b.value();
|
||||
if (_a < 0) _a = -_a;
|
||||
if (_b < 0) _b = -_b;
|
||||
uint64_t r = u64_gcd(static_cast<uint64_t>(_a), static_cast<uint64_t>(_b));
|
||||
set(c, r);
|
||||
set(c, std::gcd(a.value(), b.value()));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
|
@ -975,7 +973,7 @@ void mpz_manager<SYNCH>::gcd(mpz const & a, mpz const & b, mpz & c) {
|
|||
else {
|
||||
while (true) {
|
||||
if (is_uint64(tmp1) && is_uint64(tmp2)) {
|
||||
set(c, u64_gcd(get_uint64(tmp1), get_uint64(tmp2)));
|
||||
set(c, std::gcd(get_uint64(tmp1), get_uint64(tmp2)));
|
||||
break;
|
||||
}
|
||||
rem(tmp1, tmp2, aux);
|
||||
|
|
@ -1066,8 +1064,7 @@ void mpz_manager<SYNCH>::gcd(mpz const & a, mpz const & b, mpz & c) {
|
|||
SASSERT(ge(a1, b1));
|
||||
if (is_small(b1)) {
|
||||
if (is_small(a1)) {
|
||||
uint64_t r = u64_gcd(static_cast<uint64_t>(a1.value()), static_cast<uint64_t>(b1.value()));
|
||||
set(c, r);
|
||||
set(c, std::gcd(a1.value(), b1.value()));
|
||||
break;
|
||||
}
|
||||
else {
|
||||
|
|
@ -1081,12 +1078,12 @@ void mpz_manager<SYNCH>::gcd(mpz const & a, mpz const & b, mpz & c) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
SASSERT(!is_small(a1));
|
||||
sign_cell ca(*this, a1);
|
||||
SASSERT(!is_small(b1));
|
||||
a_sz = a1.ptr()->m_size;
|
||||
a_sz = ca.cell()->m_size;
|
||||
b_sz = b1.ptr()->m_size;
|
||||
SASSERT(b_sz <= a_sz);
|
||||
a_hat = a1.ptr()->m_digits[a_sz - 1];
|
||||
a_hat = ca.cell()->m_digits[a_sz - 1];
|
||||
b_hat = (b_sz == a_sz) ? b1.ptr()->m_digits[b_sz - 1] : 0;
|
||||
A = 1;
|
||||
B = 0;
|
||||
|
|
@ -1499,21 +1496,6 @@ void mpz_manager<SYNCH>::bitwise_not(unsigned sz, mpz const & a, mpz & c) {
|
|||
}
|
||||
}
|
||||
|
||||
template<bool SYNCH>
|
||||
void mpz_manager<SYNCH>::big_set(mpz & target, mpz const & source) {
|
||||
#ifndef _MP_GMP
|
||||
if (&target == &source)
|
||||
return;
|
||||
allocate_if_needed(target, capacity(source));
|
||||
memcpy(digits(target), digits(source), sizeof(digit_t) * size(source));
|
||||
target.set_sign(source.sign());
|
||||
#else
|
||||
// GMP version
|
||||
mk_big(target);
|
||||
mpz_set(*target.ptr(), *source.ptr());
|
||||
#endif
|
||||
}
|
||||
|
||||
template<bool SYNCH>
|
||||
int mpz_manager<SYNCH>::big_compare(mpz const & a, mpz const & b) {
|
||||
#ifndef _MP_GMP
|
||||
|
|
@ -1856,12 +1838,10 @@ void mpz_manager<SYNCH>::power(mpz const & a, unsigned p, mpz & b) {
|
|||
unsigned shift = p%(8 * sizeof(digit_t));
|
||||
SASSERT(sz > 0);
|
||||
allocate_if_needed(b, sz);
|
||||
SASSERT(b.ptr()->m_capacity >= sz);
|
||||
b.ptr()->m_size = sz;
|
||||
b.ptr()->m_size = sz;
|
||||
for (unsigned i = 0; i < sz - 1; ++i)
|
||||
b.ptr()->m_digits[i] = 0;
|
||||
b.ptr()->m_digits[sz-1] = 1 << shift;
|
||||
// b is already large after allocate_if_needed, just ensure sign is positive
|
||||
b.set_sign(1);
|
||||
}
|
||||
return;
|
||||
|
|
@ -1951,7 +1931,6 @@ void mpz_manager<SYNCH>::ensure_capacity(mpz & a, unsigned capacity) {
|
|||
int64_t val = a.value();
|
||||
uint64_t abs_val = static_cast<uint64_t>(-val);
|
||||
allocate_if_needed(a, capacity);
|
||||
SASSERT(a.ptr()->m_capacity >= capacity);
|
||||
if (sizeof(digit_t) == sizeof(uint64_t)) {
|
||||
a.ptr()->m_digits[0] = static_cast<digit_t>(abs_val);
|
||||
a.ptr()->m_size = 1;
|
||||
|
|
@ -1966,7 +1945,6 @@ void mpz_manager<SYNCH>::ensure_capacity(mpz & a, unsigned capacity) {
|
|||
else if (a.ptr()->m_capacity < capacity) {
|
||||
mpz_cell * new_cell = allocate(capacity);
|
||||
unsigned old_sz = a.ptr()->m_size;
|
||||
SASSERT(capacity >= old_sz);
|
||||
new_cell->m_size = old_sz;
|
||||
memcpy(new_cell->m_digits, digits(a), sizeof(digit_t) * old_sz);
|
||||
bool is_neg = a.sign() < 0;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ Revision History:
|
|||
#include "util/mpn.h"
|
||||
|
||||
unsigned u_gcd(unsigned u, unsigned v);
|
||||
uint64_t u64_gcd(uint64_t u, uint64_t v);
|
||||
unsigned trailing_zeros(uint64_t);
|
||||
unsigned trailing_zeros(uint32_t);
|
||||
|
||||
|
|
@ -158,14 +157,8 @@ public:
|
|||
// with values that fit, or the caller should use set_big_i64.
|
||||
SASSERT(fits_in_small(v));
|
||||
}
|
||||
|
||||
mpz(int v) noexcept : m_value(static_cast<uintptr_t>(v) << 1) {
|
||||
SASSERT(fits_in_small(v));
|
||||
}
|
||||
|
||||
mpz(unsigned v) noexcept : m_value(static_cast<uintptr_t>(v) << 1) {
|
||||
SASSERT(fits_in_small(v));
|
||||
}
|
||||
mpz(int v) : mpz(int64_t(v)) {}
|
||||
mpz(unsigned v) : mpz(int64_t(v)) {}
|
||||
|
||||
mpz(mpz_type* ptr) noexcept {
|
||||
set_ptr(ptr, false, true); // external pointer, non-negative
|
||||
|
|
@ -364,7 +357,7 @@ class mpz_manager {
|
|||
|
||||
class sign_cell {
|
||||
static const unsigned capacity = 2;
|
||||
unsigned char m_bytes[sizeof(mpz_cell) + sizeof(digit_t) * capacity];
|
||||
alignas(8) unsigned char m_bytes[sizeof(mpz_cell) + sizeof(digit_t) * capacity];
|
||||
mpz m_local;
|
||||
mpz const& m_a;
|
||||
int m_sign;
|
||||
|
|
@ -431,8 +424,6 @@ class mpz_manager {
|
|||
|
||||
void big_mul(mpz const & a, mpz const & b, mpz & c);
|
||||
|
||||
void big_set(mpz & target, mpz const & source);
|
||||
|
||||
#ifndef _MP_GMP
|
||||
|
||||
#define QUOT_ONLY 0
|
||||
|
|
@ -511,11 +502,15 @@ public:
|
|||
|
||||
static bool is_neg(mpz const & a) { return sign(a) < 0; }
|
||||
|
||||
static bool is_zero(mpz const & a) { return sign(a) == 0; }
|
||||
static bool is_zero(mpz const & a) {
|
||||
if (a.is_small())
|
||||
return a.value() == 0;
|
||||
return size(a) == 1 && digits(a)[0] == 0;
|
||||
}
|
||||
|
||||
static int sign(mpz const & a) {
|
||||
if (is_small(a)) {
|
||||
int v = a.value();
|
||||
int64_t v = a.value();
|
||||
return (v > 0) - (v < 0); // Returns -1, 0, or 1
|
||||
}
|
||||
else
|
||||
|
|
@ -597,10 +592,10 @@ public:
|
|||
|
||||
void set(mpz & target, mpz const & source) {
|
||||
if (is_small(source)) {
|
||||
target.set(source.value());
|
||||
set(target, source.value());
|
||||
}
|
||||
else {
|
||||
big_set(target, source);
|
||||
set(*source.ptr(), target, source.sign(), size(source));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -685,21 +680,21 @@ public:
|
|||
static unsigned hash(mpz const & a);
|
||||
|
||||
static bool is_one(mpz const & a) {
|
||||
#ifndef _MP_GMP
|
||||
return is_small(a) && a.value() == 1;
|
||||
#else
|
||||
if (is_small(a))
|
||||
return a.value() == 1;
|
||||
#ifndef _MP_GMP
|
||||
return size(a) == 1 && digits(a)[0] == 1 && a.sign() > 0;
|
||||
#else
|
||||
return mpz_cmp_si(*a.ptr(), 1) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool is_minus_one(mpz const & a) {
|
||||
#ifndef _MP_GMP
|
||||
return is_small(a) && a.value() == -1;
|
||||
#else
|
||||
if (is_small(a))
|
||||
return a.value() == -1;
|
||||
#ifndef _MP_GMP
|
||||
return size(a) == 1 && digits(a)[0] == 1 && a.sign() < 0;
|
||||
#else
|
||||
return mpz_cmp_si(*a.ptr(), -1) == 0;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue