@@ -814,6 +814,90 @@ constexpr auto to_dpd_d128(DecimalType val) noexcept
814814 return dpd;
815815}
816816
817+ template <typename DecimalType = decimal128_fast>
818+ constexpr auto from_dpd_d128 (detail::uint128 dpd) noexcept
819+ BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, DecimalType)
820+ {
821+ static_assert (std::is_same<DecimalType, decimal128>::value || std::is_same<DecimalType, decimal128_fast>::value,
822+ " Target decimal type must be 128-bits" );
823+
824+ if ((dpd & detail::d128_inf_mask) == detail::d128_inf_mask)
825+ {
826+ if ((dpd & detail::d128_snan_mask) == detail::d128_snan_mask)
827+ {
828+ return std::numeric_limits<DecimalType>::signaling_NaN ();
829+ }
830+ else if ((dpd & detail::d128_nan_mask) == detail::d128_nan_mask)
831+ {
832+ return std::numeric_limits<DecimalType>::quiet_NaN ();
833+ }
834+ else
835+ {
836+ return std::numeric_limits<DecimalType>::infinity ();
837+ }
838+ }
839+
840+ // The bit lengths are the same as used in the standard bid format
841+ const auto sign {(dpd.high & detail::d128_sign_mask.high ) != 0 };
842+ const auto combination_field_bits {(dpd.high & detail::d128_combination_field_mask.high ) >> 58U };
843+ const auto exponent_field_bits {(dpd.high & detail::d128_exponent_mask.high ) >> 46U };
844+ auto significand_bits {(dpd & detail::d128_significand_mask)};
845+
846+ // Case 1: 3.5.2.c.1.i
847+ // Combination field bits are 110XX or 11110X
848+ std::uint64_t d0 {};
849+ std::uint64_t leading_biased_exp_bits {};
850+ if (combination_field_bits >= 0b11000 )
851+ {
852+ // d0 = 8 + G4
853+ // Must be equal to 8 or 9
854+ d0 = 8U + (combination_field_bits & 0b00001 );
855+ BOOST_DECIMAL_ASSERT (d0 == 8 || d0 == 9 );
856+
857+ // leading exp bits are 2*G2 + G3
858+ // Must be equal to 0, 1 or 2
859+ leading_biased_exp_bits = 2U * ((combination_field_bits & 0b00100 ) >> 2U ) + ((combination_field_bits & 0b00010 ) >> 1U );
860+ BOOST_DECIMAL_ASSERT (leading_biased_exp_bits <= 2U );
861+ }
862+ // Case 2: 3.5.2.c.1.ii
863+ // Combination field bits are 0XXXX or 10XXX
864+ else
865+ {
866+ // d0 = 4 * G2 + 2 * G3 + G4
867+ // Must be in the range 0-7
868+ d0 = combination_field_bits & 0b00111 ;
869+ BOOST_DECIMAL_ASSERT (d0 <= 7 );
870+
871+ // Leading exp bits are 2 * G0 + G1
872+ // Must be equal to 0, 1 or 2
873+ leading_biased_exp_bits = (combination_field_bits & 0b11000 ) >> 3U ;
874+ BOOST_DECIMAL_ASSERT (leading_biased_exp_bits <= 2U );
875+ }
876+
877+ // Now that we have the bits we can calculate the exponents value
878+ const auto complete_exp {(leading_biased_exp_bits << 12U ) + exponent_field_bits};
879+ const auto exp {static_cast <std::int32_t >(complete_exp) - detail::bias_v<DecimalType>};
880+
881+ // We can now decode the remainder of the significand to recover the value
882+ constexpr auto num_digits {std::numeric_limits<DecimalType>::digits10};
883+ std::uint8_t digits[num_digits] {};
884+ digits[0 ] = static_cast <std::uint8_t >(d0);
885+ for (int i = num_digits - 1 ; i > 0 ; i -= 3 )
886+ {
887+ const auto declet_bits {static_cast <std::uint32_t >(significand_bits & 0b1111111111 )};
888+ significand_bits >>= 10U ;
889+ detail::decode_dpd (declet_bits, digits[i], digits[i - 1 ], digits[i - 2 ]);
890+ }
891+
892+ detail::uint128 significand {};
893+ for (int i {}; i < num_digits; ++i)
894+ {
895+ significand += static_cast <detail::uint128>(digits[i]) * detail::pow10 (static_cast <detail::uint128>(num_digits - i));
896+ }
897+
898+ return DecimalType{significand, exp, sign};
899+ }
900+
817901constexpr auto to_dpd (decimal32 val) noexcept -> std::uint32_t
818902{
819903 return to_dpd_d32 (val);
@@ -824,16 +908,26 @@ constexpr auto to_dpd(decimal32_fast val) noexcept -> std::uint32_t
824908 return to_dpd_d32 (val);
825909}
826910
827- constexpr auto to_dpd (decimal64 val) -> std::uint64_t
911+ constexpr auto to_dpd (decimal64 val) noexcept -> std::uint64_t
828912{
829913 return to_dpd_d64 (val);
830914}
831915
832- constexpr auto to_dpd (decimal64_fast val) -> std::uint64_t
916+ constexpr auto to_dpd (decimal64_fast val) noexcept -> std::uint64_t
833917{
834918 return to_dpd_d64 (val);
835919}
836920
921+ constexpr auto to_dpd (decimal128 val) noexcept -> detail::uint128
922+ {
923+ return to_dpd_d128 (val);
924+ }
925+
926+ constexpr auto to_dpd (decimal128_fast val) noexcept -> detail::uint128
927+ {
928+ return to_dpd_d128 (val);
929+ }
930+
837931template <typename DecimalType>
838932constexpr auto to_dpd (DecimalType val) noexcept
839933{
@@ -855,6 +949,25 @@ constexpr auto from_dpd(std::uint64_t bits) noexcept
855949 return from_dpd_d64<DecimalType>(bits);
856950}
857951
952+ template <typename DecimalType = decimal128_fast>
953+ constexpr auto from_dpd (detail::uint128 bits) noexcept
954+ BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, DecimalType)
955+ {
956+ return from_dpd_d128<DecimalType>(bits);
957+ }
958+
959+ #ifdef BOOST_DECIMAL_HAS_INT128
960+
961+ template <typename DecimalType = decimal128_fast>
962+ constexpr auto from_dpd (detail::uint128_t bits) noexcept
963+ BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, DecimalType)
964+ {
965+ const detail::uint128 converted_bits {bits};
966+ return from_dpd_d128<DecimalType>(converted_bits);
967+ }
968+
969+ #endif // BOOST_DECIMAL_HAS_INT128
970+
858971} // namespace decimal
859972} // namespace boost
860973
0 commit comments