Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion doc/modules/ROOT/pages/cmath.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,18 @@ constexpr decimal32_t nand32(const char* arg) noexcept;
constexpr decimal64_t nand64(const char* arg) noexcept;
constexpr decimal128_t nand128(const char* arg) noexcept;

constexpr decimal_fast32_t nand32f(const char* arg) noexcept;
constexpr decimal_fast64_t nand64f(const char* arg) noexcept;
constexpr decimal_fast128_t nand128f(const char* arg) noexcept;

constexpr decimal32_t snand32(const char* arg) noexcept;
constexpr decimal64_t snand64(const char* arg) noexcept;
constexpr decimal128_t snand128(const char* arg) noexcept;

constexpr decimal_fast32_t snand32f(const char* arg) noexcept;
constexpr decimal_fast64_t snand64f(const char* arg) noexcept;
constexpr decimal_fast128_t snand128f(const char* arg) noexcept;

} // namespace decimal
} // namespace boost
----
Expand Down Expand Up @@ -542,7 +550,7 @@ Effects: If x is an sNaN returns true, otherwise returns false.
----
template <typename Decimal>
constexpr auto read_payload(Decimal x) noexcept
-> std::enable_if_t<is_ieee_type_v<Decimal>, typename T::significand_type>;
-> typename T::significand_type;
----

Effects: if x is either a qNaN or an sNaN, returns the payload of the NaN, otherwise returns 0.
Expand Down
26 changes: 19 additions & 7 deletions include/boost/decimal/decimal_fast128_t.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ namespace decimal {

namespace detail {

BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_inf = boost::int128::uint128_t {UINT64_MAX - 2, UINT64_MAX};
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_qnan = boost::int128::uint128_t {UINT64_MAX - 1, UINT64_MAX};
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_snan = boost::int128::uint128_t {UINT64_MAX, UINT64_MAX};
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_inf_high_bits {UINT64_C(0b1) << 61U};
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_qnan_high_bits {UINT64_C(0b11) << 61U};
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_snan_high_bits {UINT64_C(0b111) << 61U};

BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_inf_high_bits = UINT64_MAX - 2;
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_qnan_high_bits = UINT64_MAX - 1;
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_snan_high_bits = UINT64_MAX;
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_inf = boost::int128::uint128_t {d128_fast_inf_high_bits, 0U};
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_qnan = boost::int128::uint128_t {d128_fast_qnan_high_bits, 0U};
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d128_fast_snan = boost::int128::uint128_t {d128_fast_snan_high_bits, 0U};

template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE TargetDecimalType>
constexpr auto to_chars_scientific_impl(char* first, char* last, const TargetDecimalType& value, chars_format fmt) noexcept -> to_chars_result;
Expand All @@ -73,6 +73,10 @@ constexpr auto to_chars_hex_impl(char* first, char* last, const TargetDecimalTyp
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE TargetDecimalType>
constexpr auto to_chars_cohort_preserving_scientific(char* first, char* last, const TargetDecimalType& value) noexcept -> to_chars_result;

template <typename TargetDecimalType, bool is_snan>
constexpr auto nan_impl(const char* arg) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_fast_type_v, TargetDecimalType);

} // namespace detail

#ifdef _MSC_VER
Expand Down Expand Up @@ -191,6 +195,14 @@ BOOST_DECIMAL_EXPORT class decimal_fast128_t final
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE TargetDecimalType>
friend constexpr auto detail::to_chars_cohort_preserving_scientific(char* first, char* last, const TargetDecimalType& value) noexcept -> to_chars_result;

template <typename TargetDecimalType, bool is_snan>
friend constexpr auto detail::nan_impl(const char* arg) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_fast_type_v, TargetDecimalType);

template <typename T>
friend constexpr auto read_payload(T value) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_fast_type_v, T, typename T::significand_type);

