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