@@ -704,7 +704,59 @@ constexpr decimal64_t::decimal64_t(T1 coeff, T2 exp, bool is_negative) noexcept
704704
705705 const auto exp_delta {biased_exp - static_cast <int >(detail::d64_max_biased_exponent)};
706706 const auto digit_delta {coeff_digits - exp_delta};
707- if (digit_delta > 0 && coeff_digits + digit_delta <= detail::precision_v<decimal64_t >)
707+ if (biased_exp < 0 && coeff_digits == 1 )
708+ {
709+ // This needs to be flushed to 0 or rounded to subnormal min
710+ // e.g. 7e-399 should not become 70e-398 but 7e-400 should become 0
711+ rounding_mode current_round_mode {_boost_decimal_global_rounding_mode};
712+
713+ #ifndef BOOST_DECIMAL_NO_CONSTEVAL_DETECTION
714+
715+ if (!BOOST_DECIMAL_IS_CONSTANT_EVALUATED (coeff))
716+ {
717+ current_round_mode = _boost_decimal_global_runtime_rounding_mode;
718+ }
719+
720+ #endif
721+
722+ bool round {false };
723+ if (biased_exp == -1 )
724+ {
725+ switch (current_round_mode)
726+ {
727+ case rounding_mode::fe_dec_to_nearest_from_zero:
728+ BOOST_DECIMAL_FALLTHROUGH
729+ case rounding_mode::fe_dec_to_nearest:
730+ if (reduced_coeff >= 5U )
731+ {
732+ round = true ;
733+ }
734+ break ;
735+ case rounding_mode::fe_dec_upward:
736+ if (!is_negative && reduced_coeff != 0 )
737+ {
738+ round = true ;
739+ }
740+ break ;
741+ default :
742+ round = false ;
743+ break ;
744+ }
745+ }
746+
747+ if (round)
748+ {
749+ // Subnormal min is just 1
750+ bits_ = UINT64_C (1 );
751+ }
752+ else
753+ {
754+ bits_ = UINT64_C (0 );
755+ }
756+
757+ bits_ |= is_negative ? detail::d64_sign_mask : UINT64_C (0 );
758+ }
759+ else if (digit_delta > 0 && coeff_digits + digit_delta <= detail::precision_v<decimal64_t >)
708760 {
709761 exp -= digit_delta;
710762 reduced_coeff *= detail::pow10 (static_cast <significand_type>(digit_delta));
@@ -730,6 +782,22 @@ constexpr decimal64_t::decimal64_t(T1 coeff, T2 exp, bool is_negative) noexcept
730782 reduced_coeff *= detail::pow10 (static_cast <significand_type>(offset));
731783 *this = decimal64_t (reduced_coeff, exp, is_negative);
732784 }
785+ else if (biased_exp > detail::max_biased_exp_v<decimal64_t >)
786+ {
787+ // Similar to subnormals, but for extremely large values
788+ const auto available_space {detail::precision_v<decimal64_t > - coeff_digits};
789+ if (available_space >= exp_delta)
790+ {
791+ reduced_coeff *= detail::pow10 (static_cast <significand_type>(available_space));
792+ exp -= available_space;
793+ *this = decimal64_t (reduced_coeff, exp, is_negative);
794+ }
795+ else
796+ {
797+ bits_ = exp < 0 ? UINT64_C (0 ) : detail::d64_inf_mask;
798+ bits_ |= is_negative ? detail::d64_sign_mask : UINT64_C (0 );
799+ }
800+ }
733801 else
734802 {
735803 // Reset the value and make sure to preserve the sign of 0/inf
0 commit comments