diff --git a/src/core/include/units/ratio.h b/src/core/include/units/ratio.h index dcb4956b..923f2355 100644 --- a/src/core/include/units/ratio.h +++ b/src/core/include/units/ratio.h @@ -60,6 +60,27 @@ struct ratio { [[nodiscard]] friend constexpr bool operator==(const ratio&, const ratio&) = default; + [[nodiscard]] friend constexpr ratio operator-(const ratio& r) + { + return ratio(-r.num, r.den, r.exp); + } + + [[nodiscard]] friend constexpr ratio operator+(ratio lhs, ratio rhs) + { + // First, get the inputs into a common exponent. + const auto common_exp = std::min(lhs.exp, rhs.exp); + auto commonify = [common_exp](ratio &r) { + while (r.exp > common_exp) { + r.num *= 10; + --r.exp; + } + }; + commonify(lhs); + commonify(rhs); + + return ratio{lhs.num * rhs.den + lhs.den * rhs.num, lhs.den * rhs.den, common_exp}; + } + [[nodiscard]] friend constexpr ratio operator*(const ratio& lhs, const ratio& rhs) { const std::intmax_t gcd1 = std::gcd(lhs.num, rhs.den); diff --git a/test/unit_test/static/ratio_test.cpp b/test/unit_test/static/ratio_test.cpp index 5067d3fa..32de5f10 100644 --- a/test/unit_test/static/ratio_test.cpp +++ b/test/unit_test/static/ratio_test.cpp @@ -40,6 +40,13 @@ static_assert(ratio(4) * ratio(1, 2) == ratio(2)); static_assert(ratio(1, 8) * ratio(2) == ratio(1, 4)); static_assert(ratio(1, 2) * ratio(8) == ratio(4)); +// ratio negation +static_assert(-ratio(3, 8) == ratio(-3, 8)); + +// ratio addition +static_assert(ratio(1, 2) + ratio(1, 3) == ratio(5, 6)); +static_assert(ratio(1, 3, 2) + ratio(11, 6) == ratio(211, 6)); // 100/3 + 11/6 + // multiply with exponents static_assert(ratio(1, 8, 2) * ratio(2, 1, 4) == ratio(1, 4, 6)); static_assert(ratio(1, 2, -4) * ratio(8, 1, 3) == ratio(4, 1, -1));