lilypond-1.4.2
[lilypond.git] / flower / rational.cc
blob5c3c8c5cbd6727b642d18a10bb397a37333abf1b
1 /*
2 rational.cc -- implement Rational
4 source file of the Flower Library
6 (c) 1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8 #include <math.h>
9 #include <stdlib.h>
10 #include "rational.hh"
11 #include "string.hh"
12 #include "string-convert.hh"
13 #include "libc-extension.hh"
15 Rational::operator bool () const
17 return sign_;
20 Rational::operator int () const
22 return sign_ * num_ / den_;
25 Rational::operator double () const
27 return (double)sign_ * num_ / den_;
30 ostream &
31 operator << (ostream &o, Rational r)
33 o << r.str ();
34 return o;
37 Rational
38 Rational::trunc_rat () const
40 return Rational (num_ - (num_ % den_), den_);
43 Rational::Rational ()
45 sign_ = 0;
46 num_ = den_ = 1;
49 Rational::Rational (int n, int d)
51 sign_ = ::sign (n) * ::sign (d);
52 num_ = abs (n);
53 den_ = abs (d);
54 normalise ();
57 static
58 int gcd (int a, int b)
60 int t;
61 while ((t = a % b))
63 a = b;
64 b = t;
66 return b;
69 static
70 int lcm (int a, int b)
72 return abs (a*b / gcd (a,b));
75 void
76 Rational::set_infinite (int s)
78 sign_ = ::sign (s) * 2;
81 Rational
82 Rational::operator - () const
84 Rational r (*this);
85 r.negate ();
86 return r;
89 Rational
90 Rational::div_rat (Rational div) const
92 Rational r (*this);
93 r /= div;
94 return r.trunc_rat ();
97 Rational
98 Rational::mod_rat (Rational div) const
100 Rational r (*this);
101 r = (r / div - r.div_rat (div)) * div;
102 return r;
105 void
106 Rational::normalise ()
108 if (!sign_)
110 den_ = 1;
111 num_ = 0;
112 return ;
114 if (!den_)
115 sign_ = 2;
116 if (!num_)
117 sign_ = 0;
119 int g = gcd (num_ , den_);
121 num_ /= g;
122 den_ /= g;
126 Rational::sign () const
128 return ::sign (sign_);
131 bool
132 Rational::infty_b () const
134 return abs (sign_) > 1;
138 Rational::compare (Rational const &r, Rational const &s)
140 if (r.sign_ < s.sign_)
141 return -1;
142 else if (r.sign_ > s.sign_)
143 return 1;
144 else if (r.infty_b ())
145 return 0;
147 return (r - s).sign ();
151 compare (Rational const &r, Rational const &s)
153 return Rational::compare (r, s );
156 Rational &
157 Rational::operator %= (Rational r)
159 *this = r.mod_rat (r);
160 return *this;
163 Rational &
164 Rational::operator += (Rational r)
166 if (infty_b ())
168 else if (r.infty_b ())
170 *this = r;
172 else
174 int n = sign_ * num_ *r.den_ + r.sign_ * den_ * r.num_;
175 int d = den_ * r.den_;
176 sign_ = ::sign (n) * ::sign (d);
177 num_ = abs (n);
178 den_ = abs (d);
179 normalise ();
181 return *this;
186 copied from libg++ 2.8.0
188 Rational::Rational (double x)
190 if (x != 0.0)
192 sign_ = ::sign (x);
193 x *= sign_;
195 int expt;
196 double mantissa = frexp (x, &expt);
198 const int FACT = 1 << 20;
201 Thanks to Afie for this too simple idea.
203 do not blindly substitute by libg++ code, since that uses
204 arbitrary-size integers. The rationals would overflow too
205 easily.
208 num_ = (unsigned int) (mantissa * FACT);
209 den_ = (unsigned int) FACT;
210 normalise ();
211 if (expt < 0)
212 den_ <<= -expt;
213 else
214 num_ <<= expt;
215 normalise ();
217 else
219 num_ = 0;
220 den_ = 1;
221 sign_ =0;
222 normalise ();
227 void
228 Rational::invert ()
230 int r (num_);
231 num_ = den_;
232 den_ = r;
235 Rational &
236 Rational::operator *= (Rational r)
238 sign_ *= ::sign (r.sign_);
239 if (r.infty_b ())
241 sign_ = sign () * 2;
242 goto exit_func;
245 num_ *= r.num_;
246 den_ *= r.den_;
248 normalise ();
249 exit_func:
250 return *this;
253 Rational &
254 Rational::operator /= (Rational r)
256 r.invert ();
257 return (*this *= r);
260 void
261 Rational::negate ()
263 sign_ *= -1;
266 Rational&
267 Rational::operator -= (Rational r)
269 r.negate ();
270 return (*this += r);
274 be paranoid about overiding libg++ stuff
276 Rational &
277 Rational::operator = (Rational const &r)
279 copy (r);
280 return *this;
283 String
284 Rational::str () const
286 if (infty_b ())
288 String s (sign_ > 0 ? "" : "-" );
289 return String (s + "infinity");
291 String s = to_str (num ());
292 if (den () != 1 && num ())
293 s += "/" + to_str (den ());
294 return s;
298 sign (Rational r)
300 return r.sign ();