1 #ifndef MATH_RATIONAL_H_
2 #define MATH_RATIONAL_H_
9 /// Rational number type.
10 /// Stores 2 Integers and has the value num / denom.
11 template<class Integer>
15 explicit Rational(Integer num = 0, Integer denom = 1)
16 : num(num), denom(denom) { }
17 template<class OtherInt>
18 explicit Rational(const Rational<OtherInt> &other)
19 : num(other.Numerator()), denom(other.Denominator()) { }
22 Integer &Numerator() { return num; }
23 const Integer &Numerator() const { return num; }
24 Integer &Denominator() { return denom; }
25 const Integer &Denominator() const { return denom; }
27 Integer Int() const { return num / denom; }
28 Integer Inv() const { return denom / num; }
29 float Float() const { return float(num) / denom; }
30 double Double() const { return double(num) / denom; }
32 bool IsWhole() const {
33 return num % denom == 0;
36 return num % denom != 0;
40 if (num == 1 || denom == 1) return;
41 if (num % denom == 0) {
44 } else if (denom % num == 0) {
51 if (num == 1 || denom == 1) return;
52 if (num % denom == 0) {
57 if (denom % num == 0) {
62 while (num % 2 == 0 && denom % 2 == 0) {
66 while (num % 3 == 0 && denom % 3 == 0) {
70 while (num % 5 == 0 && denom % 5 == 0) {
77 template<class OtherInt>
78 Rational &operator =(OtherInt i) {
83 template<class OtherInt>
84 Rational &operator =(Rational<OtherInt> r) {
86 denom = r.Denominator();
89 template<class OtherInt>
90 Rational &operator +=(OtherInt i) {
94 template<class OtherInt>
95 Rational &operator +=(Rational<OtherInt> r) {
96 num = num * r.Denominator() + r.Numerator() * denom;
97 denom *= r.Denominator();
100 template<class OtherInt>
101 Rational &operator -=(OtherInt i) {
105 template<class OtherInt>
106 Rational &operator -=(Rational<OtherInt> r) {
107 num = num * r.Denominator() - r.Numerator() * denom;
108 denom *= r.Denominator();
111 template<class OtherInt>
112 Rational &operator *=(OtherInt i) {
113 if (denom % i == 0) {
120 template<class OtherInt>
121 Rational &operator *=(const Rational<OtherInt> &r) {
122 num *= r.Numerator();
123 denom *= r.Denominator();
126 Rational &operator *=(float f) {
130 Rational &operator *=(double d) {
134 template<class OtherInt>
135 Rational &operator /=(OtherInt i) {
143 template<class OtherInt>
144 Rational &operator /=(const Rational<OtherInt> &r) {
145 num *= r.Denominator();
146 denom *= r.Numerator();
149 Rational &operator /=(float f) {
150 if (f > 1 || f < -1) {
157 Rational &operator /=(double d) {
158 if (d > 1 || d < -1) {
172 template<class Integer>
173 Rational<Integer> operator -(const Rational<Integer> &r) {
174 return Rational<Integer>(-r.Numerator(), r.Denominator());
177 template<class LInt, class RInt>
179 const Rational<LInt> &lhs,
180 const Rational<RInt> &rhs) {
181 return lhs.Numerator() * rhs.Denominator() ==
182 rhs.Numerator() * lhs.Denominator();
184 template<class LInt, class RInt>
186 const Rational<LInt> &lhs,
187 const Rational<RInt> &rhs) {
188 return !(lhs == rhs);
190 template<class LInt, class RInt>
192 const Rational<LInt> &lhs,
194 return lhs.IsWhole() && lhs.Int() == rhs;
196 template<class LInt, class RInt>
198 const Rational<LInt> &lhs,
200 return !(lhs == rhs);
202 template<class LInt, class RInt>
205 const Rational<RInt> &rhs) {
208 template<class LInt, class RInt>
211 const Rational<RInt> &rhs) {
215 template<class LInt, class RInt>
217 const Rational<LInt> &lhs,
218 const Rational<RInt> &rhs) {
219 return lhs.Numerator() * rhs.Denominator() <
220 rhs.Numerator() * lhs.Denominator();
222 template<class LInt, class RInt>
224 const Rational<LInt> &lhs,
226 return lhs.Numerator() < rhs * lhs.Denominator();
228 template<class LInt, class RInt>
231 const Rational<RInt> &rhs) {
232 return lhs * rhs.Denominator() < rhs.Numerator();
235 template<class LInt, class RInt>
237 const Rational<LInt> &lhs,
238 const Rational<RInt> &rhs) {
239 return lhs.Numerator() * rhs.Denominator() <=
240 rhs.Numerator() * lhs.Denominator();
242 template<class LInt, class RInt>
244 const Rational<LInt> &lhs,
246 return lhs.Numerator() <= rhs * lhs.Denominator();
248 template<class LInt, class RInt>
251 const Rational<RInt> &rhs) {
252 return lhs * rhs.Denominator() <= rhs.Numerator();
255 template<class LInt, class RInt>
257 const Rational<LInt> &lhs,
258 const Rational<RInt> &rhs) {
259 return lhs.Numerator() * rhs.Denominator() >
260 rhs.Numerator() * lhs.Denominator();
262 template<class LInt, class RInt>
264 const Rational<LInt> &lhs,
266 return lhs.Numerator() > rhs * lhs.Denominator();
268 template<class LInt, class RInt>
271 const Rational<RInt> &rhs) {
272 return lhs * rhs.Denominator() > rhs.Numerator();
275 template<class LInt, class RInt>
277 const Rational<LInt> &lhs,
278 const Rational<RInt> &rhs) {
279 return lhs.Numerator() * rhs.Denominator() >=
280 rhs.Numerator() * lhs.Denominator();
282 template<class LInt, class RInt>
284 const Rational<LInt> &lhs,
286 return lhs.Numerator() >= rhs * lhs.Denominator();
288 template<class LInt, class RInt>
291 const Rational<RInt> &rhs) {
292 return lhs * rhs.Denominator() >= rhs.Numerator();
295 template<class LInt, class RInt>
296 Rational<LInt> operator +(
297 const Rational<LInt> &lhs,
298 const Rational<RInt> &rhs) {
299 return Rational<LInt>(lhs) += rhs;
301 template<class LInt, class RInt>
302 Rational<LInt> operator +(
303 const Rational<LInt> &lhs,
305 return Rational<LInt>(lhs) += rhs;
307 template<class LInt, class RInt>
310 const Rational<RInt> &rhs) {
311 return lhs + rhs.Int();
314 template<class LInt, class RInt>
315 Rational<LInt> operator -(
316 const Rational<LInt> &lhs,
317 const Rational<RInt> &rhs) {
318 return Rational<LInt>(lhs) -= rhs;
320 template<class LInt, class RInt>
321 Rational<LInt> operator -(
322 const Rational<LInt> &lhs,
324 return Rational<LInt>(lhs) -= rhs;
326 template<class LInt, class RInt>
329 const Rational<RInt> &rhs) {
330 return lhs - rhs.Int();
333 template<class LInt, class RInt>
334 Rational<LInt> operator *(
335 const Rational<LInt> &lhs,
336 const Rational<RInt> &rhs) {
337 return Rational<LInt>(lhs) *= rhs;
339 template<class LInt, class RInt>
340 Rational<LInt> operator *(
341 const Rational<LInt> &lhs,
343 return Rational<LInt>(lhs) *= rhs;
345 template<class LInt, class RInt>
348 const Rational<RInt> &rhs) {
349 return lhs * rhs.Numerator() / rhs.Denominator();
352 template<class LInt, class RInt>
353 Rational<LInt> operator /(
354 const Rational<LInt> &lhs,
355 const Rational<RInt> &rhs) {
356 return Rational<LInt>(lhs) /= rhs;
358 template<class LInt, class RInt>
359 Rational<LInt> operator /(
360 const Rational<LInt> &lhs,
362 return Rational<LInt>(lhs) /= rhs;
364 template<class LInt, class RInt>
367 const Rational<RInt> &rhs) {
368 return lhs * rhs.Denominator() / rhs.Numerator();
372 template<class Integer>
373 inline std::ostream &operator <<(std::ostream &out, const Rational<Integer> &r) {
374 return out << r.Double();