mirror of
https://github.com/Z3Prover/z3
synced 2026-07-01 04:48:54 +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);
|
Z3_mk_bv_sort(ctx,i);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (std::bad_alloc) {
|
catch (std::bad_alloc&) {
|
||||||
std::cout << "caught\n";
|
std::cout << "caught\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <numeric>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include "util/mpz.h"
|
#include "util/mpz.h"
|
||||||
|
|
@ -25,6 +26,22 @@ Revision History:
|
||||||
#include "util/hash.h"
|
#include "util/hash.h"
|
||||||
#include "util/bit_util.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)
|
#if defined(_MP_INTERNAL)
|
||||||
#include "util/mpn.h"
|
#include "util/mpn.h"
|
||||||
#elif defined(_MP_GMP)
|
#elif defined(_MP_GMP)
|
||||||
|
|
@ -111,22 +128,6 @@ unsigned u_gcd(unsigned u, unsigned v) {
|
||||||
return u << shift;
|
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>
|
template<bool SYNCH>
|
||||||
mpz_manager<SYNCH>::mpz_manager():
|
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];
|
unsigned d = src.m_digits[0];
|
||||||
if (i == 1 && d <= mpz::SMALL_INT_MAX) {
|
int64_t val = sign < 0 ? -static_cast<int64_t>(d) : static_cast<int64_t>(d);
|
||||||
// src fits in small integer range
|
if (i == 1 && mpz::fits_in_small(val) && a.is_small()) {
|
||||||
a.set(sign < 0 ? -static_cast<int64_t>(d) : static_cast<int64_t>(d));
|
a.set(val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -425,6 +426,7 @@ void mpz_manager<SYNCH>::set_digits(mpz & target, unsigned sz, digit_t const * d
|
||||||
#ifndef _MP_GMP
|
#ifndef _MP_GMP
|
||||||
allocate_if_needed(target, sz);
|
allocate_if_needed(target, sz);
|
||||||
memcpy(target.ptr()->m_digits, digits, sizeof(digit_t) * sz);
|
memcpy(target.ptr()->m_digits, digits, sizeof(digit_t) * sz);
|
||||||
|
target.ptr()->m_size = sz;
|
||||||
target.set_sign(1);
|
target.set_sign(1);
|
||||||
#else
|
#else
|
||||||
mk_big(target);
|
mk_big(target);
|
||||||
|
|
@ -446,9 +448,10 @@ void mpz_manager<SYNCH>::set_digits(mpz & target, unsigned sz, digit_t const * d
|
||||||
|
|
||||||
template<bool SYNCH>
|
template<bool SYNCH>
|
||||||
void mpz_manager<SYNCH>::mul(mpz const & a, mpz const & b, mpz & c) {
|
void mpz_manager<SYNCH>::mul(mpz const & a, mpz const & b, mpz & c) {
|
||||||
STRACE(mpz, tout << "[mpz] " << to_string(a) << " * " << to_string(b) << " == ";);
|
STRACE(mpz, tout << "[mpz] " << to_string(a) << " * " << to_string(b) << " == ";);
|
||||||
if (is_small(a) && is_small(b)) {
|
int64_t result;
|
||||||
set(c, a.value() * b.value());
|
if (is_small(a) && is_small(b) && !mul_overflows(a.value(), b.value(), result)) {
|
||||||
|
set(c, result);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
big_mul(a, b, c);
|
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>
|
template<bool SYNCH>
|
||||||
void mpz_manager<SYNCH>::machine_div(mpz const & a, mpz const & b, mpz & c) {
|
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) << ") == ";);
|
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");
|
throw default_exception("division by 0");
|
||||||
|
|
||||||
if (is_small(a) && is_small(b))
|
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) {
|
void mpz_manager<SYNCH>::gcd(mpz const & a, mpz const & b, mpz & c) {
|
||||||
static_assert(sizeof(mpz) <= 16, "mpz size overflow");
|
static_assert(sizeof(mpz) <= 16, "mpz size overflow");
|
||||||
if (is_small(a) && is_small(b)) {
|
if (is_small(a) && is_small(b)) {
|
||||||
int64_t _a = a.value();
|
set(c, std::gcd(a.value(), b.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);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -975,7 +973,7 @@ void mpz_manager<SYNCH>::gcd(mpz const & a, mpz const & b, mpz & c) {
|
||||||
else {
|
else {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (is_uint64(tmp1) && is_uint64(tmp2)) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
rem(tmp1, tmp2, aux);
|
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));
|
SASSERT(ge(a1, b1));
|
||||||
if (is_small(b1)) {
|
if (is_small(b1)) {
|
||||||
if (is_small(a1)) {
|
if (is_small(a1)) {
|
||||||
uint64_t r = u64_gcd(static_cast<uint64_t>(a1.value()), static_cast<uint64_t>(b1.value()));
|
set(c, std::gcd(a1.value(), b1.value()));
|
||||||
set(c, r);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -1081,12 +1078,12 @@ void mpz_manager<SYNCH>::gcd(mpz const & a, mpz const & b, mpz & c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SASSERT(!is_small(a1));
|
sign_cell ca(*this, a1);
|
||||||
SASSERT(!is_small(b1));
|
SASSERT(!is_small(b1));
|
||||||
a_sz = a1.ptr()->m_size;
|
a_sz = ca.cell()->m_size;
|
||||||
b_sz = b1.ptr()->m_size;
|
b_sz = b1.ptr()->m_size;
|
||||||
SASSERT(b_sz <= a_sz);
|
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;
|
b_hat = (b_sz == a_sz) ? b1.ptr()->m_digits[b_sz - 1] : 0;
|
||||||
A = 1;
|
A = 1;
|
||||||
B = 0;
|
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>
|
template<bool SYNCH>
|
||||||
int mpz_manager<SYNCH>::big_compare(mpz const & a, mpz const & b) {
|
int mpz_manager<SYNCH>::big_compare(mpz const & a, mpz const & b) {
|
||||||
#ifndef _MP_GMP
|
#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));
|
unsigned shift = p%(8 * sizeof(digit_t));
|
||||||
SASSERT(sz > 0);
|
SASSERT(sz > 0);
|
||||||
allocate_if_needed(b, sz);
|
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)
|
for (unsigned i = 0; i < sz - 1; ++i)
|
||||||
b.ptr()->m_digits[i] = 0;
|
b.ptr()->m_digits[i] = 0;
|
||||||
b.ptr()->m_digits[sz-1] = 1 << shift;
|
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);
|
b.set_sign(1);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -1951,7 +1931,6 @@ void mpz_manager<SYNCH>::ensure_capacity(mpz & a, unsigned capacity) {
|
||||||
int64_t val = a.value();
|
int64_t val = a.value();
|
||||||
uint64_t abs_val = static_cast<uint64_t>(-val);
|
uint64_t abs_val = static_cast<uint64_t>(-val);
|
||||||
allocate_if_needed(a, capacity);
|
allocate_if_needed(a, capacity);
|
||||||
SASSERT(a.ptr()->m_capacity >= capacity);
|
|
||||||
if (sizeof(digit_t) == sizeof(uint64_t)) {
|
if (sizeof(digit_t) == sizeof(uint64_t)) {
|
||||||
a.ptr()->m_digits[0] = static_cast<digit_t>(abs_val);
|
a.ptr()->m_digits[0] = static_cast<digit_t>(abs_val);
|
||||||
a.ptr()->m_size = 1;
|
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) {
|
else if (a.ptr()->m_capacity < capacity) {
|
||||||
mpz_cell * new_cell = allocate(capacity);
|
mpz_cell * new_cell = allocate(capacity);
|
||||||
unsigned old_sz = a.ptr()->m_size;
|
unsigned old_sz = a.ptr()->m_size;
|
||||||
SASSERT(capacity >= old_sz);
|
|
||||||
new_cell->m_size = old_sz;
|
new_cell->m_size = old_sz;
|
||||||
memcpy(new_cell->m_digits, digits(a), sizeof(digit_t) * old_sz);
|
memcpy(new_cell->m_digits, digits(a), sizeof(digit_t) * old_sz);
|
||||||
bool is_neg = a.sign() < 0;
|
bool is_neg = a.sign() < 0;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ Revision History:
|
||||||
#include "util/mpn.h"
|
#include "util/mpn.h"
|
||||||
|
|
||||||
unsigned u_gcd(unsigned u, unsigned v);
|
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(uint64_t);
|
||||||
unsigned trailing_zeros(uint32_t);
|
unsigned trailing_zeros(uint32_t);
|
||||||
|
|
||||||
|
|
@ -158,14 +157,8 @@ public:
|
||||||
// with values that fit, or the caller should use set_big_i64.
|
// with values that fit, or the caller should use set_big_i64.
|
||||||
SASSERT(fits_in_small(v));
|
SASSERT(fits_in_small(v));
|
||||||
}
|
}
|
||||||
|
mpz(int v) : mpz(int64_t(v)) {}
|
||||||
mpz(int v) noexcept : m_value(static_cast<uintptr_t>(v) << 1) {
|
mpz(unsigned v) : mpz(int64_t(v)) {}
|
||||||
SASSERT(fits_in_small(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
mpz(unsigned v) noexcept : m_value(static_cast<uintptr_t>(v) << 1) {
|
|
||||||
SASSERT(fits_in_small(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
mpz(mpz_type* ptr) noexcept {
|
mpz(mpz_type* ptr) noexcept {
|
||||||
set_ptr(ptr, false, true); // external pointer, non-negative
|
set_ptr(ptr, false, true); // external pointer, non-negative
|
||||||
|
|
@ -364,7 +357,7 @@ class mpz_manager {
|
||||||
|
|
||||||
class sign_cell {
|
class sign_cell {
|
||||||
static const unsigned capacity = 2;
|
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 m_local;
|
||||||
mpz const& m_a;
|
mpz const& m_a;
|
||||||
int m_sign;
|
int m_sign;
|
||||||
|
|
@ -431,8 +424,6 @@ class mpz_manager {
|
||||||
|
|
||||||
void big_mul(mpz const & a, mpz const & b, mpz & c);
|
void big_mul(mpz const & a, mpz const & b, mpz & c);
|
||||||
|
|
||||||
void big_set(mpz & target, mpz const & source);
|
|
||||||
|
|
||||||
#ifndef _MP_GMP
|
#ifndef _MP_GMP
|
||||||
|
|
||||||
#define QUOT_ONLY 0
|
#define QUOT_ONLY 0
|
||||||
|
|
@ -511,11 +502,15 @@ public:
|
||||||
|
|
||||||
static bool is_neg(mpz const & a) { return sign(a) < 0; }
|
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) {
|
static int sign(mpz const & a) {
|
||||||
if (is_small(a)) {
|
if (is_small(a)) {
|
||||||
int v = a.value();
|
int64_t v = a.value();
|
||||||
return (v > 0) - (v < 0); // Returns -1, 0, or 1
|
return (v > 0) - (v < 0); // Returns -1, 0, or 1
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -597,10 +592,10 @@ public:
|
||||||
|
|
||||||
void set(mpz & target, mpz const & source) {
|
void set(mpz & target, mpz const & source) {
|
||||||
if (is_small(source)) {
|
if (is_small(source)) {
|
||||||
target.set(source.value());
|
set(target, source.value());
|
||||||
}
|
}
|
||||||
else {
|
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 unsigned hash(mpz const & a);
|
||||||
|
|
||||||
static bool is_one(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))
|
if (is_small(a))
|
||||||
return a.value() == 1;
|
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;
|
return mpz_cmp_si(*a.ptr(), 1) == 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_minus_one(mpz const & a) {
|
static bool is_minus_one(mpz const & a) {
|
||||||
#ifndef _MP_GMP
|
|
||||||
return is_small(a) && a.value() == -1;
|
|
||||||
#else
|
|
||||||
if (is_small(a))
|
if (is_small(a))
|
||||||
return a.value() == -1;
|
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;
|
return mpz_cmp_si(*a.ptr(), -1) == 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue