mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
3f9edad676
commit
e9eab22e5c
1186 changed files with 381859 additions and 0 deletions
798
lib/mpz.h
Normal file
798
lib/mpz.h
Normal file
|
@ -0,0 +1,798 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
mpz.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2010-06-17.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _MPZ_H_
|
||||
#define _MPZ_H_
|
||||
|
||||
#include<limits.h>
|
||||
#include<string>
|
||||
#include"util.h"
|
||||
#include"small_object_allocator.h"
|
||||
#include"trace.h"
|
||||
#include"scoped_numeral.h"
|
||||
#include"scoped_numeral_vector.h"
|
||||
#include"z3_omp.h"
|
||||
|
||||
unsigned u_gcd(unsigned u, unsigned v);
|
||||
uint64 u64_gcd(uint64 u, uint64 v);
|
||||
|
||||
#ifdef _MP_GMP
|
||||
typedef unsigned digit_t;
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4200)
|
||||
#endif
|
||||
|
||||
template<bool SYNCH> class mpz_manager;
|
||||
template<bool SYNCH> class mpq_manager;
|
||||
|
||||
#if !defined(_MP_GMP) && !defined(_MP_MSBIGNUM) && !defined(_MP_INTERNAL)
|
||||
#ifdef _WINDOWS
|
||||
#define _MP_INTERNAL
|
||||
#else
|
||||
#define _MP_GMP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_MP_MSBIGNUM)
|
||||
typedef size_t digit_t;
|
||||
#elif defined(_MP_INTERNAL)
|
||||
typedef unsigned int digit_t;
|
||||
#endif
|
||||
|
||||
#ifndef _MP_GMP
|
||||
class mpz_cell {
|
||||
unsigned m_size;
|
||||
unsigned m_capacity;
|
||||
digit_t m_digits[0];
|
||||
friend class mpz_manager<true>;
|
||||
friend class mpz_manager<false>;
|
||||
};
|
||||
#else
|
||||
#include<gmp.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
\brief Multi-precision integer.
|
||||
|
||||
If m_ptr == 0, the it is a small number and the value is stored at m_val.
|
||||
Otherwise, m_val contains the sign (-1 negative, 1 positive), and m_ptr points to a mpz_cell that
|
||||
store the value. <<< This last statement is true only in Windows.
|
||||
*/
|
||||
class mpz {
|
||||
int m_val;
|
||||
#ifndef _MP_GMP
|
||||
mpz_cell * m_ptr;
|
||||
#else
|
||||
mpz_t * m_ptr;
|
||||
#endif
|
||||
friend class mpz_manager<true>;
|
||||
friend class mpz_manager<false>;
|
||||
friend class mpq_manager<true>;
|
||||
friend class mpq_manager<false>;
|
||||
friend class mpq;
|
||||
friend class mpbq;
|
||||
friend class mpbq_manager;
|
||||
mpz & operator=(mpz const & other) { UNREACHABLE(); return *this; }
|
||||
public:
|
||||
mpz(int v):m_val(v), m_ptr(0) {}
|
||||
mpz():m_val(0), m_ptr(0) {}
|
||||
void swap(mpz & other) {
|
||||
std::swap(m_val, other.m_val);
|
||||
std::swap(m_ptr, other.m_ptr);
|
||||
}
|
||||
};
|
||||
|
||||
inline void swap(mpz & m1, mpz & m2) { m1.swap(m2); }
|
||||
|
||||
template<bool SYNCH = true>
|
||||
class mpz_manager {
|
||||
small_object_allocator m_allocator;
|
||||
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);
|
||||
|
||||
#ifndef _MP_GMP
|
||||
unsigned m_init_cell_capacity;
|
||||
mpz_cell * m_tmp[2];
|
||||
mpz_cell * m_arg[2];
|
||||
mpz m_int_min;
|
||||
|
||||
static unsigned cell_size(unsigned capacity) { return sizeof(mpz_cell) + sizeof(digit_t) * capacity; }
|
||||
|
||||
mpz_cell * allocate(unsigned capacity) {
|
||||
SASSERT(capacity >= m_init_cell_capacity);
|
||||
mpz_cell * cell = reinterpret_cast<mpz_cell *>(m_allocator.allocate(cell_size(capacity)));
|
||||
cell->m_capacity = capacity;
|
||||
return cell;
|
||||
}
|
||||
|
||||
// make sure that n is a big number and has capacity equal to at least c.
|
||||
void allocate_if_needed(mpz & n, unsigned c) {
|
||||
if (c < m_init_cell_capacity)
|
||||
c = m_init_cell_capacity;
|
||||
if (is_small(n)) {
|
||||
n.m_val = 1;
|
||||
n.m_ptr = allocate(c);
|
||||
n.m_ptr->m_capacity = c;
|
||||
}
|
||||
else if (capacity(n) < c) {
|
||||
deallocate(n.m_ptr);
|
||||
n.m_val = 1;
|
||||
n.m_ptr = allocate(c);
|
||||
n.m_ptr->m_capacity = c;
|
||||
}
|
||||
}
|
||||
|
||||
void deallocate(mpz_cell * ptr) {
|
||||
m_allocator.deallocate(cell_size(ptr->m_capacity), ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Make sure that m_tmp[IDX] can hold the given number of digits
|
||||
*/
|
||||
template<int IDX>
|
||||
void ensure_tmp_capacity(unsigned capacity) {
|
||||
if (m_tmp[IDX]->m_capacity >= capacity)
|
||||
return;
|
||||
deallocate(m_tmp[IDX]);
|
||||
unsigned new_capacity = (3 * capacity + 1) >> 1;
|
||||
m_tmp[IDX] = allocate(new_capacity);
|
||||
SASSERT(m_tmp[IDX]->m_capacity >= capacity);
|
||||
}
|
||||
|
||||
// Expand capacity of a while preserving its content.
|
||||
void ensure_capacity(mpz & a, unsigned sz);
|
||||
|
||||
void normalize(mpz & a);
|
||||
#else
|
||||
// GMP code
|
||||
mpz_t m_tmp, m_tmp2;
|
||||
mpz_t m_two32;
|
||||
mpz_t * m_arg[2];
|
||||
mpz_t m_uint64_max;
|
||||
mpz_t m_int64_max;
|
||||
|
||||
mpz_t * allocate() {
|
||||
mpz_t * cell = reinterpret_cast<mpz_t*>(m_allocator.allocate(sizeof(mpz_t)));
|
||||
mpz_init(*cell);
|
||||
return cell;
|
||||
}
|
||||
|
||||
void deallocate(mpz_t * ptr) { mpz_clear(*ptr); m_allocator.deallocate(sizeof(mpz_t), ptr); }
|
||||
#endif
|
||||
mpz m_two64;
|
||||
|
||||
/**
|
||||
\brief Set \c a with the value stored at m_tmp[IDX], and the given sign.
|
||||
\c sz is an overapproximation of the the size of the number stored at \c tmp.
|
||||
*/
|
||||
template<int IDX>
|
||||
void set(mpz & a, int sign, unsigned sz);
|
||||
|
||||
static int64 i64(mpz const & a) { return static_cast<int64>(a.m_val); }
|
||||
|
||||
void set_big_i64(mpz & c, int64 v);
|
||||
|
||||
void set_i64(mpz & c, int64 v) {
|
||||
if (v >= INT_MIN && v <= INT_MAX) {
|
||||
del(c);
|
||||
c.m_val = static_cast<int>(v);
|
||||
}
|
||||
else {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
set_big_i64(c, v);
|
||||
MPZ_END_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
void set_big_ui64(mpz & c, uint64 v);
|
||||
|
||||
#ifndef _MP_GMP
|
||||
static unsigned capacity(mpz const & c) { return c.m_ptr->m_capacity; }
|
||||
|
||||
static unsigned size(mpz const & c) { return c.m_ptr->m_size; }
|
||||
|
||||
static digit_t * digits(mpz const & c) { return c.m_ptr->m_digits; }
|
||||
|
||||
template<int IDX>
|
||||
void get_sign_cell(mpz const & a, int & sign, mpz_cell * & cell) {
|
||||
if (is_small(a)) {
|
||||
if (a.m_val == INT_MIN) {
|
||||
sign = -1;
|
||||
cell = m_int_min.m_ptr;
|
||||
}
|
||||
else {
|
||||
cell = m_arg[IDX];
|
||||
SASSERT(cell->m_size == 1);
|
||||
if (a.m_val < 0) {
|
||||
sign = -1;
|
||||
cell->m_digits[0] = -a.m_val;
|
||||
}
|
||||
else {
|
||||
sign = 1;
|
||||
cell->m_digits[0] = a.m_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
sign = a.m_val;
|
||||
cell = a.m_ptr;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// GMP code
|
||||
|
||||
template<int IDX>
|
||||
void get_arg(mpz const & a, mpz_t * & result) {
|
||||
if (is_small(a)) {
|
||||
result = m_arg[IDX];
|
||||
mpz_set_si(*result, a.m_val);
|
||||
}
|
||||
else {
|
||||
result = a.m_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void mk_big(mpz & a) {
|
||||
if (a.m_ptr == 0)
|
||||
a.m_ptr = allocate();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _MP_GMP
|
||||
template<bool SUB>
|
||||
void big_add_sub(mpz const & a, mpz const & b, mpz & c);
|
||||
#endif
|
||||
|
||||
void big_add(mpz const & a, mpz const & b, mpz & c);
|
||||
|
||||
void big_sub(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
|
||||
|
||||
#define QUOT_ONLY 0
|
||||
#define REM_ONLY 1
|
||||
#define QUOT_AND_REM 2
|
||||
#define qr_mode int
|
||||
|
||||
template<qr_mode MODE>
|
||||
void quot_rem_core(mpz const & a, mpz const & b, mpz & q, mpz & r);
|
||||
#endif
|
||||
|
||||
void big_div_rem(mpz const & a, mpz const & b, mpz & q, mpz & r);
|
||||
|
||||
void big_div(mpz const & a, mpz const & b, mpz & c);
|
||||
|
||||
void big_rem(mpz const & a, mpz const & b, mpz & c);
|
||||
|
||||
int big_compare(mpz const & a, mpz const & b);
|
||||
|
||||
unsigned size_info(mpz const & a);
|
||||
struct sz_lt;
|
||||
|
||||
public:
|
||||
static bool precise() { return true; }
|
||||
static bool field() { return false; }
|
||||
|
||||
typedef mpz numeral;
|
||||
|
||||
mpz_manager();
|
||||
|
||||
~mpz_manager();
|
||||
|
||||
static bool is_small(mpz const & a) { return a.m_ptr == 0; }
|
||||
|
||||
static mpz mk_z(int val) { return mpz(val); }
|
||||
|
||||
void del(mpz & a) {
|
||||
if (a.m_ptr != 0) {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
deallocate(a.m_ptr);
|
||||
MPZ_END_CRITICAL();
|
||||
a.m_ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void add(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_i64(c, i64(a) + i64(b));
|
||||
}
|
||||
else {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
big_add(a, b, c);
|
||||
MPZ_END_CRITICAL();
|
||||
}
|
||||
STRACE("mpz", tout << to_string(c) << "\n";);
|
||||
}
|
||||
|
||||
void sub(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_i64(c, i64(a) - i64(b));
|
||||
}
|
||||
else {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
big_sub(a, b, c);
|
||||
MPZ_END_CRITICAL();
|
||||
}
|
||||
STRACE("mpz", tout << to_string(c) << "\n";);
|
||||
}
|
||||
|
||||
void inc(mpz & a) { add(a, mpz(1), a); }
|
||||
|
||||
void dec(mpz & a) { add(a, mpz(-1), a); }
|
||||
|
||||
void 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_i64(c, i64(a) * i64(b));
|
||||
}
|
||||
else {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
big_mul(a, b, c);
|
||||
MPZ_END_CRITICAL();
|
||||
}
|
||||
STRACE("mpz", tout << to_string(c) << "\n";);
|
||||
}
|
||||
|
||||
// d <- a + b*c
|
||||
void addmul(mpz const & a, mpz const & b, mpz const & c, mpz & d) {
|
||||
if (is_one(b)) {
|
||||
add(a, c, d);
|
||||
}
|
||||
else if (is_minus_one(b)) {
|
||||
sub(a, c, d);
|
||||
}
|
||||
else {
|
||||
mpz tmp;
|
||||
mul(b,c,tmp);
|
||||
add(a,tmp,d);
|
||||
del(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// d <- a + b*c
|
||||
void submul(mpz const & a, mpz const & b, mpz const & c, mpz & d) {
|
||||
if (is_one(b)) {
|
||||
sub(a, c, d);
|
||||
}
|
||||
else if (is_minus_one(b)) {
|
||||
add(a, c, d);
|
||||
}
|
||||
else {
|
||||
mpz tmp;
|
||||
mul(b,c,tmp);
|
||||
sub(a,tmp,d);
|
||||
del(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void machine_div_rem(mpz const & a, mpz const & b, mpz & q, mpz & r) {
|
||||
STRACE("mpz", tout << "[mpz-ext] divrem(" << to_string(a) << ", " << to_string(b) << ") == ";);
|
||||
if (is_small(a) && is_small(b)) {
|
||||
int64 _a = i64(a);
|
||||
int64 _b = i64(b);
|
||||
set_i64(q, _a / _b);
|
||||
set_i64(r, _a % _b);
|
||||
}
|
||||
else {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
big_div_rem(a, b, q, r);
|
||||
MPZ_END_CRITICAL();
|
||||
}
|
||||
STRACE("mpz", tout << "(" << to_string(q) << ", " << to_string(r) << ")\n";);
|
||||
}
|
||||
|
||||
void 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(a) && is_small(b)) {
|
||||
set_i64(c, i64(a) / i64(b));
|
||||
}
|
||||
else {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
big_div(a, b, c);
|
||||
MPZ_END_CRITICAL();
|
||||
}
|
||||
STRACE("mpz", tout << to_string(c) << "\n";);
|
||||
}
|
||||
|
||||
void rem(mpz const & a, mpz const & b, mpz & c) {
|
||||
STRACE("mpz", tout << "[mpz-ext] rem(" << to_string(a) << ", " << to_string(b) << ") == ";);
|
||||
if (is_small(a) && is_small(b)) {
|
||||
set_i64(c, i64(a) % i64(b));
|
||||
}
|
||||
else {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
big_rem(a, b, c);
|
||||
MPZ_END_CRITICAL();
|
||||
}
|
||||
STRACE("mpz", tout << to_string(c) << "\n";);
|
||||
}
|
||||
|
||||
void div(mpz const & a, mpz const & b, mpz & c) {
|
||||
STRACE("mpz", tout << "[mpz-ext] div(" << to_string(a) << ", " << to_string(b) << ") == ";);
|
||||
if (is_neg(a)) {
|
||||
mpz tmp;
|
||||
machine_div_rem(a, b, c, tmp);
|
||||
if (!is_zero(tmp)) {
|
||||
if (is_neg(b))
|
||||
add(c, mk_z(1), c);
|
||||
else
|
||||
sub(c, mk_z(1), c);
|
||||
}
|
||||
del(tmp);
|
||||
}
|
||||
else {
|
||||
machine_div(a, b, c);
|
||||
}
|
||||
STRACE("mpz", tout << to_string(c) << "\n";);
|
||||
}
|
||||
|
||||
void mod(mpz const & a, mpz const & b, mpz & c) {
|
||||
STRACE("mpz", tout << "[mpz-ext] mod(" << to_string(a) << ", " << to_string(b) << ") == ";);
|
||||
rem(a, b, c);
|
||||
if (is_neg(c)) {
|
||||
if (is_pos(b))
|
||||
add(c, b, c);
|
||||
else
|
||||
sub(c, b, c);
|
||||
}
|
||||
STRACE("mpz", tout << to_string(c) << "\n";);
|
||||
}
|
||||
|
||||
void neg(mpz & a) {
|
||||
STRACE("mpz", tout << "[mpz] 0 - " << to_string(a) << " == ";);
|
||||
if (is_small(a) && a.m_val == INT_MIN) {
|
||||
// neg(INT_MIN) is not a small int
|
||||
set_big_i64(a, - static_cast<long long>(INT_MIN));
|
||||
return;
|
||||
}
|
||||
#ifndef _MP_GMP
|
||||
a.m_val = -a.m_val;
|
||||
#else
|
||||
if (is_small(a)) {
|
||||
a.m_val = -a.m_val;
|
||||
}
|
||||
else {
|
||||
mpz_neg(*a.m_ptr, *a.m_ptr);
|
||||
}
|
||||
#endif
|
||||
STRACE("mpz", tout << to_string(a) << "\n";);
|
||||
}
|
||||
|
||||
void abs(mpz & a) {
|
||||
if (is_small(a)) {
|
||||
if (a.m_val < 0) {
|
||||
if (a.m_val == INT_MIN) {
|
||||
// abs(INT_MIN) is not a small int
|
||||
set_big_i64(a, - static_cast<long long>(INT_MIN));
|
||||
}
|
||||
else
|
||||
a.m_val = -a.m_val;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifndef _MP_GMP
|
||||
a.m_val = 1;
|
||||
#else
|
||||
mpz_abs(*a.m_ptr, *a.m_ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_pos(mpz const & a) {
|
||||
#ifndef _MP_GMP
|
||||
return a.m_val > 0;
|
||||
#else
|
||||
if (is_small(a))
|
||||
return a.m_val > 0;
|
||||
else
|
||||
return mpz_sgn(*a.m_ptr) > 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool is_neg(mpz const & a) {
|
||||
#ifndef _MP_GMP
|
||||
return a.m_val < 0;
|
||||
#else
|
||||
if (is_small(a))
|
||||
return a.m_val < 0;
|
||||
else
|
||||
return mpz_sgn(*a.m_ptr) < 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool is_zero(mpz const & a) {
|
||||
#ifndef _MP_GMP
|
||||
return a.m_val == 0;
|
||||
#else
|
||||
if (is_small(a))
|
||||
return a.m_val == 0;
|
||||
else
|
||||
return mpz_sgn(*a.m_ptr) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int sign(mpz const & a) {
|
||||
#ifndef _MP_GMP
|
||||
return a.m_val;
|
||||
#else
|
||||
if (is_small(a))
|
||||
return a.m_val;
|
||||
else
|
||||
return mpz_sgn(*a.m_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool is_nonpos(mpz const & a) { return !is_pos(a); }
|
||||
|
||||
static bool is_nonneg(mpz const & a) { return !is_neg(a); }
|
||||
|
||||
bool eq(mpz const & a, mpz const & b) {
|
||||
if (is_small(a) && is_small(b)) {
|
||||
return a.m_val == b.m_val;
|
||||
}
|
||||
else {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
bool res = big_compare(a, b) == 0;
|
||||
MPZ_END_CRITICAL();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
bool lt(mpz const & a, mpz const & b) {
|
||||
if (is_small(a) && is_small(b)) {
|
||||
return a.m_val < b.m_val;
|
||||
}
|
||||
else {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
bool res = big_compare(a, b) < 0;
|
||||
MPZ_END_CRITICAL();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
bool neq(mpz const & a, mpz const & b) { return !eq(a, b); }
|
||||
|
||||
bool gt(mpz const & a, mpz const & b) { return lt(b, a); }
|
||||
|
||||
bool ge(mpz const & a, mpz const & b) { return !lt(a, b); }
|
||||
|
||||
bool le(mpz const & a, mpz const & b) { return !lt(b, a); }
|
||||
|
||||
void gcd(mpz const & a, mpz const & b, mpz & c);
|
||||
|
||||
void gcd(unsigned sz, mpz const * as, mpz & g);
|
||||
|
||||
/**
|
||||
\brief Extended Euclid:
|
||||
r1*a + r2*b = g
|
||||
*/
|
||||
void gcd(mpz const & r1, mpz const & r2, mpz & a, mpz & b, mpz & g);
|
||||
|
||||
void lcm(mpz const & a, mpz const & b, mpz & c);
|
||||
|
||||
/**
|
||||
\brief Return true if a | b
|
||||
*/
|
||||
bool divides(mpz const & a, mpz const & b);
|
||||
|
||||
// not a field
|
||||
void inv(mpz & a) {
|
||||
SASSERT(false);
|
||||
}
|
||||
|
||||
void bitwise_or(mpz const & a, mpz const & b, mpz & c);
|
||||
|
||||
void bitwise_and(mpz const & a, mpz const & b, mpz & c);
|
||||
|
||||
void bitwise_xor(mpz const & a, mpz const & b, mpz & c);
|
||||
|
||||
void bitwise_not(unsigned sz, mpz const & a, mpz & c);
|
||||
|
||||
void set(mpz & target, mpz const & source) {
|
||||
if (is_small(source)) {
|
||||
del(target);
|
||||
target.m_val = source.m_val;
|
||||
}
|
||||
else {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
big_set(target, source);
|
||||
MPZ_END_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
void set(mpz & a, int val) {
|
||||
del(a);
|
||||
a.m_val = val;
|
||||
}
|
||||
|
||||
void set(mpz & a, unsigned val) {
|
||||
if (val <= INT_MAX)
|
||||
set(a, static_cast<int>(val));
|
||||
else
|
||||
set(a, static_cast<int64>(static_cast<uint64>(val)));
|
||||
}
|
||||
|
||||
void set(mpz & a, char const * val);
|
||||
|
||||
void set(mpz & a, int64 val) {
|
||||
set_i64(a, val);
|
||||
}
|
||||
|
||||
void set(mpz & a, uint64 val) {
|
||||
if (val < INT_MAX) {
|
||||
del(a);
|
||||
a.m_val = static_cast<int>(val);
|
||||
}
|
||||
else {
|
||||
MPZ_BEGIN_CRITICAL();
|
||||
set_big_ui64(a, val);
|
||||
MPZ_END_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
void set(mpz & target, unsigned sz, digit_t const * digits);
|
||||
|
||||
void reset(mpz & a) {
|
||||
del(a);
|
||||
a.m_val = 0;
|
||||
}
|
||||
|
||||
void swap(mpz & a, mpz & b) {
|
||||
std::swap(a.m_val, b.m_val);
|
||||
std::swap(a.m_ptr, b.m_ptr);
|
||||
}
|
||||
|
||||
bool is_uint64(mpz const & a) const;
|
||||
|
||||
bool is_int64(mpz const & a) const;
|
||||
|
||||
uint64 get_uint64(mpz const & a) const;
|
||||
|
||||
int64 get_int64(mpz const & a) const;
|
||||
|
||||
double get_double(mpz const & a) const;
|
||||
|
||||
std::string to_string(mpz const & a) const;
|
||||
|
||||
void display(std::ostream & out, mpz const & a) const;
|
||||
|
||||
/**
|
||||
\brief Display mpz number in SMT 2.0 format.
|
||||
If decimal == true, then ".0" is appended.
|
||||
*/
|
||||
void display_smt2(std::ostream & out, mpz const & a, bool decimal) const;
|
||||
|
||||
static unsigned hash(mpz const & a);
|
||||
|
||||
static bool is_one(mpz const & a) {
|
||||
#ifndef _MP_GMP
|
||||
return is_small(a) && a.m_val == 1;
|
||||
#else
|
||||
if (is_small(a))
|
||||
return a.m_val == 1;
|
||||
return mpz_cmp_si(*a.m_ptr, 1) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool is_minus_one(mpz const & a) {
|
||||
#ifndef _MP_GMP
|
||||
return is_small(a) && a.m_val == -1;
|
||||
#else
|
||||
if (is_small(a))
|
||||
return a.m_val == -1;
|
||||
return mpz_cmp_si(*a.m_ptr, -1) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void power(mpz const & a, unsigned p, mpz & b);
|
||||
|
||||
bool is_power_of_two(mpz const & a);
|
||||
|
||||
bool is_power_of_two(mpz const & a, unsigned & shift);
|
||||
|
||||
void machine_div2k(mpz & a, unsigned k);
|
||||
|
||||
void machine_div2k(mpz const & a, unsigned k, mpz & r) { set(r, a); machine_div2k(r, k); }
|
||||
|
||||
void mul2k(mpz & a, unsigned k);
|
||||
|
||||
void mul2k(mpz const & a, unsigned k, mpz & r) { set(r, a); mul2k(r, k); }
|
||||
|
||||
/**
|
||||
\brief Return largest k s.t. n is a multiple of 2^k
|
||||
*/
|
||||
unsigned power_of_two_multiple(mpz const & n);
|
||||
|
||||
/**
|
||||
\brief Return the position of the most significant bit.
|
||||
Return 0 if the number is negative
|
||||
*/
|
||||
unsigned log2(mpz const & n);
|
||||
|
||||
/**
|
||||
\brief log2(-n)
|
||||
Return 0 if the number is nonegative
|
||||
*/
|
||||
unsigned mlog2(mpz const & n);
|
||||
|
||||
/**
|
||||
\brief Return the bit-size of n. This method is mainly used for collecting statistics.
|
||||
*/
|
||||
unsigned bitsize(mpz const & n);
|
||||
|
||||
/**
|
||||
\brief Return true if the number is a perfect square, and
|
||||
store the square root in 'root'.
|
||||
If the number n is positive and the result is false, then
|
||||
root will contain the smallest integer r such that r*r > n.
|
||||
*/
|
||||
bool is_perfect_square(mpz const & a, mpz & root);
|
||||
|
||||
/**
|
||||
\brief Return the biggest k s.t. 2^k <= a.
|
||||
|
||||
\remark Return 0 if a is not positive.
|
||||
*/
|
||||
unsigned prev_power_of_two(mpz const & a) { return log2(a); }
|
||||
|
||||
/**
|
||||
\brief Return true if a^{1/n} is an integer, and store the result in a.
|
||||
Otherwise return false, and update a with the smallest
|
||||
integer r such that r*r > n.
|
||||
|
||||
\remark This method assumes that if n is even, then a is nonegative
|
||||
*/
|
||||
bool root(mpz & a, unsigned n);
|
||||
bool root(mpz const & a, unsigned n, mpz & r) { set(r, a); return root(r, n); }
|
||||
|
||||
bool is_even(mpz const & a) {
|
||||
if (is_small(a))
|
||||
return !(a.m_val & 0x1);
|
||||
#ifndef _MP_GMP
|
||||
return !(0x1 & digits(a)[0]);
|
||||
#else
|
||||
return mpz_even_p(*a.m_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_odd(mpz const & n) { return !is_even(n); }
|
||||
|
||||
// Store the digits of n into digits, and return the sign.
|
||||
bool decompose(mpz const & n, svector<digit_t> & digits);
|
||||
};
|
||||
|
||||
typedef mpz_manager<true> synch_mpz_manager;
|
||||
typedef mpz_manager<false> unsynch_mpz_manager;
|
||||
|
||||
typedef _scoped_numeral<unsynch_mpz_manager> scoped_mpz;
|
||||
typedef _scoped_numeral<synch_mpz_manager> scoped_synch_mpz;
|
||||
typedef _scoped_numeral_vector<unsynch_mpz_manager> scoped_mpz_vector;
|
||||
|
||||
#endif /* _MPZ_H_ */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue