Skip to content

Commit 428f2e6

Browse files
committed
Add from dpd64
1 parent c8113b3 commit 428f2e6

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

include/boost/decimal/dpd_conversion.hpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
635727
constexpr auto to_dpd(decimal64 val) -> std::uint64_t
636728
{
637729
return to_dpd_d64(val);

0 commit comments

Comments
 (0)