// Copyright 2023 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #ifndef BOOST_DECIMAL_DETAIL_NORMALIZE_HPP #define BOOST_DECIMAL_DETAIL_NORMALIZE_HPP #include #include #include #include #include namespace boost { namespace decimal { namespace detail { #if defined(__GNUC__) && __GNUC__ == 7 # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wsign-conversion" #endif // Converts the significand to full precision to remove the effects of cohorts template constexpr auto normalize(T1& significand, T2& exp, bool sign = false) noexcept -> void { constexpr auto target_precision {detail::precision_v}; const auto digits {num_digits(significand)}; if (digits < target_precision) { const auto zeros_needed {target_precision - digits}; BOOST_DECIMAL_ASSERT(zeros_needed >= 0); significand *= pow10(static_cast(zeros_needed)); exp -= zeros_needed; } else if (digits > target_precision) { auto biased_exp {static_cast(exp) + detail::bias_v}; detail::coefficient_rounding(significand, exp, biased_exp, sign, digits); } } #if defined(__GNUC__) && __GNUC__ == 7 # pragma GCC diagnostic pop #endif // This is a branchless version of the above which is used for implementing basic operations, // since we know that the values in the decimal type are never larger than target_precision template constexpr auto expand_significand(T1& significand, T2& exp) noexcept -> void { constexpr auto target_precision {detail::precision_v}; const auto digits {num_digits(significand)}; const auto zeros_needed {target_precision - digits}; significand *= pow10(static_cast(zeros_needed)); exp -= zeros_needed; } } //namespace detail } //namespace decimal } //namespace boost #endif //BOOST_DECIMAL_DETAIL_NORMALIZE_HPP