- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

# 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, 2006 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