#if !defined(BOOST_DECIMAL_DISABLE_CLIB)
constexpr decimal_fast128_t(const char* str, std::size_t len);
#endif
Expand Down Expand Up @@ -645,7 +657,7 @@ constexpr auto isnan(const decimal_fast128_t& val) noexcept -> bool
constexpr auto issignaling(const decimal_fast128_t& val) noexcept -> bool
{
#ifndef BOOST_DECIMAL_FAST_MATH
return val.significand_.high == detail::d128_fast_snan_high_bits;
return val.significand_.high >= detail::d128_fast_snan_high_bits;
#else
static_cast<void>(val);
return false;
Expand Down
20 changes: 16 additions & 4 deletions include/boost/decimal/decimal_fast32_t.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ namespace decimal {

namespace detail {

BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d32_fast_inf = std::numeric_limits<std::uint32_t>::max() - 3;
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d32_fast_qnan = std::numeric_limits<std::uint32_t>::max() - 2;
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d32_fast_snan = std::numeric_limits<std::uint32_t>::max() - 1;
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d32_fast_inf {UINT32_C(0b1) << 29U};
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d32_fast_qnan {UINT32_C(0b11) << 29U};
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d32_fast_snan {UINT32_C(0b111) << 29U};

template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE TargetDecimalType>
constexpr auto to_chars_scientific_impl(char* first, char* last, const TargetDecimalType& value, chars_format fmt) noexcept -> to_chars_result;
Expand All @@ -71,6 +71,10 @@ constexpr auto to_chars_cohort_preserving_scientific(char* first, char* last, co
template <bool checked, BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
constexpr auto d32_fma_impl(T x, T y, T z) noexcept -> T;

template <typename TargetDecimalType, bool is_snan>
constexpr auto nan_impl(const char* arg) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_fast_type_v, TargetDecimalType);

} // namespace detail

BOOST_DECIMAL_EXPORT class decimal_fast32_t final
Expand Down Expand Up @@ -191,6 +195,14 @@ BOOST_DECIMAL_EXPORT class decimal_fast32_t final
template <typename DecimalType, typename T>
friend constexpr auto detail::generic_div_impl(const T& lhs, const T& rhs) noexcept -> DecimalType;

template <typename TargetDecimalType, bool is_snan>
friend constexpr auto detail::nan_impl(const char* arg) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_fast_type_v, TargetDecimalType);

template <typename T>
friend constexpr auto read_payload(T value) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_fast_type_v, T, typename T::significand_type);

#if !defined(BOOST_DECIMAL_DISABLE_CLIB)
constexpr decimal_fast32_t(const char* str, std::size_t len);
#endif
Expand Down Expand Up @@ -631,7 +643,7 @@ constexpr auto isnan(const decimal_fast32_t val) noexcept -> bool
constexpr auto issignaling(const decimal_fast32_t val) noexcept -> bool
{
#ifndef BOOST_DECIMAL_FAST_MATH
return val.significand_ == detail::d32_fast_snan;
return val.significand_ >= detail::d32_fast_snan;
#else
static_cast<void>(val);
return false;
Expand Down
20 changes: 16 additions & 4 deletions include/boost/decimal/decimal_fast64_t.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ namespace decimal {

namespace detail {

BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d64_fast_inf = std::numeric_limits<std::uint64_t>::max() - 3;
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d64_fast_qnan = std::numeric_limits<std::uint64_t>::max() - 2;
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d64_fast_snan = std::numeric_limits<std::uint64_t>::max() - 1;
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d64_fast_inf {UINT64_C(0b1) << 61U};
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d64_fast_qnan {UINT64_C(0b11) << 61U};
BOOST_DECIMAL_INLINE_CONSTEXPR_VARIABLE auto d64_fast_snan {UINT64_C(0b111) << 61U};

template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE TargetDecimalType>
constexpr auto to_chars_scientific_impl(char* first, char* last, const TargetDecimalType& value, chars_format fmt) noexcept -> to_chars_result;
Expand All @@ -73,6 +73,10 @@ constexpr auto to_chars_cohort_preserving_scientific(char* first, char* last, co
template <bool checked, BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
constexpr auto d64_fma_impl(T x, T y, T z) noexcept -> T;

template <typename TargetDecimalType, bool is_snan>
constexpr auto nan_impl(const char* arg) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_fast_type_v, TargetDecimalType);

} // namespace detail

BOOST_DECIMAL_EXPORT class decimal_fast64_t final
Expand Down Expand Up @@ -198,6 +202,14 @@ BOOST_DECIMAL_EXPORT class decimal_fast64_t final
template <bool checked, BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
friend constexpr auto detail::d64_fma_impl(T x, T y, T z) noexcept -> T;

template <typename TargetDecimalType, bool is_snan>
friend constexpr auto detail::nan_impl(const char* arg) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_fast_type_v, TargetDecimalType);

template <typename T>
friend constexpr auto read_payload(T value) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_fast_type_v, T, typename T::significand_type);

