Skip to content

Commit 7cfb824

Browse files
authored
Merge pull request #1136 from cppalliance/1107
Fixes for proper handling of IEEE Section 7.2
2 parents ca6ef19 + 7a30129 commit 7cfb824

14 files changed

+652
-300
lines changed

include/boost/decimal/decimal128_t.hpp

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,8 +1429,8 @@ constexpr auto d128_div_impl(const decimal128_t& lhs, const decimal128_t& rhs, d
14291429
#ifndef BOOST_DECIMAL_FAST_MATH
14301430
// Check pre-conditions
14311431
constexpr decimal128_t zero {0, 0};
1432-
constexpr decimal128_t nan {boost::decimal::from_bits(boost::decimal::detail::d128_snan_mask)};
1433-
constexpr decimal128_t inf {boost::decimal::from_bits(boost::decimal::detail::d128_inf_mask)};
1432+
constexpr decimal128_t nan {from_bits(detail::d128_nan_mask)};
1433+
constexpr decimal128_t inf {from_bits(detail::d128_inf_mask)};
14341434

14351435
const bool sign {lhs.isneg() != rhs.isneg()};
14361436

@@ -1447,12 +1447,28 @@ constexpr auto d128_div_impl(const decimal128_t& lhs, const decimal128_t& rhs, d
14471447
switch (lhs_fp)
14481448
{
14491449
case FP_INFINITE:
1450-
q = sign ? -inf : inf;
1451-
r = zero;
1450+
if (rhs_fp == FP_INFINITE)
1451+
{
1452+
q = nan;
1453+
r = nan;
1454+
}
1455+
else
1456+
{
1457+
q = sign ? -inf : inf;
1458+
r = zero;
1459+
}
14521460
return;
14531461
case FP_ZERO:
1454-
q = sign ? -zero : zero;
1455-
r = sign ? -zero : zero;
1462+
if (rhs_fp == FP_ZERO)
1463+
{
1464+
q = nan;
1465+
r = nan;
1466+
}
1467+
else
1468+
{
1469+
q = sign ? -zero : zero;
1470+
r = sign ? -zero : zero;
1471+
}
14561472
return;
14571473
default:
14581474
static_cast<void>(lhs);
@@ -1509,6 +1525,11 @@ constexpr auto operator+(const decimal128_t& lhs, const decimal128_t& rhs) noexc
15091525
#ifndef BOOST_DECIMAL_FAST_MATH
15101526
if (not_finite(lhs) || not_finite(rhs))
15111527
{
1528+
if (isinf(lhs) && isinf(rhs) && signbit(lhs) != signbit(rhs))
1529+
{
1530+
return from_bits(detail::d128_nan_mask);
1531+
}
1532+
15121533
return detail::check_non_finite(lhs, rhs);
15131534
}
15141535
#endif
@@ -1567,6 +1588,11 @@ constexpr auto operator-(const decimal128_t& lhs, const decimal128_t& rhs) noexc
15671588
#ifndef BOOST_DECIMAL_FAST_MATH
15681589
if (not_finite(lhs) || not_finite(rhs))
15691590
{
1591+
if (isinf(lhs) && isinf(rhs) && signbit(lhs) == signbit(rhs))
1592+
{
1593+
return from_bits(detail::d128_nan_mask);
1594+
}
1595+
15701596
return detail::check_non_finite(lhs, rhs);
15711597
}
15721598
#endif
@@ -1648,19 +1674,21 @@ constexpr auto operator*(const decimal128_t& lhs, const decimal128_t& rhs) noexc
16481674
#ifndef BOOST_DECIMAL_FAST_MATH
16491675
if (not_finite(lhs) || not_finite(rhs))
16501676
{
1677+
if ((isinf(lhs) && rhs == 0) || (isinf(rhs) && lhs == 0))
1678+
{
1679+
return from_bits(detail::d128_nan_mask);
1680+
}
1681+
16511682
return detail::check_non_finite(lhs, rhs);
16521683
}
16531684
#endif
16541685

1655-
const auto lhs_sig {lhs.full_significand()};
1656-
const auto lhs_exp {lhs.biased_exponent()};
1657-
1658-
const auto rhs_sig {rhs.full_significand()};
1659-
const auto rhs_exp {rhs.biased_exponent()};
1686+
const auto lhs_components {lhs.to_components()};
1687+
const auto rhs_components {rhs.to_components()};
16601688

16611689
return detail::d128_mul_impl<decimal128_t>(
1662-
lhs_sig, lhs_exp, lhs.isneg(),
1663-
rhs_sig, rhs_exp, rhs.isneg());
1690+
lhs_components.sig, lhs_components.exp, lhs_components.sign,
1691+
rhs_components.sig, rhs_components.exp, rhs_components.sign);
16641692
}
16651693

16661694
template <typename Integer>

include/boost/decimal/decimal32_t.hpp

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,12 @@ constexpr auto operator+(const decimal32_t lhs, const decimal32_t rhs) noexcept
875875
#ifndef BOOST_DECIMAL_FAST_MATH
876876
if (!isfinite(lhs) || !isfinite(rhs))
877877
{
878+
// Case from 7.2.d
879+
if (isinf(lhs) && isinf(rhs) && signbit(lhs) != signbit(rhs))
880+
{
881+
return from_bits(detail::d32_nan_mask);
882+
}
883+
878884
return detail::check_non_finite(lhs, rhs);
879885
}
880886
#endif
@@ -968,6 +974,12 @@ constexpr auto operator-(const decimal32_t lhs, const decimal32_t rhs) noexcept
968974
#ifndef BOOST_DECIMAL_FAST_MATH
969975
if (!isfinite(lhs) || !isfinite(rhs))
970976
{
977+
// Case from 7.2.d
978+
if (isinf(lhs) && isinf(rhs) && signbit(lhs) == signbit(rhs))
979+
{
980+
return from_bits(detail::d32_nan_mask);
981+
}
982+
971983
return detail::check_non_finite(lhs, rhs);
972984
}
973985
#endif
@@ -1645,6 +1657,11 @@ constexpr auto operator*(const decimal32_t lhs, const decimal32_t rhs) noexcept
16451657
#ifndef BOOST_DECIMAL_FAST_MATH
16461658
if (!isfinite(lhs) || !isfinite(rhs))
16471659
{
1660+
if ((isinf(lhs) && rhs == 0) || (isinf(rhs) && lhs == 0))
1661+
{
1662+
return from_bits(detail::d32_nan_mask);
1663+
}
1664+
16481665
return detail::check_non_finite(lhs, rhs);
16491666
}
16501667
#endif
@@ -1716,8 +1733,8 @@ constexpr auto div_impl(const decimal32_t lhs, const decimal32_t rhs, decimal32_
17161733
#ifndef BOOST_DECIMAL_FAST_MATH
17171734
// Check pre-conditions
17181735
constexpr decimal32_t zero {0, 0};
1719-
constexpr decimal32_t nan {boost::decimal::from_bits(boost::decimal::detail::d32_snan_mask)};
1720-
constexpr decimal32_t inf {boost::decimal::from_bits(boost::decimal::detail::d32_inf_mask)};
1736+
constexpr decimal32_t nan {from_bits(detail::d32_nan_mask)};
1737+
constexpr decimal32_t inf {from_bits(detail::d32_inf_mask)};
17211738

17221739
const bool sign {lhs.isneg() != rhs.isneg()};
17231740

@@ -1734,12 +1751,28 @@ constexpr auto div_impl(const decimal32_t lhs, const decimal32_t rhs, decimal32_
17341751
switch (lhs_fp)
17351752
{
17361753
case FP_INFINITE:
1737-
q = sign ? -inf : inf;
1738-
r = zero;
1754+
if (rhs_fp == FP_INFINITE)
1755+
{
1756+
q = nan;
1757+
r = nan;
1758+
}
1759+
else
1760+
{
1761+
q = sign ? -inf : inf;
1762+
r = zero;
1763+
}
17391764
return;
17401765
case FP_ZERO:
1741-
q = sign ? -zero : zero;
1742-
r = sign ? -zero : zero;
1766+
if (rhs_fp == FP_ZERO)
1767+
{
1768+
q = nan;
1769+
r = nan;
1770+
}
1771+
else
1772+
{
1773+
q = sign ? -zero : zero;
1774+
r = sign ? -zero : zero;
1775+
}
17431776
return;
17441777
default:
17451778
static_cast<void>(lhs);

0 commit comments

Comments
 (0)