Skip to content

Commit 61fb6cb

Browse files
committed
Fix sign on non-finite DPD conversions
1 parent 4229a7d commit 61fb6cb

File tree

1 file changed

+24
-12
lines changed

1 file changed

+24
-12
lines changed

include/boost/decimal/dpd_conversion.hpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -435,21 +435,26 @@ constexpr auto from_dpd_d32(const std::uint32_t dpd) noexcept
435435
static_assert(std::is_same<DecimalType, decimal32_t>::value || std::is_same<DecimalType, decimal_fast32_t>::value,
436436
"Target decimal type must be 32-bits");
437437

438+
const auto sign {(dpd & detail::d32_sign_mask) != 0};
439+
438440
// First we check for non-finite values
439441
// Since they are in the same initial format as BID it's easy to check with our existing masks
440442
if ((dpd & detail::d32_inf_mask) == detail::d32_inf_mask)
441443
{
442444
if ((dpd & detail::d32_snan_mask) == detail::d32_snan_mask)
443445
{
444-
return std::numeric_limits<DecimalType>::signaling_NaN();
446+
return sign ? -std::numeric_limits<DecimalType>::signaling_NaN() :
447+
std::numeric_limits<DecimalType>::signaling_NaN();
445448
}
446449
else if ((dpd & detail::d32_nan_mask) == detail::d32_nan_mask)
447450
{
448-
return std::numeric_limits<DecimalType>::quiet_NaN();
451+
return sign ? -std::numeric_limits<DecimalType>::quiet_NaN() :
452+
std::numeric_limits<DecimalType>::quiet_NaN();
449453
}
450454
else
451455
{
452-
return std::numeric_limits<DecimalType>::infinity();
456+
return sign ? -std::numeric_limits<DecimalType>::infinity() :
457+
std::numeric_limits<DecimalType>::infinity();
453458
}
454459
}
455460

@@ -458,7 +463,6 @@ constexpr auto from_dpd_d32(const std::uint32_t dpd) noexcept
458463
constexpr std::uint32_t dpd_d32_combination_mask {UINT32_C(0b0'11111'000000'0000000000'0000000000)};
459464

460465
// The bit lengths are the same as used in the standard bid format
461-
const auto sign {(dpd & detail::d32_sign_mask) != 0};
462466
const auto combination_field_bits {(dpd & dpd_d32_combination_mask) >> 26U};
463467
const auto exponent_field_bits {(dpd & dpd_d32_exponent_mask) >> 20U};
464468
const auto significand_bits {(dpd & dpd_d32_significand_mask)};
@@ -635,21 +639,26 @@ constexpr auto from_dpd_d64(const std::uint64_t dpd) noexcept
635639
static_assert(std::is_same<DecimalType, decimal64_t>::value || std::is_same<DecimalType, decimal_fast64_t>::value,
636640
"Target decimal type must be 64-bits");
637641

642+
const auto sign {(dpd & detail::d64_sign_mask) != 0};
643+
638644
// First we check for non-finite values
639645
// Since they are in the same initial format as BID it's easy to check with our existing masks
640646
if ((dpd & detail::d64_inf_mask) == detail::d64_inf_mask)
641647
{
642648
if ((dpd & detail::d64_snan_mask) == detail::d64_snan_mask)
643649
{
644-
return std::numeric_limits<DecimalType>::signaling_NaN();
650+
return sign ? -std::numeric_limits<DecimalType>::signaling_NaN() :
651+
std::numeric_limits<DecimalType>::signaling_NaN();
645652
}
646653
else if ((dpd & detail::d64_nan_mask) == detail::d64_nan_mask)
647654
{
648-
return std::numeric_limits<DecimalType>::quiet_NaN();
655+
return sign ? -std::numeric_limits<DecimalType>::quiet_NaN() :
656+
std::numeric_limits<DecimalType>::quiet_NaN();
649657
}
650658
else
651659
{
652-
return std::numeric_limits<DecimalType>::infinity();
660+
return sign ? -std::numeric_limits<DecimalType>::infinity() :
661+
std::numeric_limits<DecimalType>::infinity();
653662
}
654663
}
655664

@@ -659,7 +668,6 @@ constexpr auto from_dpd_d64(const std::uint64_t dpd) noexcept
659668
constexpr std::uint64_t dpd_d64_exponent_field_mask {UINT64_C(0b0'00000'11111111'0000000000'0000000000'0000000000'0000000000'0000000000)};
660669
constexpr std::uint64_t dpd_d64_significand_field_mask {UINT64_C(0b0'00000'00000000'1111111111'1111111111'1111111111'1111111111'1111111111)};
661670

662-
const auto sign {(dpd & detail::d64_sign_mask) != 0};
663671
const auto combination_field_bits {(dpd & dpd_d64_combination_field_mask) >> 58U};
664672
const auto exponent_field_bits {(dpd & dpd_d64_exponent_field_mask) >> 50U};
665673
auto significand_bits {(dpd & dpd_d64_significand_field_mask)};
@@ -841,19 +849,24 @@ constexpr auto from_dpd_d128(const int128::uint128_t dpd) noexcept
841849
static_assert(std::is_same<DecimalType, decimal128_t>::value || std::is_same<DecimalType, decimal_fast128_t>::value,
842850
"Target decimal type must be 128-bits");
843851

852+
const auto sign {(dpd.high & detail::d128_sign_mask) != 0};
853+
844854
if ((dpd & detail::d128_inf_mask) == detail::d128_inf_mask)
845855
{
846856
if ((dpd & detail::d128_snan_mask) == detail::d128_snan_mask)
847857
{
848-
return std::numeric_limits<DecimalType>::signaling_NaN();
858+
return sign ? -std::numeric_limits<DecimalType>::signaling_NaN() :
859+
std::numeric_limits<DecimalType>::signaling_NaN();
849860
}
850861
else if ((dpd & detail::d128_nan_mask) == detail::d128_nan_mask)
851862
{
852-
return std::numeric_limits<DecimalType>::quiet_NaN();
863+
return sign ? -std::numeric_limits<DecimalType>::quiet_NaN() :
864+
std::numeric_limits<DecimalType>::quiet_NaN();
853865
}
854866
else
855867
{
856-
return std::numeric_limits<DecimalType>::infinity();
868+
return sign ? -std::numeric_limits<DecimalType>::infinity() :
869+
std::numeric_limits<DecimalType>::infinity();
857870
}
858871
}
859872

@@ -862,7 +875,6 @@ constexpr auto from_dpd_d128(const int128::uint128_t dpd) noexcept
862875
constexpr int128::uint128_t d128_dpd_significand_mask {UINT64_C(0b1111111111'1111111111'1111111111'1111111111'111111), UINT64_MAX};
863876

864877
// The bit lengths are the same as used in the standard bid format
865-
const auto sign {(dpd.high & detail::d128_sign_mask) != 0};
866878
const auto combination_field_bits {(dpd.high & d128_dpd_combination_field_mask_high_bits) >> 58U};
867879
const auto exponent_field_bits {(dpd.high & d128_dpd_exponent_mask_high_bits) >> 46U};
868880
auto significand_bits {(dpd & d128_dpd_significand_mask)};

0 commit comments

Comments
 (0)