#if !defined(BOOST_DECIMAL_DISABLE_CLIB)
constexpr decimal_fast64_t(const char* str, std::size_t len);
#endif
Expand Down Expand Up @@ -638,7 +650,7 @@ constexpr auto isnan(const decimal_fast64_t val) noexcept -> bool
constexpr auto issignaling(const decimal_fast64_t val) noexcept -> bool
{
#ifndef BOOST_DECIMAL_FAST_MATH
return val.significand_ == detail::d64_fast_snan;
return val.significand_ >= detail::d64_fast_snan;
#else
static_cast<void>(val);
return false;
Expand Down
135 changes: 130 additions & 5 deletions include/boost/decimal/detail/cmath/nan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <boost/decimal/detail/type_traits.hpp>
#include <boost/decimal/detail/concepts.hpp>
#include <boost/decimal/detail/utilities.hpp>
#include <boost/decimal/detail/promotion.hpp>
#include <boost/decimal/cstdlib.hpp>

#ifndef BOOST_DECIMAL_BUILD_MODULE
Expand All @@ -23,8 +24,38 @@ namespace decimal {

namespace detail {

template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE TargetDecimalType, bool is_snan>
constexpr auto nan_impl(const char* arg) noexcept -> TargetDecimalType
template <typename TargetDecimalType, bool is_snan>
constexpr auto nan_impl(const char* arg) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_fast_type_v, TargetDecimalType)
{
using sig_type = typename TargetDecimalType::significand_type;

constexpr TargetDecimalType nan_type {is_snan ? std::numeric_limits<TargetDecimalType>::signaling_NaN() :
std::numeric_limits<TargetDecimalType>::quiet_NaN()};

constexpr std::uint32_t significand_field_bits {decimal_val_v<TargetDecimalType> < 64 ? 23U :
decimal_val_v<TargetDecimalType> < 128 ? 53U : 110U};

constexpr sig_type max_payload_value {(static_cast<sig_type>(1) << significand_field_bits) - 1U};

sig_type payload_value {};
const auto r {from_chars_integer_impl<sig_type, sig_type>(arg, arg + detail::strlen(arg), payload_value, 10)};

TargetDecimalType return_value {nan_type};
if (!r || payload_value > max_payload_value)
{
return return_value;
}
else
{
return_value.significand_ |= payload_value;
return return_value;
}
}

template <typename TargetDecimalType, bool is_snan>
constexpr auto nan_impl(const char* arg) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_ieee_type_v, TargetDecimalType)
{
using sig_type = typename TargetDecimalType::significand_type;

Expand All @@ -34,7 +65,7 @@ constexpr auto nan_impl(const char* arg) noexcept -> TargetDecimalType
constexpr std::uint32_t significand_field_bits {sizeof(TargetDecimalType) == sizeof(std::uint32_t) ? 23U :
sizeof(TargetDecimalType) == sizeof(std::uint64_t) ? 53U : 110U};

constexpr sig_type max_payload_value {(static_cast<sig_type>(1) << (significand_field_bits + 1U)) - 1U};
constexpr sig_type max_payload_value {(static_cast<sig_type>(1) << significand_field_bits) - 1U};
constexpr TargetDecimalType zero {};
constexpr TargetDecimalType zero_bits {zero ^ zero};

Expand All @@ -55,7 +86,7 @@ constexpr auto nan_impl(const char* arg) noexcept -> TargetDecimalType

BOOST_DECIMAL_EXPORT template <typename T>
constexpr auto nan(const char* arg) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_ieee_type_v, T)
BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T)
{
return detail::nan_impl<T, false>(arg);
}
Expand All @@ -75,9 +106,24 @@ BOOST_DECIMAL_EXPORT constexpr auto nand128(const char* arg) noexcept -> decimal
return detail::nan_impl<decimal128_t, false>(arg);
}

