Skip to content

Commit 2b920bf

Browse files
authored
Merge pull request #1386 from boostorg/1383
Fix the `quantize()` function
2 parents 769c65d + fdcc688 commit 2b920bf

12 files changed

Lines changed: 308 additions & 231 deletions

include/boost/decimal/cmath.hpp

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ BOOST_DECIMAL_EXPORT constexpr auto samequantum(decimal64_t lhs, decimal64_t rhs
201201
return samequantumd64(lhs, rhs);
202202
}
203203

204+
BOOST_DECIMAL_EXPORT constexpr auto samequantum(decimal_fast64_t lhs, decimal_fast64_t rhs) noexcept -> bool
205+
{
206+
return samequantumd64f(lhs, rhs);
207+
}
208+
204209
BOOST_DECIMAL_EXPORT constexpr auto samequantum(decimal128_t lhs, decimal128_t rhs) noexcept -> bool
205210
{
206211
return samequantumd128(lhs, rhs);
@@ -241,31 +246,6 @@ BOOST_DECIMAL_EXPORT constexpr auto quantexp(decimal_fast128_t x) noexcept -> in
241246
return quantexpd128f(x);
242247
}
243248

244-
BOOST_DECIMAL_EXPORT constexpr auto quantize(decimal32_t lhs, decimal32_t rhs) noexcept -> decimal32_t
245-
{
246-
return quantized32(lhs, rhs);
247-
}
248-
249-
BOOST_DECIMAL_EXPORT constexpr auto quantize(decimal_fast32_t lhs, decimal_fast32_t rhs) noexcept -> decimal_fast32_t
250-
{
251-
return quantized32f(lhs, rhs);
252-
}
253-
254-
BOOST_DECIMAL_EXPORT constexpr auto quantize(decimal64_t lhs, decimal64_t rhs) noexcept -> decimal64_t
255-
{
256-
return quantized64(lhs, rhs);
257-
}
258-
259-
BOOST_DECIMAL_EXPORT constexpr auto quantize(decimal128_t lhs, decimal128_t rhs) noexcept -> decimal128_t
260-
{
261-
return quantized128(lhs, rhs);
262-
}
263-
264-
BOOST_DECIMAL_EXPORT constexpr auto quantize(decimal_fast128_t lhs, decimal_fast128_t rhs) noexcept -> decimal_fast128_t
265-
{
266-
return quantized128f(lhs, rhs);
267-
}
268-
269249
} // namespace decimal
270250
} // namespace boost
271251

include/boost/decimal/decimal128_t.hpp

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <boost/decimal/detail/to_decimal.hpp>
2727
#include <boost/decimal/detail/promotion.hpp>
2828
#include <boost/decimal/detail/check_non_finite.hpp>
29+
#include <boost/decimal/detail/quantize_impl.hpp>
2930
#include <boost/decimal/detail/shrink_significand.hpp>
3031
#include <boost/decimal/detail/cmath/isfinite.hpp>
3132
#include <boost/decimal/detail/cmath/fpclassify.hpp>
@@ -556,7 +557,8 @@ BOOST_DECIMAL_EXPORT class decimal128_t final
556557
friend BOOST_DECIMAL_CUDA_CONSTEXPR auto quantexpd128(decimal128_t x) noexcept -> int;
557558

558559
// 3.6.6 Quantize
559-
friend BOOST_DECIMAL_CUDA_CONSTEXPR auto quantized128(const decimal128_t& lhs, const decimal128_t& rhs) noexcept -> decimal128_t;
560+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
561+
friend BOOST_DECIMAL_CUDA_CONSTEXPR auto quantize(T lhs, T rhs) noexcept -> T;
560562

561563
// <cmath> functions that need to be friends
562564
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
@@ -2161,44 +2163,6 @@ BOOST_DECIMAL_CUDA_CONSTEXPR auto quantexpd128(const decimal128_t x) noexcept ->
21612163
return static_cast<int>(x.unbiased_exponent());
21622164
}
21632165

