Format and improve documentation of internal grob properties.
[lilypond.git] / flower / rational.cc
blob724f0d99ca5b526dfc5f067decfbaf2066f7796c
1 /*
2 rational.cc -- implement Rational
4 source file of the Flower Library
6 (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
9 #include "rational.hh"
11 #include <cmath>
12 #include <cassert>
13 #include <cstdlib>
14 using namespace std;
16 #include "string-convert.hh"
17 #include "libc-extension.hh"
19 double
20 Rational::to_double () const
22 if (sign_ == -1 || sign_ == 1 || sign_ == 0)
23 return ((double)sign_) * num_ / den_;
24 if (sign_ == -2)
25 return -HUGE_VAL;
26 else if (sign_ == 2)
27 return HUGE_VAL;
28 else
29 assert (false);
31 return 0.0;
35 #ifdef STREAM_SUPPORT
36 ostream &
37 operator << (ostream &o, Rational r)
39 o << r.string ();
40 return o;
42 #endif
44 Rational
45 Rational::abs () const
47 return Rational (num_, den_);
50 Rational
51 Rational::trunc_rat () const
53 return Rational (num_ - (num_ % den_), den_);
56 Rational::Rational ()
58 sign_ = 0;
59 num_ = den_ = 1;
62 Rational::Rational (int n, int d)
64 sign_ = ::sign (n) * ::sign (d);
65 num_ = ::abs (n);
66 den_ = ::abs (d);
67 normalize ();
70 Rational::Rational (int n)
72 sign_ = ::sign (n);
73 num_ = ::abs (n);
74 den_ = 1;
78 void
79 Rational::set_infinite (int s)
81 sign_ = ::sign (s) * 2;
84 Rational
85 Rational::operator - () const
87 Rational r (*this);
88 r.negate ();
89 return r;
92 Rational
93 Rational::div_rat (Rational div) const
95 Rational r (*this);
96 r /= div;
97 return r.trunc_rat ();
100 Rational
101 Rational::mod_rat (Rational div) const
103 Rational r (*this);
104 r = (r / div - r.div_rat (div)) * div;
105 return r;
110 copy & paste from scm_gcd (GUILE).
112 static int
113 gcd (long u, long v)
115 long result = 0;
116 if (u == 0)
117 result = v;
118 else if (v == 0)
119 result = u;
120 else
122 long k = 1;
123 long t;
124 /* Determine a common factor 2^k */
125 while (!(1 & (u | v)))
127 k <<= 1;
128 u >>= 1;
129 v >>= 1;
131 /* Now, any factor 2^n can be eliminated */
132 if (u & 1)
133 t = -v;
134 else
136 t = u;
138 t = t >> 1;
140 if (!(1 & t))
141 goto b3;
142 if (t > 0)
143 u = t;
144 else
145 v = -t;
146 t = u - v;
147 if (t != 0)
148 goto b3;
149 result = u * k;
152 return result;
156 void
157 Rational::normalize ()
159 if (!sign_)
161 den_ = 1;
162 num_ = 0;
164 else if (!den_)
166 sign_ = 2;
167 num_ = 1;
169 else if (!num_)
171 sign_ = 0;
172 den_ = 1;
174 else
176 int g = gcd (num_, den_);
178 num_ /= g;
179 den_ /= g;
183 Rational::sign () const
185 return ::sign (sign_);
189 Rational::compare (Rational const &r, Rational const &s)
191 if (r.sign_ < s.sign_)
192 return -1;
193 else if (r.sign_ > s.sign_)
194 return 1;
195 else if (r.is_infinity ())
196 return 0;
197 else if (r.sign_ == 0)
198 return 0;
199 return r.sign_ * ::sign (int (r.num_ * s.den_) - int (s.num_ * r.den_));
203 compare (Rational const &r, Rational const &s)
205 return Rational::compare (r, s);
208 Rational &
209 Rational::operator %= (Rational r)
211 *this = mod_rat (r);
212 return *this;
215 Rational &
216 Rational::operator += (Rational r)
218 if (is_infinity ())
220 else if (r.is_infinity ())
221 *this = r;
222 else
224 int lcm = (den_ / gcd (r.den_, den_)) * r.den_;
225 int n = sign_ * num_ * (lcm / den_) + r.sign_ * r.num_ * (lcm / r.den_);
226 int d = lcm;
227 sign_ = ::sign (n) * ::sign (d);
228 num_ = ::abs (n);
229 den_ = ::abs (d);
230 normalize ();
232 return *this;
236 copied from libg++ 2.8.0
238 Rational::Rational (double x)
240 if (x != 0.0)
242 sign_ = ::sign (x);
243 x *= sign_;
245 int expt;
246 double mantissa = frexp (x, &expt);
248 const int FACT = 1 << 20;
251 Thanks to Afie for this too simple idea.
253 do not blindly substitute by libg++ code, since that uses
254 arbitrary-size integers. The rationals would overflow too
255 easily.
258 num_ = (unsigned int) (mantissa * FACT);
259 den_ = (unsigned int) FACT;
260 normalize ();
261 if (expt < 0)
262 den_ <<= -expt;
263 else
264 num_ <<= expt;
265 normalize ();
267 else
269 num_ = 0;
270 den_ = 1;
271 sign_ = 0;
272 normalize ();
276 void
277 Rational::invert ()
279 int r (num_);
280 num_ = den_;
281 den_ = r;
284 Rational &
285 Rational::operator *= (Rational r)
287 sign_ *= ::sign (r.sign_);
288 if (r.is_infinity ())
290 sign_ = sign () * 2;
291 goto exit_func;
294 num_ *= r.num_;
295 den_ *= r.den_;
297 normalize ();
298 exit_func:
299 return *this;
302 Rational &
303 Rational::operator /= (Rational r)
305 r.invert ();
306 return (*this *= r);
309 void
310 Rational::negate ()
312 sign_ *= -1;
315 Rational &
316 Rational::operator -= (Rational r)
318 r.negate ();
319 return (*this += r);
322 string
323 Rational::to_string () const
325 if (is_infinity ())
327 string s (sign_ > 0 ? "" : "-");
328 return string (s + "infinity");
331 string s = ::to_string (num ());
332 if (den () != 1 && num ())
333 s += "/" + ::to_string (den ());
334 return s;
338 Rational::to_int () const
340 return (int) num () / den ();
344 sign (Rational r)
346 return r.sign ();
349 bool
350 Rational::is_infinity () const
352 return sign_ == 2 || sign_ == -2;