Skip to content

Commit 5fb7d29

Browse files
committed
Fix construction of 128-bit subnormal values
1 parent f46c47d commit 5fb7d29

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

include/boost/decimal/decimal128_t.hpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ constexpr decimal128_t::decimal128_t(T1 coeff, T2 exp, bool sign) noexcept
745745
auto biased_exp {static_cast<int>(exp + detail::bias_v<decimal128_t>)};
746746
BOOST_DECIMAL_IF_CONSTEXPR (sizeof(T1) >= sizeof(significand_type))
747747
{
748-
if (coeff > detail::d128_max_significand_value || biased_exp < 0)
748+
if (coeff > detail::d128_max_significand_value || biased_exp < -(detail::precision_v<decimal128_t> - 1))
749749
{
750750
coeff_digits = detail::coefficient_rounding<decimal128_t>(coeff, exp, biased_exp, sign, detail::num_digits(coeff));
751751
}
@@ -788,6 +788,19 @@ constexpr decimal128_t::decimal128_t(T1 coeff, T2 exp, bool sign) noexcept
788788
reduced_coeff *= detail::pow10(static_cast<significand_type>(digit_delta));
789789
*this = decimal128_t(reduced_coeff, exp, sign);
790790
}
791+
else if (coeff_digits + biased_exp <= detail::precision_v<decimal128_t>)
792+
{
793+
// Handle the case of sub-normals that don't need further rounding
794+
bits_.high = sign ? detail::d128_sign_mask : UINT64_C(0); // Reset the sign bit
795+
const auto zeros {detail::remove_trailing_zeros(reduced_coeff)};
796+
biased_exp += zeros.number_of_removed_zeros;
797+
reduced_coeff = zeros.trimmed_number;
798+
if (biased_exp > 0)
799+
{
800+
reduced_coeff *= detail::pow10(static_cast<significand_type>(biased_exp));
801+
}
802+
bits_ |= reduced_coeff;
803+
}
791804
else if (digit_delta < 0 && coeff_digits - digit_delta <= detail::precision_v<decimal128_t>)
792805
{
793806
const auto offset {detail::precision_v<decimal128_t> - coeff_digits};

0 commit comments

Comments
 (0)