rational_number.hxx

Go to the documentation of this file.
00001 // rational_number.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2004, 2005 The Vaucanson Group.
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
00011 //
00012 // The complete GNU General Public Licence Notice can be found as the
00013 // `COPYING' file in the root directory.
00014 //
00015 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
00016 //
00017 #ifndef VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_RATIONAL_NUMBER_HXX
00018 # define VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_RATIONAL_NUMBER_HXX
00019 
00020 # include <vaucanson/misc/contract.hh>
00021 # include <vaucanson/misc/limits.hh>
00022 # include <cmath>
00023 
00031 namespace vcsn
00032 {
00033   namespace algebra
00034   {
00035     // Default constructor.
00036     inline
00037     RationalNumber::RationalNumber(int num, unsigned int denom):
00038       num_ (num),
00039       denom_ (denom)
00040     {
00041       precondition(denom != 0);
00042       set_result();
00043     }
00044 
00045     inline
00046     RationalNumber::RationalNumber():num_ (0), denom_ (1)
00047     {
00048     }
00049 
00050     // Copy constructor.
00051     inline
00052     RationalNumber::RationalNumber(const RationalNumber& nb) :
00053       num_ (nb.num_), denom_ (nb.denom_)
00054     {
00055       set_result();
00056     }
00057 
00058 
00059     template <typename T>
00060     RationalNumber::RationalNumber(const T num) : num_ (num),
00061                                                   denom_ (T(1))
00062     {
00063     }
00064 
00065     inline
00066     const int&          RationalNumber::num() const
00067     {
00068       return num_;
00069     }
00070 
00071     inline
00072     const unsigned int& RationalNumber::denom() const
00073     {
00074       return denom_;
00075     }
00076 
00077     inline
00078     RationalNumber&     RationalNumber::set_result(int num,unsigned int denom)
00079     {
00080       const int n = gcd(abs(num), denom);
00081       num_ = num/n;
00082       denom_ = denom/n;
00083       return *this;
00084     }
00085 
00086     inline
00087     RationalNumber&     RationalNumber::set_result()
00088     {
00089       const int n = gcd(abs(num_), denom_);
00090       num_ /= n;
00091       denom_ /= n;
00092       return *this;
00093     }
00094 
00095     inline
00096     std::ostream&       RationalNumber::print(std::ostream& ostr) const
00097     {
00098       return ostr << num_ << "/" << denom_;
00099     }
00100 
00101     // Operators.
00102 
00103     inline
00104     RationalNumber
00105     RationalNumber::operator+(const RationalNumber& nb) const
00106     {
00107       const int m = lcm(denom_, nb.denom());
00108 
00109       return RationalNumber(num_ * m / denom_ + nb.num() * m / nb.denom(), m);
00110     }
00111 
00112     inline
00113     RationalNumber
00114     RationalNumber::operator-(const RationalNumber& nb) const
00115     {
00116       const int m = lcm(denom_, nb.denom());
00117 
00118       return RationalNumber(num_ * m / denom_ - nb.num() * m / nb.denom(), m);
00119     }
00120 
00121     inline
00122     RationalNumber
00123     RationalNumber::operator-() const
00124     {
00125       return RationalNumber(-num_, denom_);
00126     }
00127 
00128     inline
00129     RationalNumber
00130     RationalNumber::operator*(const RationalNumber& nb) const
00131     {
00132       return RationalNumber(num_ * nb.num(), denom_ * nb.denom());
00133     }
00134 
00135     inline
00136     RationalNumber
00137     RationalNumber::operator/(const RationalNumber& nb) const
00138     {
00139       if (nb.num() < 0)
00140         return RationalNumber(-num_ * nb.denom(), denom_ * -nb.num());
00141       return RationalNumber(num_ * nb.denom(), denom_ * nb.num());
00142     }
00143 
00144     inline
00145     RationalNumber&     RationalNumber::operator+=(const RationalNumber& nb)
00146     {
00147       const int m = lcm(denom_, nb.denom());
00148       return set_result(num_ * m / denom_ + nb.num() * m / nb.denom(), m);
00149     }
00150 
00151     inline
00152     RationalNumber&     RationalNumber::operator-=(const RationalNumber& nb)
00153     {
00154       const int m = lcm(denom_, nb.denom());
00155       return set_result(num_ * m / denom_ - nb.num() * m / nb.denom(), m);
00156     }
00157 
00158     inline
00159     RationalNumber&     RationalNumber::operator*=(const RationalNumber& nb)
00160     {
00161       return set_result(num_ * nb.num(), denom_ * nb.denom());
00162     }
00163 
00164     inline
00165     RationalNumber&     RationalNumber::operator/=(const RationalNumber& nb)
00166     {
00167       if (nb.num() < 0)
00168         return set_result(-num_ * nb.denom(), denom_ * -nb.num());
00169       return set_result(num_ * nb.denom(), denom_ * nb.num());
00170     }
00171 
00172     inline
00173     bool        RationalNumber::operator<(const RationalNumber& nb) const
00174     {
00175       const int m = lcm(denom_, nb.denom());
00176       int num1 = num_ * (m / denom_);
00177       int num2 = nb.num() * (m / nb.denom());
00178       return num1 < num2;
00179     }
00180 
00181     inline
00182     bool        RationalNumber::operator>(const RationalNumber& nb) const
00183     {
00184       const int m = lcm(denom_, nb.denom());
00185       int num1 = num_ * (m / denom_);
00186       int num2 = nb.num() * (m / nb.denom());
00187       return num1 > num2;
00188     }
00189 
00190     inline
00191     bool        RationalNumber::operator<=(const RationalNumber& nb) const
00192     {
00193       const int m = lcm(denom_, nb.denom());
00194       int num1 = num_ * (m / denom_);
00195       int num2 = nb.num() * (m / nb.denom());
00196       return num1 <= num2;
00197     }
00198 
00199     inline
00200     bool        RationalNumber::operator>=(const RationalNumber& nb) const
00201     {
00202       const int m = lcm(denom_, nb.denom());
00203       int num1 = num_ * (m / denom_);
00204       int num2 = nb.num() * (m / nb.denom());
00205       return num1 >= num2;
00206     }
00207 
00208     inline
00209     bool        RationalNumber::operator==(const RationalNumber& nb) const
00210     {
00211       const int m = lcm(denom_, nb.denom());
00212       int num1 = num_ * (m / denom_);
00213       int num2 = nb.num() * (m / nb.denom());
00214       return num1 == num2;
00215     }
00216 
00217     inline
00218     bool        RationalNumber::operator!=(const RationalNumber& nb) const
00219     {
00220       const int m = lcm(denom_, nb.denom());
00221       int num1 = num_ * (m / denom_);
00222       int num2 = nb.num() * (m / nb.denom());
00223       return num1 != num2;
00224     }
00225 
00226     // Goodies.
00227 
00228     inline
00229     int         RationalNumber::to_int() const
00230     {
00231       precondition(denom_<static_cast<unsigned>(misc::limits<int>::max()));
00232       return num_ / static_cast<int> (denom_);
00233     }
00234 
00235     inline
00236     double      RationalNumber::to_double() const
00237     {
00238       return static_cast<double> (num_) / denom_;
00239     }
00240 
00241     inline
00242     std::ostream& operator<<(std::ostream& ostr, const RationalNumber& nb)
00243     {
00244       return nb.print(ostr);
00245     }
00246 
00247    inline
00248     int gcd(int a, unsigned int b)
00249     {
00250       unsigned n = b;
00251       while (n != 0)
00252         {
00253           int t = a % n;
00254           a = n;
00255           n = t;
00256         }
00257       return a;
00258     }
00259 
00260     inline
00261     int lcm(int a, unsigned int b)
00262     {
00263       int d;
00264       if (!a || !b || !(d = gcd(abs(a), b)))
00265         return 0;
00266       int r = a * b / d;
00267 
00268       postcondition_ (r != 0, "Overflow");
00269 
00270       return r;
00271     }
00272   }
00273 }
00274 
00275 namespace std
00276 {
00277   inline
00278   ::vcsn::algebra::RationalNumber
00279   numeric_limits< ::vcsn::algebra::RationalNumber >::min()
00280   {
00281     return
00282       ::vcsn::algebra::RationalNumber (std::numeric_limits<int>::min(), 1);
00283   }
00284 
00285   inline
00286   ::vcsn::algebra::RationalNumber
00287   numeric_limits< ::vcsn::algebra::RationalNumber >::max()
00288   {
00289     return
00290       ::vcsn::algebra::RationalNumber (std::numeric_limits<int>::max(), 1);
00291   }
00292 } // End of namespace std.
00293 
00294 #endif // ! VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_RATIONAL_NUMBER_HXX

Generated on Sat Jul 29 17:13:10 2006 for Vaucanson by  doxygen 1.4.6