CVC3

rational-native.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file rational-native.cpp
00004  *
00005  * \brief Implementation of class Rational using native (bounded
00006  * precision) computer arithmetic
00007  *
00008  * Author: Sergey Berezin
00009  *
00010  * Created: Mon Jul 28 12:18:03 2003
00011  *
00012  * <hr>
00013  * License to use, copy, modify, sell and/or distribute this software
00014  * and its documentation for any purpose is hereby granted without
00015  * royalty, subject to the terms and conditions defined in the \ref
00016  * LICENSE file provided with this distribution.
00017  *
00018  * <hr>
00019  *
00020  */
00021 /*****************************************************************************/
00022 
00023 #ifdef RATIONAL_NATIVE
00024 
00025 #include "compat_hash_set.h"
00026 #include "rational.h"
00027 // For atol() (ASCII to long)
00028 #include <stdlib.h>
00029 #include <limits.h>
00030 #include <errno.h>
00031 #include <sstream>
00032 #include <math.h>
00033 
00034 #define OVERFLOW_MSG "\nThis is NOT a bug, but an explicit feature to preserve soundness\nwhen CVC3 uses native computer arithmetic (finite precision).  To\navoid these types of errors, please recompile CVC3 with GMP library."
00035 
00036 namespace CVC3 {
00037 
00038   using namespace std;
00039 
00040   //! Add two integers and check for overflows
00041   static long int plus(long int x, long int y) {
00042     long int res = x+y;
00043     FatalAssert(((x > 0) != (y > 0)) || ((x > 0) == (res > 0)),
00044                 "plus(x,y): arithmetic overflow" OVERFLOW_MSG);
00045     return res;
00046   }
00047 
00048   //! Add two integers and check for overflows
00049   static unsigned long uplus(unsigned long x, unsigned long y) {
00050     unsigned long res = x+y;
00051     FatalAssert(res >= x && res >= y,
00052                 "uplus(x,y): arithmetic overflow" OVERFLOW_MSG);
00053     return res;
00054   }
00055 
00056   //! Subtract two unsigned integers and check for overflows
00057   static unsigned long unsigned_minus(unsigned long x, unsigned long y) {
00058     unsigned long res = x-y;
00059     FatalAssert(res <= x,
00060                 "unsigned_minus(x,y): arithmetic overflow" OVERFLOW_MSG);
00061     return res;
00062   }
00063 
00064   //! Multiply two unsigned integers and check for overflows
00065   static unsigned long umult(unsigned long x, unsigned long y) {
00066     unsigned long res = x*y;
00067     FatalAssert(res == 0 || res/x == y,
00068                 "umult(x,y): arithmetic overflow" OVERFLOW_MSG);
00069     return res;
00070   }
00071 
00072   //! Shift two unsigned integers and check for overflow
00073   static unsigned long ushift(unsigned long x, unsigned y) {
00074     FatalAssert(y < (unsigned)numeric_limits<unsigned long>::digits,
00075                 "ushift(x,y): arithmetic overflow" OVERFLOW_MSG);
00076     unsigned long res = (x << y);
00077     FatalAssert((res >> y) == x,
00078                 "ushift(x,y): arithmetic overflow" OVERFLOW_MSG);
00079     return res;
00080   }
00081 
00082   //! Compute GCD using Euclid's algorithm (from Aaron Stump's code)
00083   static unsigned long ugcd(unsigned long n1, unsigned long n2) {
00084     DebugAssert(n1!=0 && n2!=0,
00085     "gcd("+int2string(n1)+", "+int2string(n2)+"): bad args");
00086   if (n1 < n2) {
00087     long int tmp = n1;
00088     n1 = n2;
00089     n2 = tmp;
00090   }
00091 
00092   // at this point, n1 >= n2
00093   long int r = n1 % n2;
00094   if (!r)
00095     return n2;
00096 
00097   return ugcd(n2, r);
00098 }
00099 
00100   //! Unary minus which checks for overflows
00101   static long int uminus(long int x) {
00102     FatalAssert(x == 0 || x != -x, "uminus(x): arithmetic overflow"
00103                 OVERFLOW_MSG);
00104     return -x;
00105   }
00106 
00107   //! Multiply two integers and check for overflows
00108   static long int mult(long int x, long int y) {
00109     long int res = x*y;
00110     FatalAssert(x==0 || res/x == y, "mult(x,y): arithmetic overflow"
00111                 OVERFLOW_MSG);
00112     return res;
00113   }
00114 
00115   //! Compute GCD using Euclid's algorithm (from Aaron Stump's code)
00116   static long int gcd(long int n1, long int n2) {
00117     DebugAssert(n1!=0 && n2!=0,
00118     "gcd("+int2string(n1)+", "+int2string(n2)+"): bad args");
00119   // First, make the arguments positive
00120   if(n1 < 0) n1 = uminus(n1);
00121   if(n2 < 0) n2 = uminus(n2);
00122 
00123   if (n1 < n2) {
00124     long int tmp = n1;
00125     n1 = n2;
00126     n2 = tmp;
00127   }
00128 
00129   // at this point, n1 >= n2
00130   long int r = n1 % n2;
00131   if (!r)
00132     return n2;
00133 
00134   return gcd(n2, r);
00135 }
00136 
00137   //! Compute LCM
00138   static long int lcm(long int n1, long int n2) {
00139     long int g = gcd(n1,n2);
00140     return mult(n1/g, n2);
00141   }
00142 
00143   static long int ulcm(unsigned long n1, unsigned long n2) {
00144     long int g = ugcd(n1,n2);
00145     return umult(n1/g, n2);
00146   }
00147 
00148   // Implementation of the forward-declared internal class
00149   class Rational::Impl {
00150     long int d_num; //!< Numerator
00151     long int d_denom; //!< Denominator
00152     //! Make the rational number canonical
00153     void canonicalize();
00154   public:
00155     //! Default Constructor
00156     Impl(): d_num(0), d_denom(1) { }
00157     //! Copy constructor
00158     Impl(const Impl &x) : d_num(x.d_num), d_denom(x.d_denom) { }
00159     //! Constructor from unsigned long
00160     Impl(unsigned long n) :d_num(n), d_denom(1) {
00161       FatalAssert(d_num >= 0, "Rational::Impl(unsigned long) - arithmetic overflow");
00162     }
00163     //! Constructor from a pair of integers
00164     Impl(long int n, long int d): d_num(n), d_denom(d) { canonicalize(); }
00165     //! Constructor from a string
00166     Impl(const string &n, int base);
00167     //! Constructor from a pair of strings
00168     Impl(const string &n, const string& d, int base);
00169     // Destructor
00170     virtual ~Impl() { }
00171     //! Get numerator
00172     long int getNum() const { return d_num; }
00173     //! Get denominator
00174     long int getDen() const { return d_denom; }
00175 
00176     //! Unary minus
00177     Impl operator-() const;
00178 
00179     //! Equality
00180     friend bool operator==(const Impl& x, const Impl& y) {
00181       return (x.d_num == y.d_num && x.d_denom == y.d_denom);
00182     }
00183     //! Dis-equality
00184     friend bool operator!=(const Impl& x, const Impl& y) {
00185       return (x.d_num != y.d_num || x.d_denom != y.d_denom);
00186     }
00187     /*!
00188      * Compare x=n1/d1 and y=n2/d2 as n1*f2 < n2*f1, where f1=d1/f,
00189      * f2=d2/f, and f=lcm(d1,d2)
00190      */
00191     friend bool operator<(const Impl& x, const Impl& y) {
00192       Impl diff(x-y);
00193       return diff.d_num < 0;
00194     }
00195 
00196     friend bool operator<=(const Impl& x, const Impl& y) {
00197       return (x == y || x < y);
00198     }
00199 
00200     friend bool operator>(const Impl& x, const Impl& y) {
00201       Impl diff(x-y);
00202       return diff.d_num > 0;
00203     }
00204 
00205     friend bool operator>=(const Impl& x, const Impl& y) {
00206       return (x == y || x > y);
00207     }
00208 
00209     /*! Addition of x=n1/d1 and y=n2/d2: n1*g2 + n2*g1, where g1=d1/g,
00210      * g2=d2/g, and g=lcm(d1,d2)
00211      */
00212     friend Impl operator+(const Impl& x, const Impl& y) {
00213       long int d1(x.getDen()), d2(y.getDen());
00214       long int f(lcm(d1,d2)), f1(f/d1), f2(f/d2);
00215       long int n = plus(mult(x.getNum(), f1),  mult(y.getNum(), f2));
00216       return Impl(n, f);
00217     }
00218 
00219     friend Impl operator-(const Impl& x, const Impl& y) {
00220       TRACE("rational", "operator-(", x, ", "+y.toString()+")");
00221       long int d1(x.getDen()), d2(y.getDen());
00222       long int f(lcm(d1,d2)), f1(f/d1), f2(f/d2);
00223       long int n = plus(mult(x.getNum(), f1),  uminus(mult(y.getNum(), f2)));
00224       Impl res(n, f);
00225       TRACE("rational", "  => ", res, "");
00226       return res;
00227     }
00228 
00229     /*!
00230      * Multiplication of x=n1/d1, y=n2/d2:
00231      * (n1/g1)*(n2/g2)/(d1/g2)*(d2/g1), where g1=gcd(n1,d2) and
00232      * g2=gcd(n2,d1)
00233      */
00234     friend Impl operator*(const Impl& x, const Impl& y) {
00235       long int n1(x.getNum()), d1(x.getDen()), n2(y.getNum()), d2(y.getDen());
00236       long int g1(n1? gcd(n1,d2) : 1), g2(n2? gcd(n2,d1) : 1);
00237       long int n(mult(n1/g1, n2/g2)), d(mult(d1/g2, d2/g1));
00238       return Impl(n,d);
00239     }
00240 
00241     /*!
00242      * Division of x=n1/d1, y=n2/d2:
00243      * (n1/g1)*(d2/g2)/(d1/g2)*(n2/g1), where g1=gcd(n1,n2) and
00244      * g2=gcd(d1,d2)
00245      */
00246     friend Impl operator/(const Impl& x, const Impl& y) {
00247       long int n1(x.getNum()), d1(x.getDen()), n2(y.getNum()), d2(y.getDen());
00248       DebugAssert(n2 != 0, "Impl::operator/: divisor is 0");
00249       long int g1(n1? gcd(n1,n2) : 1), g2(gcd(d1,d2));
00250       long int n(n1? mult(n1/g1, d2/g2) : 0), d(n1? mult(d1/g2, n2/g1) : 1);
00251       return Impl(n,d);
00252     }
00253 
00254     friend Impl operator%(const Impl& x, const Impl& y) {
00255       DebugAssert(x.getDen() == 1 && y.getDen() == 1,
00256       "Impl % Impl: x and y must be integers");
00257       return Impl(x.getNum() % y.getNum(), 1);
00258     }
00259 
00260     //! Print to string
00261     string toString(int base = 10) const {
00262       ostringstream ss;
00263       if (d_num == 0) ss << "0";
00264       else if (base == 10) {
00265         ss << d_num;
00266         if (d_denom != 1)
00267           ss << "/" << d_denom;
00268       }
00269       else {
00270         vector<int> vec;
00271         long num = d_num;
00272         while (num) {
00273           vec.push_back(num % base);
00274           num = num / base;
00275         }
00276         while (!vec.empty()) {
00277           if (base > 10 && vec.back() > 10) {
00278             ss << (char)('A' + (vec.back()-10));
00279           }
00280           else ss << vec.back();
00281           vec.pop_back();
00282         }
00283         if(d_denom != 1) {
00284           ss << "/";
00285           if (d_denom == 0) ss << "0";
00286           else {
00287             num = d_denom;
00288             while (num) {
00289               vec.push_back(num % base);
00290               num = num / base;
00291             }
00292             while (!vec.empty()) {
00293               if (base > 10 && vec.back() > 10) {
00294                 ss << (char)('A' + (vec.back()-10));
00295               }
00296               else ss << vec.back();
00297               vec.pop_back();
00298             }
00299           }
00300         }
00301       }
00302       return(ss.str());
00303     }
00304 
00305     //! Printing to ostream
00306     friend ostream& operator<<(ostream& os, const Rational::Impl& n) {
00307       return os << n.toString();
00308     }
00309 
00310   };
00311 
00312   // Make the rational number canonical
00313   void Rational::Impl::canonicalize() {
00314     DebugAssert(d_denom != 0,
00315                 "Rational::Impl::canonicalize: bad denominator: "
00316                 +int2string(d_denom));
00317     if(d_num == 0) {
00318       d_denom = 1;
00319     } else {
00320       if(d_denom < 0) {
00321   d_num = uminus(d_num);
00322   d_denom = uminus(d_denom);
00323       }
00324       long int d = gcd(d_num, d_denom);
00325       if(d != 1) {
00326   d_num /= d;
00327   d_denom /= d;
00328       }
00329     }
00330   }
00331 
00332   // Constructor from a string
00333   Rational::Impl::Impl(const string &n, int base) {
00334     size_t i, iend;
00335     for(i=0,iend=n.size(); i<iend && n[i] != '/'; ++i);
00336     if(i<iend)
00337       // Found slash at i
00338       *this = Impl(n.substr(0,i-1), n.substr(i+1,iend-1), base);
00339     else
00340       *this = Impl(n, "1", base);
00341     canonicalize();
00342   }
00343   // Constructor from a pair of strings
00344   Rational::Impl::Impl(const string &n, const string& d, int base) {
00345     d_num = strtol(n.c_str(), NULL, base);
00346     FatalAssert(d_num != LONG_MIN &&  d_num != LONG_MAX,
00347                 "Rational::Impl(string, string): arithmetic overflow:"
00348                 "n = "+n+", d="+d+", base="+int2string(base)
00349                 +OVERFLOW_MSG);
00350     d_denom = strtol(d.c_str(), NULL, base);
00351     FatalAssert(d_denom != LONG_MIN &&  d_denom != LONG_MAX,
00352                 "Rational::Impl(string, string): arithmetic overflow:"
00353                 "n = "+n+", d="+d+", base="+int2string(base)
00354                 +OVERFLOW_MSG);
00355     canonicalize();
00356   }
00357 
00358   Rational::Impl Rational::Impl::operator-() const {
00359     return Impl(uminus(d_num), d_denom);
00360   }
00361 
00362 
00363   //! Default constructor
00364   Rational::Rational() : d_n(new Impl) {
00365 #ifdef _DEBUG_RATIONAL_
00366     int &num_created = getCreated();
00367     num_created++;
00368     printStats();
00369 #endif
00370   }
00371   //! Copy constructor
00372   Rational::Rational(const Rational &n) : d_n(new Impl(*n.d_n)) {
00373 #ifdef _DEBUG_RATIONAL_
00374     int &num_created = getCreated();
00375     num_created++;
00376     printStats();
00377 #endif
00378   }
00379 
00380   Rational::Rational(const Unsigned &n) : d_n(new Impl(n.getUnsigned())) {
00381 #ifdef _DEBUG_RATIONAL_
00382     int &num_created = getCreated();
00383     num_created++;
00384     printStats();
00385 #endif
00386   }
00387 
00388   //! Private constructor
00389   Rational::Rational(const Impl& t): d_n(new Impl(t)) {
00390 #ifdef _DEBUG_RATIONAL_
00391     int &num_created = getCreated();
00392     num_created++;
00393     printStats();
00394 #endif
00395   }
00396   Rational::Rational(int n, int d): d_n(new Impl(n, d)) {
00397 #ifdef _DEBUG_RATIONAL_
00398     int &num_created = getCreated();
00399     num_created++;
00400     printStats();
00401 #endif
00402   }
00403   // Constructors from strings
00404   Rational::Rational(const char* n, int base)
00405     : d_n(new Impl(string(n), base)) {
00406 #ifdef _DEBUG_RATIONAL_
00407     int &num_created = getCreated();
00408     num_created++;
00409     printStats();
00410 #endif
00411   }
00412   Rational::Rational(const string& n, int base)
00413     : d_n(new Impl(n, base)) {
00414 #ifdef _DEBUG_RATIONAL_
00415     int &num_created = getCreated();
00416     num_created++;
00417     printStats();
00418 #endif
00419   }
00420   Rational::Rational(const char* n, const char* d, int base)
00421     : d_n(new Impl(string(n), string(d), base)) {
00422 #ifdef _DEBUG_RATIONAL_
00423     int &num_created = getCreated();
00424     num_created++;
00425     printStats();
00426 #endif
00427   }
00428   Rational::Rational(const string& n, const string& d, int base)
00429     : d_n(new Impl(n, d, base)) {
00430 #ifdef _DEBUG_RATIONAL_
00431     int &num_created = getCreated();
00432     num_created++;
00433     printStats();
00434 #endif
00435   }
00436   // Destructor
00437   Rational::~Rational() {
00438     delete d_n;
00439 #ifdef _DEBUG_RATIONAL_
00440     int &num_deleted = getDeleted();
00441     num_deleted++;
00442     printStats();
00443 #endif
00444   }
00445 
00446   // Get components
00447   Rational Rational::getNumerator() const
00448     { return Rational(Impl(d_n->getNum(), 1)); }
00449   Rational Rational::getDenominator() const
00450     { return Rational(Impl(d_n->getDen(), 1)); }
00451 
00452   bool Rational::isInteger() const { return 1 == d_n->getDen(); }
00453 
00454   // Assignment
00455   Rational& Rational::operator=(const Rational& n) {
00456     if(this == &n) return *this;
00457     delete d_n;
00458     d_n = new Impl(*n.d_n);
00459     return *this;
00460   }
00461 
00462   ostream &operator<<(ostream &os, const Rational &n) {
00463     return(os << n.toString());
00464   }
00465 
00466 
00467   // Check that argument is an int and print an error message otherwise
00468 
00469   static void checkInt(const Rational& n, const string& funName) {
00470     DebugAssert(n.isInteger(),
00471     ("CVC3::Rational::" + funName
00472      + ": argument is not an integer: " + n.toString()).c_str());
00473   }
00474 
00475     /* Computes gcd and lcm on *integer* values. Result is always a
00476        positive integer.  In this implementation, it is guaranteed by
00477        GMP. */
00478 
00479   Rational gcd(const Rational &x, const Rational &y) {
00480     checkInt(x, "gcd(*x*,y)");
00481     checkInt(y, "gcd(x,*y*)");
00482     return Rational(Rational::Impl(gcd(x.d_n->getNum(), y.d_n->getNum()), 1));
00483   }
00484 
00485   Rational gcd(const vector<Rational> &v) {
00486     long int g(1);
00487     if(v.size() > 0) {
00488       checkInt(v[0], "gcd(vector<Rational>[0])");
00489       g = v[0].d_n->getNum();
00490     }
00491     for(size_t i=1; i<v.size(); i++) {
00492       checkInt(v[i], "gcd(vector<Rational>)");
00493       if(g == 0) g = v[i].d_n->getNum();
00494       else if(v[i].d_n->getNum() != 0)
00495   g = gcd(g, v[i].d_n->getNum());
00496     }
00497     return Rational(Rational::Impl(g,1));
00498   }
00499 
00500   Rational lcm(const Rational &x, const Rational &y) {
00501     long int g;
00502     checkInt(x, "lcm(*x*,y)");
00503     checkInt(y, "lcm(x,*y*)");
00504     g = lcm(x.d_n->getNum(), y.d_n->getNum());
00505     return Rational(Rational::Impl(g, 1));
00506   }
00507 
00508   Rational lcm(const vector<Rational> &v) {
00509     long int g(1);
00510     for(size_t i=0; i<v.size(); i++) {
00511       checkInt(v[i], "lcm(vector<Rational>)");
00512       if(v[i].d_n->getNum() != 0)
00513   g = lcm(g, v[i].d_n->getNum());
00514     }
00515     return Rational(Rational::Impl(g,1));
00516   }
00517 
00518   Rational abs(const Rational &x) {
00519     long int n(x.d_n->getNum());
00520     if(n>=0) return x;
00521     return Rational(Rational::Impl(-n, x.d_n->getDen()));
00522   }
00523 
00524   Rational floor(const Rational &x) {
00525     if(x.d_n->getDen() == 1) return x;
00526     long int n = x.d_n->getNum();
00527     long int nAbs = (n<0)? uminus(n) : n;
00528     long int q = nAbs / x.d_n->getDen();
00529     if(n < 0) q = plus(uminus(q), -1);
00530     return Rational(Rational::Impl(q,1));
00531   }
00532 
00533   Rational ceil(const Rational &x) {
00534     if(x.d_n->getDen() == 1) return x;
00535     long int n = x.d_n->getNum();
00536     long int nAbs = (n<0)? -n : n;
00537     long int q = nAbs / x.d_n->getDen();
00538     if(n > 0) q = plus(q, 1);
00539     else q = uminus(q);
00540     return Rational(Rational::Impl(q,1));
00541   }
00542 
00543   Rational mod(const Rational &x, const Rational &y) {
00544     checkInt(x, "mod(*x*,y)");
00545     checkInt(y, "mod(x,*y*)");
00546     long int r = x.d_n->getNum() % y.d_n->getNum();
00547     return(Rational(Rational::Impl(r,1)));
00548   }
00549 
00550   Rational intRoot(const Rational& base, unsigned long int n) {
00551     checkInt(base, "intRoot(*x*,y)");
00552     checkInt(n, "intRoot(x,*y*)");
00553     double b = base.d_n->getNum();
00554     double root = n;
00555     root = 1/root;
00556     b = ::pow(b, root);
00557     long res = (long) ::floor(b);
00558     if (::pow((long double)res, (int)n) == base.d_n->getNum()) {
00559       return Rational(Rational::Impl(res,1));
00560     }
00561     return Rational(Rational::Impl((long)0,(long)1));
00562   }
00563 
00564   string Rational::toString(int base) const {
00565     return(d_n->toString(base));
00566   }
00567 
00568   size_t Rational::hash() const {
00569     std::hash<const char *> h;
00570     return h(toString().c_str());
00571   }
00572 
00573   void Rational::print() const {
00574     cout << (*this) << endl;
00575   }
00576 
00577   // Unary minus
00578   Rational Rational::operator-() const {
00579     return Rational(Rational::Impl(-(d_n->getNum()), d_n->getDen()));
00580   }
00581 
00582   Rational &Rational::operator+=(const Rational &n2) {
00583     *this = (*this) + n2;
00584     return *this;
00585   }
00586 
00587   Rational &Rational::operator-=(const Rational &n2) {
00588     *this = (*this) - n2;
00589     return *this;
00590   }
00591 
00592   Rational &Rational::operator*=(const Rational &n2) {
00593     *this = (*this) * n2;
00594     return *this;
00595   }
00596 
00597   Rational &Rational::operator/=(const Rational &n2) {
00598     *this = (*this) / n2;
00599     return *this;
00600   }
00601 
00602   int Rational::getInt() const {
00603     checkInt(*this, "getInt()");
00604     long int res = d_n->getNum();
00605     FatalAssert(res >= INT_MIN && res <= INT_MAX,
00606                 "Rational::getInt(): arithmetic overflow on "+toString() +
00607                 OVERFLOW_MSG);
00608     return (int)res;
00609   }
00610 
00611   unsigned int Rational::getUnsigned() const {
00612     checkInt(*this, "getUnsigned()");
00613     long int res = d_n->getNum();
00614     FatalAssert(res >= 0 && res <= (long int)UINT_MAX,
00615                 "Rational::getUnsigned(): arithmetic overflow on " + toString() +
00616     OVERFLOW_MSG);
00617     return (unsigned int)res;
00618   }
00619 
00620 #ifdef _DEBUG_RATIONAL_
00621   void Rational::printStats() {
00622       int &num_created = getCreated();
00623       int &num_deleted = getDeleted();
00624       if(num_created % 1000 == 0 || num_deleted % 1000 == 0) {
00625   std::cerr << "Rational(" << *d_n << "): created " << num_created
00626       << ", deleted " << num_deleted
00627       << ", currently alive " << num_created-num_deleted
00628       << std::endl;
00629       }
00630     }
00631 #endif
00632 
00633     bool operator==(const Rational &n1, const Rational &n2) {
00634       return(*n1.d_n == *n2.d_n);
00635     }
00636 
00637     bool operator<(const Rational &n1, const Rational &n2) {
00638       return(*n1.d_n < *n2.d_n);
00639     }
00640 
00641     bool operator<=(const Rational &n1, const Rational &n2) {
00642       return(*n1.d_n <= *n2.d_n);
00643     }
00644 
00645     bool operator>(const Rational &n1, const Rational &n2) {
00646       return(*n1.d_n > *n2.d_n);
00647     }
00648 
00649     bool operator>=(const Rational &n1, const Rational &n2) {
00650       return(*n1.d_n >= *n2.d_n);
00651     }
00652 
00653     bool operator!=(const Rational &n1, const Rational &n2) {
00654       return(*n1.d_n != *n2.d_n);
00655     }
00656 
00657     Rational operator+(const Rational &n1, const Rational &n2) {
00658       return Rational(Rational::Impl(*n1.d_n + *n2.d_n));
00659     }
00660 
00661     Rational operator-(const Rational &n1, const Rational &n2) {
00662       return Rational(Rational::Impl((*n1.d_n) - (*n2.d_n)));
00663     }
00664 
00665     Rational operator*(const Rational &n1, const Rational &n2) {
00666       return Rational(Rational::Impl((*n1.d_n) * (*n2.d_n)));
00667     }
00668 
00669     Rational operator/(const Rational &n1, const Rational &n2) {
00670       return Rational(Rational::Impl(*n1.d_n / *n2.d_n));
00671     }
00672 
00673     Rational operator%(const Rational &n1, const Rational &n2) {
00674       return Rational(Rational::Impl(*n1.d_n % *n2.d_n));
00675     }
00676 
00677   // Implementation of the forward-declared internal class
00678   class Unsigned::Impl {
00679     unsigned long d_num;
00680   public:
00681     //! Default Constructor
00682     Impl(): d_num(0) { }
00683     //! Copy constructor
00684     Impl(const Impl &x) : d_num(x.d_num) { }
00685     //! Constructor from an unsigned integer
00686     Impl(unsigned long n): d_num(n) { }
00687     //! Constructor from an int
00688     Impl(int n): d_num(n) {
00689       FatalAssert(n >= 0, "Attempt to create Unsigned from negative integer");
00690     }
00691 
00692     //! Constructor from a string
00693     Impl(const string &n, int base);
00694     // Destructor
00695     virtual ~Impl() { }
00696     //! Get unsigned
00697     unsigned long getUnsigned() const { return d_num; }
00698 
00699 
00700     //! Equality
00701     friend bool operator==(const Impl& x, const Impl& y) {
00702       return (x.d_num == y.d_num);
00703     }
00704     //! Dis-equality
00705     friend bool operator!=(const Impl& x, const Impl& y) {
00706       return (x.d_num != y.d_num);
00707     }
00708     friend bool operator<(const Impl& x, const Impl& y) {
00709       return x.d_num < y.d_num;
00710     }
00711 
00712     friend bool operator<=(const Impl& x, const Impl& y) {
00713       return (x.d_num <= y.d_num);
00714     }
00715 
00716     friend bool operator>(const Impl& x, const Impl& y) {
00717       return x.d_num > y.d_num;
00718     }
00719 
00720     friend bool operator>=(const Impl& x, const Impl& y) {
00721       return x.d_num >= y.d_num;
00722     }
00723 
00724     friend Impl operator+(const Impl& x, const Impl& y) {
00725       return Impl(uplus(x.d_num, y.d_num));
00726     }
00727 
00728     friend Impl operator-(const Impl& x, const Impl& y) {
00729       unsigned long n = unsigned_minus(x.d_num, y.d_num);
00730       Impl res(n);
00731       return res;
00732     }
00733 
00734     friend Impl operator*(const Impl& x, const Impl& y) {
00735       unsigned long n(umult(x.d_num, y.d_num));
00736       return Impl(n);
00737     }
00738 
00739     friend Impl operator/(const Impl& x, const Impl& y) {
00740       DebugAssert(y.d_num != 0, "Impl::operator/: divisor is 0");
00741       unsigned long n(x.d_num / y.d_num);
00742       return Impl(n);
00743     }
00744 
00745     friend Impl operator%(const Impl& x, const Impl& y) {
00746       DebugAssert(y.d_num != 0,
00747       "Impl % Impl: y must be non-zero");
00748       return Impl(x.d_num % y.d_num);
00749     }
00750 
00751     friend Impl operator<<(const Impl& x, unsigned y) {
00752       unsigned long n(ushift(x.d_num, y));
00753       return Impl(n);
00754     }
00755 
00756     friend Impl operator&(const Impl& x, const Impl& y) {
00757       return Impl(x.d_num & y.d_num);
00758     }
00759 
00760     //! Print to string
00761     string toString(int base = 10) const {
00762       ostringstream ss;
00763       if (d_num == 0) ss << "0";
00764       else if (base == 10) {
00765         ss << d_num;
00766       }
00767       else {
00768         vector<int> vec;
00769         long num = d_num;
00770         while (num) {
00771           vec.push_back(num % base);
00772           num = num / base;
00773         }
00774         while (!vec.empty()) {
00775           if (base > 10 && vec.back() > 10) {
00776             ss << (char)('A' + (vec.back()-10));
00777           }
00778           else ss << vec.back();
00779           vec.pop_back();
00780         }
00781       }
00782       return(ss.str());
00783     }
00784 
00785     //! Printing to ostream
00786     friend ostream& operator<<(ostream& os, const Unsigned::Impl& n) {
00787       return os << n.toString();
00788     }
00789 
00790   };
00791 
00792   // Constructor from a pair of strings
00793   Unsigned::Impl::Impl(const string &n, int base) {
00794     d_num = strtoul(n.c_str(), NULL, base);
00795     FatalAssert(d_num != ULONG_MAX,
00796                 "Unsigned::Impl(string): arithmetic overflow:"
00797                 "n = "+n+", base="+int2string(base)
00798                 +OVERFLOW_MSG);
00799   }
00800 
00801   //! Default constructor
00802   Unsigned::Unsigned() : d_n(new Impl) { }
00803   //! Copy constructor
00804   Unsigned::Unsigned(const Unsigned &n) : d_n(new Impl(*n.d_n)) { }
00805 
00806   //! Private constructor
00807   Unsigned::Unsigned(const Impl& t): d_n(new Impl(t)) { }
00808 
00809   Unsigned::Unsigned(unsigned n): d_n(new Impl((unsigned long)n)) { }
00810   Unsigned::Unsigned(int n): d_n(new Impl(n)) { }
00811 
00812   // Constructors from strings
00813   Unsigned::Unsigned(const char* n, int base)
00814     : d_n(new Impl(string(n), base)) { }
00815   Unsigned::Unsigned(const string& n, int base)
00816     : d_n(new Impl(n, base)) { }
00817 
00818   // Destructor
00819   Unsigned::~Unsigned() {
00820     delete d_n;
00821   }
00822 
00823   // Assignment
00824   Unsigned& Unsigned::operator=(const Unsigned& n) {
00825     if(this == &n) return *this;
00826     delete d_n;
00827     d_n = new Impl(*n.d_n);
00828     return *this;
00829   }
00830 
00831   ostream &operator<<(ostream &os, const Unsigned &n) {
00832     return(os << n.toString());
00833   }
00834 
00835   Unsigned gcd(const Unsigned &x, const Unsigned &y) {
00836     return Unsigned(Unsigned::Impl(ugcd(x.d_n->getUnsigned(), y.d_n->getUnsigned())));
00837   }
00838 
00839   Unsigned gcd(const vector<Unsigned> &v) {
00840     unsigned long g(1);
00841     if(v.size() > 0) {
00842       g = v[0].d_n->getUnsigned();
00843     }
00844     for(size_t i=1; i<v.size(); i++) {
00845       if(g == 0) g = v[i].d_n->getUnsigned();
00846       else if(v[i].d_n->getUnsigned() != 0)
00847   g = ugcd(g, v[i].d_n->getUnsigned());
00848     }
00849     return Unsigned(Unsigned::Impl(g));
00850   }
00851 
00852   Unsigned lcm(const Unsigned &x, const Unsigned &y) {
00853     unsigned long g;
00854     g = ulcm(x.d_n->getUnsigned(), y.d_n->getUnsigned());
00855     return Unsigned(Unsigned::Impl(g));
00856   }
00857 
00858   Unsigned lcm(const vector<Unsigned> &v) {
00859     unsigned long g(1);
00860     for(size_t i=0; i<v.size(); i++) {
00861       if(v[i].d_n->getUnsigned() != 0)
00862   g = ulcm(g, v[i].d_n->getUnsigned());
00863     }
00864     return Unsigned(Unsigned::Impl(g));
00865   }
00866 
00867   Unsigned mod(const Unsigned &x, const Unsigned &y) {
00868     unsigned long r = x.d_n->getUnsigned() % y.d_n->getUnsigned();
00869     return(Unsigned(Unsigned::Impl(r)));
00870   }
00871 
00872   Unsigned intRoot(const Unsigned& base, unsigned long int n) {
00873     double b = base.d_n->getUnsigned();
00874     double root = n;
00875     root = 1/root;
00876     b = ::pow(b, root);
00877     unsigned long res = (unsigned long) ::floor(b);
00878     if (::pow((long double)res, (int)n) == base.d_n->getUnsigned()) {
00879       return Unsigned(Unsigned::Impl(res));
00880     }
00881     return Unsigned(Unsigned::Impl((unsigned long)0));
00882   }
00883 
00884   string Unsigned::toString(int base) const {
00885     return(d_n->toString(base));
00886   }
00887 
00888   size_t Unsigned::hash() const {
00889     std::hash<const char *> h;
00890     return h(toString().c_str());
00891   }
00892 
00893   void Unsigned::print() const {
00894     cout << (*this) << endl;
00895   }
00896 
00897   Unsigned &Unsigned::operator+=(const Unsigned &n2) {
00898     *this = (*this) + n2;
00899     return *this;
00900   }
00901 
00902   Unsigned &Unsigned::operator-=(const Unsigned &n2) {
00903     *this = (*this) - n2;
00904     return *this;
00905   }
00906 
00907   Unsigned &Unsigned::operator*=(const Unsigned &n2) {
00908     *this = (*this) * n2;
00909     return *this;
00910   }
00911 
00912   Unsigned &Unsigned::operator/=(const Unsigned &n2) {
00913     *this = (*this) / n2;
00914     return *this;
00915   }
00916 
00917   unsigned long Unsigned::getUnsigned() const {
00918     return d_n->getUnsigned();
00919   }
00920 
00921   bool operator==(const Unsigned &n1, const Unsigned &n2) {
00922     return(*n1.d_n == *n2.d_n);
00923   }
00924 
00925   bool operator<(const Unsigned &n1, const Unsigned &n2) {
00926     return(*n1.d_n < *n2.d_n);
00927   }
00928 
00929   bool operator<=(const Unsigned &n1, const Unsigned &n2) {
00930     return(*n1.d_n <= *n2.d_n);
00931   }
00932 
00933   bool operator>(const Unsigned &n1, const Unsigned &n2) {
00934     return(*n1.d_n > *n2.d_n);
00935   }
00936 
00937   bool operator>=(const Unsigned &n1, const Unsigned &n2) {
00938     return(*n1.d_n >= *n2.d_n);
00939   }
00940 
00941   bool operator!=(const Unsigned &n1, const Unsigned &n2) {
00942     return(*n1.d_n != *n2.d_n);
00943   }
00944 
00945   Unsigned operator+(const Unsigned &n1, const Unsigned &n2) {
00946     return Unsigned(Unsigned::Impl(*n1.d_n + *n2.d_n));
00947   }
00948 
00949   Unsigned operator-(const Unsigned &n1, const Unsigned &n2) {
00950     return Unsigned(Unsigned::Impl((*n1.d_n) - (*n2.d_n)));
00951   }
00952 
00953   Unsigned operator*(const Unsigned &n1, const Unsigned &n2) {
00954     return Unsigned(Unsigned::Impl((*n1.d_n) * (*n2.d_n)));
00955   }
00956 
00957   Unsigned operator/(const Unsigned &n1, const Unsigned &n2) {
00958     return Unsigned(Unsigned::Impl(*n1.d_n / *n2.d_n));
00959   }
00960 
00961   Unsigned operator%(const Unsigned &n1, const Unsigned &n2) {
00962     return Unsigned(Unsigned::Impl(*n1.d_n % *n2.d_n));
00963   }
00964 
00965   Unsigned operator<<(const Unsigned& n1, unsigned n2) {
00966     return Unsigned(Unsigned::Impl(*n1.d_n << n2));
00967   }
00968 
00969   Unsigned operator&(const Unsigned& n1, const Unsigned& n2) {
00970     return Unsigned(Unsigned::Impl(*n1.d_n & *n2.d_n));
00971   }
00972 
00973   Unsigned Rational::getUnsignedMP() const {
00974     checkInt(*this, "getUnsignedMP()");
00975     long int res = d_n->getNum();
00976     FatalAssert(res >= 0 && res <= (long int)UINT_MAX,
00977                 "Rational::getUnsignedMP(): arithmetic overflow on " + toString() +
00978     OVERFLOW_MSG);
00979     return Unsigned((unsigned int)res);
00980   }
00981 
00982 
00983 } /* close namespace */
00984 
00985 #endif