@@ -288,7 +288,7 @@ BOOST_DECIMAL_EXPORT class decimal32_t final // NOLINT(cppcoreguidelines-special
288288 #else
289289 template <typename T1, typename T2, std::enable_if_t <detail::is_unsigned_v<T1> && detail::is_integral_v<T2>, bool > = true >
290290 #endif
291- constexpr decimal32_t (T1 coeff, T2 exp, bool sign = false ) noexcept ;
291+ constexpr decimal32_t (T1 coeff, T2 exp, bool is_negative = false ) noexcept ;
292292
293293 #ifdef BOOST_DECIMAL_HAS_CONCEPTS
294294 template <BOOST_DECIMAL_SIGNED_INTEGRAL T1, BOOST_DECIMAL_INTEGRAL T2>
@@ -642,20 +642,20 @@ template <BOOST_DECIMAL_UNSIGNED_INTEGRAL T1, BOOST_DECIMAL_INTEGRAL T2>
642642#else
643643template <typename T1, typename T2, std::enable_if_t <detail::is_unsigned_v<T1> && detail::is_integral_v<T2>, bool >>
644644#endif
645- constexpr decimal32_t::decimal32_t (T1 coeff, T2 exp, bool sign ) noexcept // NOLINT(readability-function-cognitive-complexity,misc-no-recursion)
645+ constexpr decimal32_t::decimal32_t (T1 coeff, T2 exp, bool is_negative ) noexcept // NOLINT(readability-function-cognitive-complexity,misc-no-recursion)
646646{
647647 static_assert (detail::is_integral_v<T1>, " Coefficient must be an integer" );
648648 static_assert (detail::is_integral_v<T2>, " Exponent must be an integer" );
649649
650- bits_ = sign ? detail::d32_sign_mask : UINT32_C (0 );
650+ bits_ = is_negative ? detail::d32_sign_mask : UINT32_C (0 );
651651
652652 // If the coeff is not in range, make it so
653653 // Only count the number of digits if we absolutely have to
654654 int coeff_digits {-1 };
655655 auto biased_exp {static_cast <int >(exp + detail::bias)};
656- if (coeff > detail::d32_max_significand_value || biased_exp < 0 )
656+ if (coeff > detail::d32_max_significand_value || biased_exp < -(detail::precision_v< decimal32_t > - 1 ) )
657657 {
658- coeff_digits = detail::coefficient_rounding<decimal32_t >(coeff, exp, biased_exp, sign , detail::num_digits (coeff));
658+ coeff_digits = detail::coefficient_rounding<decimal32_t >(coeff, exp, biased_exp, is_negative , detail::num_digits (coeff));
659659 }
660660
661661 auto reduced_coeff {static_cast <significand_type>(coeff)};
@@ -708,21 +708,34 @@ constexpr decimal32_t::decimal32_t(T1 coeff, T2 exp, bool sign) noexcept // NOLI
708708 {
709709 exp -= digit_delta;
710710 reduced_coeff *= detail::pow10 (static_cast <significand_type>(digit_delta));
711- *this = decimal32_t (reduced_coeff, exp, sign);
711+ *this = decimal32_t (reduced_coeff, exp, is_negative);
712+ }
713+ else if (coeff_digits + biased_exp <= detail::precision)
714+ {
715+ // Handle the case of sub-normals that don't need further rounding
716+ bits_ = sign ? detail::d32_sign_mask : UINT32_C (0 ); // Reset the sign bit
717+ const auto zeros {detail::remove_trailing_zeros (reduced_coeff)};
718+ biased_exp += static_cast <int >(zeros.number_of_removed_zeros );
719+ reduced_coeff = zeros.trimmed_number ;
720+ if (biased_exp > 0 )
721+ {
722+ reduced_coeff *= detail::pow10 (static_cast <significand_type>(biased_exp));
723+ }
724+ bits_ |= reduced_coeff;
712725 }
713726 else if (digit_delta < 0 && coeff_digits - digit_delta <= detail::precision)
714727 {
715728 // We can expand the coefficient to use the maximum number of digits
716729 const auto offset {detail::precision - coeff_digits};
717730 exp -= offset;
718731 reduced_coeff *= detail::pow10 (static_cast <significand_type>(offset));
719- *this = decimal32_t (reduced_coeff, exp, sign );
732+ *this = decimal32_t (reduced_coeff, exp, is_negative );
720733 }
721734 else
722735 {
723736 // Reset the value and make sure to preserve the sign of 0/inf
724737 bits_ = exp < 0 ? UINT32_C (0 ) : detail::d32_inf_mask;
725- bits_ |= sign ? detail::d32_sign_mask : UINT32_C (0 );
738+ bits_ |= is_negative ? detail::d32_sign_mask : UINT32_C (0 );
726739 }
727740 }
728741}
0 commit comments