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
00031 namespace vcsn
00032 {
00033 namespace algebra
00034 {
00035
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
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
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
00227
00228 inline
00229 int RationalNumber::to_int() const
00230 {
00231 precondition(denom_<static_cast<unsigned>(utility::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 }
00293
00294 #endif // ! VCSN_ALGEBRA_IMPLEMENTATION_SEMIRING_RATIONAL_NUMBER_HXX