41 auto&& [x, y] = inner;
42 constexpr std::size_t type_1 = std::same_as<std::decay_t<
decltype(x)>, std::int64_t> ? 1U : 0U;
43 constexpr std::size_t type_2 = std::same_as<std::decay_t<
decltype(y)>, std::int64_t> ? 1U : 0U;
45 return std::integral_constant<std::size_t, type_1 + type_2>{};
47 } -> std::same_as<std::integral_constant<std::size_t, 2U>>;
54 std::int64_t numerator{};
55 std::int64_t denominator{};
57 constexpr rational()
noexcept =
default;
63 explicit constexpr rational(std::int64_t numerator) noexcept :
rational{numerator, 1} {}
65 constexpr rational(std::int64_t numerator, std::int64_t denominator) noexcept
66 : numerator{numerator}, denominator{denominator} {
73 auto&& [numerator, denominator] = std::forward<T>(obj);
75 this->numerator = numerator;
76 this->denominator = denominator;
91 return std::decay_t<T>{numerator, denominator};
98 template <std::
floating_po
int T>
99 explicit constexpr operator T() const noexcept {
100 return static_cast<T
>(numerator) /
static_cast<T
>(denominator);
105 constexpr void simplify() noexcept {
106 const auto gcd = std::gcd(numerator, denominator);
113 if (denominator < 0) {
114 numerator = -numerator;
115 denominator = -denominator;
124 return rational{denominator, numerator};
127 constexpr bool operator<(
const rational& right)
const noexcept {
128 return numerator * right.denominator < right.numerator * denominator;
131 constexpr bool operator>(
const rational& right)
const noexcept {
132 return numerator * right.denominator > right.numerator * denominator;
135 constexpr bool operator==(
const rational& right)
const noexcept {
136 return numerator * right.denominator == right.numerator * denominator;
139 constexpr bool operator!=(
const rational& right)
const noexcept {
140 return !(*
this == right);
143 constexpr bool operator<=(
const rational& right)
const noexcept {
144 return !(*
this > right);
147 constexpr bool operator>=(
const rational& right)
const noexcept {
148 return !(*
this < right);
151 friend constexpr rational operator-(
const rational& value)
noexcept {
152 return rational{-
value.numerator,
value.denominator};
155 friend constexpr rational operator+(
const rational& left,
const rational& right)
noexcept {
156 const auto lcm = std::lcm(left.denominator, right.denominator);
158 left.numerator * (lcm / left.denominator) + right.numerator * (lcm / right.denominator), lcm};
160 return (result.simplify(), result);
163 friend constexpr rational operator-(
const rational& left,
const rational& right)
noexcept {
164 return left + (-right);
167 friend constexpr rational operator*(
const rational& left,
const rational& right)
noexcept {
168 rational result{left.numerator * right.numerator, left.denominator * right.denominator};
170 return (result.simplify(), result);
173 friend constexpr rational operator/(
const rational& left,
const rational& right)
noexcept {
174 return left * right.reciprocal();