BOOST_DECIMAL_EXPORT constexpr auto nand32f(const char* arg) noexcept -> decimal_fast32_t
{
return detail::nan_impl<decimal_fast32_t, false>(arg);
}

BOOST_DECIMAL_EXPORT constexpr auto nand64f(const char* arg) noexcept -> decimal_fast64_t
{
return detail::nan_impl<decimal_fast64_t, false>(arg);
}

BOOST_DECIMAL_EXPORT constexpr auto nand128f(const char* arg) noexcept -> decimal_fast128_t
{
return detail::nan_impl<decimal_fast128_t, false>(arg);
}

BOOST_DECIMAL_EXPORT template <typename T>
constexpr auto snan(const char* arg) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_ieee_type_v, T)
BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T)
{
return detail::nan_impl<T, true>(arg);
}
Expand All @@ -97,6 +143,21 @@ BOOST_DECIMAL_EXPORT constexpr auto snand128(const char* arg) noexcept -> decima
return detail::nan_impl<decimal128_t, true>(arg);
}

BOOST_DECIMAL_EXPORT constexpr auto snand32f(const char* arg) noexcept -> decimal_fast32_t
{
return detail::nan_impl<decimal_fast32_t, true>(arg);
}

BOOST_DECIMAL_EXPORT constexpr auto snand64f(const char* arg) noexcept -> decimal_fast64_t
{
return detail::nan_impl<decimal_fast64_t, true>(arg);
}

BOOST_DECIMAL_EXPORT constexpr auto snand128f(const char* arg) noexcept -> decimal_fast128_t
{
return detail::nan_impl<decimal_fast128_t, true>(arg);
}

BOOST_DECIMAL_EXPORT template <typename T>
constexpr auto read_payload(const T value) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_ieee_type_v, T, typename T::significand_type)
Expand All @@ -115,6 +176,70 @@ constexpr auto read_payload(const T value) noexcept
}
}

namespace detail {

template <typename T>
constexpr auto get_qnan_mask();

template <>
constexpr auto get_qnan_mask<decimal_fast32_t>()
{
return d32_fast_qnan;
}

template <>
constexpr auto get_qnan_mask<decimal_fast64_t>()
{
return d64_fast_qnan;
}

template <>
constexpr auto get_qnan_mask<decimal_fast128_t>()
{
return d128_fast_qnan;
}

template <typename T>
constexpr auto get_snan_mask();

template <>
constexpr auto get_snan_mask<decimal_fast32_t>()
{
return d32_fast_snan;
}

template <>
constexpr auto get_snan_mask<decimal_fast64_t>()
{
return d64_fast_snan;
}

template <>
constexpr auto get_snan_mask<decimal_fast128_t>()
{
return d128_fast_snan;
}

} // namespace detail

BOOST_DECIMAL_EXPORT template <typename T>
constexpr auto read_payload(const T value) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_fast_type_v, T, typename T::significand_type)
{
if (!isnan(value))
{
return 0U;
}
else if (issignaling(value))
{
return value.significand_ ^ detail::get_snan_mask<T>();
}
else
{
return value.significand_ ^ detail::get_qnan_mask<T>();
}
}

} //namespace decimal
} //namespace boost

Expand Down
Loading