2164-
// 3.6.6
2165-
// Returns: a number that is equal in value (except for any rounding) and sign to x,
2166-
// and which has an exponent set to be equal to the exponent of y.
2167-
// If the exponent is being increased, the value is correctly rounded according to the current rounding mode;
2168-
// if the result does not have the same value as x, the "inexact" floating-point exception is raised.
2169-
// If the exponent is being decreased and the significand of the result has more digits than the type would allow,
2170-
// the "invalid" floating-point exception is raised and the result is NaN.
2171-
// If one or both operands are NaN the result is NaN.
2172-
// Otherwise, if only one operand is infinity, the "invalid" floating-point exception is raised and the result is NaN.
2173-
// If both operands are infinity, the result is DEC_INFINITY, with the same sign as x, converted to the type of x.
2174-
// The quantize functions do not signal underflow.
2175-
BOOST_DECIMAL_CUDA_CONSTEXPR auto quantized128(const decimal128_t& lhs, const decimal128_t& rhs) noexcept -> decimal128_t
2176-
{
2177-
#ifndef BOOST_DECIMAL_FAST_MATH
2178-
// Return the correct type of nan
2179-
if (isnan(lhs))
2180-
{
2181-
return lhs;
2182-
}
2183-
else if (isnan(rhs))
2184-
{
2185-
return rhs;
2186-
}
2187-
2188-
// If one is infinity then return a signaling NAN
2189-
if (isinf(lhs) != isinf(rhs))
2190-
{
2191-
return boost::decimal::from_bits(boost::decimal::detail::d128_snan_mask);
2192-
}
2193-
else if (isinf(lhs) && isinf(rhs))
2194-
{
2195-
return lhs;
2196-
}
2197-
#endif
2198-
2199-
return {lhs.full_significand(), rhs.biased_exponent(), lhs.isneg()};
2200-
}
2201-
22022166
BOOST_DECIMAL_CUDA_CONSTEXPR auto copysignd128(decimal128_t mag, const decimal128_t sgn) noexcept -> decimal128_t
22032167
{
22042168
mag.edit_sign(sgn.isneg());

include/boost/decimal/decimal32_t.hpp

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <boost/decimal/detail/to_decimal.hpp>
2727
#include <boost/decimal/detail/promotion.hpp>
2828
#include <boost/decimal/detail/check_non_finite.hpp>
29+
#include <boost/decimal/detail/quantize_impl.hpp>
2930
#include <boost/decimal/detail/shrink_significand.hpp>
3031
#include <boost/decimal/detail/cmath/isfinite.hpp>
3132
#include <boost/decimal/detail/cmath/fpclassify.hpp>
@@ -564,7 +565,8 @@ BOOST_DECIMAL_EXPORT class decimal32_t final // NOLINT(cppcoreguidelines-special
564565
friend constexpr auto quantexpd32(decimal32_t x) noexcept -> int;
565566

566567
// 3.6.6 Quantize
567-
friend constexpr auto quantized32(decimal32_t lhs, decimal32_t rhs) noexcept -> decimal32_t;
568+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
569+
friend BOOST_DECIMAL_CUDA_CONSTEXPR auto quantize(T lhs, T rhs) noexcept -> T;
568570

569571
// <cmath> functions that need to be friends
570572
friend constexpr auto copysignd32(decimal32_t mag, decimal32_t sgn) noexcept -> decimal32_t;
@@ -2259,44 +2261,6 @@ constexpr auto quantexpd32(const decimal32_t x) noexcept -> int
22592261
return static_cast<int>(x.unbiased_exponent());
22602262
}
22612263

