@@ -632,6 +632,98 @@ constexpr auto to_dpd_d64(DecimalType val) noexcept
632632 return dpd;
633633}
634634
635+ template <typename DecimalType = decimal64_fast>
636+ constexpr auto from_dpd_d64 (std::uint64_t dpd) noexcept
637+ BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, DecimalType)
638+ {
639+ // First we check for non-finite values
640+ // Since they are in the same initial format as BID it's easy to check with our existing masks
641+ if ((dpd & detail::d64_inf_mask) == detail::d64_inf_mask)
642+ {
643+ if ((dpd & detail::d64_snan_mask) == detail::d64_snan_mask)
644+ {
645+ return std::numeric_limits<DecimalType>::signaling_NaN ();
646+ }
647+ else if ((dpd & detail::d64_nan_mask) == detail::d64_nan_mask)
648+ {
649+ return std::numeric_limits<DecimalType>::quiet_NaN ();
650+ }
651+ else
652+ {
653+ return std::numeric_limits<DecimalType>::infinity ();
654+ }
655+ }
656+
657+ // The bit lengths are the same as used in the standard bid format
658+ const auto sign {(dpd & detail::d32_sign_mask) != 0 };
659+ const auto combination_field_bits {(dpd & detail::d64_combination_field_mask) >> 58U };
660+ const auto exponent_field_bits {(dpd & detail::d64_exponent_mask) >> 50U };
661+ auto significand_bits {(dpd & detail::d64_significand_mask)};
662+
663+ // Case 1: 3.5.2.c.1.i
664+ // Combination field bits are 110XX or 11110X
665+ std::uint64_t d0 {};
666+ std::uint64_t leading_biased_exp_bits {};
667+ if (combination_field_bits >= 0b11000 )
668+ {
669+ // d0 = 8 + G4
670+ // Must be equal to 8 or 9
671+ d0 = 8U + (combination_field_bits & 0b00001 );
672+ BOOST_DECIMAL_ASSERT (d0 == 8 || d0 == 9 );
673+
674+ // leading exp bits are 2*G2 + G3
675+ // Must be equal to 0, 1 or 2
676+ leading_biased_exp_bits = 2U * ((combination_field_bits & 0b00100 ) >> 2U ) + ((combination_field_bits & 0b00010 ) >> 1U );
677+ BOOST_DECIMAL_ASSERT (leading_biased_exp_bits <= 2U );
678+ }
679+ // Case 2: 3.5.2.c.1.ii
680+ // Combination field bits are 0XXXX or 10XXX
681+ else
682+ {
683+ // d0 = 4 * G2 + 2 * G3 + G4
684+ // Must be in the range 0-7
685+ d0 = combination_field_bits & 0b00111 ;
686+ BOOST_DECIMAL_ASSERT (d0 <= 7 );
687+
688+ // Leading exp bits are 2 * G0 + G1
689+ // Must be equal to 0, 1 or 2
690+ leading_biased_exp_bits = (combination_field_bits & 0b11000 ) >> 3U ;
691+ BOOST_DECIMAL_ASSERT (leading_biased_exp_bits <= 2U );
692+ }
693+
694+ // Now that we have the bits we can calculate the exponents value
695+ const auto complete_exp {(leading_biased_exp_bits << 8U ) + exponent_field_bits};
696+ const auto exp {static_cast <std::int32_t >(complete_exp) - detail::bias_v<DecimalType>};
697+
698+ // We can now decode the remainder of the significand to recover the value
699+ std::uint8_t digits[16 ] {};
700+ digits[0 ] = static_cast <std::uint8_t >(d0);
701+ for (int i = 15 ; i > 0 ; i -= 3 )
702+ {
703+ const auto declet_bits {static_cast <std::uint32_t >(significand_bits & 0b1111111111 )};
704+ significand_bits >>= 10U ;
705+ detail::decode_dpd (declet_bits, digits[i], digits[i - 1 ], digits[i - 2 ]);
706+ }
707+
708+ std::uint64_t significand {};
709+ for (std::uint64_t i {}; i < 16U ; ++i)
710+ {
711+ significand += digits[i] * detail::pow10 (15 - i);
712+ }
713+
714+ return DecimalType{significand, exp, sign};
715+ }
716+
717+ constexpr auto to_dpd (decimal32 val) noexcept -> std::uint32_t
718+ {
719+ return to_dpd_d32 (val);
720+ }
721+
722+ constexpr auto to_dpd (decimal32_fast val) noexcept -> std::uint32_t
723+ {
724+ return to_dpd_d32 (val);
725+ }
726+
635727constexpr auto to_dpd (decimal64 val) -> std::uint64_t
636728{
637729 return to_dpd_d64 (val);
0 commit comments