@@ -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
11731161template <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