2 rational.cc -- implement Rational
4 source file of the Flower Library
6 (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
16 #include "string-convert.hh"
17 #include "libc-extension.hh"
19 Rational::operator double () const
21 if (sign_ == -1 || sign_ == 1 || sign_ == 0)
22 return ((double)sign_) * num_ / den_;
36 operator << (ostream &o, Rational r)
44 Rational::abs () const
46 return Rational (num_, den_);
50 Rational::trunc_rat () const
52 return Rational (num_ - (num_ % den_), den_);
61 Rational::Rational (int n, int d)
63 sign_ = ::sign (n) * ::sign (d);
69 Rational::Rational (int n)
78 We can actually do a little better. See Knuth 4.5.2
81 int gcd (int a, int b)
93 Rational::set_infinite (int s)
95 sign_ = ::sign (s) * 2;
99 Rational::operator - () const
107 Rational::div_rat (Rational div) const
111 return r.trunc_rat ();
115 Rational::mod_rat (Rational div) const
118 r = (r / div - r.div_rat (div)) * div;
123 Rational::normalize ()
142 int g = gcd (num_, den_);
149 Rational::sign () const
151 return ::sign (sign_);
155 Rational::compare (Rational const &r, Rational const &s)
157 if (r.sign_ < s.sign_)
159 else if (r.sign_ > s.sign_)
161 else if (r.is_infinity ())
163 else if (r.sign_ == 0)
165 return r.sign_ * ::sign (int (r.num_ * s.den_) - int (s.num_ * r.den_));
169 compare (Rational const &r, Rational const &s)
171 return Rational::compare (r, s);
175 Rational::operator %= (Rational r)
182 Rational::operator += (Rational r)
186 else if (r.is_infinity ())
190 int lcm = (den_ / gcd (r.den_, den_)) * r.den_;
191 int n = sign_ * num_ * (lcm / den_) + r.sign_ * r.num_ * (lcm / r.den_);
193 sign_ = ::sign (n) * ::sign (d);
202 copied from libg++ 2.8.0
204 Rational::Rational (double x)
212 double mantissa = frexp (x, &expt);
214 const int FACT = 1 << 20;
217 Thanks to Afie for this too simple idea.
219 do not blindly substitute by libg++ code, since that uses
220 arbitrary-size integers. The rationals would overflow too
224 num_ = (unsigned int) (mantissa * FACT);
225 den_ = (unsigned int) FACT;
251 Rational::operator *= (Rational r)
253 sign_ *= ::sign (r.sign_);
254 if (r.is_infinity ())
269 Rational::operator /= (Rational r)
282 Rational::operator -= (Rational r)
289 Rational::to_string () const
293 string s (sign_ > 0 ? "" : "-");
294 return string (s + "infinity");
297 string s = ::to_string (num ());
298 if (den () != 1 && num ())
299 s += "/" + ::to_string (den ());
304 Rational::to_int () const
306 return (int) num () / den ();
316 Rational::is_infinity () const
318 return sign_ == 2 || sign_ == -2;