00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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 # include <cstdlib>
00024
00032 namespace vcsn
00033 {
00034 namespace algebra
00035 {
00036
00037 inline
00038 RationalNumber::RationalNumber(int num, unsigned int denom):
00039 num_ (num),
00040 denom_ (denom)
00041 {
00042 precondition(denom != 0);
00043 set_result();
00044 }
00045
00046 inline
00047 RationalNumber::RationalNumber():num_ (0), denom_ (1)
00048 {
00049 }
00050
00051
00052 inline
00053 RationalNumber::RationalNumber(const RationalNumber& nb) :
00054 num_ (nb.num_), denom_ (nb.denom_)
00055 {
00056 set_result();
00057 }
00058
00059
00060 template <typename T>
00061 RationalNumber::RationalNumber(const T num) : num_ (num),
00062 denom_ (T(1))
00063 {
00064 }
00065
00066 inline
00067 const int& RationalNumber::num() const
00068 {
00069 return num_;
00070 }
00071
00072 inline
00073 const unsigned int& RationalNumber::denom() const
00074 {
00075 return denom_;
00076 }
00077
00078 inline
00079 RationalNumber& RationalNumber::set_result(int num,unsigned int denom)
00080 {
00081 const int n = gcd(std::abs(num), denom);
00082 num_ = num/n;
00083 denom_ = denom/n;
00084 return *this;
00085 }
00086
00087 inline
00088 RationalNumber& RationalNumber::set_result()
00089 {
00090 const int n = gcd(std::abs(num_), denom_);
00091 num_ /= n;
00092 denom_ /= n;
00093 return *this;
00094 }
00095
00096 inline
00097 std::ostream& RationalNumber::print(std::ostream& ostr) const
00098 {
00099 return ostr << num_ << "/" << denom_;
00100 }
00101
00102
00103
00104 inline
00105 RationalNumber
00106 RationalNumber::operator+(const RationalNumber& nb) const
00107 {
00108 const int m = lcm(denom_, nb.denom());
00109
00110 return RationalNumber(num_ * m / denom_ + nb.num() * m / nb.denom(), m);
00111 }
00112
00113 inline
00114 RationalNumber
00115 RationalNumber::operator-(const RationalNumber& nb) const
00116 {
00117 const int m = lcm(denom_, nb.denom());
00118
00119 return RationalNumber(num_ * m / denom_ - nb.num() * m / nb.denom(), m);
00120 }
00121
00122 inline
00123 RationalNumber
00124 RationalNumber::operator-() const
00125 {
00126 return RationalNumber(-num_, denom_);
00127 }
00128
00129 inline
00130 RationalNumber
00131 RationalNumber::operator*(const RationalNumber& nb) const
00132 {
00133 return RationalNumber(num_ * nb.num(), denom_ * nb.denom());
00134 }
00135
00136 inline
00137 RationalNumber
00138 RationalNumber::operator/(const RationalNumber& nb) const
00139 {
00140 if (nb.num() < 0)
00141 return RationalNumber(-num_ * nb.denom(), denom_ * -nb.num());
00142 return RationalNumber(num_ * nb.denom(), denom_ * nb.num());
00143 }
00144
00145 inline
00146 RationalNumber& RationalNumber::operator+=(const RationalNumber& nb)
00147 {
00148 const int m = lcm(denom_, nb.denom());
00149 return set_result(num_ * m / denom_ + nb.num() * m / nb.denom(), m);
00150 }
00151
00152 inline
00153 RationalNumber& RationalNumber::operator-=(const RationalNumber& nb)
00154 {
00155 const int m = lcm(denom_, nb.denom());
00156 return set_result(num_ * m / denom_ - nb.num() * m / nb.denom(), m);
00157 }
00158
00159 inline
00160 RationalNumber& RationalNumber::operator*=(const RationalNumber& nb)
00161 {
00162 return set_result(num_ * nb.num(), denom_ * nb.denom());
00163 }
00164
00165 inline
00166 RationalNumber& RationalNumber::operator/=(const RationalNumber& nb)
00167 {
00168 if (nb.num() < 0)
00169 return set_result(-num_ * nb.denom(), denom_ * -nb.num());
00170 return set_result(num_ * nb.denom(), denom_ * nb.num());
00171 }
00172
00173 inline
00174 bool RationalNumber::operator<(const RationalNumber& nb) const
00175 {
00176 const int m = lcm(denom_, nb.denom());
00177 int num1 = num_ * (m / denom_);
00178 int num2 = nb.num() * (m / nb.denom());
00179 return num1 < num2;
00180 }
00181
00182 inline
00183 bool RationalNumber::operator>(const RationalNumber& nb) const
00184 {
00185 const int m = lcm(denom_, nb.denom());
00186 int num1 = num_ * (m / denom_);
00187 int num2 = nb.num() * (m / nb.denom());
00188 return num1 > num2;
00189 }
00190
00191 inline
00192 bool RationalNumber::operator<=(const RationalNumber& nb) const
00193 {
00194 const int m = lcm(denom_, nb.denom());
00195 int num1 = num_ * (m / denom_);
00196 int num2 = nb.num() * (m / nb.denom());
00197 return num1 <= num2;
00198 }
00199
00200 inline
00201 bool RationalNumber::operator>=(const RationalNumber& nb) const
00202 {
00203 const int m = lcm(denom_, nb.denom());
00204 int num1 = num_ * (m / denom_);
00205 int num2 = nb.num() * (m / nb.denom());
00206 return num1 >= num2;
00207 }
00208
00209 inline
00210 bool RationalNumber::operator==(const RationalNumber& nb) const
00211 {
00212 const int m = lcm(denom_, nb.denom());
00213 int num1 = num_ * (m / denom_);
00214 int num2 = nb.num() * (m / nb.denom());
00215 return num1 == num2;
00216 }
00217
00218 inline
00219 bool RationalNumber::operator!=(const RationalNumber& nb) const
00220 {
00221 const int m = lcm(denom_, nb.denom());
00222 int num1 = num_ * (m / denom_);
00223 int num2 = nb.num() * (m / nb.denom());
00224 return num1 != num2;
00225 }
00226
00227
00228
00229 inline
00230 int RationalNumber::to_int() const
00231 {
00232 precondition(denom_<static_cast<unsigned>(misc::limits<int>::max()));
00233 return num_ / static_cast<int> (denom_);
00234 }
00235
00236 inline
00237 double RationalNumber::to_double() const
00238 {
00239 return static_cast<double> (num_) / denom_;
00240 }
00241
00242 inline
00243 std::ostream& operator<<(std::ostream& ostr, const RationalNumber& nb)
00244 {
00245 return nb.print(ostr);
00246 }
00247
00248 inline
00249 int gcd(int a, unsigned int b)
00250 {
00251 unsigned n = b;
00252 while (n != 0)
00253 {
00254 int t = a % n;
00255 a = n;
00256 n = t;
00257 }
00258 return a;
00259 }
00260
00261 inline
00262 int lcm(int a, unsigned int b)
00263 {
00264 int d;
00265 if (!a || !b || !(d = gcd(std::abs(a), b)))
00266 return 0;
00267 int r = a * b / d;
00268
00269 postcondition_ (r != 0, "Overflow");
00270
00271 return r;
00272 }
00273 }
00274 }
00275
00276 namespace std
00277 {
00278 inline
00279 ::vcsn::algebra::RationalNumber
00280 numeric_limits< ::vcsn::algebra::RationalNumber >::min()
00281 {
00282 return
00283 ::vcsn::algebra::RationalNumber (std::numeric_limits<int>::min(), 1);
00284 }
00285
00286 inline
00287 ::vcsn::algebra::RationalNumber
00288 numeric_limits< ::vcsn::algebra::RationalNumber >::max()
00289 {
00290 return
00291 ::vcsn::algebra::RationalNumber (std::numeric_limits<int>::max(), 1);
00292 }
00293 }
00294
00295 #endif // ! VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_RATIONAL_NUMBER_HXX