From c1e4e57d84a5cd4786764bfdd9b7bf66d2ab6902 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Wed, 11 Dec 2019 09:28:40 +0100 Subject: [PATCH] clang-format + TODOs added to ratio --- src/include/units/ratio.h | 311 ++++++++++++++++++++------------------ 1 file changed, 160 insertions(+), 151 deletions(-) diff --git a/src/include/units/ratio.h b/src/include/units/ratio.h index 80e964f9..6e0700a0 100644 --- a/src/include/units/ratio.h +++ b/src/include/units/ratio.h @@ -23,177 +23,186 @@ #pragma once #include -#include -#include #include +#include +#include namespace units { - namespace detail { +namespace detail { - template - [[nodiscard]] constexpr T abs(T v) noexcept { return v < 0 ? -v : v; } +template +[[nodiscard]] constexpr T abs(T v) noexcept +{ + return v < 0 ? -v : v; +} - } +} // namespace detail - template - requires (Den != 0) - struct ratio { - static_assert(-INTMAX_MAX <= Num, "numerator too negative"); - static_assert(-INTMAX_MAX <= Den, "denominator too negative"); +template + requires(Den != 0) +struct ratio { + static_assert(-INTMAX_MAX <= Num, "numerator too negative"); + static_assert(-INTMAX_MAX <= Den, "denominator too negative"); - static constexpr std::intmax_t num = Num * (Den < 0 ? -1 : 1) / std::gcd(Num, Den); - static constexpr std::intmax_t den = detail::abs(Den) / std::gcd(Num, Den); + static constexpr std::intmax_t num = Num * (Den < 0 ? -1 : 1) / std::gcd(Num, Den); + static constexpr std::intmax_t den = detail::abs(Den) / std::gcd(Num, Den); - using type = ratio; - }; + using type = ratio; +}; - // is_ratio +// is_ratio - namespace detail { +namespace detail { - template - inline constexpr bool is_ratio = false; +template +inline constexpr bool is_ratio = false; - template - inline constexpr bool is_ratio> = true; +template +inline constexpr bool is_ratio> = true; - } // namespace detail +} // namespace detail - template - concept Ratio = detail::is_ratio; - - // ratio_multiply - - namespace detail { - - static constexpr std::intmax_t safe_multiply(std::intmax_t lhs, std::intmax_t rhs) - { - constexpr std::uintmax_t c = std::uintmax_t(1) << (sizeof(std::intmax_t) * 4); - - const std::uintmax_t a0 = detail::abs(lhs) % c; - const std::uintmax_t a1 = detail::abs(lhs) / c; - const std::uintmax_t b0 = detail::abs(rhs) % c; - const std::uintmax_t b1 = detail::abs(rhs) / c; - - Expects(a1 == 0 || b1 == 0); // overflow in multiplication - Expects(a0 * b1 + b0 * a1 < (c >> 1)); // overflow in multiplication - Expects(b0 * a0 <= INTMAX_MAX); // overflow in multiplication - Expects((a0 * b1 + b0 * a1) * c <= INTMAX_MAX - b0 * a0); // overflow in multiplication - - return lhs * rhs; - } - - template - struct ratio_multiply_impl { - private: - static constexpr std::intmax_t gcd1 = std::gcd(R1::num, R2::den); - static constexpr std::intmax_t gcd2 = std::gcd(R2::num, R1::den); - - public: - using type = ratio; - static constexpr std::intmax_t num = type::num; - static constexpr std::intmax_t den = type::den; - }; - - } - - template - using ratio_multiply = detail::ratio_multiply_impl::type; - - // ratio_divide - - namespace detail { - - template - struct ratio_divide_impl { - static_assert(R2::num != 0, "division by 0"); - using type = ratio_multiply>; - static constexpr std::intmax_t num = type::num; - static constexpr std::intmax_t den = type::den; - }; - - } - - template - using ratio_divide = detail::ratio_divide_impl::type; - - // ratio_pow - - namespace detail { - - template - struct ratio_pow_impl { - using type = ratio_multiply::type, R>; - }; - - template - struct ratio_pow_impl { - using type = R; - }; - - template - struct ratio_pow_impl { - using type = ratio<1>; - }; - - } - - template - using ratio_pow = detail::ratio_pow_impl::type; - - // ratio_sqrt - - namespace detail { - - constexpr std::intmax_t sqrt_impl(std::intmax_t v, std::intmax_t l, std::intmax_t r) - { - if(l == r) - return r; - - const auto mid = (r + l) / 2; - if(mid * mid >= v) - return sqrt_impl(v, l, mid); - else - return sqrt_impl(v, mid + 1, r); - } - - static constexpr std::intmax_t sqrt_impl(std::intmax_t v) - { - return sqrt_impl(v, 1, v); - } - - template - struct ratio_sqrt_impl { - using type = ratio; - }; - - template - struct ratio_sqrt_impl> { - using type = ratio<0>; - }; - - } - - template - using ratio_sqrt = detail::ratio_sqrt_impl::type; +template +concept Ratio = detail::is_ratio; - // common_ratio +// ratio_add +// TODO implement ratio_add +// template +// using ratio_add = detail::ratio_add_impl::type; - namespace detail { +// ratio_subtract +// TODO implement ratio_subtract +// template +// using ratio_subtract = detail::ratio_subtract_impl::type; - // TODO: simplified - template - struct common_ratio_impl { - static constexpr std::intmax_t gcd_num = std::gcd(R1::num, R2::num); - static constexpr std::intmax_t gcd_den = std::gcd(R1::den, R2::den); - using type = ratio; - }; +// ratio_multiply - } +namespace detail { - template - using common_ratio = detail::common_ratio_impl::type; +static constexpr std::intmax_t safe_multiply(std::intmax_t lhs, std::intmax_t rhs) +{ + constexpr std::uintmax_t c = std::uintmax_t(1) << (sizeof(std::intmax_t) * 4); + + const std::uintmax_t a0 = detail::abs(lhs) % c; + const std::uintmax_t a1 = detail::abs(lhs) / c; + const std::uintmax_t b0 = detail::abs(rhs) % c; + const std::uintmax_t b1 = detail::abs(rhs) / c; + + Expects(a1 == 0 || b1 == 0); // overflow in multiplication + Expects(a0 * b1 + b0 * a1 < (c >> 1)); // overflow in multiplication + Expects(b0 * a0 <= INTMAX_MAX); // overflow in multiplication + Expects((a0 * b1 + b0 * a1) * c <= INTMAX_MAX - b0 * a0); // overflow in multiplication + + return lhs * rhs; +} + +template +struct ratio_multiply_impl { +private: + static constexpr std::intmax_t gcd1 = std::gcd(R1::num, R2::den); + static constexpr std::intmax_t gcd2 = std::gcd(R2::num, R1::den); + +public: + using type = ratio; + static constexpr std::intmax_t num = type::num; + static constexpr std::intmax_t den = type::den; +}; + +} // namespace detail + +template +using ratio_multiply = detail::ratio_multiply_impl::type; + +// ratio_divide + +namespace detail { + +template +struct ratio_divide_impl { + static_assert(R2::num != 0, "division by 0"); + using type = ratio_multiply>; + static constexpr std::intmax_t num = type::num; + static constexpr std::intmax_t den = type::den; +}; + +} // namespace detail + +template +using ratio_divide = detail::ratio_divide_impl::type; + +// ratio_pow + +namespace detail { + +template +struct ratio_pow_impl { + using type = ratio_multiply::type, R>; +}; + +template +struct ratio_pow_impl { + using type = R; +}; + +template +struct ratio_pow_impl { + using type = ratio<1>; +}; + +} // namespace detail + +template +using ratio_pow = detail::ratio_pow_impl::type; + +// ratio_sqrt + +namespace detail { + +constexpr std::intmax_t sqrt_impl(std::intmax_t v, std::intmax_t l, std::intmax_t r) +{ + if (l == r) return r; + + const auto mid = (r + l) / 2; + if (mid * mid >= v) + return sqrt_impl(v, l, mid); + else + return sqrt_impl(v, mid + 1, r); +} + +static constexpr std::intmax_t sqrt_impl(std::intmax_t v) { return sqrt_impl(v, 1, v); } + +template +struct ratio_sqrt_impl { + using type = ratio; +}; + +template +struct ratio_sqrt_impl> { + using type = ratio<0>; +}; + +} // namespace detail + +template +using ratio_sqrt = detail::ratio_sqrt_impl::type; + +// common_ratio + +namespace detail { + +// TODO: simplified +template +struct common_ratio_impl { + static constexpr std::intmax_t gcd_num = std::gcd(R1::num, R2::num); + static constexpr std::intmax_t gcd_den = std::gcd(R1::den, R2::den); + using type = ratio; +}; + +} // namespace detail + +template +using common_ratio = detail::common_ratio_impl::type; } // namespace units