CVC3

rational.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file rational.cpp
00004  * 
00005  * Author: Sergey Berezin
00006  * 
00007  * Created: Dec 12 22:00:18 GMT 2002
00008  *
00009  * <hr>
00010  *
00011  * License to use, copy, modify, sell and/or distribute this software
00012  * and its documentation for any purpose is hereby granted without
00013  * royalty, subject to the terms and conditions defined in the \ref
00014  * LICENSE file provided with this distribution.
00015  * 
00016  * <hr>
00017  * 
00018  */
00019 /*****************************************************************************/
00020 // Class: Rational
00021 // Author: Sergey Berezin, 12/12/2002 (adapted from Bignum)
00022 //
00023 // Description: Implementation of class Rational.  See comments in
00024 // rational.h file.
00025 ///////////////////////////////////////////////////////////////////////////////
00026 
00027 #ifdef RATIONAL_GMPXX
00028 
00029 #include <gmpxx.h>
00030 #include "compat_hash_set.h"
00031 #include "rational.h"
00032 
00033 namespace CVC3 {
00034 
00035   using namespace std;
00036 
00037   // Implementation of the forward-declared internal class
00038   class Rational::Impl : public mpq_class {
00039   public:
00040     //    mpz_class _n;
00041     // Constructors
00042     Impl() : mpq_class() { }
00043     // Constructor from integer
00044     //    Impl(const mpz_class &x) : mpq_class(x) { }
00045     // Constructor from rational
00046     Impl(const mpq_class &x) : mpq_class(x) { }
00047     // Copy constructor
00048     Impl(const Impl &x) : mpq_class(x) { }
00049     // From pair of integers / strings
00050     Impl(int n, int d) : mpq_class(n,d) { canonicalize(); }
00051     Impl(const mpz_class& n, const mpz_class& d)
00052       : mpq_class(n,d) { canonicalize(); }
00053     // From string(s)
00054     Impl(const string &n, int base): mpq_class(n, base) { canonicalize(); }
00055     Impl(const string &n, const string& d, int base)
00056       : mpq_class(n + "/" + d, base)  { canonicalize(); }
00057     // Destructor
00058     virtual ~Impl() { }
00059     // Getting numerator and denominator.  DON NOT ASSIGN to the result
00060     mpz_class getNum() { return get_num(); }
00061     mpz_class getDen() { return get_den(); }
00062   };
00063 
00064   // Constructors
00065   Rational::Rational() : d_n(new Impl) {
00066 #ifdef _DEBUG_RATIONAL_
00067     int &num_created = getCreated();
00068     num_created++;
00069     printStats();
00070 #endif
00071   }
00072     // Copy constructor
00073   Rational::Rational(const Rational &n) : d_n(new Impl(*n.d_n)) {
00074 #ifdef _DEBUG_RATIONAL_
00075     int &num_created = getCreated();
00076     num_created++;
00077     printStats();
00078 #endif
00079   }
00080 
00081   // Private constructor
00082   Rational::Rational(const Impl& t): d_n(new Impl(t)) {
00083 #ifdef _DEBUG_RATIONAL_
00084     int &num_created = getCreated();
00085     num_created++;
00086     printStats();
00087 #endif
00088   }
00089   Rational::Rational(int n, int d): d_n(new Impl(n, d)) {
00090 #ifdef _DEBUG_RATIONAL_
00091     int &num_created = getCreated();
00092     num_created++;
00093     printStats();
00094 #endif
00095   }
00096   // Constructors from strings
00097   Rational::Rational(const char* n, int base)
00098     : d_n(new Impl(string(n), base)) {
00099 #ifdef _DEBUG_RATIONAL_
00100     int &num_created = getCreated();
00101     num_created++;
00102     printStats();
00103 #endif
00104   }
00105   Rational::Rational(const string& n, int base)
00106     : d_n(new Impl(n, base)) {
00107 #ifdef _DEBUG_RATIONAL_
00108     int &num_created = getCreated();
00109     num_created++;
00110     printStats();
00111 #endif
00112   }
00113   Rational::Rational(const char* n, const char* d, int base)
00114     : d_n(new Impl(string(n), string(d), base)) {
00115 #ifdef _DEBUG_RATIONAL_
00116     int &num_created = getCreated();
00117     num_created++;
00118     printStats();
00119 #endif
00120   }
00121   Rational::Rational(const string& n, const string& d, int base)
00122     : d_n(new Impl(n, d, base)) {
00123 #ifdef _DEBUG_RATIONAL_
00124     int &num_created = getCreated();
00125     num_created++;
00126     printStats();
00127 #endif
00128   }
00129   // Destructor
00130   Rational::~Rational() {
00131     delete d_n;
00132 #ifdef _DEBUG_RATIONAL_
00133     int &num_deleted = getDeleted();
00134     num_deleted++;
00135     printStats();
00136 #endif
00137   }
00138 
00139   // Get components
00140   Rational Rational::getNumerator() const
00141     { return Rational(Impl(d_n->getNum(), 1)); }
00142   Rational Rational::getDenominator() const
00143     { return Rational(Impl(d_n->getDen(), 1)); }
00144 
00145   bool Rational::isInteger() const { return 1 == d_n->getDen(); }
00146 
00147   // Assignment
00148   Rational& Rational::operator=(const Rational& n) {
00149     if(this == &n) return *this;
00150     delete d_n;
00151     d_n = new Impl(*n.d_n);
00152     return *this;
00153   }
00154 
00155   ostream &operator<<(ostream &os, const Rational &n) {
00156     return(os << n.toString());
00157   }
00158 
00159 
00160   // Check that argument is an int and print an error message otherwise
00161 
00162   static void checkInt(const Rational& n, const string& funName) {
00163     DebugAssert(n.isInteger(),
00164     ("CVC3::Rational::" + funName
00165      + ": argument is not an integer: " + n.toString()).c_str());
00166   }
00167 
00168     /* Computes gcd and lcm on *integer* values. Result is always a
00169        positive integer.  In this implementation, it is guaranteed by
00170        GMP. */
00171 
00172   Rational gcd(const Rational &x, const Rational &y) {
00173     mpz_class g;
00174     checkInt(x, "gcd(*x*,y)");
00175     checkInt(y, "gcd(x,*y*)");
00176     mpz_gcd(g.get_mpz_t(), x.d_n->get_num_mpz_t(), y.d_n->get_num_mpz_t());
00177     return Rational(Rational::Impl(g,1));
00178   }
00179  
00180   Rational gcd(const vector<Rational> &v) {
00181     mpz_class g(1);
00182     if(v.size() > 0) {
00183       checkInt(v[0], "gcd(vector<Rational>[0])");
00184       g = v[0].d_n->getNum();
00185     }
00186     for(unsigned i=1; i<v.size(); i++) {
00187       checkInt(v[i], "gcd(vector<Rational>)");
00188       if(*v[i].d_n != 0)
00189   mpz_gcd(g.get_mpz_t(), g.get_mpz_t(), v[i].d_n->get_num_mpz_t());
00190     }
00191     return Rational(Rational::Impl(g,1));
00192   }
00193 
00194   Rational lcm(const Rational &x, const Rational &y) {
00195     mpz_class g;
00196     checkInt(x, "lcm(*x*,y)");
00197     checkInt(y, "lcm(x,*y*)");
00198     mpz_lcm(g.get_mpz_t(), x.d_n->get_num_mpz_t(), y.d_n->get_num_mpz_t());
00199     return Rational(Rational::Impl(g, 1));
00200   }
00201 
00202   Rational lcm(const vector<Rational> &v) {
00203     mpz_class g(1);
00204     for(unsigned i=0; i<v.size(); i++) {
00205       checkInt(v[i], "lcm(vector<Rational>)");
00206       if(*v[i].d_n != 0)
00207   mpz_lcm(g.get_mpz_t(), g.get_mpz_t(), v[i].d_n->get_num_mpz_t());
00208     }
00209     return Rational(Rational::Impl(g,1));
00210   }
00211 
00212   Rational abs(const Rational &x) {
00213     return Rational(Rational::Impl(abs(*x.d_n)));
00214   }
00215 
00216   Rational floor(const Rational &x) {
00217     mpz_class q;
00218     mpz_fdiv_q(q.get_mpz_t(), x.d_n->get_num_mpz_t(), x.d_n->get_den_mpz_t());
00219     return Rational(Rational::Impl(q,1));
00220   }
00221 
00222   Rational ceil(const Rational &x) {
00223     mpz_class q;
00224     mpz_cdiv_q(q.get_mpz_t(), x.d_n->get_num_mpz_t(), x.d_n->get_den_mpz_t());
00225     return Rational(Rational::Impl(q,1));
00226   }
00227 
00228   Rational mod(const Rational &x, const Rational &y) {
00229     checkInt(x, "mod(*x*,y)");
00230     checkInt(y, "mod(x,*y*)");
00231     mpz_class r;
00232     mpz_mod(r.get_mpz_t(), x.d_n->get_num_mpz_t(), y.d_n->get_num_mpz_t());
00233     return(Rational(Rational::Impl(r,1)));
00234   }
00235 
00236   Rational intRoot(const Rational& base, unsigned long int n)
00237   {
00238     return Rational(Rational::Impl(0,1));
00239   }
00240 
00241   string Rational::toString(int base) const {
00242     char *tmp = mpq_get_str(NULL, base, d_n->get_mpq_t());
00243     string res(tmp);
00244 //    delete tmp;
00245     free(tmp);
00246     return(res);
00247   }
00248 
00249   size_t Rational::hash() const {
00250     std::hash<const char *> h;
00251     return h(toString().c_str());
00252   }
00253   
00254   void Rational::print() const {
00255     cout << (*d_n) << endl;
00256   }
00257 
00258 
00259 
00260   // Unary minus
00261   Rational Rational::operator-() const {
00262     return Rational(Rational::Impl(- (*d_n)));
00263   }
00264   
00265   Rational &Rational::operator+=(const Rational &n2) {
00266     *d_n += (*n2.d_n);
00267     return *this;
00268   }
00269   
00270   Rational &Rational::operator-=(const Rational &n2) {
00271     *d_n -= (*n2.d_n);
00272     return *this;
00273   }
00274   
00275   Rational &Rational::operator*=(const Rational &n2) {
00276     *d_n *= (*n2.d_n);
00277     return *this;
00278   }
00279   
00280   Rational &Rational::operator/=(const Rational &n2) {
00281     *d_n /= (*n2.d_n);
00282     return *this;
00283   }
00284 
00285   int Rational::getInt() const {
00286     checkInt(*this, "getInt()");
00287     return mpz_get_si(d_n->get_num_mpz_t());
00288   }
00289 
00290   unsigned int Rational::getUnsigned() const {
00291     checkInt(*this, "getUnsigned()");
00292     return mpz_get_ui(d_n->get_num_mpz_t());
00293   }
00294 
00295 #ifdef _DEBUG_RATIONAL_
00296   void Rational::printStats() {
00297       int &num_created = getCreated();
00298       int &num_deleted = getDeleted();
00299       if(num_created % 1000 == 0 || num_deleted % 1000 == 0) {
00300   std::cerr << "Rational(" << *d_n << "): created " << num_created
00301       << ", deleted " << num_deleted
00302       << ", currently alive " << num_created-num_deleted
00303       << std::endl;
00304       }
00305     }
00306 #endif
00307 
00308     bool operator==(const Rational &n1, const Rational &n2) {
00309       return(*n1.d_n == *n2.d_n);
00310     }
00311 
00312     bool operator<(const Rational &n1, const Rational &n2) {
00313       return(*n1.d_n < *n2.d_n);
00314     }
00315 
00316     bool operator<=(const Rational &n1, const Rational &n2) {
00317       return(*n1.d_n <= *n2.d_n);
00318     }
00319 
00320     bool operator>(const Rational &n1, const Rational &n2) {
00321       return(*n1.d_n > *n2.d_n);
00322     }
00323 
00324     bool operator>=(const Rational &n1, const Rational &n2) {
00325       return(*n1.d_n >= *n2.d_n);
00326     }
00327 
00328     bool operator!=(const Rational &n1, const Rational &n2) {
00329       return(*n1.d_n != *n2.d_n);
00330     }
00331 
00332     Rational operator+(const Rational &n1, const Rational &n2) {
00333       return Rational(Rational::Impl(*n1.d_n + *n2.d_n));
00334     }
00335 
00336     Rational operator-(const Rational &n1, const Rational &n2) {
00337       return Rational(Rational::Impl((*n1.d_n) - (*n2.d_n)));
00338     }
00339 
00340     Rational operator*(const Rational &n1, const Rational &n2) {
00341       return Rational(Rational::Impl((*n1.d_n) * (*n2.d_n)));
00342     }
00343 
00344     Rational operator/(const Rational &n1, const Rational &n2) {
00345       return Rational(Rational::Impl(*n1.d_n / *n2.d_n));
00346     }
00347 
00348     Rational operator%(const Rational &n1, const Rational &n2) {
00349       return Rational(Rational::Impl(*n1.d_n + *n2.d_n));
00350     }
00351 
00352 
00353   // Implementation of the forward-declared internal class
00354   class Unsigned::Impl : public mpz_class {
00355   public:
00356     //    mpz_class _n;
00357     // Constructors
00358     Impl() : mpz_class() { }
00359     // Constructor from integer
00360     //    Impl(const mpz_class &x) : mpq_class(x) { }
00361     // Constructor from rational
00362     Impl(const mpz_class &x) : mpz_class(x) { }
00363     // Copy constructor
00364     Impl(const Impl &x) : mpz_class(x) { }
00365     // From pair of integers / strings
00366     Impl(int n) : mpz_class(n) { }
00367     Impl(const mpz_class& n, const mpz_class& d)
00368       : mpq_class(n,d) { canonicalize(); }
00369     // From string(s)
00370     Impl(const string &n, int base): mpz_class(n, base) { }
00371     // Destructor
00372     virtual ~Impl() { }
00373   };
00374 
00375   // Constructors
00376   Unsigned::Unsigned() : d_n(new Impl) { }
00377   // Copy constructor
00378   Unsigned::Unsigned(const Unsigned &n) : d_n(new Impl(*n.d_n)) { }
00379 
00380   // Private constructor
00381   Unsigned::Unsigned(const Impl& t): d_n(new Impl(t)) { }
00382   // Constructors from strings
00383   Unsigned::Unsigned(const char* n, int base)
00384     : d_n(new Impl(string(n), base)) { }
00385   Unsigned::Unsigned(const string& n, int base)
00386     : d_n(new Impl(n, base)) { }
00387   // Destructor
00388   Unsigned::~Unsigned() {
00389     delete d_n;
00390   }
00391 
00392   // Assignment
00393   Unsigned& Unsigned::operator=(const Unsigned& n) {
00394     if(this == &n) return *this;
00395     delete d_n;
00396     d_n = new Impl(*n.d_n);
00397     return *this;
00398   }
00399 
00400   ostream &operator<<(ostream &os, const Unsigned &n) {
00401     return(os << n.toString());
00402   }
00403 
00404 
00405     /* Computes gcd and lcm on *integer* values. Result is always a
00406        positive integer.  In this implementation, it is guaranteed by
00407        GMP. */
00408 
00409   Unsigned gcd(const Unsigned &x, const Unsigned &y) {
00410     mpz_class g;
00411     mpz_gcd(g, *(x.d_n), *(y.d_n));
00412     return Unsigned(Unsigned::Impl(g));
00413   }
00414  
00415   Unsigned gcd(const vector<Unsigned> &v) {
00416     mpz_class g(1);
00417     if(v.size() > 0) {
00418       g = *(v[0].d_n);
00419     }
00420     for(unsigned i=1; i<v.size(); i++) {
00421       if(*v[i].d_n != 0)
00422   mpz_gcd(g, g, *(v[i].d_n));
00423     }
00424     return Unsigned(Unsigned::Impl(g));
00425   }
00426 
00427   Unsigned lcm(const Unsigned &x, const Unsigned &y) {
00428     mpz_class g;
00429     mpz_lcm(g, *x.d_n, *y.d_n);
00430     return Unsigned(Unsigned::Impl(g));
00431   }
00432 
00433   Unsigned lcm(const vector<Unsigned> &v) {
00434     mpz_class g(1);
00435     for(unsigned i=0; i<v.size(); i++) {
00436       if(*v[i].d_n != 0)
00437   mpz_lcm(g, g, *v[i].d_n);
00438     }
00439     return Unsigned(Unsigned::Impl(g));
00440   }
00441 
00442   Unsigned abs(const Unsigned &x) {
00443     return Unsigned(Unsigned::Impl(abs(*x.d_n)));
00444   }
00445 
00446   Unsigned mod(const Unsigned &x, const Unsigned &y) {
00447     mpz_class r;
00448     mpz_mod(r, *x.d_n, *y.d_n);
00449     return(Unsigned(Unsigned::Impl(r)));
00450   }
00451 
00452   Unsigned intRoot(const Unsigned& base, unsigned long int n)
00453   {
00454     return Unsigned(Unsigned::Impl(0,1));
00455   }
00456 
00457   string Unsigned::toString(int base) const {
00458     char *tmp = mpz_get_str(NULL, base, *d_n);
00459     string res(tmp);
00460 //    delete tmp;
00461     free(tmp);
00462     return(res);
00463   }
00464 
00465   size_t Unsigned::hash() const {
00466     std::hash<const char *> h;
00467     return h(toString().c_str());
00468   }
00469   
00470   void Unsigned::print() const {
00471     cout << (*d_n) << endl;
00472   }
00473 
00474 
00475 
00476   // Unary minus
00477   Unsigned Unsigned::operator-() const {
00478     return Unsigned(Unsigned::Impl(- (*d_n)));
00479   }
00480   
00481   Unsigned &Unsigned::operator+=(const Unsigned &n2) {
00482     *d_n += (*n2.d_n);
00483     return *this;
00484   }
00485   
00486   Unsigned &Unsigned::operator-=(const Unsigned &n2) {
00487     *d_n -= (*n2.d_n);
00488     return *this;
00489   }
00490   
00491   Unsigned &Unsigned::operator*=(const Unsigned &n2) {
00492     *d_n *= (*n2.d_n);
00493     return *this;
00494   }
00495   
00496   Unsigned &Unsigned::operator/=(const Unsigned &n2) {
00497     *d_n /= (*n2.d_n);
00498     return *this;
00499   }
00500 
00501   int Unsigned::getInt() const {
00502     return mpz_get_si(*d_n);
00503   }
00504 
00505   unsigned int Unsigned::getUnsigned() const {
00506     return mpz_get_ui(*d_n);
00507   }
00508 
00509     bool operator==(const Unsigned &n1, const Unsigned &n2) {
00510       return(*n1.d_n == *n2.d_n);
00511     }
00512 
00513     bool operator<(const Unsigned &n1, const Unsigned &n2) {
00514       return(*n1.d_n < *n2.d_n);
00515     }
00516 
00517     bool operator<=(const Unsigned &n1, const Unsigned &n2) {
00518       return(*n1.d_n <= *n2.d_n);
00519     }
00520 
00521     bool operator>(const Unsigned &n1, const Unsigned &n2) {
00522       return(*n1.d_n > *n2.d_n);
00523     }
00524 
00525     bool operator>=(const Unsigned &n1, const Unsigned &n2) {
00526       return(*n1.d_n >= *n2.d_n);
00527     }
00528 
00529     bool operator!=(const Unsigned &n1, const Unsigned &n2) {
00530       return(*n1.d_n != *n2.d_n);
00531     }
00532 
00533     Unsigned operator+(const Unsigned &n1, const Unsigned &n2) {
00534       return Unsigned(Unsigned::Impl(*n1.d_n + *n2.d_n));
00535     }
00536 
00537     Unsigned operator-(const Unsigned &n1, const Unsigned &n2) {
00538       return Unsigned(Unsigned::Impl((*n1.d_n) - (*n2.d_n)));
00539     }
00540 
00541     Unsigned operator*(const Unsigned &n1, const Unsigned &n2) {
00542       return Unsigned(Unsigned::Impl((*n1.d_n) * (*n2.d_n)));
00543     }
00544 
00545     Unsigned operator/(const Unsigned &n1, const Unsigned &n2) {
00546       return Unsigned(Unsigned::Impl(*n1.d_n / *n2.d_n));
00547     }
00548 
00549     Unsigned operator%(const Unsigned &n1, const Unsigned &n2) {
00550       return Unsigned(Unsigned::Impl(*n1.d_n + *n2.d_n));
00551     }
00552 
00553 }; /* close namespace */
00554 
00555 
00556 #endif