cel_rational.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00004 //
00005 // (C) 2003-2006 Celartem Technology Inc. All rights reserved.
00006 //----------------------------------------------------------------------------
00007 
00008 #ifndef _cel_rational_h_
00009 #define _cel_rational_h_
00010 
00011 #include "cel_types.h"
00012 #include "cel_endian.h"
00013 #include "cel_exception.h"
00014 #include "cel_datatraits.h"
00015 #include "cel_iostream.h"
00016 
00017 namespace Celartem
00018 {
00019 
00054     template<typename Int> struct Rational
00055     {
00059         Int num;
00060 
00064         Int den;
00065 
00069         Rational() : num(0), den(1) {}
00070 
00076         Rational(const Int& n) : num(n), den(1) {}
00077 
00086         Rational(const Int& n, const Int& d) : num(n), den(d) {normalize();}
00087 
00094         Rational(const Rational& r) : num(r.num), den(r.den) {}
00095 
00103         inline Rational& operator=(const Rational& r)
00104         {
00105             num = r.num;
00106             den = r.den;
00107             return *this;
00108         }
00109 
00118         inline Rational& operator=(const Int& n)
00119         {
00120             num = n;
00121             den = 1;
00122             return *this;
00123         }
00124 
00134         inline void assign(const Int& n, const Int& d)
00135         {
00136             num = n;
00137             den = d;
00138             normalize();
00139         }
00140 
00151         void normalize()
00152         {
00153             if(den == zero())
00154                 celThrow(errInvalidState); // ???
00155 
00156             if(num == zero())
00157             {
00158                 den = 1;
00159                 return;
00160             }
00161 
00162             Int g = gcd(num, den);
00163             if(den < zero())
00164                 g = zero() - g;
00165 
00166             num /= g;
00167             den /= g;
00168         }
00169 
00177         inline Rational& operator+=(const Rational& r)
00178         {
00179             Int g = gcd(den, r.den);
00180             den /= g;
00181             num = num * (r.den / g) + r.num * den;
00182             g = gcd(num, g);
00183             num /= g;
00184             den *= r.den / g;
00185             return *this;
00186         }
00187 
00195         inline Rational& operator-=(const Rational& r)
00196         {
00197             Int g = gcd(den, r.den);
00198             den /= g;
00199             num = num * (r.den / g) - r.num * den;
00200             g = gcd(num, g);
00201             num /= g;
00202             den *= r.den / g;
00203             return *this;
00204         }
00205 
00214         inline Rational& operator*=(const Rational& r)
00215         {
00216             Int gcd1 = gcd(num, r.den);
00217             Int gcd2 = gcd(r.num, den);
00218             num = (num / gcd1) * (r.num / gcd2);
00219             den = (den / gcd2) * (r.den / gcd1);
00220             return *this;
00221         }
00222 
00233         inline Rational& operator/=(const Rational& r)
00234         {
00235             if(num == zero())
00236                 return *this;
00237 
00238             if(r.den == zero())
00239                 celThrow(errDivByZero);
00240 
00241             Int gcd1 = gcd(num, r.num);
00242             Int gcd2 = gcd(r.den, den);
00243             num = (num / gcd1) * (r.den / gcd2);
00244             den = (den / gcd2) * (r.num / gcd1);
00245             return *this;
00246         }
00247 
00253         inline const Rational& operator++()
00254         {
00255             num += den;
00256             return *this;
00257         }
00258 
00264         inline const Rational& operator--()
00265         {
00266             num -= den;
00267             return *this;
00268         }
00269 
00277         Rational operator+(const Rational<Int>& r) const
00278         {
00279             Rational temp = *this;
00280             temp += r;
00281             return temp;
00282         }
00283 
00291         Rational operator-(const Rational<Int>& r) const
00292         {
00293             Rational temp = *this;
00294             temp -= r;
00295             return temp;
00296         }
00297 
00305         Rational operator*(const Rational<Int>& r) const
00306         {
00307             Rational temp = *this;
00308             temp *= r;
00309             return temp;
00310         }
00311 
00319         Rational operator/(const Rational<Int>& r) const
00320         {
00321             Rational temp = *this;
00322             temp /= r;
00323             return temp;
00324         }
00325 
00326 #if 0
00327 
00333         Rational operator+() const
00334         {
00335             return *this;
00336         }
00337 
00343         Rational operator-() const
00344         {
00345             return Rational(-r.num, r.den);
00346         }
00347 #endif
00348 
00359         bool operator<(const Rational& r) const
00360         {
00361             if(num < zero() && r.num >= zero())
00362                 return true;
00363             if(num >= zero() && r.num <= zero())
00364                 return false;
00365 
00366             Int gcd1 = gcd(num, r.num);
00367             Int gcd2 = gcd(r.den, den);
00368             return
00369                 (num / gcd1) * (r.den / gcd2)
00370                 < (den / gcd2) * (r.num / gcd1);
00371         }
00372 
00383         inline bool operator<=(const Rational& r) const
00384         {
00385             return (*this == r) || (*this < r);
00386         }
00387 
00398         inline bool operator==(const Rational& r) const
00399         {
00400             return (num == r.num && den == r.den);
00401         }
00402 
00413         inline bool operator!=(const Rational& r) const
00414         {
00415             return (num != r.num || den != r.den);
00416         }
00417 
00428         inline bool operator>(const Rational& r) const
00429         {
00430             return !(*this <= r);
00431         }
00432 
00443         inline bool operator>=(const Rational& r) const
00444         {
00445             return !(*this < r);
00446         }
00447 
00453         Rational reciprocal() const
00454         {
00455             return Rational(den, num);
00456         }
00457 
00464         void serialize(
00465             Stream *inStream, size_t inLevel, Endian inEndian) const
00466         {
00467             write<Int>(inStream, num, inEndian);
00468             write<Int>(inStream, den, inEndian);
00469         }
00470 
00477         void deserialize(
00478             Stream *inStream, size_t inLevel, Endian inEndian)
00479         {
00480             num = read<Int>(inStream, inEndian);
00481             den = read<Int>(inStream, inEndian);
00482         }
00483 
00484     private:
00485         static inline const Int& zero()
00486         {
00487             static Int _zero(0);
00488             return _zero;
00489         }
00490 
00491         static Int gcd(Int n, Int m)
00492         {
00493             if(n < zero()) n = zero() - n;
00494             if(m < zero()) m = zero() - m;
00495 
00496             for(;;)
00497             {
00498                 if(m == zero())
00499                     return n;
00500                 n %= m;
00501                 if(n == zero())
00502                     return m;
00503                 m %= n;
00504             }
00505         }
00506 
00507         static Int lcm(Int n, Int m)
00508         {
00509             if(n == zero() || n == zero())
00510                 return zero();
00511             n /= gcd(n, m);
00512             n *= m;
00513             if(n < zero())
00514                 return -n;
00515             return n;
00516         }
00517     };
00518 
00523     template<typename Int> struct DataTraits< Rational<Int> >
00524     {
00525         static const CopyPolicy
00526             copyPolicy = byMemcpy; 
00527         static const StoragePolicy
00528             storagePolicy = byClassMethods; 
00529     };
00530 
00538     typedef Rational<uint32_t> TIFF_RATIONAL;
00539 
00547     typedef Rational<int32_t> TIFF_SRATIONAL;
00548 
00549     template<> TIFF_RATIONAL swap<TIFF_RATIONAL>(const TIFF_RATIONAL& num);
00550     template<> TIFF_SRATIONAL swap<TIFF_SRATIONAL>(const TIFF_SRATIONAL& num);
00551 }
00552 
00553 #endif // _cel_rational_h_

This document is automatically generated using doxygen 1.5.4 at Fri Jun 27 18:21:54 2008.