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
00032
00033
00034
00035 #ifdef RATIONAL_GMPXX
00036
00037 #include <gmpxx.h>
00038 #include "compat_hash_set.h"
00039 #include "rational.h"
00040
00041 namespace CVCL {
00042
00043 using namespace std;
00044
00045
00046 class Rational::Impl : public mpq_class {
00047 public:
00048
00049
00050 Impl() : mpq_class() { }
00051
00052
00053
00054 Impl(const mpq_class &x) : mpq_class(x) { }
00055
00056 Impl(const Impl &x) : mpq_class(x) { }
00057
00058 Impl(int n, int d) : mpq_class(n,d) { canonicalize(); }
00059 Impl(const mpz_class& n, const mpz_class& d)
00060 : mpq_class(n,d) { canonicalize(); }
00061
00062 Impl(const string &n, int base): mpq_class(n, base) { canonicalize(); }
00063 Impl(const string &n, const string& d, int base)
00064 : mpq_class(n + "/" + d, base) { canonicalize(); }
00065
00066 virtual ~Impl() { }
00067
00068 mpz_class getNum() { return get_num(); }
00069 mpz_class getDen() { return get_den(); }
00070 };
00071
00072
00073 Rational::Rational() : d_n(new Impl) {
00074 #ifdef _DEBUG_RATIONAL_
00075 int &num_created = getCreated();
00076 num_created++;
00077 printStats();
00078 #endif
00079 }
00080
00081 Rational::Rational(const Rational &n) : d_n(new Impl(*n.d_n)) {
00082 #ifdef _DEBUG_RATIONAL_
00083 int &num_created = getCreated();
00084 num_created++;
00085 printStats();
00086 #endif
00087 }
00088
00089
00090 Rational::Rational(const Impl& t): d_n(new Impl(t)) {
00091 #ifdef _DEBUG_RATIONAL_
00092 int &num_created = getCreated();
00093 num_created++;
00094 printStats();
00095 #endif
00096 }
00097 Rational::Rational(int n, int d): d_n(new Impl(n, d)) {
00098 #ifdef _DEBUG_RATIONAL_
00099 int &num_created = getCreated();
00100 num_created++;
00101 printStats();
00102 #endif
00103 }
00104
00105 Rational::Rational(const char* n, int base)
00106 : d_n(new Impl(string(n), base)) {
00107 #ifdef _DEBUG_RATIONAL_
00108 int &num_created = getCreated();
00109 num_created++;
00110 printStats();
00111 #endif
00112 }
00113 Rational::Rational(const string& n, int base)
00114 : d_n(new Impl(n, base)) {
00115 #ifdef _DEBUG_RATIONAL_
00116 int &num_created = getCreated();
00117 num_created++;
00118 printStats();
00119 #endif
00120 }
00121 Rational::Rational(const char* n, const char* d, int base)
00122 : d_n(new Impl(string(n), string(d), base)) {
00123 #ifdef _DEBUG_RATIONAL_
00124 int &num_created = getCreated();
00125 num_created++;
00126 printStats();
00127 #endif
00128 }
00129 Rational::Rational(const string& n, const string& d, int base)
00130 : d_n(new Impl(n, d, base)) {
00131 #ifdef _DEBUG_RATIONAL_
00132 int &num_created = getCreated();
00133 num_created++;
00134 printStats();
00135 #endif
00136 }
00137
00138 Rational::~Rational() {
00139 delete d_n;
00140 #ifdef _DEBUG_RATIONAL_
00141 int &num_deleted = getDeleted();
00142 num_deleted++;
00143 printStats();
00144 #endif
00145 }
00146
00147
00148 Rational Rational::getNumerator() const
00149 { return Rational(Impl(d_n->getNum(), 1)); }
00150 Rational Rational::getDenominator() const
00151 { return Rational(Impl(d_n->getDen(), 1)); }
00152
00153 bool Rational::isInteger() const { return 1 == d_n->getDen(); }
00154
00155
00156 Rational& Rational::operator=(const Rational& n) {
00157 if(this == &n) return *this;
00158 delete d_n;
00159 d_n = new Impl(*n.d_n);
00160 return *this;
00161 }
00162
00163 ostream &operator<<(ostream &os, const Rational &n) {
00164 return(os << n.toString());
00165 }
00166
00167
00168
00169
00170 static void checkInt(const Rational& n, const string& funName) {
00171 DebugAssert(n.isInteger(),
00172 ("CVCL::Rational::" + funName
00173 + ": argument is not an integer: " + n.toString()).c_str());
00174 }
00175
00176
00177
00178
00179
00180 Rational gcd(const Rational &x, const Rational &y) {
00181 mpz_class g;
00182 checkInt(x, "gcd(*x*,y)");
00183 checkInt(y, "gcd(x,*y*)");
00184 mpz_gcd(g.get_mpz_t(), x.d_n->get_num_mpz_t(), y.d_n->get_num_mpz_t());
00185 return Rational(Rational::Impl(g,1));
00186 }
00187
00188 Rational gcd(const vector<Rational> &v) {
00189 mpz_class g(1);
00190 if(v.size() > 0) {
00191 checkInt(v[0], "gcd(vector<Rational>[0])");
00192 g = v[0].d_n->getNum();
00193 }
00194 for(unsigned i=1; i<v.size(); i++) {
00195 checkInt(v[i], "gcd(vector<Rational>)");
00196 if(*v[i].d_n != 0)
00197 mpz_gcd(g.get_mpz_t(), g.get_mpz_t(), v[i].d_n->get_num_mpz_t());
00198 }
00199 return Rational(Rational::Impl(g,1));
00200 }
00201
00202 Rational lcm(const Rational &x, const Rational &y) {
00203 mpz_class g;
00204 checkInt(x, "lcm(*x*,y)");
00205 checkInt(y, "lcm(x,*y*)");
00206 mpz_lcm(g.get_mpz_t(), x.d_n->get_num_mpz_t(), y.d_n->get_num_mpz_t());
00207 return Rational(Rational::Impl(g, 1));
00208 }
00209
00210 Rational lcm(const vector<Rational> &v) {
00211 mpz_class g(1);
00212 for(unsigned i=0; i<v.size(); i++) {
00213 checkInt(v[i], "lcm(vector<Rational>)");
00214 if(*v[i].d_n != 0)
00215 mpz_lcm(g.get_mpz_t(), g.get_mpz_t(), v[i].d_n->get_num_mpz_t());
00216 }
00217 return Rational(Rational::Impl(g,1));
00218 }
00219
00220 Rational abs(const Rational &x) {
00221 return Rational(Rational::Impl(abs(*x.d_n)));
00222 }
00223
00224 Rational floor(const Rational &x) {
00225 mpz_class q;
00226 mpz_fdiv_q(q.get_mpz_t(), x.d_n->get_num_mpz_t(), x.d_n->get_den_mpz_t());
00227 return Rational(Rational::Impl(q,1));
00228 }
00229
00230 Rational ceil(const Rational &x) {
00231 mpz_class q;
00232 mpz_cdiv_q(q.get_mpz_t(), x.d_n->get_num_mpz_t(), x.d_n->get_den_mpz_t());
00233 return Rational(Rational::Impl(q,1));
00234 }
00235
00236 Rational mod(const Rational &x, const Rational &y) {
00237 checkInt(x, "mod(*x*,y)");
00238 checkInt(y, "mod(x,*y*)");
00239 mpz_class r;
00240 mpz_mod(r.get_mpz_t(), x.d_n->get_num_mpz_t(), y.d_n->get_num_mpz_t());
00241 return(Rational(Rational::Impl(r,1)));
00242 }
00243
00244
00245 string Rational::toString(int base) const {
00246 char *tmp = mpq_get_str(NULL, base, d_n->get_mpq_t());
00247 string res(tmp);
00248
00249 free(tmp);
00250 return(res);
00251 }
00252
00253 size_t Rational::hash() const {
00254 std::hash<const char *> h;
00255 return h(toString().c_str());
00256 }
00257
00258 void Rational::print() const {
00259 cout << (*d_n) << endl;
00260 }
00261
00262
00263 Rational Rational::operator-() const {
00264 return Rational(Rational::Impl(- (*d_n)));
00265 }
00266
00267 Rational &Rational::operator+=(const Rational &n2) {
00268 *d_n += (*n2.d_n);
00269 return *this;
00270 }
00271
00272 Rational &Rational::operator-=(const Rational &n2) {
00273 *d_n -= (*n2.d_n);
00274 return *this;
00275 }
00276
00277 Rational &Rational::operator*=(const Rational &n2) {
00278 *d_n *= (*n2.d_n);
00279 return *this;
00280 }
00281
00282 Rational &Rational::operator/=(const Rational &n2) {
00283 *d_n /= (*n2.d_n);
00284 return *this;
00285 }
00286
00287 int Rational::getInt() const {
00288 checkInt(*this, "getInt()");
00289 return mpz_get_si(d_n->get_num_mpz_t());
00290 }
00291
00292 unsigned int Rational::getUnsigned() const {
00293 checkInt(*this, "getUnsigned()");
00294 return mpz_get_ui(d_n->get_num_mpz_t());
00295 }
00296
00297 #ifdef _DEBUG_RATIONAL_
00298 void Rational::printStats() {
00299 int &num_created = getCreated();
00300 int &num_deleted = getDeleted();
00301 if(num_created % 1000 == 0 || num_deleted % 1000 == 0) {
00302 std::cerr << "Rational(" << *d_n << "): created " << num_created
00303 << ", deleted " << num_deleted
00304 << ", currently alive " << num_created-num_deleted
00305 << std::endl;
00306 }
00307 }
00308 #endif
00309
00310 bool operator==(const Rational &n1, const Rational &n2) {
00311 return(*n1.d_n == *n2.d_n);
00312 }
00313
00314 bool operator<(const Rational &n1, const Rational &n2) {
00315 return(*n1.d_n < *n2.d_n);
00316 }
00317
00318 bool operator<=(const Rational &n1, const Rational &n2) {
00319 return(*n1.d_n <= *n2.d_n);
00320 }
00321
00322 bool operator>(const Rational &n1, const Rational &n2) {
00323 return(*n1.d_n > *n2.d_n);
00324 }
00325
00326 bool operator>=(const Rational &n1, const Rational &n2) {
00327 return(*n1.d_n >= *n2.d_n);
00328 }
00329
00330 bool operator!=(const Rational &n1, const Rational &n2) {
00331 return(*n1.d_n != *n2.d_n);
00332 }
00333
00334 Rational operator+(const Rational &n1, const Rational &n2) {
00335 return Rational(Rational::Impl(*n1.d_n + *n2.d_n));
00336 }
00337
00338 Rational operator-(const Rational &n1, const Rational &n2) {
00339 return Rational(Rational::Impl((*n1.d_n) - (*n2.d_n)));
00340 }
00341
00342 Rational operator*(const Rational &n1, const Rational &n2) {
00343 return Rational(Rational::Impl((*n1.d_n) * (*n2.d_n)));
00344 }
00345
00346 Rational operator/(const Rational &n1, const Rational &n2) {
00347 return Rational(Rational::Impl(*n1.d_n / *n2.d_n));
00348 }
00349
00350 Rational operator%(const Rational &n1, const Rational &n2) {
00351 return Rational(Rational::Impl(*n1.d_n + *n2.d_n));
00352 }
00353
00354 };
00355
00356 #endif