2262-
// 3.6.6
2263-
// Returns: a number that is equal in value (except for any rounding) and sign to x,
2264-
// and which has an exponent set to be equal to the exponent of y.
2265-
// If the exponent is being increased, the value is correctly rounded according to the current rounding mode;
2266-
// if the result does not have the same value as x, the "inexact" floating-point exception is raised.
2267-
// If the exponent is being decreased and the significand of the result has more digits than the type would allow,
2268-
// the "invalid" floating-point exception is raised and the result is NaN.
2269-
// If one or both operands are NaN the result is NaN.
2270-
// Otherwise, if only one operand is infinity, the "invalid" floating-point exception is raised and the result is NaN.
2271-
// If both operands are infinity, the result is DEC_INFINITY, with the same sign as x, converted to the type of x.
2272-
// The quantize functions do not signal underflow.
2273-
constexpr auto quantized32(const decimal32_t lhs, const decimal32_t rhs) noexcept -> decimal32_t
2274-
{
2275-
#ifndef BOOST_DECIMAL_FAST_MATH
2276-
// Return the correct type of nan
2277-
if (isnan(lhs))
2278-
{
2279-
return lhs;
2280-
}
2281-
if (isnan(rhs))
2282-
{
2283-
return rhs;
2284-
}
2285-
2286-
// If one is infinity then return a signaling NAN
2287-
if (isinf(lhs) != isinf(rhs))
2288-
{
2289-
return from_bits(detail::d32_snan_mask);
2290-
}
2291-
if (isinf(lhs) && isinf(rhs))
2292-
{
2293-
return lhs;
2294-
}
2295-
#endif
2296-
2297-
return {lhs.full_significand(), rhs.biased_exponent(), lhs.isneg()};
2298-
}
2299-
23002264
constexpr auto scalblnd32(decimal32_t num, const long exp) noexcept -> decimal32_t
23012265
{
23022266
#ifndef BOOST_DECIMAL_FAST_MATH

include/boost/decimal/decimal64_t.hpp

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <boost/decimal/detail/comparison.hpp>
2929
#include <boost/decimal/detail/mixed_decimal_arithmetic.hpp>
3030
#include <boost/decimal/detail/check_non_finite.hpp>
31+
#include <boost/decimal/detail/quantize_impl.hpp>
3132
#include <boost/decimal/detail/shrink_significand.hpp>
3233
#include <boost/decimal/detail/cmath/isfinite.hpp>
3334
#include <boost/decimal/detail/cmath/fpclassify.hpp>
@@ -575,7 +576,8 @@ BOOST_DECIMAL_EXPORT class decimal64_t final
575576
friend BOOST_DECIMAL_CUDA_CONSTEXPR auto quantexpd64(decimal64_t x) noexcept -> int;
576577

577578
// 3.6.6 Quantize
578-
friend BOOST_DECIMAL_CUDA_CONSTEXPR auto quantized64(decimal64_t lhs, decimal64_t rhs) noexcept -> decimal64_t;
579+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
580+
friend BOOST_DECIMAL_CUDA_CONSTEXPR auto quantize(T lhs, T rhs) noexcept -> T;
579581

580582
// <cmath> functions that need to be friends
581583
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
@@ -2167,44 +2169,6 @@ BOOST_DECIMAL_CUDA_CONSTEXPR auto quantexpd64(const decimal64_t x) noexcept -> i
21672169
return static_cast<int>(x.unbiased_exponent());
21682170
}
21692171

