• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

q_number.hxx

00001 // q_number.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2011 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_Q_NUMBER_HXX
00018 # define VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_Q_NUMBER_HXX
00019 
00020 # include <vaucanson/algebra/implementation/semiring/q_number.hh>
00021 # include <vaucanson/misc/algebra.hh>
00022 # include <vaucanson/misc/contract.hh>
00023 
00024 # include <iostream>
00025 # include <cassert>
00026 
00027 namespace vcsn {
00028 
00029   namespace algebra {
00030 
00031     template<typename NUMType, typename DENType>
00032     inline
00033     TRationalNumber<NUMType, DENType>::TRationalNumber ()
00034     : num_ (NUMType(0)), // 0 or 1
00035       den_ (DENType(1))
00036     {
00037     }
00038 
00039     template<typename NUMType, typename DENType>
00040     inline
00041     TRationalNumber<NUMType, DENType>::TRationalNumber (const NUMType num)
00042     : num_ (num),
00043       den_ (DENType(1))
00044     {
00045     }
00046 
00047     template<typename NUMType, typename DENType>
00048     inline
00049     TRationalNumber<NUMType, DENType>::TRationalNumber (const NUMType num, const DENType den)
00050     {
00051       set_rational (num, den);
00052     }
00053 
00054     template<typename NUMType, typename DENType>
00055     inline
00056     TRationalNumber<NUMType, DENType>::TRationalNumber (const TRationalNumber<NUMType, DENType>& nb)
00057     {
00058       set_rational (nb.num_, nb.den_);
00059     }
00060 
00061     template<typename NUMType, typename DENType>
00062     inline
00063     TRationalNumber<NUMType, DENType>::~TRationalNumber ()
00064     {}
00065 
00066     template<typename NUMType, typename DENType>
00067     inline
00068     vcsn::algebra::TRationalNumber<NUMType, DENType>&
00069     TRationalNumber<NUMType, DENType>::set (const NUMType num, const DENType den)
00070     {
00071       set_rational (num, den);
00072       return (*this);
00073     }
00074 
00075     template<typename NUMType, typename DENType>
00076     inline
00077     NUMType
00078     TRationalNumber<NUMType, DENType>::num_get () const
00079     {
00080       return num_;
00081     }
00082 
00083     template<typename NUMType, typename DENType>
00084     inline
00085     DENType
00086     TRationalNumber<NUMType, DENType>::den_get () const
00087     {
00088       return den_;
00089     }
00090 
00091     template<typename NUMType, typename DENType>
00092     inline
00093     std::ostream&
00094     TRationalNumber<NUMType, DENType>::print (std::ostream& ostr) const
00095     {
00096       if (den_ != 1)
00097         return ostr << num_ << '/' << den_;
00098       return ostr << num_;
00099     }
00100 
00101     template<typename NUMType, typename DENType>
00102     inline
00103     TRationalNumber<NUMType, DENType>
00104     TRationalNumber<NUMType, DENType>::operator+ (const TRationalNumber<NUMType, DENType>& nb) const
00105     {
00106       return TRationalNumber<NUMType, DENType> (num_ * nb.den_ + nb.num_ * den_, den_ * nb.den_);
00107     }
00108 
00109     template<typename NUMType, typename DENType>
00110     inline
00111     TRationalNumber<NUMType, DENType>
00112     TRationalNumber<NUMType, DENType>::operator- (const TRationalNumber<NUMType, DENType>& nb) const
00113     {
00114       using vcsn::misc::abs;
00115       NUMType a = den_;
00116       NUMType b = nb.den_;
00117 
00118       return TRationalNumber<NUMType, DENType> ((num_ * b) - (nb.num_ * a), den_ * nb.den_);
00119     }
00120 
00121     template<typename NUMType, typename DENType>
00122     inline
00123     TRationalNumber<NUMType, DENType>
00124     TRationalNumber<NUMType, DENType>::operator- () const
00125     {
00126       return TRationalNumber<NUMType, DENType> (- num_, den_);
00127     }
00128 
00129     template<typename NUMType, typename DENType>
00130     inline
00131     TRationalNumber<NUMType, DENType>
00132     TRationalNumber<NUMType, DENType>::operator* (const TRationalNumber<NUMType, DENType>& nb) const
00133     {
00134       NUMType d1 = vcsn::misc::gcd (vcsn::misc::abs(num_), nb.den_get ());
00135       NUMType d2 = vcsn::misc::gcd (den_, vcsn::misc::abs(nb.num_get ()));
00136 
00137       return TRationalNumber<NUMType, DENType> ((num_ / d1) * (nb.num_get () / d2),
00138                              (den_ / d2) * (nb.den_get () / d1));
00139     }
00140 
00141     template<typename NUMType, typename DENType>
00142     inline
00143     TRationalNumber<NUMType, DENType>
00144     TRationalNumber<NUMType, DENType>::operator/ (const TRationalNumber<NUMType, DENType>& nb) const
00145     {
00146       NUMType signe = 1;
00147       assert(nb.num_ != 0);
00148       NUMType numgcd = vcsn::misc::gcd (vcsn::misc::abs (num_), vcsn::misc::abs (nb.num_));
00149       NUMType dengcd = vcsn::misc::gcd (den_, nb.den_);
00150       if(nb.num_ < 0)
00151         signe = -1;
00152       return TRationalNumber<NUMType, DENType> (signe * ((num_ / numgcd)
00153                                                          * ((NUMType) nb.den_get() /dengcd)),
00154                                                 (signe * nb.num_get()
00155                                                          / numgcd) *
00156                                                 (den_ / dengcd));
00157     }
00158 
00159     template<typename NUMType, typename DENType>
00160     inline
00161     TRationalNumber<NUMType, DENType>&
00162     TRationalNumber<NUMType, DENType>::operator+= (const TRationalNumber<NUMType, DENType>& nb)
00163     {
00164       // std::cout << "+=" << std::endl;
00165       // std::cout << *this << '+' << nb << "= " << num_ * nb.den_ +
00166       //        nb.num_ * den_ << '\'' << den_ * nb.den_<< std::endl;
00167       set_rational (num_ * nb.den_ + nb.num_ * den_, den_ * nb.den_);
00168       return (*this);
00169     }
00170 
00171     template<typename NUMType, typename DENType>
00172     inline
00173     TRationalNumber<NUMType, DENType>&
00174     TRationalNumber<NUMType, DENType>::operator-= (const TRationalNumber<NUMType, DENType>& nb)
00175     {
00176       set_rational (num_ * nb.den_ - nb.num_ * den_, den_ * nb.den_);
00177       return (*this);
00178     }
00179 
00180     template<typename NUMType, typename DENType>
00181     inline
00182     TRationalNumber<NUMType, DENType>&
00183     TRationalNumber<NUMType, DENType>::operator*= (const TRationalNumber<NUMType, DENType>& nb)
00184     {
00185       DENType d1 = vcsn::misc::gcd (vcsn::misc::abs(num_), nb.den_get ());
00186       DENType d2 = vcsn::misc::gcd (den_, vcsn::misc::abs(nb.num_get ()));
00187       set_unsafe_rational ((num_ / d1) * (nb.num_get () / d2),
00188                            (den_ / d2) * (nb.den_get () / d1));
00189       return (*this);
00190     }
00191 
00192     template<typename NUMType, typename DENType>
00193     inline
00194     TRationalNumber<NUMType, DENType>&
00195     TRationalNumber<NUMType, DENType>::operator/= (const TRationalNumber<NUMType, DENType>& nb)
00196     {
00197       NUMType signe = 1;
00198       assert(nb.num_ != 0);
00199       NUMType numgcd = vcsn::misc::gcd (vcsn::misc::abs (num_), vcsn::misc::abs (nb.num_));
00200       NUMType dengcd = vcsn::misc::gcd (den_, nb.den_);
00201       if(nb.num_ < 0)
00202         signe = -1;
00203       set_unsafe_rational (signe * ((num_ / numgcd) * ((NUMType) nb.den_get() /dengcd)),
00204                                                 (signe * nb.num_get() / numgcd) * (den_ / dengcd));
00205       return *this;
00206     }
00207 
00208     template<typename NUMType, typename DENType>
00209     inline
00210     bool
00211     TRationalNumber<NUMType, DENType>::operator== (const TRationalNumber<NUMType, DENType>& nb) const
00212     {
00213       //return (den_ * nb.num_ == nb.den_ * num_);
00214        if (!num_)
00215          return (!nb.num_);
00216        return (den_ == nb.den_) && (num_ == nb.num_);
00217     }
00218 
00219     template<typename NUMType, typename DENType>
00220     inline
00221     bool
00222     TRationalNumber<NUMType, DENType>::operator!= (const TRationalNumber<NUMType, DENType>& nb) const
00223     {
00224       // return (den_ * nb.num_ != nb.den_ * num_);
00225       if (!num_)
00226         return (!!nb.num_);
00227       return (den_ != nb.den_) || (num_ != nb.num_);
00228     }
00229 
00230     template<typename NUMType, typename DENType>
00231     inline
00232     bool
00233     TRationalNumber<NUMType, DENType>::operator< (const TRationalNumber<NUMType, DENType>& nb) const
00234     {
00235       return num_ * nb.den_ < nb.num_ * den_;
00236     }
00237 
00238     template<typename NUMType, typename DENType>
00239     inline
00240     bool
00241     TRationalNumber<NUMType, DENType>::operator<= (const TRationalNumber<NUMType, DENType>& nb) const
00242     {
00243       return num_ * nb.den_ <= nb.num_ * den_;
00244     }
00245 
00246     template<typename NUMType, typename DENType>
00247     inline
00248     bool
00249     TRationalNumber<NUMType, DENType>::operator> (const TRationalNumber<NUMType, DENType>& nb) const
00250     {
00251       return num_ * nb.den_ > nb.num_ * den_;
00252     }
00253 
00254     template<typename NUMType, typename DENType>
00255     inline
00256     bool
00257     TRationalNumber<NUMType, DENType>::operator>= (const TRationalNumber<NUMType, DENType>& nb) const
00258     {
00259       return num_ * nb.den_ >= nb.num_ * den_;
00260     }
00261 
00262     template<typename NUMType, typename DENType>
00263     inline
00264     TRationalNumber<NUMType, DENType>::operator float () const
00265     {
00266       return to_float ();
00267     }
00268 
00269     template<typename NUMType, typename DENType>
00270     inline
00271     int
00272     TRationalNumber<NUMType, DENType>::to_int () const
00273     {
00274       return num_ / den_;
00275     }
00276 
00277     template<typename NUMType, typename DENType>
00278     inline
00279     float
00280     TRationalNumber<NUMType, DENType>::to_float () const
00281     {
00282       return (static_cast<float> (num_)) / den_;
00283     }
00284 
00285     template<typename NUMType, typename DENType>
00286     inline
00287     double
00288     TRationalNumber<NUMType, DENType>::to_double () const
00289     {
00290       return (static_cast<double> (num_)) / den_;
00291     }
00292 #include <iostream>
00293     template<typename NUMType, typename DENType>
00294     inline
00295     void
00296     TRationalNumber<NUMType, DENType>::set_rational (const NUMType num, const DENType den)
00297     {
00298       if (num)
00299       {
00300         assert(den);
00301         NUMType div = vcsn::misc::gcd(vcsn::misc::abs(num), den);
00302         if (div < 0)
00303           std::cout << "false";
00304         num_ = num / div;
00305         den_ = den / div;
00306         if (1  != vcsn::misc::gcd(vcsn::misc::abs(num_), den_)) {
00307           std::cout << num_ << ' ' << den_ << std::endl;
00308         }
00309 
00310 
00311         assert(1u == vcsn::misc::gcd(vcsn::misc::abs(num_), den_));
00312         return;
00313       }
00314       else
00315       {
00316         num_ = 0;
00317         den_ = 1;
00318         return;
00319       }
00320     }
00321 
00322     template<typename NUMType, typename DENType>
00323     inline
00324     void
00325     TRationalNumber<NUMType, DENType>::set_unsafe_rational (const NUMType num, const DENType den)
00326     {
00327       assert (den != 0);
00328 
00329       num_ = num;
00330       den_ = den;
00331 
00332       assert (vcsn::misc::is_coprime (num_, den_));
00333     }
00334 
00335     template<typename NUMType, typename DENType>
00336     inline
00337     void
00338     TRationalNumber<NUMType, DENType>::set_rational ()
00339     {
00340       set_rational (num_, den_);
00341     }
00342 
00343     template<typename NUMType, typename DENType>
00344     inline
00345     std::ostream&
00346     operator<< (std::ostream& ostr, const TRationalNumber<NUMType, DENType>& nb)
00347     {
00348       nb.print (ostr);
00349       return ostr;
00350     }
00351 
00352     template<typename NUMType, typename DENType>
00353     inline
00354     std::istream&
00355     operator>> (std::istream& istr, TRationalNumber<NUMType, DENType>& a)
00356     {
00357       NUMType num;
00358 
00359       istr >> num;
00360       char slash;
00361       if (!istr.eof())
00362         istr.get(slash);
00363       if ('/' != slash) // Test if a slash is present.
00364       {
00365         istr.unget();
00366         a.set(num, 1);
00367         return istr;
00368        }
00369 
00370       // Otherwise read the denominator.
00371       DENType den;
00372       istr >> den;
00373       a.set(num, den);
00374 
00375       return istr;
00376     }
00377   } // !algebra
00378 
00379 } // !vcsn
00380 
00381 #endif // ! VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_Q_NUMBER_HXX

Generated on Fri Jul 8 2011 22:06:59 for Vaucanson by  doxygen 1.7.1