@@ -421,16 +421,6 @@ constexpr auto to_dpd_d32(DecimalType val) noexcept
421421 return dpd;
422422}
423423
424- constexpr auto to_dpd (decimal32 val) noexcept -> std::uint32_t
425- {
426- return to_dpd_d32 (val);
427- }
428-
429- constexpr auto to_dpd (decimal32_fast val) noexcept -> std::uint32_t
430- {
431- return to_dpd_d32 (val);
432- }
433-
434424template <typename DecimalType = decimal32_fast>
435425constexpr auto from_dpd_d32 (std::uint32_t dpd) noexcept
436426 BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, DecimalType)
@@ -513,13 +503,239 @@ constexpr auto from_dpd_d32(std::uint32_t dpd) noexcept
513503 return DecimalType{significand, exp, sign};
514504}
515505
506+ template <typename DecimalType>
507+ constexpr auto to_dpd_d64 (DecimalType val) noexcept
508+ BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, DecimalType, std::uint64_t )
509+ {
510+ static_assert (std::is_same<DecimalType, decimal64>::value ||
511+ std::is_same<DecimalType, decimal64_fast>::value, " The input must be a 64-bit decimal type" );
512+
513+ // In the non-finite cases the encodings are the same
514+ // 3.5.2.a and 3.5.2.b
515+ if (!isfinite (val))
516+ {
517+ return to_bid (val);
518+ }
519+
520+ const auto sign {val.isneg ()};
521+ const auto exp {val.unbiased_exponent ()};
522+ const auto significand {val.full_significand ()};
523+
524+ std::uint64_t dpd {};
525+ // Set the sign bit as applicable
526+ if (sign)
527+ {
528+ dpd |= detail::d64_sign_mask;
529+ }
530+
531+ std::uint8_t d[std::numeric_limits<DecimalType>::digits10] {};
532+ auto temp_sig {significand};
533+ for (int i = 15 ; i >= 0 ; --i)
534+ {
535+ d[i] = static_cast <std::uint8_t >(temp_sig % 10U );
536+ temp_sig /= 10U ;
537+ }
538+ BOOST_DECIMAL_ASSERT (d[0 ] >= 0 && d[0 ] <= 9 );
539+ BOOST_DECIMAL_ASSERT (temp_sig == 0 );
540+
541+ constexpr std::uint64_t leading_two_exp_bits_mask {0b1100000000 };
542+ const auto leading_two_bits {(exp & leading_two_exp_bits_mask) >> 8U };
543+ BOOST_DECIMAL_ASSERT (leading_two_bits >= 0 && leading_two_bits <= 2 );
544+ constexpr std::uint64_t trailing_exp_bits_mask {0b0011111111 };
545+ const auto trailing_exp_bits {(exp & trailing_exp_bits_mask)};
546+
547+ std::uint64_t combination_field_bits {};
548+
549+ // Now based on what the value of d[0] and the leading bits of exp are we can set the value of the combination field
550+ // See 3.5.2.c.1
551+ // If d0 is 8 or 9 then we follow section i
552+ if (d[0 ] >= 8 )
553+ {
554+ const auto d0_is_nine {d[0 ] == 9 };
555+ switch (leading_two_bits)
556+ {
557+ case 0U :
558+ combination_field_bits = d0_is_nine ? 0b11001 : 0b11000 ;
559+ break ;
560+ case 1U :
561+ combination_field_bits = d0_is_nine ? 0b11011 : 0b11010 ;
562+ break ;
563+ case 2U :
564+ combination_field_bits = d0_is_nine ? 0b11101 : 0b11100 ;
565+ break ;
566+ // LCOV_EXCL_START
567+ default :
568+ BOOST_DECIMAL_UNREACHABLE;
569+ // LCOV_EXCL_STOP
570+ }
571+ }
572+ // If d0 is 0 to 7 then we follow section II
573+ else
574+ {
575+ // In here the value of d[0] = 4*G2 + 2*G3 + G4
576+ const auto d0_mask {static_cast <std::uint64_t >(d[0 ])};
577+ switch (leading_two_bits)
578+ {
579+ case 0U :
580+ // 00XXX
581+ combination_field_bits |= d0_mask;
582+ break ;
583+ case 1U :
584+ // 01XXX
585+ combination_field_bits = 0b01000 ;
586+ combination_field_bits |= d0_mask;
587+ break ;
588+ case 2U :
589+ // 10XXX
590+ combination_field_bits = 0b10000 ;
591+ combination_field_bits |= d0_mask;
592+ break ;
593+ // LCOV_EXCL_START
594+ default :
595+ BOOST_DECIMAL_UNREACHABLE;
596+ // LCOV_EXCL_STOP
597+ }
598+ }
599+
600+ // Write the now known combination field and trailing exp bits to the result
601+ dpd |= (combination_field_bits << 58U );
602+ dpd |= (trailing_exp_bits << 50U );
603+
604+ // Now we need to encode all the declets
605+ // Once we have the declet right it into the result
606+ int offset {4 };
607+ for (std::size_t i {1 }; i < 15 ; i += 3U )
608+ {
609+ const auto declet {static_cast <std::uint64_t >(detail::encode_dpd (d[i], d[i + 1 ], d[i + 2 ]))};
610+ dpd |= (declet << (10 * offset));
611+ --offset;
612+ }
613+
614+ return dpd;
615+ }
616+
617+ template <typename DecimalType = decimal64_fast>
618+ constexpr auto from_dpd_d64 (std::uint64_t dpd) noexcept
619+ BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, DecimalType)
620+ {
621+ // First we check for non-finite values
622+ // Since they are in the same initial format as BID it's easy to check with our existing masks
623+ if ((dpd & detail::d64_inf_mask) == detail::d64_inf_mask)
624+ {
625+ if ((dpd & detail::d64_snan_mask) == detail::d64_snan_mask)
626+ {
627+ return std::numeric_limits<DecimalType>::signaling_NaN ();
628+ }
629+ else if ((dpd & detail::d64_nan_mask) == detail::d64_nan_mask)
630+ {
631+ return std::numeric_limits<DecimalType>::quiet_NaN ();
632+ }
633+ else
634+ {
635+ return std::numeric_limits<DecimalType>::infinity ();
636+ }
637+ }
638+
639+ // The bit lengths are the same as used in the standard bid format
640+ const auto sign {(dpd & detail::d64_sign_mask) != 0 };
641+ const auto combination_field_bits {(dpd & detail::d64_combination_field_mask) >> 58U };
642+ const auto exponent_field_bits {(dpd & detail::d64_exponent_mask) >> 50U };
643+ auto significand_bits {(dpd & detail::d64_significand_mask)};
644+
645+ // Case 1: 3.5.2.c.1.i
646+ // Combination field bits are 110XX or 11110X
647+ std::uint64_t d0 {};
648+ std::uint64_t leading_biased_exp_bits {};
649+ if (combination_field_bits >= 0b11000 )
650+ {
651+ // d0 = 8 + G4
652+ // Must be equal to 8 or 9
653+ d0 = 8U + (combination_field_bits & 0b00001 );
654+ BOOST_DECIMAL_ASSERT (d0 == 8 || d0 == 9 );
655+
656+ // leading exp bits are 2*G2 + G3
657+ // Must be equal to 0, 1 or 2
658+ leading_biased_exp_bits = 2U * ((combination_field_bits & 0b00100 ) >> 2U ) + ((combination_field_bits & 0b00010 ) >> 1U );
659+ BOOST_DECIMAL_ASSERT (leading_biased_exp_bits <= 2U );
660+ }
661+ // Case 2: 3.5.2.c.1.ii
662+ // Combination field bits are 0XXXX or 10XXX
663+ else
664+ {
665+ // d0 = 4 * G2 + 2 * G3 + G4
666+ // Must be in the range 0-7
667+ d0 = combination_field_bits & 0b00111 ;
668+ BOOST_DECIMAL_ASSERT (d0 <= 7 );
669+
670+ // Leading exp bits are 2 * G0 + G1
671+ // Must be equal to 0, 1 or 2
672+ leading_biased_exp_bits = (combination_field_bits & 0b11000 ) >> 3U ;
673+ BOOST_DECIMAL_ASSERT (leading_biased_exp_bits <= 2U );
674+ }
675+
676+ // Now that we have the bits we can calculate the exponents value
677+ const auto complete_exp {(leading_biased_exp_bits << 8U ) + exponent_field_bits};
678+ const auto exp {static_cast <std::int32_t >(complete_exp) - detail::bias_v<DecimalType>};
679+
680+ // We can now decode the remainder of the significand to recover the value
681+ std::uint8_t digits[16 ] {};
682+ digits[0 ] = static_cast <std::uint8_t >(d0);
683+ for (int i = 15 ; i > 0 ; i -= 3 )
684+ {
685+ const auto declet_bits {static_cast <std::uint32_t >(significand_bits & 0b1111111111 )};
686+ significand_bits >>= 10U ;
687+ detail::decode_dpd (declet_bits, digits[i], digits[i - 1 ], digits[i - 2 ]);
688+ }
689+
690+ std::uint64_t significand {};
691+ for (std::uint64_t i {}; i < 16U ; ++i)
692+ {
693+ significand += digits[i] * detail::pow10 (15 - i);
694+ }
695+
696+ return DecimalType{significand, exp, sign};
697+ }
698+
699+ constexpr auto to_dpd (decimal32 val) noexcept -> std::uint32_t
700+ {
701+ return to_dpd_d32 (val);
702+ }
703+
704+ constexpr auto to_dpd (decimal32_fast val) noexcept -> std::uint32_t
705+ {
706+ return to_dpd_d32 (val);
707+ }
708+
709+ constexpr auto to_dpd (decimal64 val) -> std::uint64_t
710+ {
711+ return to_dpd_d64 (val);
712+ }
713+
714+ constexpr auto to_dpd (decimal64_fast val) -> std::uint64_t
715+ {
716+ return to_dpd_d64 (val);
717+ }
718+
719+ template <typename DecimalType>
720+ constexpr auto to_dpd (DecimalType val) noexcept
721+ {
722+ static_assert (detail::is_decimal_floating_point_v<DecimalType>, " Must be a decimal floating point type." );
723+ return to_dpd (val);
724+ }
725+
516726template <typename DecimalType = decimal32_fast>
517727constexpr auto from_dpd (std::uint32_t bits) noexcept
518728 BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, DecimalType)
519729{
520730 return from_dpd_d32<DecimalType>(bits);
521731}
522732
733+ template <typename DecimalType = decimal64_fast>
734+ constexpr auto from_dpd (std::uint64_t bits) noexcept
735+ BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, DecimalType)
736+ {
737+ return from_dpd_d64<DecimalType>(bits);
738+ }
523739
524740} // namespace decimal
525741} // namespace boost
0 commit comments