00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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)),
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
00165
00166
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
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
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)
00364 {
00365 istr.unget();
00366 a.set(num, 1);
00367 return istr;
00368 }
00369
00370
00371 DENType den;
00372 istr >> den;
00373 a.set(num, den);
00374
00375 return istr;
00376 }
00377 }
00378
00379 }
00380
00381 #endif // ! VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_Q_NUMBER_HXX