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 Rational::set_infinite (int s)
80 sign_ = ::sign (s) * 2;
84 Rational::operator - () const
92 Rational::div_rat (Rational div) const
96 return r.trunc_rat ();
100 Rational::mod_rat (Rational div) const
103 r = (r / div - r.div_rat (div)) * div;
109 copy & paste from scm_gcd (GUILE).
123 /* Determine a common factor 2^k */
124 while (!(1 & (u | v)))
130 /* Now, any factor 2^n can be eliminated */
156 Rational::normalize ()
175 int g = gcd (num_, den_);
182 Rational::sign () const
184 return ::sign (sign_);
188 Rational::compare (Rational const &r, Rational const &s)
190 if (r.sign_ < s.sign_)
192 else if (r.sign_ > s.sign_)
194 else if (r.is_infinity ())
196 else if (r.sign_ == 0)
198 return r.sign_ * ::sign (int (r.num_ * s.den_) - int (s.num_ * r.den_));
202 compare (Rational const &r, Rational const &s)
204 return Rational::compare (r, s);
208 Rational::operator %= (Rational r)
215 Rational::operator += (Rational r)
219 else if (r.is_infinity ())
223 int lcm = (den_ / gcd (r.den_, den_)) * r.den_;
224 int n = sign_ * num_ * (lcm / den_) + r.sign_ * r.num_ * (lcm / r.den_);
226 sign_ = ::sign (n) * ::sign (d);
235 copied from libg++ 2.8.0
237 Rational::Rational (double x)
245 double mantissa = frexp (x, &expt);
247 const int FACT = 1 << 20;
250 Thanks to Afie for this too simple idea.
252 do not blindly substitute by libg++ code, since that uses
253 arbitrary-size integers. The rationals would overflow too
257 num_ = (unsigned int) (mantissa * FACT);
258 den_ = (unsigned int) FACT;
284 Rational::operator *= (Rational r)
286 sign_ *= ::sign (r.sign_);
287 if (r.is_infinity ())
302 Rational::operator /= (Rational r)
315 Rational::operator -= (Rational r)
322 Rational::to_string () const
326 string s (sign_ > 0 ? "" : "-");
327 return string (s + "infinity");
330 string s = ::to_string (num ());
331 if (den () != 1 && num ())
332 s += "/" + ::to_string (den ());
337 Rational::to_int () const
339 return (int) num () / den ();
349 Rational::is_infinity () const
351 return sign_ == 2 || sign_ == -2;