/*****************************************************************************/
/*!
* \file rational.cpp
*
* Author: Sergey Berezin
*
* Created: Dec 12 22:00:18 GMT 2002
*
*
*
* License to use, copy, modify, sell and/or distribute this software
* and its documentation for any purpose is hereby granted without
* royalty, subject to the terms and conditions defined in the \ref
* LICENSE file provided with this distribution.
*
*
*
*/
/*****************************************************************************/
// Class: Rational
// Author: Sergey Berezin, 12/12/2002 (adapted from Bignum)
//
// Description: Implementation of class Rational. See comments in
// rational.h file.
///////////////////////////////////////////////////////////////////////////////
#ifdef RATIONAL_GMPXX
#include
#include "compat_hash_set.h"
#include "rational.h"
namespace CVC3 {
using namespace std;
// Implementation of the forward-declared internal class
class Rational::Impl : public mpq_class {
public:
// mpz_class _n;
// Constructors
Impl() : mpq_class() { }
// Constructor from integer
// Impl(const mpz_class &x) : mpq_class(x) { }
// Constructor from rational
Impl(const mpq_class &x) : mpq_class(x) { }
// Copy constructor
Impl(const Impl &x) : mpq_class(x) { }
// From pair of integers / strings
Impl(int n, int d) : mpq_class(n,d) { canonicalize(); }
Impl(const mpz_class& n, const mpz_class& d)
: mpq_class(n,d) { canonicalize(); }
// From string(s)
Impl(const string &n, int base): mpq_class(n, base) { canonicalize(); }
Impl(const string &n, const string& d, int base)
: mpq_class(n + "/" + d, base) { canonicalize(); }
// Destructor
virtual ~Impl() { }
// Getting numerator and denominator. DON NOT ASSIGN to the result
mpz_class getNum() { return get_num(); }
mpz_class getDen() { return get_den(); }
};
// Constructors
Rational::Rational() : d_n(new Impl) {
#ifdef _DEBUG_RATIONAL_
int &num_created = getCreated();
num_created++;
printStats();
#endif
}
// Copy constructor
Rational::Rational(const Rational &n) : d_n(new Impl(*n.d_n)) {
#ifdef _DEBUG_RATIONAL_
int &num_created = getCreated();
num_created++;
printStats();
#endif
}
// Private constructor
Rational::Rational(const Impl& t): d_n(new Impl(t)) {
#ifdef _DEBUG_RATIONAL_
int &num_created = getCreated();
num_created++;
printStats();
#endif
}
Rational::Rational(int n, int d): d_n(new Impl(n, d)) {
#ifdef _DEBUG_RATIONAL_
int &num_created = getCreated();
num_created++;
printStats();
#endif
}
// Constructors from strings
Rational::Rational(const char* n, int base)
: d_n(new Impl(string(n), base)) {
#ifdef _DEBUG_RATIONAL_
int &num_created = getCreated();
num_created++;
printStats();
#endif
}
Rational::Rational(const string& n, int base)
: d_n(new Impl(n, base)) {
#ifdef _DEBUG_RATIONAL_
int &num_created = getCreated();
num_created++;
printStats();
#endif
}
Rational::Rational(const char* n, const char* d, int base)
: d_n(new Impl(string(n), string(d), base)) {
#ifdef _DEBUG_RATIONAL_
int &num_created = getCreated();
num_created++;
printStats();
#endif
}
Rational::Rational(const string& n, const string& d, int base)
: d_n(new Impl(n, d, base)) {
#ifdef _DEBUG_RATIONAL_
int &num_created = getCreated();
num_created++;
printStats();
#endif
}
// Destructor
Rational::~Rational() {
delete d_n;
#ifdef _DEBUG_RATIONAL_
int &num_deleted = getDeleted();
num_deleted++;
printStats();
#endif
}
// Get components
Rational Rational::getNumerator() const
{ return Rational(Impl(d_n->getNum(), 1)); }
Rational Rational::getDenominator() const
{ return Rational(Impl(d_n->getDen(), 1)); }
bool Rational::isInteger() const { return 1 == d_n->getDen(); }
// Assignment
Rational& Rational::operator=(const Rational& n) {
if(this == &n) return *this;
delete d_n;
d_n = new Impl(*n.d_n);
return *this;
}
ostream &operator<<(ostream &os, const Rational &n) {
return(os << n.toString());
}
// Check that argument is an int and print an error message otherwise
static void checkInt(const Rational& n, const string& funName) {
DebugAssert(n.isInteger(),
("CVC3::Rational::" + funName
+ ": argument is not an integer: " + n.toString()).c_str());
}
/* Computes gcd and lcm on *integer* values. Result is always a
positive integer. In this implementation, it is guaranteed by
GMP. */
Rational gcd(const Rational &x, const Rational &y) {
mpz_class g;
checkInt(x, "gcd(*x*,y)");
checkInt(y, "gcd(x,*y*)");
mpz_gcd(g.get_mpz_t(), x.d_n->get_num_mpz_t(), y.d_n->get_num_mpz_t());
return Rational(Rational::Impl(g,1));
}
Rational gcd(const vector &v) {
mpz_class g(1);
if(v.size() > 0) {
checkInt(v[0], "gcd(vector[0])");
g = v[0].d_n->getNum();
}
for(unsigned i=1; i)");
if(*v[i].d_n != 0)
mpz_gcd(g.get_mpz_t(), g.get_mpz_t(), v[i].d_n->get_num_mpz_t());
}
return Rational(Rational::Impl(g,1));
}
Rational lcm(const Rational &x, const Rational &y) {
mpz_class g;
checkInt(x, "lcm(*x*,y)");
checkInt(y, "lcm(x,*y*)");
mpz_lcm(g.get_mpz_t(), x.d_n->get_num_mpz_t(), y.d_n->get_num_mpz_t());
return Rational(Rational::Impl(g, 1));
}
Rational lcm(const vector &v) {
mpz_class g(1);
for(unsigned i=0; i)");
if(*v[i].d_n != 0)
mpz_lcm(g.get_mpz_t(), g.get_mpz_t(), v[i].d_n->get_num_mpz_t());
}
return Rational(Rational::Impl(g,1));
}
Rational abs(const Rational &x) {
return Rational(Rational::Impl(abs(*x.d_n)));
}
Rational floor(const Rational &x) {
mpz_class q;
mpz_fdiv_q(q.get_mpz_t(), x.d_n->get_num_mpz_t(), x.d_n->get_den_mpz_t());
return Rational(Rational::Impl(q,1));
}
Rational ceil(const Rational &x) {
mpz_class q;
mpz_cdiv_q(q.get_mpz_t(), x.d_n->get_num_mpz_t(), x.d_n->get_den_mpz_t());
return Rational(Rational::Impl(q,1));
}
Rational mod(const Rational &x, const Rational &y) {
checkInt(x, "mod(*x*,y)");
checkInt(y, "mod(x,*y*)");
mpz_class r;
mpz_mod(r.get_mpz_t(), x.d_n->get_num_mpz_t(), y.d_n->get_num_mpz_t());
return(Rational(Rational::Impl(r,1)));
}
string Rational::toString(int base) const {
char *tmp = mpq_get_str(NULL, base, d_n->get_mpq_t());
string res(tmp);
// delete tmp;
free(tmp);
return(res);
}
size_t Rational::hash() const {
std::hash h;
return h(toString().c_str());
}
void Rational::print() const {
cout << (*d_n) << endl;
}
// Unary minus
Rational Rational::operator-() const {
return Rational(Rational::Impl(- (*d_n)));
}
Rational &Rational::operator+=(const Rational &n2) {
*d_n += (*n2.d_n);
return *this;
}
Rational &Rational::operator-=(const Rational &n2) {
*d_n -= (*n2.d_n);
return *this;
}
Rational &Rational::operator*=(const Rational &n2) {
*d_n *= (*n2.d_n);
return *this;
}
Rational &Rational::operator/=(const Rational &n2) {
*d_n /= (*n2.d_n);
return *this;
}
int Rational::getInt() const {
checkInt(*this, "getInt()");
return mpz_get_si(d_n->get_num_mpz_t());
}
unsigned int Rational::getUnsigned() const {
checkInt(*this, "getUnsigned()");
return mpz_get_ui(d_n->get_num_mpz_t());
}
#ifdef _DEBUG_RATIONAL_
void Rational::printStats() {
int &num_created = getCreated();
int &num_deleted = getDeleted();
if(num_created % 1000 == 0 || num_deleted % 1000 == 0) {
std::cerr << "Rational(" << *d_n << "): created " << num_created
<< ", deleted " << num_deleted
<< ", currently alive " << num_created-num_deleted
<< std::endl;
}
}
#endif
bool operator==(const Rational &n1, const Rational &n2) {
return(*n1.d_n == *n2.d_n);
}
bool operator<(const Rational &n1, const Rational &n2) {
return(*n1.d_n < *n2.d_n);
}
bool operator<=(const Rational &n1, const Rational &n2) {
return(*n1.d_n <= *n2.d_n);
}
bool operator>(const Rational &n1, const Rational &n2) {
return(*n1.d_n > *n2.d_n);
}
bool operator>=(const Rational &n1, const Rational &n2) {
return(*n1.d_n >= *n2.d_n);
}
bool operator!=(const Rational &n1, const Rational &n2) {
return(*n1.d_n != *n2.d_n);
}
Rational operator+(const Rational &n1, const Rational &n2) {
return Rational(Rational::Impl(*n1.d_n + *n2.d_n));
}
Rational operator-(const Rational &n1, const Rational &n2) {
return Rational(Rational::Impl((*n1.d_n) - (*n2.d_n)));
}
Rational operator*(const Rational &n1, const Rational &n2) {
return Rational(Rational::Impl((*n1.d_n) * (*n2.d_n)));
}
Rational operator/(const Rational &n1, const Rational &n2) {
return Rational(Rational::Impl(*n1.d_n / *n2.d_n));
}
Rational operator%(const Rational &n1, const Rational &n2) {
return Rational(Rational::Impl(*n1.d_n + *n2.d_n));
}
}; /* close namespace */
#endif