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