Py2Cpp 1.6.3; VERSION ${PROJECT_VERSION}
Loading...
Searching...
No Matches
fractions.hpp
Go to the documentation of this file.
1#pragma once
2
7// #include <boost/operators.hpp>
8// #include <cmath>
9// #include <numeric>
10#include <type_traits>
11#include <utility>
12
13// #include "common_concepts.h"
14
15#if __cpp_constexpr >= 201304
16# define CONSTEXPR14 constexpr
17#else
18# define CONSTEXPR14 inline
19#endif
20
21namespace fun {
22
32 template <typename T> CONSTEXPR14 auto abs(const T& a) ->
33 typename std::enable_if<std::is_unsigned<T>::value, T>::type {
34 return a;
35 }
36
43 template <typename T> CONSTEXPR14 auto abs(const T& a) ->
44 typename std::enable_if<!std::is_unsigned<T>::value, T>::type {
45 return (a < T(0)) ? -a : a;
46 }
47
58 template <typename Mn> CONSTEXPR14 auto gcd_recur(const Mn& _m, const Mn& _n) -> Mn {
59 if (_n == 0) {
60 return abs(_m);
61 }
62 return gcd_recur(_n, _m % _n);
63 }
64
75 template <typename Mn> CONSTEXPR14 auto gcd(const Mn& _m, const Mn& _n) -> Mn {
76 if (_m == 0) {
77 return abs(_n);
78 }
79 return gcd_recur(_m, _n);
80 }
81
90 template <typename Mn> CONSTEXPR14 auto lcm(const Mn& _m, const Mn& _n) -> Mn {
91 if (_m == 0 || _n == 0) {
92 return 0;
93 }
94 return (abs(_m) / gcd(_m, _n)) * abs(_n);
95 }
96
102 template <typename Z> struct Fraction {
105
112 CONSTEXPR14 Fraction(Z num, Z den) : _num{std::move(num)}, _den{std::move(den)} {
113 this->normalize();
114 }
115
121 CONSTEXPR14 auto normalize() -> Z {
122 this->normalize1();
123 return this->normalize2();
124 }
125
132 if (this->_den < Z(0)) {
133 this->_num = -this->_num;
134 this->_den = -this->_den;
135 }
136 }
137
144 Z common = gcd(this->_num, this->_den);
145 if (common == Z(1) || common == Z(0)) {
146 return common;
147 }
148 this->_num /= common;
149 this->_den /= common;
150 return common;
151 }
152
158 CONSTEXPR14 explicit Fraction(Z&& num) : _num{std::move(num)}, _den(Z(1)) {}
159
165 CONSTEXPR14 explicit Fraction(const Z& num) : _num{num}, _den(1) {}
166
171
177 CONSTEXPR14 auto num() const noexcept -> const Z& { return _num; }
178
184 CONSTEXPR14 auto den() const noexcept -> const Z& { return _den; }
185
192 CONSTEXPR14 auto cross(const Fraction& rhs) const -> Z {
193 return this->_num * rhs._den - this->_den * rhs._num;
194 }
195
200
208 friend CONSTEXPR14 auto operator==(const Fraction& lhs, const Z& rhs) -> bool {
209 if (lhs._den == Z(1) || rhs == Z(0)) {
210 return lhs._num == rhs;
211 }
212 auto lhs2{lhs};
213 auto rhs2{rhs};
214 std::swap(lhs2._den, rhs2);
215 lhs2.normalize2();
216 return lhs2._num < lhs2._den * rhs2;
217 }
218
226 friend CONSTEXPR14 auto operator<(const Fraction& lhs, const Z& rhs) -> bool {
227 if (lhs._den == Z(1) || rhs == Z(0)) {
228 return lhs._num < rhs;
229 }
230 auto lhs2{lhs};
231 auto rhs2{rhs};
232 std::swap(lhs2._den, rhs2);
233 lhs2.normalize2();
234 return lhs2._num < lhs2._den * rhs2;
235 }
236
244 friend CONSTEXPR14 auto operator<(const Z& lhs, const Fraction& rhs) -> bool {
245 if (rhs._den == Z(1) || lhs == Z(0)) {
246 return lhs < rhs._num;
247 }
248 auto lhs2{lhs};
249 auto rhs2{rhs};
250 std::swap(rhs2._den, lhs2);
251 rhs2.normalize2();
252 return rhs2._den * lhs2 < rhs2._num;
253 }
254
262 friend CONSTEXPR14 auto operator==(const Z& lhs, const Fraction& rhs) -> bool {
263 return rhs == lhs;
264 }
265
273 friend CONSTEXPR14 auto operator==(const Fraction& lhs, const Fraction& rhs) -> bool {
274 if (lhs._den == rhs._den) {
275 return lhs._num == rhs._num;
276 }
277 auto lhs2{lhs};
278 auto rhs2{rhs};
279 std::swap(lhs2._den, rhs2._num);
280 lhs2.normalize2();
281 rhs2.normalize2();
282 return lhs2._num * rhs2._den == lhs2._den * rhs2._num;
283 }
284
292 friend CONSTEXPR14 auto operator<(const Fraction& lhs, const Fraction& rhs) -> bool {
293 if (lhs._den == rhs._den) {
294 return lhs._num < rhs._num;
295 }
296 auto lhs2{lhs};
297 auto rhs2{rhs};
298 std::swap(lhs2._den, rhs2._num);
299 lhs2.normalize2();
300 rhs2.normalize2();
301 return lhs2._num * rhs2._den < lhs2._den * rhs2._num;
302 }
303
310 CONSTEXPR14 auto operator!=(const Fraction& rhs) const -> bool { return !(*this == rhs); }
311
318 CONSTEXPR14 auto operator>(const Fraction& rhs) const -> bool { return rhs < *this; }
319
326 CONSTEXPR14 auto operator>=(const Fraction& rhs) const -> bool { return !(*this < rhs); }
327
334 CONSTEXPR14 auto operator<=(const Fraction& rhs) const -> bool { return !(rhs < *this); }
335
342 CONSTEXPR14 auto operator>(const Z& rhs) const -> bool { return rhs < *this; }
343
350 CONSTEXPR14 auto operator<=(const Z& rhs) const -> bool { return !(rhs < *this); }
351
358 CONSTEXPR14 auto operator>=(const Z& rhs) const -> bool { return !(*this < rhs); }
359
367 friend CONSTEXPR14 auto operator>(const Z& lhs, const Fraction& rhs) -> bool {
368 return rhs < lhs;
369 }
370
378 friend CONSTEXPR14 auto operator<=(const Z& lhs, const Fraction& rhs) -> bool {
379 return !(rhs < lhs);
380 }
381
389 friend CONSTEXPR14 auto operator>=(const Z& lhs, const Fraction& rhs) -> bool {
390 return !(lhs < rhs);
391 }
392
394
400 std::swap(this->_num, this->_den);
401 this->normalize1();
402 }
403
411 std::swap(this->_num, rhs._num);
412 this->normalize2();
413 rhs.normalize2();
414 this->_num *= rhs._num;
415 this->_den *= rhs._den;
416 return *this;
417 }
418
426 friend CONSTEXPR14 auto operator*(Fraction lhs, const Fraction& rhs) -> Fraction {
427 return lhs *= rhs;
428 }
429
437 std::swap(this->_num, rhs);
438 this->normalize2();
439 this->_num *= rhs;
440 return *this;
441 }
442
450 friend CONSTEXPR14 auto operator*(Fraction lhs, const Z& rhs) -> Fraction {
451 return lhs *= rhs;
452 }
453
461 friend CONSTEXPR14 auto operator*(const Z& lhs, Fraction rhs) -> Fraction {
462 return rhs *= lhs;
463 }
464
472 std::swap(this->_den, rhs._num);
473 this->normalize();
474 rhs.normalize2();
475 this->_num *= rhs._den;
476 this->_den *= rhs._num;
477 return *this;
478 }
479
487 friend CONSTEXPR14 auto operator/(Fraction lhs, const Fraction& rhs) -> Fraction {
488 return lhs /= rhs;
489 }
490
498 std::swap(this->_den, rhs);
499 this->normalize();
500 this->_den *= rhs;
501 return *this;
502 }
503
511 friend CONSTEXPR14 auto operator/(Fraction lhs, const Z& rhs) -> Fraction {
512 return lhs /= rhs;
513 }
514
522 friend CONSTEXPR14 auto operator/(const Z& lhs, Fraction rhs) -> Fraction {
523 rhs.reciprocal();
524 return rhs *= lhs;
525 }
526
533 auto res = Fraction(*this);
534 res._num = -res._num;
535 return res;
536 }
537
544 CONSTEXPR14 auto operator+(const Fraction& rhs) const -> Fraction {
545 if (this->_den == rhs._den) {
546 return Fraction(this->_num + rhs._num, this->_den);
547 }
548 const auto common = gcd(this->_den, rhs._den);
549 if (common == Z(0)) {
550 return Fraction(rhs._den * this->_num + this->_den * rhs._num, Z(0));
551 }
552 const auto l = this->_den / common;
553 const auto r = rhs._den / common;
554 auto d = this->_den * r;
555 auto n = r * this->_num + l * rhs._num;
556 return Fraction(std::move(n), std::move(d));
557 }
558
565 CONSTEXPR14 auto operator-(const Fraction& frac) const -> Fraction {
566 return *this + (-frac);
567 }
568
576 friend CONSTEXPR14 auto operator+(Fraction frac, const Z& i) -> Fraction {
577 return frac += i;
578 }
579
587 friend CONSTEXPR14 auto operator+(const Z& i, Fraction frac) -> Fraction {
588 return frac += i;
589 }
590
597 CONSTEXPR14 auto operator-(const Z& i) const -> Fraction { return *this + (-i); }
598
605 CONSTEXPR14 auto operator+=(const Fraction& rhs) -> Fraction& { return *this -= (-rhs); }
606
614 if (this->_den == rhs._den) {
615 this->_num -= rhs._num;
616 this->normalize2();
617 return *this;
618 }
619
620 auto other{rhs};
621 std::swap(this->_den, other._num);
622 auto common_n = this->normalize2();
623 auto common_d = other.normalize2();
624 std::swap(this->_den, other._num);
625 this->_num = this->cross(other);
626 this->_den *= other._den;
627 std::swap(this->_den, common_d);
628 this->normalize2();
629 this->_num *= common_n;
630 this->_den *= common_d;
631 this->normalize2();
632 return *this;
633 }
634
641 CONSTEXPR14 auto operator+=(const Z& i) -> Fraction& { return *this -= (-i); }
642
649 CONSTEXPR14 auto operator-=(const Z& rhs) -> Fraction& {
650 if (this->_den == Z(1)) {
651 this->_num -= rhs;
652 return *this;
653 }
654
655 auto other{rhs};
656 std::swap(this->_den, other);
657 auto common_n = this->normalize2();
658 std::swap(this->_den, other);
659 this->_num -= other * this->_den;
660 this->_num *= common_n;
661 this->normalize2();
662 return *this;
663 }
664
672 friend CONSTEXPR14 auto operator-(const Z& c, const Fraction& frac) -> Fraction {
673 return c + (-frac);
674 }
675
683 friend CONSTEXPR14 auto operator+(int&& c, const Fraction& frac) -> Fraction {
684 return frac + Z(c);
685 }
686
694 friend CONSTEXPR14 auto operator-(int&& c, const Fraction& frac) -> Fraction {
695 return (-frac) + Z(c);
696 }
697
705 friend CONSTEXPR14 auto operator*(int&& c, const Fraction& frac) -> Fraction {
706 return frac * Z(c);
707 }
708
717 template <typename Stream> friend auto operator<<(Stream& os, const Fraction& frac)
718 -> Stream& {
719 os << "(" << frac.num() << "/" << frac.den() << ")";
720 return os;
721 }
722 };
723
724 // For template deduction
725 // typename{Z} Fraction(const Z &, const Z &) noexcept -> Fraction<Z>;
726
727} // namespace fun
#define CONSTEXPR14
Definition fractions.hpp:18
Definition fractions.hpp:21
CONSTEXPR14 auto gcd(const Mn &_m, const Mn &_n) -> Mn
Greatest common divisor.
Definition fractions.hpp:75
CONSTEXPR14 auto lcm(const Mn &_m, const Mn &_n) -> Mn
Least common multiple.
Definition fractions.hpp:90
CONSTEXPR14 auto abs(const T &a) -> typename std::enable_if< std::is_unsigned< T >::value, T >::type
Absolute value for unsigned types.
Definition fractions.hpp:32
CONSTEXPR14 auto gcd_recur(const Mn &_m, const Mn &_n) -> Mn
Greatest common divisor (recursive)
Definition fractions.hpp:58
Fraction.
Definition fractions.hpp:102
friend auto operator<<(Stream &os, const Fraction &frac) -> Stream &
Stream output operator for Fraction.
Definition fractions.hpp:717
Z _den
Definition fractions.hpp:104
CONSTEXPR14 auto operator>(const Fraction &rhs) const -> bool
Greater than.
Definition fractions.hpp:318
CONSTEXPR14 auto operator-(const Fraction &frac) const -> Fraction
Subtract.
Definition fractions.hpp:565
CONSTEXPR14 auto operator+=(const Z &i) -> Fraction &
Add and assign an integer.
Definition fractions.hpp:641
friend CONSTEXPR14 auto operator<(const Z &lhs, const Fraction &rhs) -> bool
Less than.
Definition fractions.hpp:244
friend CONSTEXPR14 auto operator+(Fraction frac, const Z &i) -> Fraction
Add.
Definition fractions.hpp:576
CONSTEXPR14 auto operator>(const Z &rhs) const -> bool
Greater than.
Definition fractions.hpp:342
CONSTEXPR14 auto normalize2() -> Z
normalize to a canonical form
Definition fractions.hpp:143
friend CONSTEXPR14 auto operator==(const Fraction &lhs, const Z &rhs) -> bool
Equal to.
Definition fractions.hpp:208
CONSTEXPR14 auto operator!=(const Fraction &rhs) const -> bool
Not equal to.
Definition fractions.hpp:310
CONSTEXPR14 auto num() const noexcept -> const Z &
Get the numerator.
Definition fractions.hpp:177
friend CONSTEXPR14 auto operator*(const Z &lhs, Fraction rhs) -> Fraction
multiply
Definition fractions.hpp:461
CONSTEXPR14 auto operator-=(const Fraction &rhs) -> Fraction &
Subtract and assign a fraction.
Definition fractions.hpp:613
friend CONSTEXPR14 auto operator*(Fraction lhs, const Z &rhs) -> Fraction
multiply
Definition fractions.hpp:450
CONSTEXPR14 auto operator/=(Fraction rhs) -> Fraction &
divide and assign
Definition fractions.hpp:471
friend CONSTEXPR14 auto operator-(const Z &c, const Fraction &frac) -> Fraction
Subtract a fraction from an integer.
Definition fractions.hpp:672
CONSTEXPR14 auto operator>=(const Z &rhs) const -> bool
Greater than or equal to.
Definition fractions.hpp:358
CONSTEXPR14 void reciprocal()
reciprocal
Definition fractions.hpp:399
CONSTEXPR14 auto operator*=(Fraction rhs) -> Fraction &
multiply and assign
Definition fractions.hpp:410
friend CONSTEXPR14 auto operator>(const Z &lhs, const Fraction &rhs) -> bool
Greater than.
Definition fractions.hpp:367
CONSTEXPR14 auto operator>=(const Fraction &rhs) const -> bool
Greater than or euqal to.
Definition fractions.hpp:326
CONSTEXPR14 Fraction(Z num, Z den)
Construct a new Fraction object.
Definition fractions.hpp:112
friend CONSTEXPR14 auto operator<(const Fraction &lhs, const Fraction &rhs) -> bool
Less than.
Definition fractions.hpp:292
CONSTEXPR14 void normalize1()
normalize to a canonical form
Definition fractions.hpp:131
friend CONSTEXPR14 auto operator==(const Z &lhs, const Fraction &rhs) -> bool
Equal to.
Definition fractions.hpp:262
CONSTEXPR14 auto operator<=(const Fraction &rhs) const -> bool
Less than or equal to.
Definition fractions.hpp:334
Z _num
Definition fractions.hpp:103
CONSTEXPR14 auto normalize() -> Z
normalize to a canonical form
Definition fractions.hpp:121
CONSTEXPR14 auto cross(const Fraction &rhs) const -> Z
cross product
Definition fractions.hpp:192
CONSTEXPR14 Fraction()
Construct a new Fraction object (default constructor)
Definition fractions.hpp:170
friend CONSTEXPR14 auto operator<=(const Z &lhs, const Fraction &rhs) -> bool
Less than or equal to.
Definition fractions.hpp:378
CONSTEXPR14 auto operator+(const Fraction &rhs) const -> Fraction
Add.
Definition fractions.hpp:544
friend CONSTEXPR14 auto operator/(Fraction lhs, const Z &rhs) -> Fraction
divide
Definition fractions.hpp:511
friend CONSTEXPR14 auto operator>=(const Z &lhs, const Fraction &rhs) -> bool
Greater than or euqal to.
Definition fractions.hpp:389
CONSTEXPR14 auto operator*=(Z rhs) -> Fraction &
multiply and assign
Definition fractions.hpp:436
CONSTEXPR14 auto operator-=(const Z &rhs) -> Fraction &
Subtract and assign an integer.
Definition fractions.hpp:649
friend CONSTEXPR14 auto operator==(const Fraction &lhs, const Fraction &rhs) -> bool
Equal to.
Definition fractions.hpp:273
friend CONSTEXPR14 auto operator*(Fraction lhs, const Fraction &rhs) -> Fraction
multiply
Definition fractions.hpp:426
friend CONSTEXPR14 auto operator/(const Z &lhs, Fraction rhs) -> Fraction
divide
Definition fractions.hpp:522
friend CONSTEXPR14 auto operator*(int &&c, const Fraction &frac) -> Fraction
Multiply a fraction by an integer rvalue.
Definition fractions.hpp:705
CONSTEXPR14 auto operator-(const Z &i) const -> Fraction
Subtract an integer from the fraction.
Definition fractions.hpp:597
friend CONSTEXPR14 auto operator-(int &&c, const Fraction &frac) -> Fraction
Subtract a fraction from an integer rvalue.
Definition fractions.hpp:694
friend CONSTEXPR14 auto operator+(const Z &i, Fraction frac) -> Fraction
Add.
Definition fractions.hpp:587
CONSTEXPR14 auto operator/=(Z rhs) -> Fraction &
divide and assign
Definition fractions.hpp:497
CONSTEXPR14 auto operator-() const -> Fraction
Negate.
Definition fractions.hpp:532
friend CONSTEXPR14 auto operator+(int &&c, const Fraction &frac) -> Fraction
Add a fraction to an integer rvalue.
Definition fractions.hpp:683
CONSTEXPR14 Fraction(const Z &num)
Construct a new Fraction object.
Definition fractions.hpp:165
CONSTEXPR14 auto operator+=(const Fraction &rhs) -> Fraction &
Add and assign a fraction.
Definition fractions.hpp:605
friend CONSTEXPR14 auto operator/(Fraction lhs, const Fraction &rhs) -> Fraction
divide
Definition fractions.hpp:487
CONSTEXPR14 auto den() const noexcept -> const Z &
Get the denominator.
Definition fractions.hpp:184
CONSTEXPR14 Fraction(Z &&num)
Construct a new Fraction object.
Definition fractions.hpp:158
CONSTEXPR14 auto operator<=(const Z &rhs) const -> bool
Less than or equal to.
Definition fractions.hpp:350
friend CONSTEXPR14 auto operator<(const Fraction &lhs, const Z &rhs) -> bool
Less than.
Definition fractions.hpp:226