00001
00002 #ifndef vnl_rational_h_
00003 #define vnl_rational_h_
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
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <vcl_iostream.h>
00047 #include <vcl_cassert.h>
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 class vnl_rational
00068 {
00069 long num_;
00070 long den_;
00071
00072 public:
00073
00074
00075
00076
00077
00078 inline vnl_rational (long num = 0L, long den = 1L)
00079 : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); }
00080
00081
00082
00083
00084
00085 explicit inline vnl_rational (int num, int den = 1)
00086 : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); }
00087 explicit inline vnl_rational (unsigned int num, unsigned int den = 1)
00088 : num_((long)num), den_((long)den) { assert(num!=0||den!=0); normalize(); }
00089
00090
00091
00092 explicit vnl_rational (double d);
00093
00094 inline vnl_rational (vnl_rational const& from)
00095 : num_(from.numerator()), den_(from.denominator()) {}
00096
00097 inline ~vnl_rational() {}
00098
00099 inline void set(long num, long den) { assert(num!=0||den!=0); num_=num; den_=den; normalize(); }
00100
00101
00102 inline long numerator () const { return num_; }
00103
00104 inline long denominator () const { return den_; }
00105
00106
00107 inline vnl_rational& operator= (vnl_rational const& rhs) {
00108 num_ = rhs.numerator(); den_ = rhs.denominator(); return *this; }
00109
00110
00111 inline bool operator== (vnl_rational const& rhs) const {
00112 return num_ == rhs.numerator() && den_ == rhs.denominator(); }
00113 inline bool operator!= (vnl_rational const& rhs) const { return !operator==(rhs); }
00114 inline bool operator== (long rhs) const { return num_ == rhs && den_ == 1; }
00115 inline bool operator!= (long rhs) const { return !operator==(rhs); }
00116 inline bool operator== (int rhs) const { return num_ == rhs && den_ == 1; }
00117 inline bool operator!= (int rhs) const { return !operator==(rhs); }
00118
00119
00120 inline vnl_rational operator-() const { return vnl_rational(-num_, den_); }
00121
00122 inline vnl_rational operator+() const { return *this; }
00123
00124 inline bool operator!() const { return num_ == 0L; }
00125
00126 inline vnl_rational abs() const { return vnl_rational(num_<0?-num_:num_, den_); }
00127
00128
00129 vnl_rational& invert () {
00130 long t = num_; num_ = den_; den_ = t; normalize(); return *this; }
00131
00132
00133
00134 inline vnl_rational& operator+= (vnl_rational const& r) {
00135 if (den_ == r.denominator()) num_ += r.numerator();
00136 else { long c = vnl_rational::gcd(den_,r.denominator()); if (c==0) c=1;
00137 num_ = num_*(r.denominator()/c) + (den_/c)*r.numerator();
00138 den_ *= r.denominator()/c; }
00139 assert(num_!=0 || den_ != 0);
00140 normalize (); return *this;
00141 }
00142 inline vnl_rational& operator+= (long r) { num_ += den_*r; return *this; }
00143
00144
00145 inline vnl_rational& operator-= (vnl_rational const& r) {
00146 if (den_ == r.denominator()) num_ -= r.num_;
00147 else { long c = vnl_rational::gcd(den_,r.denominator()); if (c==0) c=1;
00148 num_ = num_*(r.denominator()/c) - (den_/c)*r.numerator();
00149 den_ *= r.denominator()/c; }
00150 assert(num_!=0 || den_ != 0);
00151 normalize (); return *this;
00152 }
00153 inline vnl_rational& operator-= (long r) { num_ -= den_*r; return *this; }
00154
00155
00156 inline vnl_rational& operator*= (vnl_rational const& r) {
00157 num_ *= r.numerator(); den_ *= r.denominator();
00158 assert(num_!=0 || den_ != 0);
00159 normalize (); return *this;
00160 }
00161 inline vnl_rational& operator*= (long r) {num_*=r;normalize();return *this;}
00162
00163
00164 inline vnl_rational& operator/= (vnl_rational const& r) {
00165 num_ *= r.denominator(); den_ *= r.numerator();
00166 assert(num_!=0 || den_ != 0);
00167 normalize (); return *this;
00168 }
00169 inline vnl_rational& operator/= (long r) {
00170 den_ *= r; assert(num_!=0 || den_ != 0);
00171 normalize (); return *this;
00172 }
00173
00174
00175 inline vnl_rational& operator%= (vnl_rational const& r) {
00176 assert(r.numerator() != 0);
00177 if (den_ == r.denominator()) num_ %= r.numerator();
00178 else { long c = vnl_rational::gcd(den_,r.denominator()); if (c==0) c=1;
00179 num_ *= r.denominator()/c;
00180 num_ %= (den_/c)*r.numerator();
00181 den_ *= r.denominator()/c; }
00182 normalize (); return *this;
00183 }
00184 inline vnl_rational& operator%=(long r){assert(r);num_%=den_*r;normalize();return *this;}
00185
00186
00187 inline vnl_rational& operator++ () { num_ += den_; return *this; }
00188
00189 inline vnl_rational& operator-- () { num_ -= den_; return *this; }
00190
00191 inline vnl_rational operator++(int){vnl_rational b=*this;num_+=den_;return b;}
00192
00193 inline vnl_rational operator--(int){vnl_rational b=*this;num_-=den_;return b;}
00194
00195 inline bool operator< (vnl_rational const& rhs) const {
00196 if (den_ == rhs.denominator())
00197 return num_ < rhs.numerator();
00198
00199 else
00200 return num_ * rhs.denominator() < den_ * rhs.numerator();
00201 }
00202 inline bool operator> (vnl_rational const& r) const { return r < *this; }
00203 inline bool operator<= (vnl_rational const& r) const { return !operator>(r); }
00204 inline bool operator>= (vnl_rational const& r) const { return !operator<(r); }
00205 inline bool operator< (long r) const { return num_ < den_ * r; }
00206 inline bool operator> (long r) const { return num_ > den_ * r; }
00207 inline bool operator<= (long r) const { return !operator>(r); }
00208 inline bool operator>= (long r) const { return !operator<(r); }
00209 inline bool operator< (int r) const { return num_ < den_ * r; }
00210 inline bool operator> (int r) const { return num_ > den_ * r; }
00211 inline bool operator<= (int r) const { return !operator>(r); }
00212 inline bool operator>= (int r) const { return !operator<(r); }
00213 inline bool operator< (double r) const { return num_ < den_ * r; }
00214 inline bool operator> (double r) const { return num_ > den_ * r; }
00215 inline bool operator<= (double r) const { return !operator>(r); }
00216 inline bool operator>= (double r) const { return !operator<(r); }
00217
00218
00219 inline long truncate () const { assert(den_ != 0); return num_/den_; }
00220
00221 inline long floor () const { long t = truncate();
00222 return num_<0L && (num_%den_) != 0 ? t-1 : t; }
00223
00224 inline long ceil () const { long t = truncate();
00225 return num_>0L && (num_%den_) != 0 ? t+1 : t; }
00226
00227 inline long round () const { long t = truncate();
00228 if (num_ < 0) return ((-num_)%den_) >= 0.5*den_ ? t-1 : t;
00229 else return (num_ %den_) >= 0.5*den_ ? t+1 : t;
00230 }
00231
00232
00233 inline operator short () {
00234 long t = truncate (); short r = (short)t;
00235 assert(r == t);
00236 return r;
00237 }
00238 inline operator int () {
00239 long t = truncate (); int r = (int)t;
00240 assert(r == t);
00241 return r;
00242 }
00243 inline operator long () const { return truncate(); }
00244 inline operator long () { return truncate(); }
00245 inline operator float () const { return ((float)num_)/((float)den_); }
00246 inline operator float () { return ((float)num_)/((float)den_); }
00247 inline operator double () const { return ((double)num_)/((double)den_); }
00248 inline operator double () { return ((double)num_)/((double)den_); }
00249
00250
00251
00252 static inline long gcd (long l1, long l2) {
00253 while (l2!=0) { long t = l2; l2 = l1 % l2; l1 = t; }
00254 return l1<0 ? (-l1) : l1;
00255 }
00256
00257 private:
00258
00259
00260
00261 inline void normalize () {
00262 if (num_ == 0) { den_ = 1; return; }
00263 if (den_ == 0) { num_ = (num_>0) ? 1 : -1; return; }
00264 if (num_ != 1 && num_ != -1 && den_ != 1) {
00265 long common = vnl_rational::gcd (num_, den_);
00266 if (common != 1) { num_ /= common; den_ /= common; }
00267 }
00268
00269 if (den_ < 0) { num_ *= -1; den_ *= -1; }
00270 }
00271 };
00272
00273
00274
00275 inline vcl_ostream& operator<< (vcl_ostream& s, vnl_rational const& r)
00276 {
00277 return s << r.numerator() << '/' << r.denominator();
00278 }
00279
00280
00281
00282 inline vcl_istream& operator>> (vcl_istream& s, vnl_rational& r)
00283 {
00284 long n, d; s >> n >> d;
00285 r.set(n,d); return s;
00286 }
00287
00288
00289
00290 inline vnl_rational operator+ (vnl_rational const& r1, vnl_rational const& r2)
00291 {
00292 vnl_rational result(r1); return result += r2;
00293 }
00294
00295 inline vnl_rational operator+ (vnl_rational const& r1, long r2)
00296 {
00297 vnl_rational result(r1); return result += r2;
00298 }
00299
00300 inline vnl_rational operator+ (vnl_rational const& r1, int r2)
00301 {
00302 vnl_rational result(r1); return result += (long)r2;
00303 }
00304
00305 inline vnl_rational operator+ (long r2, vnl_rational const& r1)
00306 {
00307 vnl_rational result(r1); return result += r2;
00308 }
00309
00310 inline vnl_rational operator+ (int r2, vnl_rational const& r1)
00311 {
00312 vnl_rational result(r1); return result += (long)r2;
00313 }
00314
00315
00316
00317 inline vnl_rational operator- (vnl_rational const& r1, vnl_rational const& r2)
00318 {
00319 vnl_rational result(r1); return result -= r2;
00320 }
00321
00322 inline vnl_rational operator- (vnl_rational const& r1, long r2)
00323 {
00324 vnl_rational result(r1); return result -= r2;
00325 }
00326
00327 inline vnl_rational operator- (vnl_rational const& r1, int r2)
00328 {
00329 vnl_rational result(r1); return result -= (long)r2;
00330 }
00331
00332 inline vnl_rational operator- (long r2, vnl_rational const& r1)
00333 {
00334 vnl_rational result(-r1); return result += r2;
00335 }
00336
00337 inline vnl_rational operator- (int r2, vnl_rational const& r1)
00338 {
00339 vnl_rational result(-r1); return result += (long)r2;
00340 }
00341
00342
00343
00344 inline vnl_rational operator* (vnl_rational const& r1, vnl_rational const& r2)
00345 {
00346 vnl_rational result(r1); return result *= r2;
00347 }
00348
00349 inline vnl_rational operator* (vnl_rational const& r1, long r2)
00350 {
00351 vnl_rational result(r1); return result *= r2;
00352 }
00353
00354 inline vnl_rational operator* (vnl_rational const& r1, int r2)
00355 {
00356 vnl_rational result(r1); return result *= (long)r2;
00357 }
00358
00359 inline vnl_rational operator* (long r2, vnl_rational const& r1)
00360 {
00361 vnl_rational result(r1); return result *= r2;
00362 }
00363
00364 inline vnl_rational operator* (int r2, vnl_rational const& r1)
00365 {
00366 vnl_rational result(r1); return result *= (long)r2;
00367 }
00368
00369
00370
00371 inline vnl_rational operator/ (vnl_rational const& r1, vnl_rational const& r2)
00372 {
00373 vnl_rational result(r1); return result /= r2;
00374 }
00375
00376 inline vnl_rational operator/ (vnl_rational const& r1, long r2)
00377 {
00378 vnl_rational result(r1); return result /= r2;
00379 }
00380
00381 inline vnl_rational operator/ (vnl_rational const& r1, int r2)
00382 {
00383 vnl_rational result(r1); return result /= (long)r2;
00384 }
00385
00386 inline vnl_rational operator/ (long r1, vnl_rational const& r2)
00387 {
00388 vnl_rational result(r1); return result /= r2;
00389 }
00390
00391 inline vnl_rational operator/ (int r1, vnl_rational const& r2)
00392 {
00393 vnl_rational result((long)r1); return result /= r2;
00394 }
00395
00396
00397
00398 inline vnl_rational operator% (vnl_rational const& r1, vnl_rational const& r2)
00399 {
00400 vnl_rational result(r1); return result %= r2;
00401 }
00402
00403 inline vnl_rational operator% (vnl_rational const& r1, long r2)
00404 {
00405 vnl_rational result(r1); return result %= r2;
00406 }
00407
00408 inline vnl_rational operator% (vnl_rational const& r1, int r2)
00409 {
00410 vnl_rational result(r1); return result %= (long)r2;
00411 }
00412
00413 inline vnl_rational operator% (long r1, vnl_rational const& r2)
00414 {
00415 vnl_rational result(r1); return result %= r2;
00416 }
00417
00418 inline vnl_rational operator% (int r1, vnl_rational const& r2)
00419 {
00420 vnl_rational result((long)r1); return result %= r2;
00421 }
00422
00423 inline bool operator== (int r1, vnl_rational const& r2) { return r2==r1; }
00424 inline bool operator== (long r1, vnl_rational const& r2) { return r2==r1; }
00425 inline bool operator!= (int r1, vnl_rational const& r2) { return r2!=r1; }
00426 inline bool operator!= (long r1, vnl_rational const& r2) { return r2!=r1; }
00427 inline bool operator< (int r1, vnl_rational const& r2) { return r2> r1; }
00428 inline bool operator< (long r1, vnl_rational const& r2) { return r2> r1; }
00429 inline bool operator> (int r1, vnl_rational const& r2) { return r2< r1; }
00430 inline bool operator> (long r1, vnl_rational const& r2) { return r2< r1; }
00431 inline bool operator<= (int r1, vnl_rational const& r2) { return r2>=r1; }
00432 inline bool operator<= (long r1, vnl_rational const& r2) { return r2>=r1; }
00433 inline bool operator>= (int r1, vnl_rational const& r2) { return r2<=r1; }
00434 inline bool operator>= (long r1, vnl_rational const& r2) { return r2<=r1; }
00435
00436 inline long truncate (vnl_rational const& r) { return r.truncate(); }
00437 inline long floor (vnl_rational const& r) { return r.floor(); }
00438 inline long ceil (vnl_rational const& r) { return r.ceil(); }
00439 inline long round (vnl_rational const& r) { return r.round(); }
00440
00441 inline vnl_rational vnl_math_abs(vnl_rational const& x) { return x<0L ? -x : x; }
00442 inline vnl_rational vnl_math_squared_magnitude(vnl_rational const& x) { return x*x; }
00443 inline vnl_rational vnl_math_sqr(vnl_rational const& x) { return x*x; }
00444 inline bool vnl_math_isnan(vnl_rational const& ){return false;}
00445 inline bool vnl_math_isfinite(vnl_rational const& x){return x.denominator() != 0L;}
00446
00447 #endif // vnl_rational_h_