Skip to content

Commit 6f3c75c

Browse files
authored
Merge pull request #739 from boostorg/syntax_double_fp
Simplify syntax cpp_double_fp_backend
2 parents 6ec5a7d + 156e03e commit 6f3c75c

File tree

5 files changed

+478
-110
lines changed

5 files changed

+478
-110
lines changed

include/boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_constants.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
#include <type_traits>
1414

15-
#if (defined(__GNUC__) && defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128))
15+
#if (defined(BOOST_GCC) && defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128))
1616
//
1717
// This is the only way we can avoid
1818
// warning: non-standard suffix on floating constant [-Wpedantic]

include/boost/multiprecision/cpp_double_fp.hpp

Lines changed: 117 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,7 @@ class cpp_double_fp_backend
249249
typename ::std::enable_if<( cpp_df_qf_detail::is_floating_point<OtherFloatType>::value
250250
&& (!std::is_same<FloatingPointType, OtherFloatType>::value))>::type const* = nullptr>
251251
constexpr cpp_double_fp_backend(const cpp_double_fp_backend<OtherFloatType>& a)
252-
: cpp_double_fp_backend(a.my_first())
253-
{
254-
// TBD: Maybe specialize this constructor for cases either wider or less wide.
255-
operator+=(a.my_second());
256-
}
252+
: cpp_double_fp_backend(cpp_double_fp_backend(a.my_first()) += a.my_second()) { }
257253

258254
// Constructors from integers.
259255
template <typename SignedIntegralType,
@@ -281,7 +277,7 @@ class cpp_double_fp_backend
281277
{
282278
using local_unsigned_integral_type = UnsignedIntegralType;
283279

284-
if (u > cpp_df_qf_detail::float_mask<UnsignedIntegralType, float_type>())
280+
if (u > cpp_df_qf_detail::float_mask<local_unsigned_integral_type, float_type>())
285281
{
286282
local_unsigned_integral_type
287283
local_flt_mask
@@ -332,9 +328,9 @@ class cpp_double_fp_backend
332328

333329
constexpr cpp_double_fp_backend(const cpp_df_qf_detail::pair<float_type, float_type>& p) noexcept : data(p) { }
334330

335-
cpp_double_fp_backend(const char* s)
331+
cpp_double_fp_backend(const char* p_str)
336332
{
337-
*this = s;
333+
*this = p_str;
338334
}
339335

340336
// Assignment operator.
@@ -377,9 +373,9 @@ class cpp_double_fp_backend
377373
return operator=(cpp_double_fp_backend(n));
378374
}
379375

380-
auto operator=(const char* v) -> cpp_double_fp_backend&
376+
auto operator=(const char* p_str) -> cpp_double_fp_backend&
381377
{
382-
rd_string(v);
378+
rd_string(p_str);
383379

384380
return *this;
385381
}
@@ -388,9 +384,6 @@ class cpp_double_fp_backend
388384
{
389385
std::size_t result { UINT8_C(0) };
390386

391-
int n_first { };
392-
int n_second { };
393-
394387
#if defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128)
395388
using local_float_type = typename std::conditional<::std::is_same<float_type, ::boost::float128_type>::value,
396389
long double,
@@ -399,10 +392,8 @@ class cpp_double_fp_backend
399392
using local_float_type = float_type;
400393
#endif
401394

402-
boost::multiprecision::detail::hash_combine(result, static_cast<local_float_type>(cpp_df_qf_detail::ccmath::frexp(data.first, &n_first)));
403-
boost::multiprecision::detail::hash_combine(result, static_cast<local_float_type>(cpp_df_qf_detail::ccmath::frexp(data.second, &n_second)));
404-
boost::multiprecision::detail::hash_combine(result, n_first);
405-
boost::multiprecision::detail::hash_combine(result, n_second);
395+
boost::multiprecision::detail::hash_combine(result, static_cast<local_float_type>(data.first));
396+
boost::multiprecision::detail::hash_combine(result, static_cast<local_float_type>(data.second));
406397

407398
return result;
408399
}
@@ -895,9 +886,9 @@ class cpp_double_fp_backend
895886
// Use cpp_bin_float when writing to string. This is similar
896887
// to the use of cpp_bin_float when reading from string.
897888

898-
cpp_bin_float_read_write_type f_bin { data.first };
889+
cpp_bin_float_read_write_backend_type f_bin { data.first };
899890

900-
f_bin += data.second;
891+
eval_add(f_bin, cpp_bin_float_read_write_backend_type(data.second));
901892

902893
return f_bin.str(number_of_digits, format_flags);
903894
}
@@ -1029,11 +1020,8 @@ class cpp_double_fp_backend
10291020
rep_type data;
10301021