2170-
// 3.6.6
2171-
// Returns: a number that is equal in value (except for any rounding) and sign to x,
2172-
// and which has an exponent set to be equal to the exponent of y.
2173-
// If the exponent is being increased, the value is correctly rounded according to the current rounding mode;
2174-
// if the result does not have the same value as x, the "inexact" floating-point exception is raised.
2175-
// If the exponent is being decreased and the significand of the result has more digits than the type would allow,
2176-
// the "invalid" floating-point exception is raised and the result is NaN.
2177-
// If one or both operands are NaN the result is NaN.
2178-
// Otherwise, if only one operand is infinity, the "invalid" floating-point exception is raised and the result is NaN.
2179-
// If both operands are infinity, the result is DEC_INFINITY, with the same sign as x, converted to the type of x.
2180-
// The quantize functions do not signal underflow.
2181-
BOOST_DECIMAL_CUDA_CONSTEXPR auto quantized64(const decimal64_t lhs, const decimal64_t rhs) noexcept -> decimal64_t
2182-
{
2183-
#ifndef BOOST_DECIMAL_FAST_MATH
2184-
// Return the correct type of nan
2185-
if (isnan(lhs))
2186-
{
2187-
return lhs;
2188-
}
2189-
if (isnan(rhs))
2190-
{
2191-
return rhs;
2192-
}
2193-
2194-
// If one is infinity then return a signaling NAN
2195-
if (isinf(lhs) != isinf(rhs))
2196-
{
2197-
return boost::decimal::from_bits(boost::decimal::detail::d64_snan_mask);
2198-
}
2199-
if (isinf(lhs) && isinf(rhs))
2200-
{
2201-
return lhs;
2202-
}
2203-
#endif
2204-
2205-
return {lhs.full_significand(), rhs.biased_exponent(), lhs.isneg()};
2206-
}
2207-
22082172
BOOST_DECIMAL_CUDA_CONSTEXPR auto scalblnd64(decimal64_t num, const long exp) noexcept -> decimal64_t
22092173
{
22102174
#ifndef BOOST_DECIMAL_FAST_MATH

include/boost/decimal/decimal_fast128_t.hpp

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <boost/decimal/detail/to_decimal.hpp>
2727
#include <boost/decimal/detail/promotion.hpp>
2828
#include <boost/decimal/detail/check_non_finite.hpp>
29+
#include <boost/decimal/detail/quantize_impl.hpp>
2930
#include <boost/decimal/detail/shrink_significand.hpp>
3031
#include <boost/decimal/detail/cmath/isfinite.hpp>
3132
#include <boost/decimal/detail/cmath/fpclassify.hpp>
@@ -499,7 +500,8 @@ BOOST_DECIMAL_EXPORT class alignas(16) decimal_fast128_t final
499500
friend constexpr auto quantexpd128f(const decimal_fast128_t& x) noexcept -> int;
500501

501502
// 3.6.6 Quantize
502-
friend constexpr auto quantized128f(const decimal_fast128_t& lhs, const decimal_fast128_t& rhs) noexcept -> decimal_fast128_t;
503+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
504+
friend BOOST_DECIMAL_CUDA_CONSTEXPR auto quantize(T lhs, T rhs) noexcept -> T;
503505
};
504506

505507
#ifdef _MSC_VER
@@ -1696,44 +1698,6 @@ constexpr auto quantexpd128f(const decimal_fast128_t& x) noexcept -> int
16961698
return static_cast<int>(x.unbiased_exponent());
16971699
}
16981700

1699-
// 3.6.6
1700-
// Returns: a number that is equal in value (except for any rounding) and sign to x,
1701-
// and which has an exponent set to be equal to the exponent of y.
1702-
// If the exponent is being increased, the value is correctly rounded according to the current rounding mode;
1703-
// if the result does not have the same value as x, the "inexact" floating-point exception is raised.
1704-
// If the exponent is being decreased and the significand of the result has more digits than the type would allow,
1705-
// the "invalid" floating-point exception is raised and the result is NaN.
1706-
// If one or both operands are NaN the result is NaN.
1707-
// Otherwise, if only one operand is infinity, the "invalid" floating-point exception is raised and the result is NaN.
1708-
// If both operands are infinity, the result is DEC_INFINITY, with the same sign as x, converted to the type of x.
1709-
// The quantize functions do not signal underflow.
1710-
constexpr auto quantized128f(const decimal_fast128_t& lhs, const decimal_fast128_t& rhs) noexcept -> decimal_fast128_t
1711-
{
1712-
#ifndef BOOST_DECIMAL_FAST_MATH
1713-
// Return the correct type of nan
1714-
if (isnan(lhs))
1715-
{
1716-
return lhs;
1717-
}
1718-
else if (isnan(rhs))
1719-
{
1720-
return rhs;
1721-
}
1722-
1723-
// If one is infinity then return a signaling NAN
1724-
if (isinf(lhs) != isinf(rhs))
1725-
{
1726-
return boost::decimal::direct_init_d128(boost::decimal::detail::d128_fast_qnan, 0, false);
1727-
}
1728-
else if (isinf(lhs) && isinf(rhs))
1729-
{
1730-
return lhs;
1731-
}
1732-
#endif
1733-
1734-
return {lhs.full_significand(), rhs.biased_exponent(), lhs.isneg()};
1735-
}
1736-
17371701
#if !defined(BOOST_DECIMAL_DISABLE_CLIB)
17381702

