00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifdef RATIONAL_GMP
00032
00033 #include "compat_hash_set.h"
00034 #include "rational.h"
00035
00036 #include <sstream>
00037 #include <gmp.h>
00038
00039 namespace CVCL {
00040
00041 using namespace std;
00042
00043
00044 class Rational::Impl {
00045 mpq_t d_n;
00046
00047 void canonicalize() { mpq_canonicalize(d_n); }
00048 public:
00049
00050 Impl() { mpq_init(d_n); }
00051
00052 Impl(const Impl &x) { mpq_init(d_n); mpq_set(d_n, x.d_n); }
00053
00054 Impl(mpq_t n) {
00055 mpq_init(d_n);
00056 mpq_set(d_n, n);
00057 canonicalize();
00058 }
00059
00060 Impl(mpz_t n, mpz_t d) {
00061 mpq_init(d_n);
00062 mpq_set_num(d_n, n); mpq_set_den(d_n, d);
00063 canonicalize();
00064 }
00065
00066 Impl(mpz_t n) {
00067 mpq_init(d_n);
00068 mpq_set_num(d_n, n);
00069 canonicalize();
00070 }
00071
00072 Impl(long int n, long int d);
00073
00074 Impl(unsigned int n, unsigned int d, unsigned int );
00075
00076 Impl(const string &n, int base);
00077
00078 Impl(const string &n, const string& d, int base);
00079
00080 virtual ~Impl() { mpq_clear(d_n); }
00081
00082
00083 Impl& operator=(const Impl& x) {
00084 if(this == &x) return *this;
00085 mpq_set(d_n, x.d_n);
00086 return *this;
00087 }
00088
00089
00090 Impl getNum() const {
00091 return Impl(mpq_numref(const_cast<Impl*>(this)->d_n));
00092 }
00093
00094 Impl getDen() const {
00095 return Impl(mpq_denref(const_cast<Impl*>(this)->d_n));
00096 }
00097
00098 int getInt() const {
00099
00100 static Impl min((int)INT_MIN, 1), max((int)INT_MAX, 1);
00101 FatalAssert(isInteger() && min <= *this && *this <= max,
00102 "Rational::getInt(): Arithmetic overflow for "
00103 +toString());
00104 return mpz_get_si(mpq_numref(d_n));
00105 }
00106
00107 unsigned int getUnsigned() const {
00108
00109 static Impl min(0, 1, 0), max(UINT_MAX, 1, 0);
00110 FatalAssert(min <= *this && *this <= max,
00111 "Rational::getUnsigned(): Arithmetic overflow for "
00112 +toString());
00113 return mpz_get_ui(mpq_numref(d_n));
00114 }
00115
00116
00117 Impl operator-() const;
00118
00119 Impl floor() const;
00120
00121 Impl ceil() const;
00122
00123
00124 bool isInteger() const;
00125
00126
00127 friend bool operator==(const Impl& x, const Impl& y) {
00128 return mpq_equal(x.d_n, y.d_n);
00129 }
00130
00131
00132 friend bool operator!=(const Impl& x, const Impl& y) {
00133 return !mpq_equal(x.d_n, y.d_n);
00134 }
00135
00136 friend bool operator<(const Impl& x, const Impl& y) {
00137 return mpq_cmp(x.d_n, y.d_n) < 0;
00138 }
00139
00140 friend bool operator<=(const Impl& x, const Impl& y) {
00141 return mpq_cmp(x.d_n, y.d_n) <= 0;
00142 }
00143
00144 friend bool operator>(const Impl& x, const Impl& y) {
00145 return mpq_cmp(x.d_n, y.d_n) > 0;
00146 }
00147
00148 friend bool operator>=(const Impl& x, const Impl& y) {
00149 return mpq_cmp(x.d_n, y.d_n) >= 0;
00150 }
00151
00152
00153 friend Impl operator+(const Impl& x, const Impl& y) {
00154 Impl res;
00155 mpq_add(res.d_n, x.d_n, y.d_n);
00156 return res;
00157 }
00158
00159
00160 friend Impl operator-(const Impl& x, const Impl& y) {
00161 Impl res;
00162 mpq_sub(res.d_n, x.d_n, y.d_n);
00163 return res;
00164 }
00165
00166
00167 friend Impl operator*(const Impl& x, const Impl& y) {
00168 Impl res;
00169 mpq_mul(res.d_n, x.d_n, y.d_n);
00170 return res;
00171 }
00172
00173
00174 friend Impl operator/(const Impl& x, const Impl& y) {
00175 Impl res;
00176 mpq_div(res.d_n, x.d_n, y.d_n);
00177 return res;
00178 }
00179
00180 friend Impl operator%(const Impl& x, const Impl& y) {
00181 DebugAssert(x.isInteger() && y.isInteger(),
00182 "Impl % Impl: x and y must be integers");
00183 mpz_t res;
00184 mpz_init(res);
00185
00186 mpz_fdiv_r(res, mpq_numref(x.d_n), mpq_numref(y.d_n));
00187 Impl r(res);
00188 mpz_clear(res);
00189 return r;
00190 }
00191
00192
00193 friend Impl mod(const Impl& x, const Impl& y) {
00194 DebugAssert(x.isInteger() && y.isInteger(),
00195 "Rational::Impl::mod(): x="+x.toString()
00196 +", y="+y.toString());
00197 mpz_t res;
00198 mpz_init(res);
00199 mpz_mod(res, mpq_numref(x.d_n), mpq_numref(y.d_n));
00200 Impl r(res);
00201 mpz_clear(res);
00202 return r;
00203 }
00204
00205 friend Impl gcd(const Impl& x, const Impl& y) {
00206 DebugAssert(x.isInteger() && y.isInteger(),
00207 "Rational::Impl::gcd(): x="+x.toString()
00208 +", y="+y.toString());
00209 TRACE("rational", "Impl::gcd(", x, ", "+y.toString()+") {");
00210 mpz_t res;
00211 mpz_init(res);
00212 mpz_gcd(res, mpq_numref(x.d_n), mpq_numref(y.d_n));
00213 Impl r(res);
00214 mpz_clear(res);
00215 TRACE("rational", "Impl::gcd => ", r, "}");
00216 return r;
00217 }
00218
00219 friend Impl lcm(const Impl& x, const Impl& y) {
00220 DebugAssert(x.isInteger() && y.isInteger(),
00221 "Rational::Impl::lcm(): x="+x.toString()
00222 +", y="+y.toString());
00223 mpz_t res;
00224 mpz_init(res);
00225 mpz_lcm(res, mpq_numref(x.d_n), mpq_numref(y.d_n));
00226 Impl r(res);
00227 mpz_clear(res);
00228 return r;
00229 }
00230
00231
00232 string toString(int base = 10) const {
00233 char* str = (char*)malloc(mpz_sizeinbase(mpq_numref(d_n), base)
00234 +mpz_sizeinbase(mpq_denref(d_n), base)+3);
00235 mpq_get_str(str, base, d_n);
00236 string res(str);
00237 free(str);
00238 return res;
00239 }
00240
00241
00242 friend ostream& operator<<(ostream& os, const Rational::Impl& n) {
00243 return os << n.toString();
00244 }
00245
00246 };
00247
00248
00249 Rational::Impl::Impl(long int n, long int d) {
00250 mpq_init(d_n);
00251 DebugAssert(d > 0, "Rational::Impl(long n, long d): d = "+int2string(d));
00252 mpq_set_si(d_n, n, (unsigned long int)d);
00253 canonicalize();
00254 }
00255
00256
00257 Rational::Impl::Impl(unsigned int n, unsigned int d,
00258 unsigned int ) {
00259 mpq_init(d_n);
00260 mpq_set_ui(d_n, n, (unsigned long int)d);
00261 canonicalize();
00262 }
00263
00264
00265 Rational::Impl::Impl(const string &n, int base) {
00266 mpq_init(d_n);
00267 mpq_set_str(d_n, n.c_str(), base);
00268 canonicalize();
00269 }
00270
00271
00272 Rational::Impl::Impl(const string &n, const string& d, int base) {
00273 mpq_init(d_n);
00274 mpq_set_str(d_n, (n+"/"+d).c_str(), base);
00275 canonicalize();
00276 }
00277
00278 Rational::Impl Rational::Impl::operator-() const {
00279 Impl res;
00280 mpq_neg(res.d_n, d_n);
00281 return res;
00282 }
00283
00284 Rational::Impl Rational::Impl::floor() const {
00285 mpz_t res;
00286 mpz_init(res);
00287 mpz_fdiv_q(res, mpq_numref(d_n), mpq_denref(d_n));
00288 Impl r(res);
00289 mpz_clear(res);
00290 return r;
00291 }
00292
00293 Rational::Impl Rational::Impl::ceil() const {
00294 mpz_t res;
00295 mpz_init(res);
00296 mpz_cdiv_q(res, mpq_numref(d_n), mpq_denref(d_n));
00297 Impl r(res);
00298 mpz_clear(res);
00299 return r;
00300 }
00301
00302 bool Rational::Impl::isInteger() const {
00303 bool res(mpz_cmp_ui(mpq_denref(d_n), 1) == 0);
00304 TRACE("rational", "Impl::isInteger(", *this,
00305 ") => "+string(res? "true" : "false"));
00306 return res;
00307 }
00308
00309
00310 Rational::Rational() : d_n(new Impl) {
00311 #ifdef _DEBUG_RATIONAL_
00312 int &num_created = getCreated();
00313 num_created++;
00314 printStats();
00315 #endif
00316 }
00317
00318 Rational::Rational(const Rational &n) : d_n(new Impl(*n.d_n)) {
00319 #ifdef _DEBUG_RATIONAL_
00320 int &num_created = getCreated();
00321 num_created++;
00322 printStats();
00323 #endif
00324 }
00325
00326
00327 Rational::Rational(const Impl& t): d_n(new Impl(t)) {
00328 #ifdef _DEBUG_RATIONAL_
00329 int &num_created = getCreated();
00330 num_created++;
00331 printStats();
00332 #endif
00333 }
00334 Rational::Rational(int n, int d): d_n(new Impl(n, d)) {
00335 #ifdef _DEBUG_RATIONAL_
00336 int &num_created = getCreated();
00337 num_created++;
00338 printStats();
00339 #endif
00340 }
00341
00342 Rational::Rational(const char* n, int base)
00343 : d_n(new Impl(string(n), base)) {
00344 #ifdef _DEBUG_RATIONAL_
00345 int &num_created = getCreated();
00346 num_created++;
00347 printStats();
00348 #endif
00349 }
00350 Rational::Rational(const string& n, int base)
00351 : d_n(new Impl(n, base)) {
00352 #ifdef _DEBUG_RATIONAL_
00353 int &num_created = getCreated();
00354 num_created++;
00355 printStats();
00356 #endif
00357 }
00358 Rational::Rational(const char* n, const char* d, int base)
00359 : d_n(new Impl(string(n), string(d), base)) {
00360 #ifdef _DEBUG_RATIONAL_
00361 int &num_created = getCreated();
00362 num_created++;
00363 printStats();
00364 #endif
00365 }
00366 Rational::Rational(const string& n, const string& d, int base)
00367 : d_n(new Impl(n, d, base)) {
00368 #ifdef _DEBUG_RATIONAL_
00369 int &num_created = getCreated();
00370 num_created++;
00371 printStats();
00372 #endif
00373 }
00374
00375 Rational::~Rational() {
00376 delete d_n;
00377 #ifdef _DEBUG_RATIONAL_
00378 int &num_deleted = getDeleted();
00379 num_deleted++;
00380 printStats();
00381 #endif
00382 }
00383
00384
00385 Rational Rational::getNumerator() const
00386 { return Rational(d_n->getNum()); }
00387 Rational Rational::getDenominator() const
00388 { return Rational(d_n->getDen()); }
00389
00390 bool Rational::isInteger() const { return d_n->isInteger(); }
00391
00392
00393 Rational& Rational::operator=(const Rational& 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 Rational &n) {
00401 return(os << n.toString());
00402 }
00403
00404
00405
00406
00407 static void checkInt(const Rational& n, const string& funName) {
00408 TRACE("rational", "checkInt(", n, ")");
00409 DebugAssert(n.isInteger(),
00410 "CVCL::Rational::" + funName
00411 + ": argument is not an integer: " + n.toString());
00412 }
00413
00414
00415
00416
00417
00418 Rational gcd(const Rational &x, const Rational &y) {
00419 checkInt(x, "gcd(*x*,y)");
00420 checkInt(y, "gcd(x,*y*)");
00421 return Rational(gcd(*x.d_n, *y.d_n));
00422 }
00423
00424 Rational gcd(const vector<Rational> &v) {
00425 Rational::Impl g(1,1), zero;
00426 if(v.size() > 0) {
00427 checkInt(v[0], "gcd(vector<Rational>[0])");
00428 g = *v[0].d_n;
00429 }
00430 for(size_t i=1; i<v.size(); i++) {
00431 checkInt(v[i], "gcd(vector<Rational>)");
00432 if(g == zero)
00433 g = *(v[i].d_n);
00434 else if(*(v[i].d_n) != zero)
00435 g = gcd(g, *(v[i].d_n));
00436 }
00437 return Rational(g);
00438 }
00439
00440 Rational lcm(const Rational &x, const Rational &y) {
00441 checkInt(x, "lcm(*x*,y)");
00442 checkInt(y, "lcm(x,*y*)");
00443 return Rational(lcm(*x.d_n, *y.d_n));
00444 }
00445
00446 Rational lcm(const vector<Rational> &v) {
00447 Rational::Impl g(1,1), zero;
00448 for(size_t i=0; i<v.size(); i++) {
00449 checkInt(v[i], "lcm(vector<Rational>)");
00450 if(*v[i].d_n != zero)
00451 g = lcm(g, *v[i].d_n);
00452 }
00453 return Rational(g);
00454 }
00455
00456 Rational abs(const Rational &x) {
00457 if(x<0) return -x;
00458 return x;
00459 }
00460
00461 Rational floor(const Rational &x) {
00462 return Rational(x.d_n->floor());
00463 }
00464
00465 Rational ceil(const Rational &x) {
00466 return Rational(x.d_n->ceil());
00467 }
00468
00469 Rational mod(const Rational &x, const Rational &y) {
00470 checkInt(x, "mod(*x*,y)");
00471 checkInt(y, "mod(x,*y*)");
00472 return(Rational(mod(*x.d_n, *y.d_n)));
00473 }
00474
00475 string Rational::toString(int base) const {
00476 return(d_n->toString(base));
00477 }
00478
00479 size_t Rational::hash() const {
00480 std::hash<const char *> h;
00481 return h(toString().c_str());
00482 }
00483
00484 void Rational::print() const {
00485 cout << (*this) << endl;
00486 }
00487
00488
00489 Rational Rational::operator-() const {
00490 return Rational(-(*d_n));
00491 }
00492
00493 Rational &Rational::operator+=(const Rational &n2) {
00494 *this = (*this) + n2;
00495 return *this;
00496 }
00497
00498 Rational &Rational::operator-=(const Rational &n2) {
00499 *this = (*this) - n2;
00500 return *this;
00501 }
00502
00503 Rational &Rational::operator*=(const Rational &n2) {
00504 *this = (*this) * n2;
00505 return *this;
00506 }
00507
00508 Rational &Rational::operator/=(const Rational &n2) {
00509 *this = (*this) / n2;
00510 return *this;
00511 }
00512
00513 int Rational::getInt() const {
00514 checkInt(*this, "getInt()");
00515 return d_n->getInt();
00516 }
00517
00518 unsigned int Rational::getUnsigned() const {
00519 checkInt(*this, "getUnsigned()");
00520 return d_n->getUnsigned();
00521 }
00522
00523 #ifdef _DEBUG_RATIONAL_
00524 void Rational::printStats() {
00525 int &num_created = getCreated();
00526 int &num_deleted = getDeleted();
00527 if(num_created % 1000 == 0 || num_deleted % 1000 == 0) {
00528 std::cerr << "Rational(" << *d_n << "): created " << num_created
00529 << ", deleted " << num_deleted
00530 << ", currently alive " << num_created-num_deleted
00531 << std::endl;
00532 }
00533 }
00534 #endif
00535
00536 bool operator==(const Rational &n1, const Rational &n2) {
00537 return(*n1.d_n == *n2.d_n);
00538 }
00539
00540 bool operator<(const Rational &n1, const Rational &n2) {
00541 return(*n1.d_n < *n2.d_n);
00542 }
00543
00544 bool operator<=(const Rational &n1, const Rational &n2) {
00545 return(*n1.d_n <= *n2.d_n);
00546 }
00547
00548 bool operator>(const Rational &n1, const Rational &n2) {
00549 return(*n1.d_n > *n2.d_n);
00550 }
00551
00552 bool operator>=(const Rational &n1, const Rational &n2) {
00553 return(*n1.d_n >= *n2.d_n);
00554 }
00555
00556 bool operator!=(const Rational &n1, const Rational &n2) {
00557 return(*n1.d_n != *n2.d_n);
00558 }
00559
00560 Rational operator+(const Rational &n1, const Rational &n2) {
00561 return Rational((*n1.d_n) + (*n2.d_n));
00562 }
00563
00564 Rational operator-(const Rational &n1, const Rational &n2) {
00565 return Rational((*n1.d_n) - (*n2.d_n));
00566 }
00567
00568 Rational operator*(const Rational &n1, const Rational &n2) {
00569 return Rational((*n1.d_n) * (*n2.d_n));
00570 }
00571
00572 Rational operator/(const Rational &n1, const Rational &n2) {
00573 return Rational((*n1.d_n) / (*n2.d_n));
00574 }
00575
00576 Rational operator%(const Rational &n1, const Rational &n2) {
00577 return Rational((*n1.d_n) + (*n2.d_n));
00578 }
00579
00580 };
00581
00582 #endif