src/math/ds/rational/lib.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "../../../nt/gl/gcd/lib.hpp" | ||
| 4 | #include "../../../util/traits/others/lib.hpp" | ||
| 5 | |||
| 6 | namespace tifa_libs { | ||
| 7 | |||
| 8 | template <int_c T> | ||
| 9 | struct rational { | ||
| 10 | T num, den; | ||
| 11 | |||
| 12 | 23 | CEXP rational(T numerator = T(0), T denominator = T(1)) NE : num{numerator}, den{denominator} { | |
| 13 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 23 times.
|
23 | if (assert(den != 0); num == 0) den = 1; |
| 14 | else { | ||
| 15 | 23 | const T g = (T)gcd(num, den); | |
| 16 | 23 | if CEXP (num /= g, den /= g; std::is_signed_v<T>) | |
| 17 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | if (den < 0) num = -num, den = -den; |
| 18 | } | ||
| 19 | 23 | } | |
| 20 | |||
| 21 | CEXP rational& operator+=(T x) NE { | ||
| 22 | num += x * den; | ||
| 23 | return *this; | ||
| 24 | } | ||
| 25 | CEXP rational& operator-=(T x) NE { | ||
| 26 | num -= x * den; | ||
| 27 | return *this; | ||
| 28 | } | ||
| 29 | CEXP rational& operator*=(T x) NE { | ||
| 30 | const T g = (T)gcd(x, den); | ||
| 31 | num *= x / g, den /= g; | ||
| 32 | return *this; | ||
| 33 | } | ||
| 34 | CEXP rational& operator/=(T x) NE { | ||
| 35 | assert(x); | ||
| 36 | const T g = (T)gcd(x, num); | ||
| 37 | if CEXP (num /= g, den *= x / g; std::is_signed_v<T>) | ||
| 38 | if (den < 0) num = -num, den = -den; | ||
| 39 | return *this; | ||
| 40 | } | ||
| 41 | 269 | CEXP rational& operator+=(rational CR x) NE { | |
| 42 | 269 | T g = (T)gcd(den, x.den); | |
| 43 | 269 | num = num * (x.den / g) + x.num * (den /= g); | |
| 44 | 269 | g = (T)gcd(num, g); | |
| 45 | 269 | num /= g, den *= x.den / g; | |
| 46 | 269 | return *this; | |
| 47 | } | ||
| 48 | 315 | CEXP rational& operator-=(rational CR x) NE { | |
| 49 | 315 | T g = (T)gcd(den, x.den); | |
| 50 | 315 | num = num * (x.den / g) - x.num * (den /= g); | |
| 51 | 315 | g = (T)gcd(num, g); | |
| 52 | 315 | num /= g, den *= x.den / g; | |
| 53 | 315 | return *this; | |
| 54 | } | ||
| 55 | CEXP rational& operator*=(rational CR x) NE { | ||
| 56 | const T g1 = (T)gcd(num, x.den), g2 = (T)gcd(x.num, den); | ||
| 57 | num = num / g1 * (x.num / g2); | ||
| 58 | den = den / g2 * (x.den / g1); | ||
| 59 | return *this; | ||
| 60 | } | ||
| 61 | CEXP rational& operator/=(rational CR x) NE { | ||
| 62 | const T g1 = (T)gcd(num, x.num), g2 = (T)gcd(den, x.den); | ||
| 63 | if CEXP (num = num / g1 * (x.den / g2), den = den / g2 * (x.num / g1); std::is_signed_v<T>) | ||
| 64 | if (den < 0) num = -num, den = -den; | ||
| 65 | return *this; | ||
| 66 | } | ||
| 67 | friend CEXP rational operator+(rational x, T y) NE { return x += y; } | ||
| 68 | friend CEXP rational operator-(rational x, T y) NE { return x -= y; } | ||
| 69 | friend CEXP rational operator*(rational x, T y) NE { return x *= y; } | ||
| 70 | friend CEXP rational operator/(rational x, T y) NE { return x /= y; } | ||
| 71 | friend CEXP rational operator+(rational x, rational CR y) NE { return x += y; } | ||
| 72 | 292 | friend CEXP rational operator-(rational x, rational CR y) NE { return x -= y; } | |
| 73 | friend CEXP rational operator*(rational x, rational CR y) NE { return x *= y; } | ||
| 74 | friend CEXP rational operator/(rational x, rational CR y) NE { return x /= y; } | ||
| 75 | CEXP rational operator+() CNE { return *this; } | ||
| 76 | CEXP rational operator-() CNE { return rational(-num, den); } | ||
| 77 | CEXP rational& operator++() NE { | ||
| 78 | num += den; | ||
| 79 | return *this; | ||
| 80 | } | ||
| 81 | CEXP rational& operator--() NE { | ||
| 82 | num -= den; | ||
| 83 | return *this; | ||
| 84 | } | ||
| 85 | 292 | friend CEXP int operator<=>(rational CR x, rational CR y) NE { | |
| 86 | 292 | const auto _ = (x - y).num; | |
| 87 |
2/2✓ Branch 0 taken 269 times.
✓ Branch 1 taken 23 times.
|
292 | retif_((_ < 0), -1, _ > 0); |
| 88 | } | ||
| 89 | friend CEXP bool operator==(rational CR x, rational CR y) NE { return x.num == y.num && x.den == y.den; } | ||
| 90 | friend auto& operator>>(istream_c auto& is, rational& x) NE { return is >> x.num >> x.den; } | ||
| 91 | friend auto& operator<<(ostream_c auto& os, rational CR x) NE { return os << x.num << ' ' << x.den; } | ||
| 92 | template <arithm_c U> | ||
| 93 | CEXP U convert_to() CNE { return U(num) / U(den); } | ||
| 94 | }; | ||
| 95 | |||
| 96 | } // namespace tifa_libs | ||
| 97 |