17391703
constexpr decimal_fast128_t::decimal_fast128_t(const char* str, const std::size_t len)

include/boost/decimal/decimal_fast32_t.hpp

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <boost/decimal/detail/to_decimal.hpp>
2727
#include <boost/decimal/detail/promotion.hpp>
2828
#include <boost/decimal/detail/check_non_finite.hpp>
29+
#include <boost/decimal/detail/quantize_impl.hpp>
2930
#include <boost/decimal/detail/shrink_significand.hpp>
3031
#include <boost/decimal/detail/cmath/isfinite.hpp>
3132
#include <boost/decimal/detail/cmath/fpclassify.hpp>
@@ -497,7 +498,8 @@ BOOST_DECIMAL_EXPORT class alignas(4) decimal_fast32_t final
497498
// Specific decimal functionality
498499
friend constexpr auto samequantumd32f(decimal_fast32_t lhs, decimal_fast32_t rhs) noexcept -> bool;
499500
friend constexpr auto quantexpd32f(decimal_fast32_t x) noexcept -> int;
500-
friend constexpr auto quantized32f(decimal_fast32_t lhs, decimal_fast32_t rhs) noexcept -> decimal_fast32_t;
501+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
502+
friend BOOST_DECIMAL_CUDA_CONSTEXPR auto quantize(T lhs, T rhs) noexcept -> T;
501503
};
502504

503505
#ifdef _MSC_VER
@@ -1684,43 +1686,6 @@ constexpr auto quantexpd32f(const decimal_fast32_t x) noexcept -> int
16841686
return static_cast<int>(x.unbiased_exponent());
16851687
}
16861688

1687-
// Returns: a number that is equal in value (except for any rounding) and sign to x,
1688-
// and which has an exponent set to be equal to the exponent of y.
1689-
// If the exponent is being increased, the value is correctly rounded according to the current rounding mode;
1690-
// if the result does not have the same value, as x, the "inexact" floating-point exception is raised.
1691-
// If the exponent is being decreased and the significand of the result has more digits than the type would allow,
1692-
// the "invalid" floating-point exception is raised and the result is NaN.
1693-
// If one or both operands are NaN, the result is NaN.
1694-
// Otherwise, if only one operand is infinity, the "invalid" floating-point exception is raised and the result is NaN.
1695-
// If both operands are infinity, the result is DEC_INFINITY, with the same sign as x, converted to the type of x.
1696-
// The quantize functions do not signal underflow.
1697-
constexpr auto quantized32f(const decimal_fast32_t lhs, const decimal_fast32_t rhs) noexcept -> decimal_fast32_t
1698-
{
1699-
#ifndef BOOST_DECIMAL_FAST_MATH
1700-
// Return the correct type of nan
1701-
if (isnan(lhs))
1702-
{
1703-
return lhs;
1704-
}
1705-
else if (isnan(rhs))
1706-
{
1707-
return rhs;
1708-
}
1709-
1710-
// If one is infinity then return a signaling NAN
1711-
if (isinf(lhs) != isinf(rhs))
1712-
{
1713-
return direct_init(detail::d32_fast_snan, UINT8_C(0));
1714-
}
1715-
else if (isinf(lhs) && isinf(rhs))
1716-
{
1717-
return lhs;
1718-
}
1719-
#endif
1720-
1721-
return {lhs.full_significand(), rhs.biased_exponent(), lhs.isneg()};
1722-
}
1723-
17241689
#if !defined(BOOST_DECIMAL_DISABLE_CLIB)
17251690

17261691
constexpr decimal_fast32_t::decimal_fast32_t(const char* str, const std::size_t len)

0 commit comments

Comments
 (0)