mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-07-21 13:23:49 +00:00
Try handle more double_fp findings
This commit is contained in:
@@ -56,15 +56,20 @@ struct pair
|
||||
|
||||
using float_type = FloatingPointTypeA;
|
||||
|
||||
#if (defined(BOOST_CXX_VERSION) && (BOOST_CXX_VERSION >= 202002L))
|
||||
float_type first;
|
||||
float_type second;
|
||||
#else
|
||||
float_type first { };
|
||||
float_type second { };
|
||||
#endif
|
||||
|
||||
constexpr pair() : first { }, second { } { };
|
||||
constexpr pair(float_type a, float_type b) : first { a }, second { b } { }
|
||||
constexpr pair(const pair& other) : first { other.first }, second { other.second } { }
|
||||
constexpr pair() noexcept { }
|
||||
constexpr pair(float_type a, float_type b) noexcept : first { a }, second { b } { }
|
||||
constexpr pair(const pair& other) noexcept : first { other.first }, second { other.second } { }
|
||||
constexpr pair(pair&& other) noexcept : first { other.first }, second { other.second } { }
|
||||
|
||||
constexpr auto operator=(const pair& other) -> pair&
|
||||
constexpr auto operator=(const pair& other) noexcept -> pair&
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
|
||||
#if (defined(__GNUC__) && defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128))
|
||||
#if (defined(BOOST_GCC) && defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128))
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
|
||||
@@ -139,7 +139,7 @@ constexpr auto eval_convert_to(OtherFloatingPointType* result, const cpp_double_
|
||||
|
||||
// TBD: constexpr on hash_value?
|
||||
template <typename FloatingPointType>
|
||||
auto hash_value(const cpp_double_fp_backend<FloatingPointType>& a) -> ::std::size_t;
|
||||
constexpr auto hash_value(const cpp_double_fp_backend<FloatingPointType>& a) -> ::std::size_t;
|
||||
|
||||
template <typename FloatingPointType>
|
||||
constexpr auto fabs(const cpp_double_fp_backend<FloatingPointType>& a) -> cpp_double_fp_backend<FloatingPointType>;
|
||||
@@ -385,38 +385,12 @@ class cpp_double_fp_backend
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto hash() const -> ::std::size_t
|
||||
constexpr auto hash() const -> ::std::size_t
|
||||
{
|
||||
// Hash the raw values of the data field with direct-memory access.
|
||||
// Use 16-bit (2 byte) chunks as the data size when hashing.
|
||||
|
||||
static_assert( ( sizeof(data.first) == sizeof(data.second))
|
||||
&& ( sizeof(float_type) >= sizeof(std::uint16_t))
|
||||
&& ((sizeof(float_type) % sizeof(std::uint16_t)) == std::size_t { UINT8_C(0) }),
|
||||
"Error: float_type size is inappropriate for hashing routine");
|
||||
|
||||
auto hash_one
|
||||
{
|
||||
[](std::size_t& res, const float_type& val)
|
||||
{
|
||||
const std::uint16_t* first { reinterpret_cast<const std::uint16_t*>(&val) };
|
||||
const std::uint16_t* last { first + std::size_t { sizeof(float_type) / sizeof(std::uint16_t) } };
|
||||
|
||||
while (first != last)
|
||||
{
|
||||
boost::multiprecision::detail::hash_combine(res, *first);
|
||||
|
||||
++first;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
std::size_t result { UINT8_C(0) };
|
||||
|
||||
static_cast<void>(hash_one(result, data.first));
|
||||
static_cast<void>(hash_one(result, data.second));
|
||||
boost::multiprecision::detail::hash_combine(result, data.first);
|
||||
boost::multiprecision::detail::hash_combine(result, data.second);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -574,6 +548,21 @@ class cpp_double_fp_backend
|
||||
|
||||
data = arithmetic::two_diff(data.first, v.data.first);
|
||||
|
||||
if (cpp_df_qf_detail::ccmath::isinf(data.first))
|
||||
{
|
||||
// Handle overflow.
|
||||
const bool b_neg { (data.first < float_type { 0.0F }) };
|
||||
|
||||
*this = cpp_double_fp_backend::my_value_inf();
|
||||
|
||||
if (b_neg)
|
||||
{
|
||||
negate();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
data = arithmetic::two_hilo_sum(data.first, data.second + thi_tlo.first);
|
||||
|
||||
data = arithmetic::two_hilo_sum(data.first, thi_tlo.second + data.second);
|
||||
@@ -885,7 +874,7 @@ class cpp_double_fp_backend
|
||||
}
|
||||
}
|
||||
|
||||
auto str(std::streamsize number_of_digits, const std::ios::fmtflags format_flags) const -> std::string
|
||||
constexpr auto str(std::streamsize number_of_digits, const std::ios::fmtflags format_flags) const -> std::string
|
||||
{
|
||||
if (number_of_digits == 0)
|
||||
{
|
||||
@@ -1033,7 +1022,7 @@ class cpp_double_fp_backend
|
||||
|
||||
using cpp_bin_float_read_write_type = boost::multiprecision::number<cpp_bin_float_read_write_backend_type, boost::multiprecision::et_off>;
|
||||
|
||||
auto rd_string(const char* pstr) -> bool;
|
||||
constexpr auto rd_string(const char* pstr) -> bool;
|
||||
|
||||
constexpr auto add_unchecked(const cpp_double_fp_backend& v) -> void
|
||||
{
|
||||
@@ -1041,6 +1030,21 @@ class cpp_double_fp_backend
|
||||
|
||||
data = arithmetic::two_sum(data.first, v.data.first);
|
||||
|
||||
if (cpp_df_qf_detail::ccmath::isinf(data.first))
|
||||
{
|
||||
// Handle overflow.
|
||||
const bool b_neg { (data.first < float_type { 0.0F }) };
|
||||
|
||||
*this = cpp_double_fp_backend::my_value_inf();
|
||||
|
||||
if (b_neg)
|
||||
{
|
||||
negate();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
data = arithmetic::two_hilo_sum(data.first, data.second + thi_tlo.first);
|
||||
|
||||
data = arithmetic::two_hilo_sum(data.first, thi_tlo.second + data.second);
|
||||
@@ -1052,6 +1056,19 @@ class cpp_double_fp_backend
|
||||
|
||||
data = arithmetic::two_sum(data.first, v_first);
|
||||
|
||||
if (cpp_df_qf_detail::ccmath::isinf(data.first))
|
||||
{
|
||||
// Handle overflow.
|
||||
*this = cpp_double_fp_backend::my_value_inf();
|
||||
|
||||
if (data.first)
|
||||
{
|
||||
negate();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
data = arithmetic::two_hilo_sum(data.first, data.second + thi);
|
||||
|
||||
data = arithmetic::two_hilo_sum(data.first, data.second);
|
||||
@@ -1156,7 +1173,7 @@ class cpp_double_fp_backend
|
||||
};
|
||||
|
||||
template <typename FloatingPointType>
|
||||
auto cpp_double_fp_backend<FloatingPointType>::rd_string(const char* pstr) -> bool
|
||||
constexpr auto cpp_double_fp_backend<FloatingPointType>::rd_string(const char* pstr) -> bool
|
||||
{
|
||||
cpp_bin_float_read_write_type f_bin { pstr };
|
||||
|
||||
@@ -2458,7 +2475,7 @@ constexpr auto eval_convert_to(OtherFloatingPointType* result, const cpp_double_
|
||||
}
|
||||
|
||||
template <typename FloatingPointType>
|
||||
auto hash_value(const cpp_double_fp_backend<FloatingPointType>& a) -> ::std::size_t
|
||||
constexpr auto hash_value(const cpp_double_fp_backend<FloatingPointType>& a) -> ::std::size_t
|
||||
{
|
||||
return a.hash();
|
||||
}
|
||||
|
||||
@@ -499,8 +499,6 @@ namespace local
|
||||
result_is_ok = (result_unf_is_ok && result_is_ok);
|
||||
}
|
||||
|
||||
// TBD: See open issues for reminder to get this working in cpp_double_fp_backend.
|
||||
BOOST_IF_CONSTEXPR(!::has_poor_exp_range_or_precision_support<float_type>::value)
|
||||
{
|
||||
using std::ldexp;
|
||||
|
||||
@@ -524,8 +522,6 @@ namespace local
|
||||
result_is_ok = (result_ovf_is_ok && result_is_ok);
|
||||
}
|
||||
|
||||
// TBD: See open issues for reminder to get this working in cpp_double_fp_backend.
|
||||
BOOST_IF_CONSTEXPR(!::has_poor_exp_range_or_precision_support<float_type>::value)
|
||||
{
|
||||
using std::ldexp;
|
||||
|
||||
@@ -549,6 +545,29 @@ namespace local
|
||||
result_is_ok = (result_ovf_is_ok && result_is_ok);
|
||||
}
|
||||
|
||||
{
|
||||
using std::ldexp;
|
||||
|
||||
float_type flt_near_lowest { -ldexp((std::numeric_limits<float_type>::max)(), -1) };
|
||||
|
||||
const float_type neg_flt_less_near_max { -ldexp((std::numeric_limits<float_type>::max)(), -4) };
|
||||
|
||||
unsigned index { };
|
||||
|
||||
while((index < max_index) && (!(boost::multiprecision::isinf)(flt_near_lowest)))
|
||||
{
|
||||
flt_near_lowest += (neg_flt_less_near_max * dis(gen));
|
||||
|
||||
++index;
|
||||
}
|
||||
|
||||
const bool result_ovf_is_ok { ((index > 1U) && (index < max_index)) && signbit(flt_near_lowest) };
|
||||
|
||||
BOOST_TEST(result_ovf_is_ok);
|
||||
|
||||
result_is_ok = (result_ovf_is_ok && result_is_ok);
|
||||
}
|
||||
|
||||
for(int n_loop = static_cast<int>(INT8_C(-16)); n_loop < static_cast<int>(INT8_C(-8)); ++n_loop)
|
||||
{
|
||||
using std::ldexp;
|
||||
|
||||
Reference in New Issue
Block a user