3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-11 03:33:35 +00:00
z3/lib/gmp_big_rational.h
Leonardo de Moura e9eab22e5c Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:35:25 -07:00

194 lines
4.9 KiB
C++

/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
gmp_big_rational.h
Abstract:
Big rationals using gmp
Author:
Leonardo de Moura (leonardo) 2006-09-26.
Revision History:
--*/
#ifndef _GMP_BIG_RATIONAL_H_
#define _GMP_BIG_RATIONAL_H_
#ifndef NO_GMP
#include<string>
#include<gmp.h>
#include"util.h"
#include"debug.h"
#include"trace.h"
class big_rational {
mpq_t m_data;
static mpz_t m_tmp;
static bool m_tmp_initialized;
static mpz_t & get_tmp() {
if (!m_tmp_initialized) {
mpz_init(m_tmp);
m_tmp_initialized = true;
}
return m_tmp;
}
static mpz_t m_int_min;
static mpz_t m_int_max;
static mpz_t m_uint_max;
static mpz_t m_two32;
static mpz_t m_int64_min;
static mpz_t m_int64_max;
static mpz_t m_uint64_max;
static bool m_has_limits;
static void init_limits();
static mpz_t & int64_min() {
if (!m_has_limits) {
init_limits();
}
return m_int64_min;
}
static mpz_t & int64_max() {
if (!m_has_limits) {
init_limits();
}
return m_int64_max;
}
static mpz_t & uint64_max() {
if (!m_has_limits) {
init_limits();
}
return m_uint64_max;
}
static mpz_t & uint_max() {
if (!m_has_limits) {
init_limits();
}
return m_uint_max;
}
static mpz_t & two32() {
if (!m_has_limits) {
init_limits();
}
return m_two32;
}
public:
big_rational() { mpq_init(m_data); reset(); }
big_rational(int n) { mpq_init(m_data); mpq_set_si(m_data, n, 1); }
~big_rational() { mpq_clear(m_data); }
void reset() { mpq_set_si(m_data, 0, 1); }
unsigned hash() const { return mpz_get_si(mpq_numref(m_data)); }
void set(int num, int den) {
mpq_set_si(m_data, num, den);
mpq_canonicalize(m_data);
}
void setu(unsigned num) {
mpq_set_ui(m_data, num, 1);
mpq_canonicalize(m_data);
}
void set(const char * str) {
mpq_set_str(m_data, str, 10);
}
bool is_int() const {
return mpz_cmp_ui(mpq_denref(m_data), 1) == 0;
}
bool is_even() const {
if (!is_int()) {
return false;
}
mpz_t & tmp = get_tmp();
mpq_get_num(tmp, m_data);
return mpz_even_p(tmp) != 0;
}
bool is_int64() const {
if (!is_int()) {
return false;
}
mpz_t & tmp = get_tmp();
mpq_get_num(tmp, m_data);
return mpz_fits_slong_p(tmp) ||
(mpz_cmp(tmp, int64_min()) >= 0 && mpz_cmp(tmp, int64_max()) <= 0);
}
bool is_uint64() const {
if (!is_int()) {
return false;
}
mpz_t & tmp = get_tmp();
mpq_get_num(tmp, m_data);
return mpz_sgn(tmp) >= 0 && (mpz_fits_ulong_p(tmp) || mpz_cmp(tmp, uint64_max()) <= 0);
}
int64 get_int64() const;
uint64 get_uint64() const;
void neg() { mpq_neg(m_data, m_data); }
big_rational & operator=(const big_rational & r) {
mpq_set(m_data, r.m_data);
return *this;
}
bool operator==(const big_rational & r) const { return mpq_equal(m_data, r.m_data) != 0; }
bool operator<(const big_rational & r) const { return mpq_cmp(m_data, r.m_data) < 0; }
big_rational & operator+=(const big_rational & r) {
mpq_add(m_data, m_data, r.m_data);
return *this;
}
big_rational & operator-=(const big_rational & r) {
mpq_sub(m_data, m_data, r.m_data);
return *this;
}
big_rational & operator*=(const big_rational & r) {
mpq_mul(m_data, m_data, r.m_data);
return *this;
}
big_rational & operator/=(const big_rational & r) {
mpq_div(m_data, m_data, r.m_data);
return *this;
}
big_rational & operator%=(const big_rational & r) {
mpz_t & tmp = get_tmp();
mpz_tdiv_r(tmp, mpq_numref(m_data), mpq_numref(r.m_data));
mpq_set_z(m_data, tmp);
return *this;
}
friend void div(const big_rational & r1, const big_rational & r2, big_rational & result) {
mpz_t & tmp = get_tmp();
mpz_tdiv_q(tmp, mpq_numref(r1.m_data), mpq_numref(r2.m_data));
mpq_set_z(result.m_data, tmp);
}
void get_numerator(big_rational & result) {
mpz_t & tmp = get_tmp();
mpq_get_num(tmp, m_data);
mpq_set_z(result.m_data, tmp);
}
void get_denominator(big_rational & result) {
mpz_t & tmp = get_tmp();
mpq_get_den(tmp, m_data);
mpq_set_z(result.m_data, tmp);
}
void get_floor(big_rational & result) {
mpz_t & tmp = get_tmp();
mpz_fdiv_q(tmp, mpq_numref(m_data), mpq_denref(m_data));
mpq_set_z(result.m_data, tmp);
}
std::string to_string() const;
#ifdef Z3DEBUG
static void test() {
init_limits();
}
#endif
};
#endif
#endif /* _GMP_BIG_RATIONAL_H_ */