CVC3
|
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