10
10
#ifndef BOOST_MP_CPP_DOUBLE_FP_2021_06_05_HPP
11
11
#define BOOST_MP_CPP_DOUBLE_FP_2021_06_05_HPP
12
12
13
- #if (defined(_MSC_VER) && (_MSC_VER <= 1900))
14
- #pragma warning(push)
15
- #pragma warning (disable : 4814)
13
+ #if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS)
14
+ #define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
16
15
#endif
17
16
18
- #include < limits>
19
- #include < string>
20
- #include < type_traits>
21
-
22
17
#include < boost/multiprecision/cpp_dec_float.hpp>
23
18
#include < boost/multiprecision/cpp_df_qf/cpp_df_qf_detail.hpp>
24
19
#include < boost/multiprecision/detail/float_string_cvt.hpp>
42
37
#include < boost/math/special_functions/gamma.hpp>
43
38
#endif
44
39
40
+ #include < limits>
41
+ #include < string>
42
+ #include < type_traits>
43
+
45
44
#if (defined(__clang__) && (__clang_major__ <= 9))
46
45
#define BOOST_MP_DF_QF_NUM_LIMITS_CLASS_TYPE struct
47
46
#else
@@ -244,8 +243,8 @@ class cpp_double_fp_backend
244
243
245
244
// Constructors from integers
246
245
template <typename SignedIntegralType,
247
- typename ::std::enable_if<( boost::multiprecision::detail::is_integral<SignedIntegralType>::value
248
- && !boost::multiprecision::detail::is_unsigned<SignedIntegralType>::value
246
+ typename ::std::enable_if<( boost::multiprecision::detail::is_integral<SignedIntegralType>::value
247
+ && ( !boost::multiprecision::detail::is_unsigned<SignedIntegralType>::value)
249
248
&& (static_cast <int >(sizeof (SignedIntegralType) * 8u ) <= cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits))>::type const * = nullptr >
250
249
constexpr cpp_double_fp_backend (const SignedIntegralType& n)
251
250
: data(static_cast <float_type>(n), static_cast<float_type>(0 .0F )) { }
@@ -276,8 +275,8 @@ class cpp_double_fp_backend
276
275
) { }
277
276
278
277
template <typename SignedIntegralType,
279
- typename ::std::enable_if<( boost::multiprecision::detail::is_integral<SignedIntegralType>::value
280
- && !boost::multiprecision::detail::is_unsigned<SignedIntegralType>::value
278
+ typename ::std::enable_if<( boost::multiprecision::detail::is_integral<SignedIntegralType>::value
279
+ && ( !boost::multiprecision::detail::is_unsigned<SignedIntegralType>::value)
281
280
&& (static_cast <int >(sizeof (SignedIntegralType) * 8u ) > cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits))>::type const * = nullptr >
282
281
constexpr cpp_double_fp_backend (SignedIntegralType n)
283
282
: data
@@ -355,7 +354,7 @@ class cpp_double_fp_backend
355
354
// TBD: Is there a faster or more simple hash method?
356
355
// TBD: Is there any constexpr support for rudimentary hashing?
357
356
358
- const auto str_to_hash = str (cpp_double_fp_backend::my_digits10, std::ios::scientific);
357
+ const std::string str_to_hash { str (cpp_double_fp_backend::my_digits10, std::ios::scientific) } ;
359
358
360
359
auto result = static_cast <std::size_t >(UINT8_C (0 ));
361
360
@@ -387,11 +386,11 @@ class cpp_double_fp_backend
387
386
}
388
387
else if (isinf_u)
389
388
{
390
- data.first = -data.first ;
389
+ data.first = -data.first ;
391
390
}
392
391
else
393
392
{
394
- data.first = -data.first ;
393
+ data.first = -data.first ;
395
394
396
395
if (data.second != 0 ) { data.second = -data.second ; }
397
396
@@ -405,13 +404,14 @@ class cpp_double_fp_backend
405
404
constexpr const float_type& my_first () const noexcept { return data.first ; }
406
405
constexpr const float_type& my_second () const noexcept { return data.second ; }
407
406
408
- constexpr rep_type& rep () noexcept { return data; }
407
+ constexpr rep_type& rep () noexcept { return data; }
409
408
410
- constexpr const rep_type& rep () const noexcept { return data; }
409
+ constexpr const rep_type& rep () const noexcept { return data; }
411
410
412
411
constexpr const rep_type& crep () const noexcept { return data; }
413
412
414
- // Unary add/sub/mul/div.
413
+ // Unary add/sub/mul/div follow in the upcoming paragraphs.
414
+
415
415
constexpr cpp_double_fp_backend& operator +=(const cpp_double_fp_backend& v)
416
416
{
417
417
const auto fpc_u = eval_fpclassify (*this );
@@ -527,12 +527,12 @@ class cpp_double_fp_backend
527
527
const auto fpc_v = eval_fpclassify (v);
528
528
529
529
// Handle special cases like zero, inf and NaN.
530
- const bool isinf_u = ( fpc_u == FP_INFINITE) ;
531
- const bool isinf_v = ( fpc_v == FP_INFINITE) ;
532
- const bool isnan_u = ( fpc_u == FP_NAN) ;
533
- const bool isnan_v = ( fpc_v == FP_NAN) ;
534
- const bool iszero_u = ( fpc_u == FP_ZERO) ;
535
- const bool iszero_v = ( fpc_v == FP_ZERO) ;
530
+ const bool isinf_u { fpc_u == FP_INFINITE } ;
531
+ const bool isinf_v { fpc_v == FP_INFINITE } ;
532
+ const bool isnan_u { fpc_u == FP_NAN } ;
533
+ const bool isnan_v { fpc_v == FP_NAN } ;
534
+ const bool iszero_u { fpc_u == FP_ZERO } ;
535
+ const bool iszero_v { fpc_v == FP_ZERO } ;
536
536
537
537
if ((isnan_u || isnan_v) || (isinf_u && iszero_v) || (isinf_v && iszero_u))
538
538
{
@@ -828,7 +828,12 @@ class cpp_double_fp_backend
828
828
if (number_of_digits == 0 )
829
829
number_of_digits = cpp_double_fp_backend::my_digits10;
830
830
831
- const std::string my_str = boost::multiprecision::detail::convert_to_string (*this , number_of_digits, format_flags);
831
+ cpp_dec_float_read_write_type f_dec { 0 };
832
+
833
+ f_dec += data.second ;
834
+ f_dec += data.first ;
835
+
836
+ const std::string my_str { f_dec.str (number_of_digits, format_flags) };
832
837
833
838
return my_str;
834
839
}
@@ -935,6 +940,18 @@ class cpp_double_fp_backend
935
940
private:
936
941
rep_type data;
937
942
943
+ static constexpr auto cpp_dec_float_read_write_digits10 =
944
+ static_cast <int >
945
+ (
946
+ static_cast <float >
947
+ (
948
+ static_cast <float >(my_digits) * 0 .9F
949
+ )
950
+ );
951
+
952
+ using cpp_dec_float_read_write_type = boost::multiprecision::cpp_dec_float<static_cast <unsigned >(cpp_dec_float_read_write_digits10), std::int32_t , std::allocator<void >>;
953
+ using cpp_dec_float_read_write_exp_type = typename cpp_dec_float_read_write_type::exponent_type;
954
+
938
955
bool rd_string (const char * pstr);
939
956
940
957
static constexpr rep_type two_sum (const float_type a, const float_type b)
@@ -982,19 +999,7 @@ bool cpp_double_fp_backend<FloatingPointType>::rd_string(const char* pstr)
982
999
983
1000
using local_double_fp_type = cpp_double_fp_backend<FloatingPointType>;
984
1001
985
- constexpr auto local_cpp_dec_float_digits10 =
986
- static_cast <int >
987
- (
988
- static_cast <float >
989
- (
990
- static_cast <float >(local_double_fp_type::my_digits) * 0 .9F
991
- )
992
- );
993
-
994
- using local_cpp_dec_float_type = boost::multiprecision::cpp_dec_float<static_cast <unsigned >(local_cpp_dec_float_digits10), std::int32_t , std::allocator<void >>;
995
- using local_cpp_dec_float_exp_type = typename local_cpp_dec_float_type::exponent_type;
996
-
997
- local_cpp_dec_float_type f_dec = pstr;
1002
+ cpp_dec_float_read_write_type f_dec = pstr;
998
1003
999
1004
const auto fpc = eval_fpclassify (f_dec);
1000
1005
@@ -1006,7 +1011,7 @@ bool cpp_double_fp_backend<FloatingPointType>::rd_string(const char* pstr)
1006
1011
}
1007
1012
else
1008
1013
{
1009
- local_cpp_dec_float_type dummy_frexp { };
1014
+ cpp_dec_float_read_write_type dummy_frexp { };
1010
1015
auto e2_from_f_dec = int { };
1011
1016
eval_frexp (dummy_frexp, f_dec, &e2_from_f_dec);
1012
1017
@@ -1015,7 +1020,7 @@ bool cpp_double_fp_backend<FloatingPointType>::rd_string(const char* pstr)
1015
1020
// TBD: A detailed, clear comparison (or something close to a comparison)
1016
1021
// is still needed for input values having (e2_from_f_dec == my_min_exponent).
1017
1022
(fpc == FP_ZERO)
1018
- || (e2_from_f_dec < static_cast <local_cpp_dec_float_exp_type >(local_double_fp_type::my_min_exponent))
1023
+ || (e2_from_f_dec < static_cast <cpp_dec_float_read_write_exp_type >(local_double_fp_type::my_min_exponent))
1019
1024
);
1020
1025
1021
1026
if (is_definitely_zero)
@@ -1027,7 +1032,7 @@ bool cpp_double_fp_backend<FloatingPointType>::rd_string(const char* pstr)
1027
1032
{
1028
1033
// TBD: A detailed, clear comparison (or something close to a comparison)
1029
1034
// is still needed for input values having (e2_from_f_dec == my_max_exponent).
1030
- const auto is_definitely_inf = (e2_from_f_dec > static_cast <local_cpp_dec_float_exp_type >(local_double_fp_type::my_max_exponent));
1035
+ const auto is_definitely_inf = (e2_from_f_dec > static_cast <cpp_dec_float_read_write_exp_type >(local_double_fp_type::my_max_exponent));
1031
1036
1032
1037
if (is_definitely_inf)
1033
1038
{
@@ -1063,18 +1068,18 @@ bool cpp_double_fp_backend<FloatingPointType>::rd_string(const char* pstr)
1063
1068
1064
1069
if (has_pow2_scaling_for_small_input)
1065
1070
{
1066
- f_dec *= local_cpp_dec_float_type ::pow2 (static_cast <long long >(pow2_scaling_for_small_input));
1071
+ f_dec *= cpp_dec_float_read_write_type ::pow2 (static_cast <long long >(pow2_scaling_for_small_input));
1067
1072
}
1068
1073
1069
1074
for (auto i = static_cast <unsigned >(UINT8_C (0 ));
1070
1075
i < dig_lim;
1071
1076
i = static_cast <unsigned >(i + static_cast <unsigned >(cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits)))
1072
1077
{
1073
- local_cpp_dec_float_type f_dec_abs { };
1078
+ cpp_dec_float_read_write_type f_dec_abs { };
1074
1079
1075
1080
eval_fabs (f_dec_abs, f_dec);
1076
1081
1077
- if (f_dec_abs.compare ((local_cpp_dec_float_type ::min)()) <= 0 )
1082
+ if (f_dec_abs.compare ((cpp_dec_float_read_write_type ::min)()) <= 0 )
1078
1083
{
1079
1084
break ;
1080
1085
}
@@ -1212,7 +1217,7 @@ constexpr cpp_double_fp_backend<FloatingPointType> operator/(const cpp_double_fp
1212
1217
// Input/Output Streaming
1213
1218
template <typename FloatingPointType, typename char_type, typename traits_type>
1214
1219
::std::basic_ostream<char_type, traits_type>&
1215
- operator <<(std::basic_ostream<char_type, traits_type>& os, const cpp_double_fp_backend<FloatingPointType>& f)
1220
+ operator <<(:: std::basic_ostream<char_type, traits_type>& os, const cpp_double_fp_backend<FloatingPointType>& f)
1216
1221
{
1217
1222
const auto str_result = f.str (os.precision (), os.flags ());
1218
1223
@@ -1221,7 +1226,7 @@ operator<<(std::basic_ostream<char_type, traits_type>& os, const cpp_double_fp_b
1221
1226
1222
1227
template <typename FloatingPointType, typename char_type, typename traits_type>
1223
1228
::std::basic_istream<char_type, traits_type>&
1224
- operator >>(std::basic_istream<char_type, traits_type>& is, cpp_double_fp_backend<FloatingPointType>& f)
1229
+ operator >>(:: std::basic_istream<char_type, traits_type>& is, cpp_double_fp_backend<FloatingPointType>& f)
1225
1230
{
1226
1231
std::string input_str;
1227
1232
@@ -1859,7 +1864,7 @@ constexpr void eval_log(cpp_double_fp_backend<FloatingPointType>& result, const
1859
1864
else if (eval_lt (x, double_float_type (1 )))
1860
1865
{
1861
1866
// TBD: Optimize check with 1.
1862
- // TBD: optimize inversion and negation.
1867
+ // TBD: Optimize inversion and negation.
1863
1868
1864
1869
double_float_type x_inv;
1865
1870
eval_divide (x_inv, double_float_type (1 ), x);
@@ -1889,7 +1894,7 @@ constexpr void eval_log(cpp_double_fp_backend<FloatingPointType>& result, const
1889
1894
// Do one single step of Newton-Raphson iteration.
1890
1895
result = s + ((x2 - E) / E);
1891
1896
1892
- double_float_type xn2 (n2) ;
1897
+ double_float_type xn2 { n2 } ;
1893
1898
1894
1899
eval_multiply (xn2, cpp_df_qf_detail::constant_df_ln_two<typename double_float_type::float_type>());
1895
1900
@@ -2304,8 +2309,4 @@ struct precision<boost::multiprecision::number<boost::multiprecision::cpp_double
2304
2309
} } } // namespace boost::math::policies
2305
2310
#endif
2306
2311
2307
- #if (defined(_MSC_VER) && (_MSC_VER <= 1900))
2308
- #pragma warning(pop)
2309
- #endif
2310
-
2311
2312
#endif // BOOST_MP_CPP_DOUBLE_FP_2021_06_05_HPP
0 commit comments