10311022
using cpp_bin_float_read_write_backend_type = boost::multiprecision::backends::cpp_bin_float<static_cast<unsigned>(my_digits), digit_base_2, void, int, cpp_df_qf_detail::ccmath::numeric_limits<float_type>::min_exponent, cpp_df_qf_detail::ccmath::numeric_limits<float_type>::max_exponent>;
1032-
using cpp_bin_float_read_write_exp_type = typename cpp_bin_float_read_write_backend_type::exponent_type;
10331023

1034-
using cpp_bin_float_read_write_type = boost::multiprecision::number<cpp_bin_float_read_write_backend_type, boost::multiprecision::et_off>;
1035-
1036-
constexpr auto rd_string(const char* pstr) -> bool;
1024+
constexpr auto rd_string(const char* p_str) -> bool;
10371025

10381026
constexpr auto add_unchecked(const cpp_double_fp_backend& v) -> void
10391027
{
@@ -1171,11 +1159,15 @@ class cpp_double_fp_backend
11711159
};
11721160

11731161
template <typename FloatingPointType>
1174-
constexpr auto cpp_double_fp_backend<FloatingPointType>::rd_string(const char* pstr) -> bool
1162+
constexpr auto cpp_double_fp_backend<FloatingPointType>::rd_string(const char* p_str) -> bool
11751163
{
1176-
cpp_bin_float_read_write_type f_bin { pstr };
1164+
// Use an intermediate cpp_bin_float backend type for reading string input.
1165+
1166+
cpp_bin_float_read_write_backend_type f_bin { };
11771167

1178-
const int fpc { fpclassify(f_bin) };
1168+
f_bin = p_str;
1169+
1170+
const int fpc { eval_fpclassify(f_bin) };
11791171

11801172
const bool is_definitely_nan { (fpc == FP_NAN) };
11811173

@@ -1184,98 +1176,130 @@ constexpr auto cpp_double_fp_backend<FloatingPointType>::rd_string(const char* p
11841176
if (is_definitely_nan)
11851177
{
11861178
static_cast<void>(operator=(local_double_fp_type::my_value_nan()));
1179+
1180+
return true;
11871181
}
1188-
else
1189-
{
1190-
const bool b_neg { (signbit(f_bin) == 1) };
11911182

1192-
if (b_neg) { f_bin = -f_bin; }
1183+
const bool b_neg { (eval_signbit(f_bin) == 1) };
11931184

1194-
const int
1195-
expval_from_f_bin
1185+
if (b_neg) { f_bin.negate(); }
1186+
1187+
const int
1188+
expval_from_f_bin
1189+
{
1190+
[&f_bin]()
11961191
{
1197-
[&f_bin]()
1198-
{
1199-
int expval;
1192+
int expval { };
12001193

1201-
frexp(f_bin, &expval);
1194+
cpp_bin_float_read_write_backend_type dummy { };
12021195

1203-
return expval;
1204-
}()
1205-
};
1196+
eval_frexp(dummy, f_bin, &expval);
12061197

1207-
const auto is_zero_or_subnormal =
1208-
(
1209-
(fpc == FP_ZERO)
1210-
|| (expval_from_f_bin < static_cast<cpp_bin_float_read_write_exp_type>(local_double_fp_type::my_min_exponent))
1211-
);
1198+
return expval;
1199+
}()
1200+
};
12121201

1213-
if (is_zero_or_subnormal)
1202+
const auto is_zero_or_subnormal =
1203+
(
1204+
(fpc == FP_ZERO)
1205+
|| (expval_from_f_bin < static_cast<typename cpp_bin_float_read_write_backend_type::exponent_type>(local_double_fp_type::my_min_exponent))
1206+
);
1207+
1208+
if (is_zero_or_subnormal)
1209+
{
1210+
data.first = float_type { 0.0F };
1211+
data.second = float_type { 0.0F };
1212+
1213+
return true;
1214+
}
1215+
1216+
float_type flt_inf_check_first { };
1217+
1218+
eval_convert_to(&flt_inf_check_first, f_bin);
1219+
1220+
bool is_definitely_inf { ((fpc == FP_INFINITE) || cpp_df_qf_detail::ccmath::isinf(flt_inf_check_first)) };
1221+
1222+
if (!is_definitely_inf)
1223+
{
1224+
if (flt_inf_check_first > my_value_max().my_first())
12141225
{
1215-
data.first = float_type { 0.0F };
1216-
data.second = float_type { 0.0F };
1226+
cpp_bin_float_read_write_backend_type f_bin_inf_check(f_bin);
1227+
1228+
eval_subtract(f_bin_inf_check, cpp_bin_float_read_write_backend_type(flt_inf_check_first));
1229+
1230+
float_type flt_inf_check_second { };
1231+
1232+
eval_convert_to(&flt_inf_check_second, f_bin_inf_check);
1233+
1234+
is_definitely_inf = eval_gt(local_double_fp_type(flt_inf_check_first, flt_inf_check_second), my_value_max());
12171235
}
1218-
else
1236+
};
1237+
1238+
if (is_definitely_inf)
1239+
{
1240+
static_cast<void>(operator=(local_double_fp_type::my_value_inf()));
1241+
1242+
if (b_neg)
12191243
{
1220-
const auto is_definitely_inf = (f_bin > (::std::numeric_limits<cpp_bin_float_read_write_type>::max)());
1244+
negate();
1245+
}
12211246

1222-
if (is_definitely_inf)
1223-
{
1224-
static_cast<void>(operator=(local_double_fp_type::my_value_inf()));
1247+
return true;
1248+
}
12251249

1226-
if (b_neg) { negate(); }
1227-
}
1228-
else
1229-
{
1230-
data.first = float_type { 0.0F };
1231-
data.second = float_type { 0.0F };
1250+
// The input string is normal. We will now extract its value.
12321251

1233-
using local_builtin_float_type = typename std::conditional<(sizeof(float_type) <= sizeof(double)), double, float_type>::type;
1252+
data.first = float_type { 0.0F };
1253+
data.second = float_type { 0.0F };
12341254

1235-
constexpr int pow2_scaling_for_small_input { cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits };
1255+
constexpr int pow2_scaling_for_small_input { cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits };
12361256

1237-
const auto has_pow2_scaling_for_small_input =
1238-
(
1239-
expval_from_f_bin < static_cast<int>(local_double_fp_type::my_min_exponent + pow2_scaling_for_small_input)
1240-
);
1257+
const auto has_pow2_scaling_for_small_input =
1258+
(
1259+
expval_from_f_bin < static_cast<int>(local_double_fp_type::my_min_exponent + pow2_scaling_for_small_input)
1260+
);
12411261

1242-
if (has_pow2_scaling_for_small_input)
1243-
{
1244-
f_bin = ldexp(f_bin, pow2_scaling_for_small_input);
1245-
}
1262+
if (has_pow2_scaling_for_small_input)
1263+
{
1264+
eval_ldexp(f_bin, f_bin, pow2_scaling_for_small_input);
1265+
}
12461266

1247-
constexpr auto dig_lim =
1248-
static_cast<unsigned>
1249-
(
1250-
static_cast<int>
1251-
(
1252-
(local_double_fp_type::my_digits / cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits)
1253-
+ (((local_double_fp_type::my_digits % cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits) != 0) ? 1 : 0)
1254-
)
1255-
* cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits
1256-
);
1267+
using local_builtin_float_type = typename std::conditional<(sizeof(float_type) <= sizeof(double)), double, float_type>::type;
12571268

1258-
for(auto i = static_cast<unsigned>(UINT8_C(0));
1259-
i < dig_lim;
1260-
i = static_cast<unsigned>(i + static_cast<unsigned>(cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits)))
1261-
{
1262-
const local_builtin_float_type f { static_cast<local_builtin_float_type>(f_bin) };
1269+
constexpr unsigned
1270+
digit_limit
1271+
{
1272+
static_cast<unsigned>
1273+
(
1274+
static_cast<int>
1275+
(
1276+
(local_double_fp_type::my_digits / cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits)
1277+
+ (((local_double_fp_type::my_digits % cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits) != 0) ? 1 : 0)
1278+
)
1279+
* cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits
1280+
)
1281+
};
12631282

1264-
f_bin -= cpp_bin_float_read_write_type { f };
1283+
for(auto i = static_cast<unsigned>(UINT8_C(0));
1284+
i < digit_limit;
1285+
i = static_cast<unsigned>(i + static_cast<unsigned>(cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits)))
1286+
{
1287+
local_builtin_float_type flt_part { };
12651288

1266-
eval_add(*this, local_double_fp_type { f });
1267-
}
1289+
eval_convert_to(&flt_part, f_bin);
12681290

1269-
if (has_pow2_scaling_for_small_input)
1270-
{
1271-
eval_ldexp(*this, *this, -pow2_scaling_for_small_input);
1272-
}
1291+
eval_subtract(f_bin, cpp_bin_float_read_write_backend_type(flt_part));
12731292

1274-
if (b_neg) { negate(); }
1275-
}
1276-
}
1293+
eval_add(*this, local_double_fp_type { flt_part });
12771294
}
12781295

1296+
if (has_pow2_scaling_for_small_input)
1297+
{
1298+
eval_ldexp(*this, *this, -pow2_scaling_for_small_input);
1299+
}
1300+
1301+
if (b_neg) { negate(); }
1302+
12791303
return true;
12801304
}
12811305

0 commit comments

Comments
 (0)