File indexing completed on 2026-08-17 08:51:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_MP_CPP_DOUBLE_FP_2021_06_05_HPP
0012 #define BOOST_MP_CPP_DOUBLE_FP_2021_06_05_HPP
0013
0014 #include <boost/multiprecision/cpp_bin_float.hpp>
0015 #include <boost/multiprecision/cpp_df_qf/cpp_df_qf_detail.hpp>
0016 #include <boost/multiprecision/detail/hash.hpp>
0017 #include <boost/multiprecision/traits/max_digits10.hpp>
0018 #include <boost/multiprecision/traits/std_integer_traits.hpp>
0019
0020 #ifdef BOOST_MP_MATH_AVAILABLE
0021
0022
0023
0024 #include <boost/math/policies/policy.hpp>
0025
0026
0027
0028 #include <boost/math/special_functions/acosh.hpp>
0029 #include <boost/math/special_functions/asinh.hpp>
0030 #include <boost/math/special_functions/atanh.hpp>
0031 #include <boost/math/special_functions/cbrt.hpp>
0032 #include <boost/math/special_functions/expm1.hpp>
0033 #include <boost/math/special_functions/gamma.hpp>
0034 #endif
0035
0036 #include <limits>
0037 #include <string>
0038 #include <type_traits>
0039
0040 #if (defined(BOOST_CLANG) && defined(BOOST_CLANG_VERSION) && (BOOST_CLANG_VERSION <= 90000))
0041 #define BOOST_MP_DF_QF_NUM_LIMITS_CLASS_TYPE struct
0042 #else
0043 #define BOOST_MP_DF_QF_NUM_LIMITS_CLASS_TYPE class
0044 #endif
0045
0046 namespace boost { namespace multiprecision { namespace backends {
0047
0048 template <typename FloatingPointType>
0049 class cpp_double_fp_backend;
0050
0051 template <typename FloatingPointType>
0052 constexpr auto eval_add(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void;
0053 template <typename FloatingPointType>
0054 constexpr auto eval_add(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> void;
0055 template <typename FloatingPointType>
0056 constexpr auto eval_subtract(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void;
0057 template <typename FloatingPointType>
0058 constexpr auto eval_subtract(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> void;
0059 template <typename FloatingPointType>
0060 constexpr auto eval_multiply(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void;
0061 template <typename FloatingPointType>
0062 constexpr auto eval_multiply(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> void;
0063 template <typename FloatingPointType>
0064 constexpr auto eval_divide(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void;
0065 template <typename FloatingPointType>
0066 constexpr auto eval_divide(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> void;
0067 template <typename FloatingPointType>
0068 constexpr auto eval_eq(const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> bool;
0069 template <typename FloatingPointType>
0070 constexpr auto eval_lt(const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> bool;
0071 template <typename FloatingPointType>
0072 constexpr auto eval_gt(const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> bool;
0073 template <typename FloatingPointType>
0074 constexpr auto eval_is_zero(const cpp_double_fp_backend<FloatingPointType>& x) -> bool;
0075 template <typename FloatingPointType>
0076 constexpr auto eval_signbit(const cpp_double_fp_backend<FloatingPointType>& x) -> int;
0077
0078 template <typename FloatingPointType>
0079 constexpr auto eval_fabs(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a) -> void;
0080 template <typename FloatingPointType>
0081 constexpr auto eval_frexp(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, int* v) -> void;
0082 template <typename FloatingPointType>
0083 constexpr auto eval_ldexp(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, int v) -> void;
0084 template <typename FloatingPointType>
0085 constexpr auto eval_floor(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void;
0086 template <typename FloatingPointType>
0087 constexpr auto eval_ceil(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void;
0088 template <typename FloatingPointType>
0089 constexpr auto eval_fpclassify(const cpp_double_fp_backend<FloatingPointType>& o) -> int;
0090
0091 template <typename FloatingPointType>
0092 constexpr auto eval_sqrt(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& o) -> void;
0093
0094 template <typename FloatingPointType>
0095 constexpr auto eval_pow(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x, const cpp_double_fp_backend<FloatingPointType>& a) -> void;
0096
0097 template <typename FloatingPointType,
0098 typename IntegralType>
0099 constexpr auto eval_pow(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x, IntegralType n) -> typename ::std::enable_if<boost::multiprecision::detail::is_integral<IntegralType>::value, void>::type;
0100
0101 template <typename FloatingPointType,
0102 typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && ((cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits10 * 2) < 16))>::type const* = nullptr>
0103 constexpr auto eval_exp(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void;
0104
0105 template <typename FloatingPointType,
0106 typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (((cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits10 * 2) >= 16) && ((cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits10 * 2) <= 36)))>::type const* = nullptr>
0107 constexpr auto eval_exp(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void;
0108
0109 template <typename FloatingPointType,
0110 typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && ((cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits10 * 2) > 36))>::type const* = nullptr>
0111 constexpr auto eval_exp(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void;
0112
0113 template <typename FloatingPointType>
0114 constexpr auto eval_log(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void;
0115
0116 template <typename FloatingPointType>
0117 constexpr auto eval_convert_to(signed long long* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> void;
0118
0119 template <typename FloatingPointType>
0120 constexpr auto eval_convert_to(unsigned long long* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> void;
0121
0122 #ifdef BOOST_HAS_INT128
0123 template <typename FloatingPointType>
0124 constexpr auto eval_convert_to(boost::int128_type* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> typename std::enable_if<(cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits > 24), void>::type;
0125
0126 template <typename FloatingPointType>
0127 constexpr auto eval_convert_to(boost::int128_type* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> typename std::enable_if<!(cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits > 24), void>::type;
0128
0129 template <typename FloatingPointType>
0130 constexpr auto eval_convert_to(boost::uint128_type* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> typename std::enable_if<(cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits > 24), void>::type;
0131
0132 template <typename FloatingPointType>
0133 constexpr auto eval_convert_to(boost::uint128_type* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> typename std::enable_if<!(cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits > 24), void>::type;
0134 #endif
0135
0136 template <typename FloatingPointType,
0137 typename OtherFloatingPointType>
0138 constexpr auto eval_convert_to(OtherFloatingPointType* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> typename ::std::enable_if<cpp_df_qf_detail::is_floating_point<OtherFloatingPointType>::value>::type;
0139
0140 template <typename FloatingPointType>
0141 constexpr auto hash_value(const cpp_double_fp_backend<FloatingPointType>& a) -> ::std::size_t;
0142
0143 template <typename FloatingPointType>
0144 constexpr auto fabs(const cpp_double_fp_backend<FloatingPointType>& a) -> cpp_double_fp_backend<FloatingPointType>;
0145
0146 } } }
0147
0148 namespace std {
0149
0150
0151
0152 template <typename FloatingPointType,
0153 const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
0154 BOOST_MP_DF_QF_NUM_LIMITS_CLASS_TYPE numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >;
0155
0156 }
0157
0158 namespace boost { namespace multiprecision {
0159
0160 template <typename FloatingPointType>
0161 struct number_category<backends::cpp_double_fp_backend<FloatingPointType>> : public std::integral_constant<int, number_kind_floating_point> { };
0162
0163 namespace backends {
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 template <typename FloatingPointType>
0176 class cpp_double_fp_backend
0177 {
0178 public:
0179 using float_type = FloatingPointType;
0180
0181 static_assert
0182 (
0183 cpp_df_qf_detail::is_floating_point<float_type>::value
0184 && bool
0185 {
0186 ((cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits == 24) && cpp_df_qf_detail::ccmath::numeric_limits<float_type>::is_specialized && cpp_df_qf_detail::ccmath::numeric_limits<float_type>::is_iec559)
0187 || ((cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits == 53) && cpp_df_qf_detail::ccmath::numeric_limits<float_type>::is_specialized && cpp_df_qf_detail::ccmath::numeric_limits<float_type>::is_iec559)
0188 || ((cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits == 64) && cpp_df_qf_detail::ccmath::numeric_limits<float_type>::is_specialized && cpp_df_qf_detail::ccmath::numeric_limits<float_type>::is_iec559)
0189 || (cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits == 113)
0190 }, "Error: float_type does not fulfill the backend requirements of cpp_double_fp_backend"
0191 );
0192
0193 using rep_type = cpp_df_qf_detail::pair<float_type, float_type>;
0194 using arithmetic = cpp_df_qf_detail::exact_arithmetic<float_type>;
0195
0196 using signed_types = std::tuple<signed char, signed short, signed int, signed long, signed long long, std::intmax_t>;
0197 using unsigned_types = std::tuple<unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long, std::uintmax_t>;
0198 using float_types = std::tuple<float, double, long double>;
0199 using exponent_type = int;
0200
0201 static constexpr int my_digits = static_cast<int>(cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits * static_cast<int>(INT8_C(2)));
0202 static constexpr int my_digits10 = static_cast<int>(boost::multiprecision::detail::calc_digits10 <static_cast<unsigned>(my_digits)>::value);
0203 static constexpr int my_max_digits10 = static_cast<int>(boost::multiprecision::detail::calc_max_digits10<static_cast<unsigned>(my_digits)>::value);
0204 static constexpr int my_max_exponent = cpp_df_qf_detail::ccmath::numeric_limits<float_type>::max_exponent;
0205 static constexpr int my_max_exponent10 = cpp_df_qf_detail::ccmath::numeric_limits<float_type>::max_exponent10;
0206
0207 static constexpr int my_min_exponent =
0208 static_cast<int>
0209 (
0210 cpp_df_qf_detail::ccmath::numeric_limits<float_type>::min_exponent
0211 + cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits
0212 );
0213
0214 static constexpr int my_min_exponent10 =
0215 static_cast<int>
0216 (
0217 -static_cast<int>
0218 (
0219 boost::multiprecision::detail::calc_digits10<static_cast<unsigned>(-my_min_exponent)>::value
0220 )
0221 );
0222
0223
0224 constexpr cpp_double_fp_backend() noexcept { }
0225
0226
0227 constexpr cpp_double_fp_backend(const cpp_double_fp_backend& other) : data(other.data) { }
0228
0229
0230 constexpr cpp_double_fp_backend(cpp_double_fp_backend&& other) noexcept : data(static_cast<rep_type&&>(other.data)) { }
0231
0232
0233 template <typename OtherFloatType,
0234 typename ::std::enable_if<( cpp_df_qf_detail::is_floating_point<OtherFloatType>::value
0235 && (cpp_df_qf_detail::ccmath::numeric_limits<OtherFloatType>::digits <= cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits))>::type const* = nullptr>
0236 constexpr cpp_double_fp_backend(const OtherFloatType& f)
0237 : data(f, static_cast<float_type>(0.0F)) { }
0238
0239 template <typename OtherFloatType,
0240 typename ::std::enable_if<( cpp_df_qf_detail::is_floating_point<OtherFloatType>::value
0241 && (cpp_df_qf_detail::ccmath::numeric_limits<OtherFloatType>::digits > cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits))>::type const* = nullptr>
0242 constexpr cpp_double_fp_backend(const OtherFloatType& f)
0243 : data(static_cast<float_type>(f),
0244 static_cast<float_type>(f - static_cast<OtherFloatType>(static_cast<float_type>(f)))) { }
0245
0246
0247
0248 template <typename OtherFloatType,
0249 typename ::std::enable_if<( cpp_df_qf_detail::is_floating_point<OtherFloatType>::value
0250 && (!std::is_same<FloatingPointType, OtherFloatType>::value))>::type const* = nullptr>
0251 constexpr cpp_double_fp_backend(const cpp_double_fp_backend<OtherFloatType>& a)
0252 : cpp_double_fp_backend(cpp_double_fp_backend(a.my_first()) += a.my_second()) { }
0253
0254
0255 template <typename SignedIntegralType,
0256 typename ::std::enable_if<( boost::multiprecision::detail::is_integral<SignedIntegralType>::value
0257 && (!boost::multiprecision::detail::is_unsigned<SignedIntegralType>::value)
0258 && ((static_cast<int>(sizeof(SignedIntegralType) * 8) - 1) <= cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits))>::type const* = nullptr>
0259 constexpr cpp_double_fp_backend(const SignedIntegralType& n)
0260 : data(static_cast<float_type>(n), static_cast<float_type>(0.0F)) { }
0261
0262 template <typename UnsignedIntegralType,
0263 typename ::std::enable_if<( boost::multiprecision::detail::is_integral<UnsignedIntegralType>::value
0264 && boost::multiprecision::detail::is_unsigned<UnsignedIntegralType>::value
0265 && (static_cast<int>(sizeof(UnsignedIntegralType) * 8u) <= cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits))>::type const* = nullptr>
0266 constexpr cpp_double_fp_backend(const UnsignedIntegralType& u)
0267 : data(static_cast<float_type>(u), static_cast<float_type>(0.0F)) { }
0268
0269
0270 template <typename UnsignedIntegralType,
0271 typename ::std::enable_if<( boost::multiprecision::detail::is_integral<UnsignedIntegralType>::value
0272 && boost::multiprecision::detail::is_unsigned<UnsignedIntegralType>::value
0273 && (static_cast<int>(sizeof(UnsignedIntegralType) * 8u) > cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits))>::type const* = nullptr>
0274 constexpr cpp_double_fp_backend(UnsignedIntegralType u)
0275 : data(static_cast<float_type>(u & cpp_df_qf_detail::float_mask<UnsignedIntegralType, float_type>()),
0276 static_cast<float_type>(0.0F))
0277 {
0278 using local_unsigned_integral_type = UnsignedIntegralType;
0279
0280 if (u > cpp_df_qf_detail::float_mask<local_unsigned_integral_type, float_type>())
0281 {
0282 local_unsigned_integral_type
0283 local_flt_mask
0284 {
0285 cpp_df_qf_detail::float_mask<local_unsigned_integral_type, float_type>()
0286 };
0287
0288 for (int index_mask_lsb = cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits;
0289 (index_mask_lsb < static_cast<int>(sizeof(local_unsigned_integral_type) * 8u))
0290 && (local_flt_mask != local_unsigned_integral_type { UINT8_C(0) });
0291 index_mask_lsb += cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits)
0292 {
0293 local_flt_mask <<= static_cast<unsigned>(cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits);
0294
0295 add_unchecked_limb(static_cast<float_type>(u & local_flt_mask));
0296 }
0297 }
0298 }
0299
0300 template <typename SignedIntegralType,
0301 typename ::std::enable_if<( boost::multiprecision::detail::is_integral<SignedIntegralType>::value
0302 && (!boost::multiprecision::detail::is_unsigned<SignedIntegralType>::value)
0303 && ((static_cast<int>(sizeof(SignedIntegralType) * 8) - 1) > cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits))>::type const* = nullptr>
0304 constexpr cpp_double_fp_backend(SignedIntegralType n)
0305 {
0306 const bool is_neg { (n < SignedIntegralType { INT8_C(0) }) };
0307
0308 using local_unsigned_integral_type = typename boost::multiprecision::detail::make_unsigned<SignedIntegralType>::type;
0309
0310 const local_unsigned_integral_type
0311 u_val
0312 {
0313 (!is_neg)
0314 ? static_cast<local_unsigned_integral_type>(n)
0315 : static_cast<local_unsigned_integral_type>
0316 (
0317 static_cast<local_unsigned_integral_type>(~n)
0318 + static_cast<local_unsigned_integral_type>(UINT8_C(1))
0319 )
0320 };
0321
0322 data = cpp_double_fp_backend(u_val).data;
0323
0324 if(is_neg) { negate(); }
0325 }
0326
0327 constexpr cpp_double_fp_backend(const float_type& a, const float_type& b) noexcept : data(a, b) { }
0328
0329 constexpr cpp_double_fp_backend(const cpp_df_qf_detail::pair<float_type, float_type>& p) noexcept : data(p) { }
0330
0331 cpp_double_fp_backend(const char* p_str)
0332 {
0333 *this = p_str;
0334 }
0335
0336
0337 constexpr auto operator=(const cpp_double_fp_backend& other) -> cpp_double_fp_backend&
0338 {
0339 if (this != &other)
0340 {
0341 data = other.data;
0342 }
0343
0344 return *this;
0345 }
0346
0347
0348 constexpr auto operator=(cpp_double_fp_backend&& other) noexcept -> cpp_double_fp_backend&
0349 {
0350 data = static_cast<rep_type&&>(other.data);
0351
0352 return *this;
0353 }
0354
0355
0356 template <typename OtherFloatType,
0357 typename ::std::enable_if<( cpp_df_qf_detail::is_floating_point<OtherFloatType>::value
0358 && (!std::is_same<FloatingPointType, OtherFloatType>::value))>::type const* = nullptr>
0359 constexpr auto operator=(const cpp_double_fp_backend<OtherFloatType>& other) -> cpp_double_fp_backend&
0360 {
0361 return operator=(cpp_double_fp_backend(other));
0362 }
0363
0364 template <typename OtherFloatType>
0365 constexpr auto operator=(const OtherFloatType f) -> typename ::std::enable_if<cpp_df_qf_detail::is_floating_point<OtherFloatType>::value, cpp_double_fp_backend&>::type
0366 {
0367 return operator=(cpp_double_fp_backend(f));
0368 }
0369
0370 template <typename IntegralType>
0371 constexpr auto operator=(const IntegralType n) -> typename ::std::enable_if<boost::multiprecision::detail::is_integral<IntegralType>::value, cpp_double_fp_backend&>::type
0372 {
0373 return operator=(cpp_double_fp_backend(n));
0374 }
0375
0376 auto operator=(const char* p_str) -> cpp_double_fp_backend&
0377 {
0378 rd_string(p_str);
0379
0380 return *this;
0381 }
0382
0383 constexpr auto hash() const -> ::std::size_t
0384 {
0385 #if defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128)
0386 using local_float_type = typename std::conditional<::std::is_same<float_type, ::boost::float128_type>::value,
0387 long double,
0388 float_type>::type;
0389 #else
0390 using local_float_type = float_type;
0391 #endif
0392
0393 std::size_t result { UINT8_C(0) };
0394
0395 int n_first { };
0396 int n_second { };
0397
0398 boost::multiprecision::detail::hash_combine(result, static_cast<local_float_type>(cpp_df_qf_detail::ccmath::frexp(data.first, &n_first)));
0399 boost::multiprecision::detail::hash_combine(result, static_cast<local_float_type>(cpp_df_qf_detail::ccmath::frexp(data.second, &n_second)));
0400 boost::multiprecision::detail::hash_combine(result, n_first);
0401 boost::multiprecision::detail::hash_combine(result, n_second);
0402
0403 return result;
0404 }
0405
0406
0407
0408 constexpr auto isneg_unchecked() const noexcept -> bool { return (data.first < 0); }
0409
0410 constexpr auto iszero_unchecked() const noexcept -> bool { return (data.first == float_type { 0.0F }); }
0411
0412 constexpr auto is_one() const noexcept -> bool
0413 {
0414 return
0415 (
0416 (data.second == float_type { 0.0F })
0417 && (data.first == float_type { 1.0F })
0418 );
0419 }
0420
0421 constexpr auto negate() -> void
0422 {
0423 const bool isinf_u { (cpp_df_qf_detail::ccmath::isinf)(data.first) };
0424 const bool isnan_u { (cpp_df_qf_detail::ccmath::isnan)(data.first) };
0425
0426 if (isnan_u) { }
0427 else if (isinf_u)
0428 {
0429 data.first = -data.first;
0430 }
0431 else
0432 {
0433 if (!iszero_unchecked())
0434 {
0435 data = arithmetic::normalize(-data.first, -data.second);
0436 }
0437 }
0438 }
0439
0440
0441 constexpr auto my_first () const noexcept -> const float_type& { return data.first; }
0442 constexpr auto my_second() const noexcept -> const float_type& { return data.second; }
0443
0444 constexpr auto rep() noexcept -> rep_type& { return data; }
0445
0446 constexpr auto rep() const noexcept -> const rep_type& { return data; }
0447
0448 constexpr auto crep() const noexcept -> const rep_type& { return data; }
0449
0450
0451
0452 constexpr auto operator+=(const cpp_double_fp_backend& v) -> cpp_double_fp_backend&
0453 {
0454 const int fpc_u { eval_fpclassify(*this) };
0455 const int fpc_v { eval_fpclassify(v) };
0456
0457 if ((fpc_u != FP_NORMAL) || (fpc_v != FP_NORMAL))
0458 {
0459
0460
0461 if (fpc_u == FP_NAN)
0462 {
0463 return *this;
0464 }
0465
0466 const bool isinf_v { (fpc_v == FP_INFINITE) };
0467
0468 if (fpc_u == FP_INFINITE)
0469 {
0470 if (isinf_v && (isneg_unchecked() != v.isneg_unchecked()))
0471 {
0472 *this = cpp_double_fp_backend::my_value_nan();
0473 }
0474
0475 return *this;
0476 }
0477
0478 const bool iszero_u { ((fpc_u == FP_ZERO) || (fpc_u == FP_SUBNORMAL)) };
0479 const bool isnan_v { (fpc_v == FP_NAN) };
0480
0481 if (iszero_u || (isnan_v || isinf_v))
0482 {
0483 if (iszero_u)
0484 {
0485 data.first = float_type { 0.0F };
0486 data.second = float_type { 0.0F };
0487 }
0488
0489 const bool iszero_v { ((fpc_v == FP_ZERO) || (fpc_v == FP_SUBNORMAL)) };
0490
0491 return ((!iszero_v) ? operator=(v) : *this);
0492 }
0493 }
0494
0495 add_unchecked(v);
0496
0497 return *this;
0498 }
0499
0500 constexpr auto operator-=(const cpp_double_fp_backend& v) -> cpp_double_fp_backend&
0501 {
0502 const int fpc_u { eval_fpclassify(*this) };
0503 const int fpc_v { eval_fpclassify(v) };
0504
0505 if ((fpc_u != FP_NORMAL) || (fpc_v != FP_NORMAL))
0506 {
0507
0508
0509 if (fpc_u == FP_NAN)
0510 {
0511 return *this;
0512 }
0513
0514 const bool isinf_v { (fpc_v == FP_INFINITE) };
0515
0516 if (fpc_u == FP_INFINITE)
0517 {
0518 if (isinf_v && (isneg_unchecked() == v.isneg_unchecked()))
0519 {
0520 *this = cpp_double_fp_backend::my_value_nan();
0521 }
0522
0523 return *this;
0524 }
0525
0526 const bool iszero_u { ((fpc_u == FP_ZERO) || (fpc_u == FP_SUBNORMAL)) };
0527 const bool isnan_v { (fpc_v == FP_NAN) };
0528
0529 if (iszero_u || (isnan_v || isinf_v))
0530 {
0531 if (iszero_u)
0532 {
0533 data.first = float_type { 0.0F };
0534 data.second = float_type { 0.0F };
0535 }
0536
0537 const bool iszero_v { ((fpc_v == FP_ZERO) || (fpc_v == FP_SUBNORMAL)) };
0538
0539 return ((!iszero_v) ? operator=(-v) : *this);
0540 }
0541 }
0542
0543 if (this == &v)
0544 {
0545 data.first = float_type { 0.0F };
0546 data.second = float_type { 0.0F };
0547
0548 return *this;
0549 }
0550
0551 const rep_type thi_tlo { arithmetic::two_diff(data.second, v.data.second) };
0552
0553 data = arithmetic::two_diff(data.first, v.data.first);
0554
0555 if (cpp_df_qf_detail::ccmath::isinf(data.first))
0556 {
0557
0558 const bool b_neg { (data.first < float_type { 0.0F }) };
0559
0560 *this = cpp_double_fp_backend::my_value_inf();
0561
0562 if (b_neg)
0563 {
0564 negate();
0565 }
0566
0567 return *this;
0568 }
0569
0570 data = arithmetic::two_hilo_sum(data.first, data.second + thi_tlo.first);
0571
0572 data = arithmetic::two_hilo_sum(data.first, thi_tlo.second + data.second);
0573
0574 return *this;
0575 }
0576
0577 constexpr auto operator*=(const cpp_double_fp_backend& v) -> cpp_double_fp_backend&
0578 {
0579
0580
0581 const int fpc_u { eval_fpclassify(*this) };
0582 const int fpc_v { eval_fpclassify(v) };
0583
0584 if ((fpc_u != FP_NORMAL) || (fpc_v != FP_NORMAL))
0585 {
0586
0587 const bool isinf_u { (fpc_u == FP_INFINITE) };
0588 const bool isinf_v { (fpc_v == FP_INFINITE) };
0589 const bool iszero_u { (fpc_u == FP_ZERO) };
0590 const bool iszero_v { (fpc_v == FP_ZERO) };
0591
0592 if (((fpc_u == FP_NAN) || (fpc_v == FP_NAN)) || (isinf_u && iszero_v) || (isinf_v && iszero_u))
0593 {
0594 return operator=( cpp_double_fp_backend::my_value_nan());
0595 }
0596
0597 if (isinf_u || isinf_v)
0598 {
0599 const bool b_neg { (isneg_unchecked() != v.isneg_unchecked()) };
0600
0601 *this = cpp_double_fp_backend::my_value_inf();
0602
0603 if (b_neg)
0604 {
0605 negate();
0606 }
0607
0608 return *this;
0609 }
0610
0611 if (iszero_u || iszero_v)
0612 {
0613 return operator=(cpp_double_fp_backend(0));
0614 }
0615 }
0616
0617 mul_unchecked(v);
0618
0619 return *this;
0620 }
0621
0622 constexpr auto operator/=(const cpp_double_fp_backend& v) -> cpp_double_fp_backend&
0623 {
0624 const int fpc_u { eval_fpclassify(*this) };
0625 const int fpc_v { eval_fpclassify(v) };
0626
0627 if ((fpc_u != FP_NORMAL) || (fpc_v != FP_NORMAL))
0628 {
0629
0630 const bool isnan_u { (fpc_u == FP_NAN) };
0631 const bool isnan_v { (fpc_v == FP_NAN) };
0632
0633 if (isnan_u || isnan_v)
0634 {
0635 return operator=(cpp_double_fp_backend::my_value_nan());
0636 }
0637
0638 const bool iszero_u { (fpc_u == FP_ZERO) };
0639 const bool iszero_v { (fpc_v == FP_ZERO) };
0640
0641 if (iszero_u)
0642 {
0643 if (iszero_v)
0644 {
0645 return operator=(cpp_double_fp_backend::my_value_nan());
0646 }
0647 else
0648 {
0649 return operator=(cpp_double_fp_backend(0));
0650 }
0651 }
0652
0653
0654 if (iszero_v)
0655 {
0656 const bool b_neg = isneg_unchecked();
0657
0658 *this = cpp_double_fp_backend::my_value_inf();
0659
0660 if (b_neg)
0661 {
0662 negate();
0663 }
0664
0665 return *this;
0666 }
0667
0668 const bool isinf_v { (fpc_v == FP_INFINITE) };
0669 const bool isinf_u { (fpc_u == FP_INFINITE) };
0670
0671 if (isinf_u)
0672 {
0673 if (isinf_v)
0674 {
0675 return operator=(cpp_double_fp_backend::my_value_nan());
0676 }
0677 else
0678 {
0679 const bool b_neg { isneg_unchecked() };
0680
0681 return operator=((!b_neg) ? cpp_double_fp_backend::my_value_inf() : -cpp_double_fp_backend::my_value_inf());
0682 }
0683 }
0684
0685 if (isinf_v)
0686 {
0687 return operator=(cpp_double_fp_backend(0));
0688 }
0689 }
0690
0691 if (this == &v)
0692 {
0693 data.first = float_type { 1.0F };
0694 data.second = float_type { 0.0F };
0695
0696 return *this;
0697 }
0698
0699
0700
0701
0702
0703
0704
0705 const float_type C { data.first / v.data.first };
0706
0707 float_type c { cpp_df_qf_detail::split_maker<float_type>::value * C };
0708
0709 float_type hc { };
0710
0711 if (cpp_df_qf_detail::ccmath::isinf(c))
0712 {
0713
0714
0715 hc =
0716 cpp_df_qf_detail::ccmath::ldexp
0717 (
0718 C - float_type { C - cpp_df_qf_detail::ccmath::ldexp(C, -cpp_df_qf_detail::split_maker<float_type>::n_shl) },
0719 cpp_df_qf_detail::split_maker<float_type>::n_shl
0720 );
0721 }
0722 else
0723 {
0724 hc = c - float_type { c - C };
0725 }
0726
0727 float_type u { cpp_df_qf_detail::split_maker<float_type>::value * v.data.first };
0728
0729 const float_type hv =
0730 (
0731 cpp_df_qf_detail::ccmath::isinf(u)
0732 ? cpp_df_qf_detail::ccmath::ldexp
0733 (
0734
0735 v.data.first - float_type { v.data.first - cpp_df_qf_detail::ccmath::ldexp(v.data.first, -cpp_df_qf_detail::split_maker<float_type>::n_shl) },
0736 cpp_df_qf_detail::split_maker<float_type>::n_shl
0737 )
0738 : u - float_type { u - v.data.first }
0739 );
0740
0741 const float_type U { C * v.data.first };
0742
0743 u = cpp_df_qf_detail::ccmath::unsafe::fma(hc, hv, -U);
0744
0745 {
0746 const float_type tv { v.data.first - hv };
0747
0748 u = cpp_df_qf_detail::ccmath::unsafe::fma(hc, tv, u);
0749
0750 const float_type tc { C - hc };
0751
0752 u = cpp_df_qf_detail::ccmath::unsafe::fma(tc, hv, u);
0753 u = cpp_df_qf_detail::ccmath::unsafe::fma(tc, tv, u);
0754 }
0755
0756 c = float_type { (data.first - U) - u } + data.second;
0757
0758 c = (c - float_type { C * v.data.second }) / v.data.first;
0759
0760
0761 data.first = C + c;
0762 data.second = float_type { C - data.first } + c;
0763
0764 return *this;
0765 }
0766
0767
0768 constexpr auto operator-() const -> cpp_double_fp_backend
0769 {
0770 cpp_double_fp_backend v { *this };
0771
0772 v.negate();
0773
0774 return v;
0775 }
0776
0777
0778 static constexpr auto pown(cpp_double_fp_backend& result, const cpp_double_fp_backend& x, int p) -> void
0779 {
0780 using local_float_type = cpp_double_fp_backend;
0781
0782 if (p == 2)
0783 {
0784 result = x; result.mul_unchecked(x);
0785 }
0786 else if (p == 3)
0787 {
0788 result = x; result.mul_unchecked(x); result.mul_unchecked(x);
0789 }
0790 else if (p == 4)
0791 {
0792 local_float_type x2 { x };
0793 x2.mul_unchecked(x);
0794
0795 result = x2;
0796 result.mul_unchecked(x2);
0797 }
0798 else if (p == 1)
0799 {
0800 result = x;
0801 }
0802 else if (p < 0)
0803 {
0804
0805
0806 pown(result, local_float_type(1U) / x, -p);
0807 }
0808 else
0809 {
0810 result = local_float_type(1U);
0811
0812 local_float_type y(x);
0813
0814 auto p_local = static_cast<std::uint32_t>(p);
0815
0816 for (;;)
0817 {
0818 if (static_cast<std::uint_fast8_t>(p_local & static_cast<std::uint32_t>(UINT8_C(1))) != static_cast<std::uint_fast8_t>(UINT8_C(0)))
0819 {
0820 result.mul_unchecked(y);
0821 }
0822
0823 p_local >>= 1U;
0824
0825 if (p_local == static_cast<std::uint32_t>(UINT8_C(0)))
0826 {
0827 break;
0828 }
0829 else
0830 {
0831 y.mul_unchecked(y);
0832 }
0833 }
0834 }
0835 }
0836
0837 constexpr auto swap(cpp_double_fp_backend& other) -> void
0838 {
0839 if (this != &other)
0840 {
0841 const rep_type tmp { data };
0842
0843 data = other.data;
0844
0845 other.data = tmp;
0846 }
0847 }
0848
0849 constexpr auto swap(cpp_double_fp_backend&& other) noexcept -> void
0850 {
0851 const rep_type tmp { static_cast<typename cpp_double_fp_backend::rep_type&&>(data) };
0852
0853 data = other.data;
0854
0855 other.data = tmp;
0856 }
0857
0858 constexpr auto compare(const cpp_double_fp_backend& other) const noexcept -> int
0859 {
0860
0861
0862 if ((cpp_df_qf_detail::ccmath::isnan)(data.first))
0863 {
0864 return -1;
0865 }
0866 else
0867 {
0868 return (my_first() > other.my_first()) ? 1 : (my_first() < other.my_first())
0869 ? -1 : (my_second() > other.my_second())
0870 ? 1 : (my_second() < other.my_second())
0871 ? -1 : 0;
0872 }
0873 }
0874
0875
0876
0877
0878
0879 auto str(std::streamsize number_of_digits, const std::ios::fmtflags format_flags) const -> std::string
0880 {
0881
0882
0883
0884 cpp_bin_float_read_write_backend_type f_bin { data.first };
0885
0886 eval_add(f_bin, cpp_bin_float_read_write_backend_type(data.second));
0887
0888 return f_bin.str(number_of_digits, format_flags);
0889 }
0890
0891 constexpr auto order02() const -> int
0892 {
0893
0894
0895
0896
0897
0898
0899 int e2 { };
0900
0901 cpp_double_fp_backend dummy { };
0902
0903 eval_frexp(dummy, *this, &e2);
0904
0905 return e2;
0906 }
0907
0908 static constexpr auto my_value_max() noexcept -> cpp_double_fp_backend
0909 {
0910
0911
0912
0913 return
0914 cpp_double_fp_backend
0915 (
0916 arithmetic::two_hilo_sum
0917 (
0918 float_type
0919 (
0920 (cpp_df_qf_detail::ccmath::numeric_limits<float_type>::max)()
0921 * (
0922 static_cast<float_type>(1.0F)
0923 - static_cast<float_type>(1.5F) * cpp_df_qf_detail::ccmath::sqrt(cpp_df_qf_detail::ccmath::numeric_limits<float_type>::epsilon())
0924 )
0925 ),
0926 float_type
0927 (
0928 cpp_df_qf_detail::ccmath::ldexp
0929 (
0930 (cpp_df_qf_detail::ccmath::numeric_limits<float_type>::max)(),
0931 -cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits
0932 )
0933 )
0934 )
0935 );
0936 }
0937
0938 static constexpr auto my_value_min() noexcept -> cpp_double_fp_backend
0939 {
0940
0941
0942
0943 return
0944 cpp_double_fp_backend
0945 (
0946 float_type
0947 (
0948 cpp_df_qf_detail::ccmath::ldexp
0949 (
0950 (cpp_df_qf_detail::ccmath::numeric_limits<float_type>::min)(),
0951 cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits
0952 )
0953 )
0954 );
0955 }
0956
0957 static constexpr auto my_value_eps() noexcept -> cpp_double_fp_backend
0958 {
0959 return
0960 cpp_double_fp_backend
0961 (
0962 float_type(cpp_df_qf_detail::ccmath::ldexp(float_type { 1 }, int { 3 - my_digits }))
0963 );
0964 }
0965
0966 static constexpr auto my_value_nan() noexcept -> cpp_double_fp_backend
0967 {
0968 return cpp_double_fp_backend(static_cast<float_type>(NAN), static_cast<float_type>(0.0F));
0969 }
0970
0971 static constexpr auto my_value_inf() noexcept -> cpp_double_fp_backend
0972 {
0973 return cpp_double_fp_backend(static_cast<float_type>(HUGE_VAL), static_cast<float_type>(0.0F));
0974 }
0975
0976 static constexpr auto my_value_logmax() -> cpp_double_fp_backend
0977 {
0978 return
0979 cpp_double_fp_backend
0980 (
0981 cpp_df_qf_detail::ccmath::log
0982 (
0983 float_type
0984 (
0985 (cpp_df_qf_detail::ccmath::numeric_limits<float_type>::max)()
0986 * (
0987 static_cast<float_type>(1.0F)
0988 - static_cast<float_type>(1.5F) * cpp_df_qf_detail::ccmath::sqrt(cpp_df_qf_detail::ccmath::numeric_limits<float_type>::epsilon())
0989 )
0990 )
0991 )
0992 );
0993 }
0994
0995 static constexpr auto my_value_logmin() -> cpp_double_fp_backend
0996 {
0997 return
0998 cpp_double_fp_backend
0999 (
1000 cpp_df_qf_detail::ccmath::log
1001 (
1002 float_type
1003 (
1004 cpp_df_qf_detail::ccmath::ldexp
1005 (
1006 (cpp_df_qf_detail::ccmath::numeric_limits<float_type>::min)(),
1007 cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits
1008 )
1009 )
1010 )
1011 );
1012 }
1013
1014 constexpr auto add_unchecked_limb(const float_type v_first) -> void
1015 {
1016 const float_type thi { data.second };
1017
1018 data = arithmetic::two_sum(data.first, v_first);
1019
1020 data = arithmetic::two_hilo_sum(data.first, data.second + thi);
1021
1022 data = arithmetic::two_hilo_sum(data.first, data.second);
1023 }
1024
1025 private:
1026 rep_type data;
1027
1028 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>;
1029
1030 constexpr auto rd_string(const char* p_str) -> bool;
1031
1032 constexpr auto add_unchecked(const cpp_double_fp_backend& v) -> void
1033 {
1034 const rep_type thi_tlo { arithmetic::two_sum(data.second, v.data.second) };
1035
1036 data = arithmetic::two_sum(data.first, v.data.first);
1037
1038 if (cpp_df_qf_detail::ccmath::isinf(data.first))
1039 {
1040
1041 const bool b_neg { (data.first < float_type { 0.0F }) };
1042
1043 *this = cpp_double_fp_backend::my_value_inf();
1044
1045 if (b_neg)
1046 {
1047 negate();
1048 }
1049
1050 return;
1051 }
1052
1053 data = arithmetic::two_hilo_sum(data.first, data.second + thi_tlo.first);
1054
1055 data = arithmetic::two_hilo_sum(data.first, thi_tlo.second + data.second);
1056 }
1057
1058 constexpr auto mul_unchecked(const cpp_double_fp_backend& v) -> void
1059 {
1060
1061
1062
1063
1064
1065
1066 float_type C { cpp_df_qf_detail::split_maker<float_type>::value * data.first };
1067
1068 float_type hu { };
1069
1070 if (cpp_df_qf_detail::ccmath::isinf(C))
1071 {
1072
1073
1074 C = data.first - cpp_df_qf_detail::ccmath::ldexp(data.first, -cpp_df_qf_detail::split_maker<float_type>::n_shl);
1075
1076 hu = cpp_df_qf_detail::ccmath::ldexp(data.first - C, cpp_df_qf_detail::split_maker<float_type>::n_shl);
1077 }
1078 else
1079 {
1080 hu = C - float_type { C - data.first };
1081 }
1082
1083 C = data.first * v.data.first;
1084
1085 if (cpp_df_qf_detail::ccmath::isinf(C))
1086 {
1087
1088 const bool b_neg { (isneg_unchecked() != v.isneg_unchecked()) };
1089
1090 *this = cpp_double_fp_backend::my_value_inf();
1091
1092 if (b_neg)
1093 {
1094 negate();
1095 }
1096
1097 return;
1098 }
1099
1100 float_type c { cpp_df_qf_detail::split_maker<float_type>::value * v.data.first };
1101
1102 float_type hv { };
1103
1104 if (cpp_df_qf_detail::ccmath::isinf(c))
1105 {
1106
1107
1108 c = v.data.first - cpp_df_qf_detail::ccmath::ldexp(v.data.first, -cpp_df_qf_detail::split_maker<float_type>::n_shl);
1109
1110 hv = cpp_df_qf_detail::ccmath::ldexp(v.data.first - c, cpp_df_qf_detail::split_maker<float_type>::n_shl);
1111 }
1112 else
1113 {
1114 hv = c - float_type { c - v.data.first };
1115 }
1116
1117 {
1118 const float_type tv { v.data.first - hv };
1119
1120 const float_type
1121 t1
1122 {
1123 cpp_df_qf_detail::ccmath::unsafe::fma
1124 (
1125 hu,
1126 tv,
1127 cpp_df_qf_detail::ccmath::unsafe::fma(hu, hv, -C)
1128 )
1129 };
1130
1131 const float_type tu { data.first - hu };
1132
1133 c = cpp_df_qf_detail::ccmath::unsafe::fma(tu, tv, cpp_df_qf_detail::ccmath::unsafe::fma(tu, hv, t1))
1134 + (data.first * v.data.second)
1135 + (data.second * v.data.first);
1136 }
1137
1138
1139 data.first = C + c;
1140 data.second = float_type { C - data.first } + c;
1141 }
1142
1143 template <typename OtherFloatingPointType,
1144 typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<OtherFloatingPointType>::value && ((cpp_df_qf_detail::ccmath::numeric_limits<OtherFloatingPointType>::digits10 * 2) < 16))>::type const*>
1145 friend constexpr auto eval_exp(cpp_double_fp_backend<OtherFloatingPointType>& result, const cpp_double_fp_backend<OtherFloatingPointType>& x) -> void;
1146
1147 template <typename OtherFloatingPointType,
1148 typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<OtherFloatingPointType>::value && (((cpp_df_qf_detail::ccmath::numeric_limits<OtherFloatingPointType>::digits10 * 2) >= 16) && ((cpp_df_qf_detail::ccmath::numeric_limits<OtherFloatingPointType>::digits10 * 2) <= 36)))>::type const*>
1149 friend constexpr auto eval_exp(cpp_double_fp_backend<OtherFloatingPointType>& result, const cpp_double_fp_backend<OtherFloatingPointType>& x) -> void;
1150
1151 template <typename OtherFloatingPointType,
1152 typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<OtherFloatingPointType>::value && ((cpp_df_qf_detail::ccmath::numeric_limits<OtherFloatingPointType>::digits10 * 2) > 36))>::type const*>
1153 friend constexpr auto eval_exp(cpp_double_fp_backend<OtherFloatingPointType>& result, const cpp_double_fp_backend<OtherFloatingPointType>& x) -> void;
1154 };
1155
1156 template <typename FloatingPointType>
1157 constexpr auto cpp_double_fp_backend<FloatingPointType>::rd_string(const char* p_str) -> bool
1158 {
1159
1160
1161 cpp_bin_float_read_write_backend_type f_bin { };
1162
1163 f_bin = p_str;
1164
1165 const int fpc { eval_fpclassify(f_bin) };
1166
1167 const bool is_definitely_nan { (fpc == FP_NAN) };
1168
1169 using local_double_fp_type = cpp_double_fp_backend<FloatingPointType>;
1170
1171 if (is_definitely_nan)
1172 {
1173 static_cast<void>(operator=(local_double_fp_type::my_value_nan()));
1174
1175 return true;
1176 }
1177
1178 const bool b_neg { (eval_signbit(f_bin) == 1) };
1179
1180 if (b_neg) { f_bin.negate(); }
1181
1182 const int
1183 expval_from_f_bin
1184 {
1185 [&f_bin]()
1186 {
1187 int expval { };
1188
1189 cpp_bin_float_read_write_backend_type dummy { };
1190
1191 eval_frexp(dummy, f_bin, &expval);
1192
1193 return expval;
1194 }()
1195 };
1196
1197 const auto is_zero_or_subnormal =
1198 (
1199 (fpc == FP_ZERO)
1200 || (expval_from_f_bin < static_cast<typename cpp_bin_float_read_write_backend_type::exponent_type>(local_double_fp_type::my_min_exponent))
1201 );
1202
1203 if (is_zero_or_subnormal)
1204 {
1205 data.first = float_type { 0.0F };
1206 data.second = float_type { 0.0F };
1207
1208 return true;
1209 }
1210
1211 float_type flt_inf_check_first { };
1212
1213 eval_convert_to(&flt_inf_check_first, f_bin);
1214
1215 bool is_definitely_inf { ((fpc == FP_INFINITE) || cpp_df_qf_detail::ccmath::isinf(flt_inf_check_first)) };
1216
1217 if ((!is_definitely_inf) && (flt_inf_check_first > my_value_max().my_first()))
1218 {
1219 cpp_bin_float_read_write_backend_type f_bin_inf_check(f_bin);
1220
1221 eval_subtract(f_bin_inf_check, cpp_bin_float_read_write_backend_type(flt_inf_check_first));
1222
1223 float_type flt_inf_check_second { };
1224
1225 eval_convert_to(&flt_inf_check_second, f_bin_inf_check);
1226
1227 is_definitely_inf = eval_gt(local_double_fp_type(flt_inf_check_first, flt_inf_check_second), my_value_max());
1228 };
1229
1230 if (is_definitely_inf)
1231 {
1232 static_cast<void>(operator=(local_double_fp_type::my_value_inf()));
1233
1234 if (b_neg)
1235 {
1236 negate();
1237 }
1238
1239 return true;
1240 }
1241
1242
1243
1244 data.first = float_type { 0.0F };
1245 data.second = float_type { 0.0F };
1246
1247
1248
1249 constexpr int pow2_scaling_for_small_input { cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits };
1250
1251 const bool
1252 has_pow2_scaling_for_small_input
1253 {
1254 (expval_from_f_bin < static_cast<int>(local_double_fp_type::my_min_exponent + pow2_scaling_for_small_input))
1255 };
1256
1257 if (has_pow2_scaling_for_small_input)
1258 {
1259 eval_ldexp(f_bin, f_bin, pow2_scaling_for_small_input);
1260 }
1261
1262 using local_builtin_float_type = typename std::conditional<(sizeof(float_type) <= sizeof(double)), double, float_type>::type;
1263
1264 constexpr unsigned
1265 digit_limit
1266 {
1267 static_cast<unsigned>
1268 (
1269 static_cast<int>
1270 (
1271 (local_double_fp_type::my_digits / cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits)
1272 + (((local_double_fp_type::my_digits % cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits) != 0) ? 1 : 0)
1273 )
1274 * cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits
1275 )
1276 };
1277
1278 for(auto i = static_cast<unsigned>(UINT8_C(0));
1279 i < digit_limit;
1280 i = static_cast<unsigned>(i + static_cast<unsigned>(cpp_df_qf_detail::ccmath::numeric_limits<local_builtin_float_type>::digits)))
1281 {
1282 local_builtin_float_type flt_part { };
1283
1284 eval_convert_to(&flt_part, f_bin);
1285
1286 eval_subtract(f_bin, cpp_bin_float_read_write_backend_type(flt_part));
1287
1288 eval_add(*this, local_double_fp_type { flt_part });
1289 }
1290
1291 if (has_pow2_scaling_for_small_input)
1292 {
1293 eval_ldexp(*this, *this, -pow2_scaling_for_small_input);
1294 }
1295
1296 if (b_neg) { negate(); }
1297
1298 return true;
1299 }
1300
1301 } } }
1302
1303 #include <boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_constants.hpp>
1304
1305 namespace boost { namespace multiprecision { namespace backends {
1306
1307 template <typename FloatingPointType>
1308 constexpr int cpp_double_fp_backend<FloatingPointType>::my_digits;
1309 template <typename FloatingPointType>
1310 constexpr int cpp_double_fp_backend<FloatingPointType>::my_digits10;
1311 template <typename FloatingPointType>
1312 constexpr int cpp_double_fp_backend<FloatingPointType>::my_max_digits10;
1313 template <typename FloatingPointType>
1314 constexpr int cpp_double_fp_backend<FloatingPointType>::my_max_exponent;
1315 template <typename FloatingPointType>
1316 constexpr int cpp_double_fp_backend<FloatingPointType>::my_min_exponent;
1317 template <typename FloatingPointType>
1318 constexpr int cpp_double_fp_backend<FloatingPointType>::my_max_exponent10;
1319 template <typename FloatingPointType>
1320 constexpr int cpp_double_fp_backend<FloatingPointType>::my_min_exponent10;
1321
1322 template <typename FloatingPointType>
1323 constexpr cpp_double_fp_backend<FloatingPointType> operator+(const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) { return cpp_double_fp_backend<FloatingPointType>(a) += b; }
1324 template <typename FloatingPointType>
1325 constexpr cpp_double_fp_backend<FloatingPointType> operator-(const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) { return cpp_double_fp_backend<FloatingPointType>(a) -= b; }
1326 template <typename FloatingPointType>
1327 constexpr cpp_double_fp_backend<FloatingPointType> operator*(const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) { return cpp_double_fp_backend<FloatingPointType>(a) *= b; }
1328 template <typename FloatingPointType>
1329 constexpr cpp_double_fp_backend<FloatingPointType> operator/(const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) { return cpp_double_fp_backend<FloatingPointType>(a) /= b; }
1330
1331 template <typename FloatingPointType>
1332 constexpr auto eval_add(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void { result += x; }
1333 template <typename FloatingPointType>
1334 constexpr auto eval_add(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> void { result = cpp_double_fp_backend<FloatingPointType>(a) += b; }
1335 template <typename FloatingPointType>
1336 constexpr auto eval_subtract(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void { result -= x; }
1337 template <typename FloatingPointType>
1338 constexpr auto eval_subtract(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> void { result = cpp_double_fp_backend<FloatingPointType>(a) -= b; }
1339 template <typename FloatingPointType>
1340 constexpr auto eval_multiply(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void { result *= x; }
1341 template <typename FloatingPointType>
1342 constexpr auto eval_multiply(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> void { result = cpp_double_fp_backend<FloatingPointType>(a) *= b; }
1343 template <typename FloatingPointType>
1344 constexpr auto eval_divide(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void { result /= x; }
1345 template <typename FloatingPointType>
1346 constexpr auto eval_divide(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> void { result = cpp_double_fp_backend<FloatingPointType>(a) /= b; }
1347 template <typename FloatingPointType>
1348 constexpr auto eval_eq(const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> bool { return (a.compare(b) == 0); }
1349 template <typename FloatingPointType>
1350 constexpr auto eval_lt(const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> bool { return (a.compare(b) == -1); }
1351 template <typename FloatingPointType>
1352 constexpr auto eval_gt(const cpp_double_fp_backend<FloatingPointType>& a, const cpp_double_fp_backend<FloatingPointType>& b) -> bool { return (a.compare(b) == 1); }
1353 template <typename FloatingPointType>
1354
1355 constexpr auto eval_is_zero(const cpp_double_fp_backend<FloatingPointType>& x) -> bool
1356 {
1357 return x.iszero_unchecked();
1358 }
1359
1360 template <typename FloatingPointType>
1361 constexpr auto eval_signbit(const cpp_double_fp_backend<FloatingPointType>& x) -> int
1362 {
1363 return (x.isneg_unchecked() ? 1 : 0);
1364 }
1365
1366 template <typename FloatingPointType>
1367 constexpr auto eval_fabs(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a) -> void
1368 {
1369 result = a;
1370
1371 if (a.isneg_unchecked())
1372 {
1373 result.negate();
1374 }
1375 }
1376
1377 template <typename FloatingPointType>
1378 constexpr auto eval_frexp(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, int* v) -> void
1379 {
1380 using local_backend_type = cpp_double_fp_backend<FloatingPointType>;
1381 using local_float_type = typename local_backend_type::float_type;
1382
1383 int expptr { };
1384
1385 const local_float_type fhi { cpp_df_qf_detail::ccmath::frexp(a.rep().first, &expptr) };
1386 const local_float_type flo { cpp_df_qf_detail::ccmath::ldexp(a.rep().second, -expptr) };
1387
1388 if (v != nullptr)
1389 {
1390 *v = expptr;
1391 }
1392
1393 result.rep() = local_backend_type::arithmetic::normalize(fhi, flo);
1394 }
1395
1396 template <typename FloatingPointType>
1397 constexpr auto eval_ldexp(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& a, int v) -> void
1398 {
1399 using local_backend_type = cpp_double_fp_backend<FloatingPointType>;
1400 using local_float_type = typename local_backend_type::float_type;
1401
1402 const local_float_type fhi { cpp_df_qf_detail::ccmath::ldexp(a.crep().first, v) };
1403 const local_float_type flo { cpp_df_qf_detail::ccmath::ldexp(a.crep().second, v) };
1404
1405 result.rep() = local_backend_type::arithmetic::normalize(fhi, flo);
1406 }
1407
1408 template <typename FloatingPointType>
1409 constexpr auto eval_floor(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void
1410 {
1411 using local_backend_type = cpp_double_fp_backend<FloatingPointType>;
1412 using local_float_type = typename local_backend_type::float_type;
1413
1414 const local_float_type fhi { cpp_df_qf_detail::ccmath::floor(x.my_first()) };
1415
1416 if (fhi != x.my_first())
1417 {
1418 result.rep().first = fhi;
1419 result.rep().second = local_float_type { 0 };
1420 }
1421 else
1422 {
1423 const local_float_type flo = { cpp_df_qf_detail::ccmath::floor(x.my_second()) };
1424
1425 result.rep() = local_backend_type::arithmetic::normalize(fhi, flo);
1426 }
1427 }
1428
1429 template <typename FloatingPointType>
1430 constexpr auto eval_ceil(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void
1431 {
1432
1433 eval_floor(result, -x);
1434
1435 result.negate();
1436 }
1437
1438 template <typename FloatingPointType>
1439 constexpr auto eval_fpclassify(const cpp_double_fp_backend<FloatingPointType>& o) -> int
1440 {
1441 if (cpp_df_qf_detail::ccmath::isnan(o.crep().first)) { return FP_NAN; }
1442 else if (cpp_df_qf_detail::ccmath::isinf(o.crep().first)) { return FP_INFINITE; }
1443 else if (eval_is_zero(o)) { return FP_ZERO; }
1444 else
1445 {
1446 using local_backend_type = cpp_double_fp_backend<FloatingPointType>;
1447 using local_float_type = typename local_backend_type::float_type;
1448
1449 const local_float_type fabs_x { cpp_df_qf_detail::ccmath::fabs(o.crep().first) };
1450
1451 if ((fabs_x > 0) && (fabs_x < (cpp_df_qf_detail::ccmath::numeric_limits<local_float_type>::min)()))
1452 {
1453 return FP_SUBNORMAL;
1454 }
1455 else
1456 {
1457 return FP_NORMAL;
1458 }
1459 }
1460 }
1461
1462 template <typename FloatingPointType>
1463 constexpr auto eval_sqrt(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& o) -> void
1464 {
1465 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
1466 using local_float_type = typename double_float_type::float_type;
1467
1468 const int fpc { eval_fpclassify(o) };
1469
1470 const bool isneg_o { o.isneg_unchecked() };
1471
1472 if ((fpc != FP_NORMAL) || isneg_o)
1473 {
1474 if (fpc == FP_ZERO)
1475 {
1476 result = double_float_type(0);
1477
1478 return;
1479 }
1480 else if ((fpc == FP_NAN) || isneg_o)
1481 {
1482 result = double_float_type::my_value_nan();
1483
1484 return;
1485 }
1486 else if (fpc == FP_INFINITE)
1487 {
1488 result = double_float_type::my_value_inf();
1489
1490 return;
1491 }
1492 }
1493
1494
1495
1496
1497 const local_float_type c { cpp_df_qf_detail::ccmath::sqrt(o.crep().first) };
1498
1499 local_float_type p { cpp_df_qf_detail::split_maker<local_float_type>::value * c };
1500
1501 const local_float_type hx { local_float_type { c - p } + p };
1502 const local_float_type tx { c - hx };
1503
1504 local_float_type q = hx * tx;
1505
1506 q = q + q;
1507
1508 p = hx * hx;
1509
1510 const local_float_type u { p + q };
1511
1512 const local_float_type uu { cpp_df_qf_detail::ccmath::unsafe::fma(tx, tx, local_float_type { p - u } + q) };
1513
1514 const local_float_type
1515 cc
1516 {
1517 local_float_type { local_float_type { o.crep().first - u } - uu + o.crep().second } / local_float_type { c + c }
1518 };
1519
1520 result.rep().first = c + cc;
1521 result.rep().second = local_float_type { c - result.my_first() } + cc;
1522 }
1523
1524 template <typename FloatingPointType>
1525 constexpr auto eval_pow(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x, const cpp_double_fp_backend<FloatingPointType>& a) -> void
1526 {
1527 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
1528
1529 constexpr double_float_type zero { 0 };
1530
1531 result = zero;
1532
1533 signed long long val_nll { };
1534
1535 eval_convert_to(&val_nll, a);
1536
1537 const int na { static_cast<int>(val_nll) };
1538
1539 const int fpc_a { eval_fpclassify(a) };
1540
1541 if((fpc_a == FP_NORMAL) && (a.compare(double_float_type(na)) == 0))
1542 {
1543 eval_pow(result, x, na);
1544 }
1545 else
1546 {
1547 constexpr double_float_type one { 1 };
1548
1549 const int fpc_x { eval_fpclassify(x) };
1550
1551 if (fpc_a == FP_ZERO)
1552 {
1553
1554
1555 result = one;
1556 }
1557 else if (fpc_x == FP_ZERO)
1558 {
1559 if ((fpc_a == FP_NORMAL) || (fpc_a == FP_INFINITE))
1560 {
1561
1562
1563
1564
1565
1566
1567 result = (eval_signbit(a) ? double_float_type::my_value_inf() : zero);
1568 }
1569 else if (fpc_a == FP_NAN)
1570 {
1571 result = double_float_type::my_value_nan();
1572 }
1573 }
1574 else if (fpc_x == FP_INFINITE)
1575 {
1576 if ((fpc_a == FP_NORMAL) || (fpc_a == FP_INFINITE))
1577 {
1578
1579
1580
1581 result = (eval_signbit(a) ? zero : double_float_type::my_value_inf());
1582 }
1583 else if (fpc_a == FP_NAN)
1584 {
1585 result = double_float_type::my_value_nan();
1586 }
1587 }
1588 else if (fpc_x != FP_NORMAL)
1589 {
1590 result = x;
1591 }
1592 else
1593 {
1594 if (fpc_a == FP_INFINITE)
1595 {
1596 constexpr double_float_type one_minus { -1 };
1597
1598 if (x.compare(one_minus) == 0)
1599 {
1600 result = one;
1601 }
1602 else
1603 {
1604 double_float_type xabs { };
1605
1606 eval_fabs(xabs, x);
1607
1608 const int compare_one_result { xabs.compare(one) };
1609
1610 result =
1611 (
1612 (compare_one_result < 0) ? (eval_signbit(a) ? double_float_type::my_value_inf() : zero)
1613 : (compare_one_result > 0) ? (eval_signbit(a) ? zero : double_float_type::my_value_inf())
1614 : one
1615 );
1616 }
1617 }
1618 else if (fpc_a == FP_NAN)
1619 {
1620 result = (x.compare(one) == 0) ? one : double_float_type::my_value_nan();
1621 }
1622 else
1623 {
1624 double_float_type log_x { };
1625
1626 eval_log(log_x, x);
1627
1628 double_float_type a_log_x { };
1629
1630 eval_multiply(a_log_x, a, log_x);
1631
1632 eval_exp(result, a_log_x);
1633 }
1634 }
1635 }
1636 }
1637
1638 template <typename FloatingPointType,
1639 typename IntegralType>
1640 constexpr auto eval_pow(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x, IntegralType p) -> typename ::std::enable_if<::boost::multiprecision::detail::is_integral<IntegralType>::value, void>::type
1641 {
1642 const int fpc { eval_fpclassify(x) };
1643
1644 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
1645
1646 using local_integral_type = IntegralType;
1647
1648 const bool p_is_odd { (static_cast<local_integral_type>(p & 1) != static_cast<local_integral_type>(0)) };
1649
1650 if (p == static_cast<local_integral_type>(0))
1651 {
1652
1653
1654 result = double_float_type { unsigned { UINT8_C(1) } };
1655 }
1656 else if (fpc != FP_NORMAL)
1657 {
1658 if (fpc == FP_ZERO)
1659 {
1660
1661
1662
1663
1664
1665
1666
1667
1668 result = ((p < static_cast<local_integral_type>(0)) ? double_float_type::my_value_inf() : double_float_type { unsigned { UINT8_C(0) } });
1669 }
1670 else if (fpc == FP_INFINITE)
1671 {
1672 if (eval_signbit(x))
1673 {
1674 if (p < static_cast<local_integral_type>(0))
1675 {
1676
1677
1678
1679 result = double_float_type { unsigned { UINT8_C(0) } };
1680 }
1681 else
1682 {
1683
1684
1685
1686 result = (p_is_odd ? -double_float_type::my_value_inf() : double_float_type::my_value_inf());
1687 }
1688 }
1689 else
1690 {
1691
1692
1693
1694 result = ((p < static_cast<local_integral_type>(0)) ? double_float_type { unsigned { UINT8_C(0) } } : double_float_type::my_value_inf());
1695 }
1696 }
1697 else
1698 {
1699 result = double_float_type::my_value_nan();
1700 }
1701 }
1702 else
1703 {
1704 double_float_type::pown(result, x, p);
1705 }
1706 }
1707
1708 template <typename FloatingPointType,
1709 typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && ((cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits10 * 2) < 16))>::type const*>
1710 constexpr auto eval_exp(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void
1711 {
1712 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
1713
1714 constexpr double_float_type one { 1 };
1715
1716 const int fpc { eval_fpclassify(x) };
1717
1718 const bool b_neg { x.isneg_unchecked() };
1719
1720 if (fpc == FP_ZERO)
1721 {
1722 result = one;
1723 }
1724 else if (fpc != FP_NORMAL)
1725 {
1726 if (fpc == FP_INFINITE)
1727 {
1728 result = (b_neg ? double_float_type { 0.0F } : double_float_type::my_value_inf());
1729 }
1730 else if (fpc == FP_NAN)
1731 {
1732 result = x;
1733 }
1734 }
1735 else
1736 {
1737 using local_float_type = typename double_float_type::float_type;
1738
1739
1740 const double_float_type xx { (!b_neg) ? x : -x };
1741
1742
1743 if (eval_lt(x, double_float_type::my_value_logmin()))
1744 {
1745 result = double_float_type(0U);
1746 }
1747 else if (eval_gt(xx, double_float_type::my_value_logmax()))
1748 {
1749 result = double_float_type::my_value_inf();
1750 }
1751 else if (xx.is_one())
1752 {
1753 if(!b_neg)
1754 {
1755 result = cpp_df_qf_detail::constant_df_exp1<local_float_type>();
1756 }
1757 else
1758 {
1759 eval_divide(result, one, cpp_df_qf_detail::constant_df_exp1<local_float_type>());
1760 }
1761 }
1762 else
1763 {
1764
1765
1766 double_float_type nf { };
1767
1768
1769 const bool b_scale { (xx.order02() > -1) };
1770
1771 double_float_type r { };
1772
1773 if (b_scale)
1774 {
1775 eval_floor(nf, xx / cpp_df_qf_detail::constant_df_ln_two<local_float_type>());
1776
1777 eval_ldexp(r, xx - (nf * cpp_df_qf_detail::constant_df_ln_two<local_float_type>()), -2);
1778 }
1779 else
1780 {
1781 r = xx;
1782 }
1783
1784
1785
1786
1787
1788
1789 constexpr double_float_type n84(84);
1790 constexpr double_float_type n240(240);
1791 constexpr double_float_type n7920(7920);
1792
1793 constexpr double_float_type n665280(665280);
1794 constexpr double_float_type n332640(332640);
1795 constexpr double_float_type n75600(75600);
1796 constexpr double_float_type n10080(10080);
1797 constexpr double_float_type n840(840);
1798 constexpr double_float_type n42(42);
1799
1800 const double_float_type r2 { r * r };
1801
1802
1803 result = (n84 * r * (n7920 + (n240 + r2) * r2));
1804 const double_float_type bot = (n665280 + r * (-n332640 + r * (n75600 + r * (-n10080 + r * (n840 + (-n42 + r) * r)))));
1805
1806 eval_divide(result, bot);
1807 result.add_unchecked_limb(local_float_type { 1.0F });
1808
1809
1810 if (b_scale)
1811 {
1812 result *= result;
1813 result *= result;
1814
1815 signed long long lln { };
1816
1817 eval_convert_to(&lln, nf);
1818
1819 const int n { static_cast<int>(lln) };
1820
1821 if (n > 0)
1822 {
1823 eval_ldexp(result, result, n);
1824 }
1825 }
1826
1827 if (b_neg)
1828 {
1829 eval_divide(result, one, result);
1830 }
1831 }
1832 }
1833 }
1834
1835 template <typename FloatingPointType,
1836 typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (((cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits10 * 2) >= 16) && ((cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits10 * 2) <= 36)))>::type const*>
1837 constexpr auto eval_exp(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void
1838 {
1839 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
1840
1841 constexpr double_float_type one { 1 };
1842
1843 const int fpc { eval_fpclassify(x) };
1844
1845 const bool b_neg { x.isneg_unchecked() };
1846
1847 if (fpc == FP_ZERO)
1848 {
1849 result = one;
1850 }
1851 else if (fpc != FP_NORMAL)
1852 {
1853 if (fpc == FP_INFINITE)
1854 {
1855 result = (b_neg ? double_float_type(0) : double_float_type::my_value_inf());
1856 }
1857 else if (fpc == FP_NAN)
1858 {
1859 result = x;
1860 }
1861 }
1862 else
1863 {
1864 using local_float_type = typename double_float_type::float_type;
1865
1866
1867 const double_float_type xx { (!b_neg) ? x : -x };
1868
1869
1870 if (eval_lt(x, double_float_type::my_value_logmin()))
1871 {
1872 result = double_float_type(0U);
1873 }
1874 else if (eval_gt(xx, double_float_type::my_value_logmax()))
1875 {
1876 result = double_float_type::my_value_inf();
1877 }
1878 else if (xx.is_one())
1879 {
1880 if(!b_neg)
1881 {
1882 result = cpp_df_qf_detail::constant_df_exp1<local_float_type>();
1883 }
1884 else
1885 {
1886 eval_divide(result, one, cpp_df_qf_detail::constant_df_exp1<local_float_type>());
1887 }
1888 }
1889 else
1890 {
1891
1892
1893 double_float_type nf { };
1894
1895
1896 const bool b_scale { (xx.order02() > -4) };
1897
1898 double_float_type r { };
1899
1900 if (b_scale)
1901 {
1902 eval_floor(nf, xx / cpp_df_qf_detail::constant_df_ln_two<local_float_type>());
1903
1904 eval_ldexp(r, xx - (nf * cpp_df_qf_detail::constant_df_ln_two<local_float_type>()), -4);
1905 }
1906 else
1907 {
1908 r = xx;
1909 }
1910
1911
1912
1913
1914 constexpr double_float_type n144(144U);
1915 constexpr double_float_type n3603600(3603600UL);
1916 constexpr double_float_type n120120(120120UL);
1917 constexpr double_float_type n770(770U);
1918
1919 constexpr double_float_type n518918400(518918400UL);
1920 constexpr double_float_type n259459200(259459200UL);
1921 constexpr double_float_type n60540480(60540480UL);
1922 constexpr double_float_type n8648640(8648640UL);
1923 constexpr double_float_type n831600(831600UL);
1924 constexpr double_float_type n55440(55440U);
1925 constexpr double_float_type n2520(2520U);
1926 constexpr double_float_type n72(72U);
1927
1928 const double_float_type r2 { r * r };
1929
1930 result = (n144 * r) * (n3603600 + r2 * (n120120 + r2 * (n770 + r2)));
1931 const double_float_type bot = (n518918400 + r * (-n259459200 + r * (n60540480 + r * (-n8648640 + r * (n831600 + r * (-n55440 + r * (n2520 + r * (-n72 + r))))))));
1932
1933 eval_divide(result, bot);
1934 result.add_unchecked_limb(local_float_type { 1.0F });
1935
1936
1937 if (b_scale)
1938 {
1939 result *= result;
1940 result *= result;
1941 result *= result;
1942 result *= result;
1943
1944 signed long long lln { };
1945
1946 eval_convert_to(&lln, nf);
1947
1948 const int n { static_cast<int>(lln) };
1949
1950 if (n > 0)
1951 {
1952 eval_ldexp(result, result, n);
1953 }
1954 }
1955
1956 if (b_neg)
1957 {
1958 eval_divide(result, one, result);
1959 }
1960 }
1961 }
1962 }
1963
1964 template <typename FloatingPointType,
1965 typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && ((cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits10 * 2) > 36))>::type const*>
1966 constexpr auto eval_exp(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void
1967 {
1968 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
1969
1970 constexpr double_float_type one { 1 };
1971
1972 const int fpc { eval_fpclassify(x) };
1973
1974 const bool b_neg { x.isneg_unchecked() };
1975
1976 if (fpc == FP_ZERO)
1977 {
1978 result = one;
1979 }
1980 else if (fpc != FP_NORMAL)
1981 {
1982 if (fpc == FP_INFINITE)
1983 {
1984 result = (b_neg ? double_float_type(0) : double_float_type::my_value_inf());
1985 }
1986 else if (fpc == FP_NAN)
1987 {
1988 result = x;
1989 }
1990 }
1991 else
1992 {
1993 using local_float_type = typename double_float_type::float_type;
1994
1995
1996 const double_float_type xx { (!b_neg) ? x : -x };
1997
1998
1999 if (eval_lt(x, double_float_type::my_value_logmin()))
2000 {
2001 result = double_float_type(0U);
2002 }
2003 else if (eval_gt(xx, double_float_type::my_value_logmax()))
2004 {
2005 result = double_float_type::my_value_inf();
2006 }
2007 else if (xx.is_one())
2008 {
2009 if(!b_neg)
2010 {
2011 result = cpp_df_qf_detail::constant_df_exp1<local_float_type>();
2012 }
2013 else
2014 {
2015 eval_divide(result, one, cpp_df_qf_detail::constant_df_exp1<local_float_type>());
2016 }
2017 }
2018 else
2019 {
2020
2021
2022 double_float_type nf { };
2023
2024
2025 const bool b_scale { (xx.order02() > -4) };
2026
2027 double_float_type xh { };
2028
2029 if (b_scale)
2030 {
2031 eval_floor(nf, xx / cpp_df_qf_detail::constant_df_ln_two<local_float_type>());
2032
2033 eval_ldexp(xh, xx - (nf * cpp_df_qf_detail::constant_df_ln_two<local_float_type>()), -4);
2034 }
2035 else
2036 {
2037 xh = xx;
2038 }
2039
2040 double_float_type x_pow_n_div_n_fact(xh);
2041
2042 result = x_pow_n_div_n_fact;
2043 result.add_unchecked_limb(local_float_type { 1.0F });
2044
2045 double_float_type dummy { };
2046
2047
2048
2049
2050 for (unsigned n { UINT8_C(2) }; n < unsigned { UINT8_C(64) }; ++n)
2051 {
2052 eval_multiply(x_pow_n_div_n_fact, xh);
2053
2054 eval_divide(x_pow_n_div_n_fact, double_float_type(n));
2055
2056 int n_tol { };
2057
2058 eval_frexp(dummy, x_pow_n_div_n_fact, &n_tol);
2059
2060 if ((n > 4U) && (n_tol < -(double_float_type::my_digits - 1)))
2061 {
2062 break;
2063 }
2064
2065 eval_add(result, x_pow_n_div_n_fact);
2066 }
2067
2068
2069 if (b_scale)
2070 {
2071 result *= result;
2072 result *= result;
2073 result *= result;
2074 result *= result;
2075
2076 signed long long lln { };
2077
2078 eval_convert_to(&lln, nf);
2079
2080 const int n { static_cast<int>(lln) };
2081
2082 if (n > 0)
2083 {
2084 eval_ldexp(result, result, n);
2085 }
2086 }
2087
2088 if (b_neg)
2089 {
2090 eval_divide(result, one, result);
2091 }
2092 }
2093 }
2094 }
2095
2096 template <typename FloatingPointType>
2097 constexpr auto eval_log(cpp_double_fp_backend<FloatingPointType>& result, const cpp_double_fp_backend<FloatingPointType>& x) -> void
2098 {
2099 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
2100
2101 constexpr double_float_type one { 1 };
2102
2103 const int result_compare_with_one { x.compare(one) };
2104
2105 const int fpc { eval_fpclassify(x) };
2106
2107 if (fpc == FP_ZERO)
2108 {
2109 result = -double_float_type::my_value_inf();
2110 }
2111 else if (x.isneg_unchecked() || (fpc == FP_NAN))
2112 {
2113 result = double_float_type::my_value_nan();
2114 }
2115 else if (fpc == FP_INFINITE)
2116 {
2117 result = double_float_type::my_value_inf();
2118 }
2119 else if (result_compare_with_one == -1)
2120 {
2121
2122
2123 double_float_type x_inv { };
2124
2125 eval_divide(x_inv, one, x);
2126 eval_log(result, x_inv);
2127
2128 result.negate();
2129 }
2130 else if (result_compare_with_one == 1)
2131 {
2132
2133
2134
2135 double_float_type x2 { };
2136
2137 int n2 { };
2138
2139 eval_frexp(x2, x, &n2);
2140
2141
2142 using local_float_type = typename double_float_type::float_type;
2143
2144 const local_float_type s { cpp_df_qf_detail::ccmath::log(x2.my_first()) };
2145
2146 double_float_type E { };
2147
2148 eval_exp(E, double_float_type(s));
2149
2150
2151
2152
2153 eval_subtract(result, x2, E);
2154 eval_divide(result, E);
2155 result.add_unchecked_limb(s);
2156
2157 double_float_type xn2 { n2 };
2158
2159 eval_multiply(xn2, cpp_df_qf_detail::constant_df_ln_two<local_float_type>());
2160
2161 eval_add(result, xn2);
2162 }
2163 else
2164 {
2165 result = double_float_type { 0 };
2166 }
2167 }
2168
2169 namespace detail {
2170
2171 template<typename DestType, typename FloatingPointType>
2172 constexpr auto extract(cpp_double_fp_backend<FloatingPointType>& source) -> DestType
2173 {
2174 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
2175 using local_float_type = typename double_float_type::float_type;
2176
2177 using destination_type = DestType;
2178
2179 destination_type result { };
2180
2181 constexpr double_float_type zero { 0 };
2182
2183 result = static_cast<destination_type>(0);
2184
2185 unsigned fail_safe { UINT32_C(32) };
2186
2187 constexpr bool
2188 destination_type_is_longer
2189 {
2190 (std::numeric_limits<signed long long>::digits > cpp_df_qf_detail::ccmath::numeric_limits<local_float_type>::digits)
2191 };
2192
2193 using float_extract_type = typename std::conditional<destination_type_is_longer, local_float_type, float>::type;
2194
2195 while((source.compare(zero) != 0) && (fail_safe > unsigned { UINT8_C(0) }))
2196 {
2197 const float_extract_type next_flt_val { static_cast<float_extract_type>(source.my_first()) };
2198
2199 result += static_cast<destination_type>(next_flt_val);
2200
2201 eval_subtract(source, double_float_type(next_flt_val));
2202
2203 --fail_safe;
2204 }
2205
2206 return result;
2207 }
2208
2209 }
2210
2211 template <typename FloatingPointType>
2212 constexpr auto eval_convert_to(signed long long* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> void
2213 {
2214 const auto fpc = eval_fpclassify(backend);
2215
2216 if (fpc != FP_NORMAL)
2217 {
2218 *result = static_cast<signed long long>(backend.crep().first);
2219 }
2220 else
2221 {
2222 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
2223 using local_float_type = typename double_float_type::float_type;
2224
2225 static_assert(std::is_same<local_float_type, FloatingPointType>::value, "Error something went wrong with the limb type");
2226
2227 constexpr bool
2228 long_long_is_longer
2229 {
2230 (std::numeric_limits<signed long long>::digits > cpp_df_qf_detail::ccmath::numeric_limits<local_float_type>::digits)
2231 };
2232
2233 using longer_type = typename ::std::conditional<long_long_is_longer, signed long long, double_float_type>::type;
2234
2235 constexpr longer_type my_max_val { static_cast<longer_type>((std::numeric_limits<signed long long>::max)()) };
2236 constexpr longer_type my_min_val { static_cast<longer_type>((std::numeric_limits<signed long long>::min)()) };
2237
2238 constexpr double_float_type my_max_val_dd { static_cast<double_float_type>(my_max_val) };
2239 constexpr double_float_type my_min_val_dd { static_cast<double_float_type>(my_min_val) };
2240
2241 if (backend.compare(my_max_val_dd) >= 0)
2242 {
2243 *result = (std::numeric_limits<signed long long>::max)();
2244 }
2245 else if (backend.compare(my_min_val_dd) <= 0)
2246 {
2247 *result = (std::numeric_limits<signed long long>::min)();
2248 }
2249 else
2250 {
2251 double_float_type source { backend };
2252
2253 *result = detail::extract<signed long long>(source);
2254
2255 #if !defined(__x86_64__) && !defined(_M_X64)
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269 constexpr bool
2270 needs_workaround
2271 {
2272 (sizeof(signed long long) == 8U)
2273 && (std::is_same<local_float_type, double>::value || (std::is_same<local_float_type, long double>::value))
2274 };
2275
2276 BOOST_IF_CONSTEXPR (needs_workaround)
2277 {
2278
2279 constexpr signed long long upper_bound = 9223372036854775296LL;
2280
2281 if (!eval_signbit(backend) && *result >= upper_bound)
2282 {
2283
2284
2285
2286 *result += static_cast<signed long long>(1);
2287 }
2288 }
2289
2290 #endif
2291 }
2292 }
2293 }
2294
2295 template <typename FloatingPointType>
2296 constexpr auto eval_convert_to(unsigned long long* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> void
2297 {
2298 const auto fpc = eval_fpclassify(backend);
2299
2300 if (fpc != FP_NORMAL)
2301 {
2302 *result = static_cast<unsigned long long>(backend.crep().first);
2303 }
2304 else
2305 {
2306 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
2307 using local_float_type = typename double_float_type::float_type;
2308
2309 static_assert(std::is_same<local_float_type, FloatingPointType>::value, "Error something went wrong with the limb type");
2310
2311 constexpr bool
2312 ulong_long_is_longer
2313 {
2314 (std::numeric_limits<unsigned long long>::digits > cpp_df_qf_detail::ccmath::numeric_limits<local_float_type>::digits)
2315 };
2316
2317 using longer_type = typename ::std::conditional<ulong_long_is_longer, unsigned long long, double_float_type>::type;
2318
2319 constexpr longer_type my_max_val { static_cast<longer_type>((std::numeric_limits<unsigned long long>::max)()) };
2320
2321 constexpr double_float_type my_max_val_dd { static_cast<double_float_type>(my_max_val) };
2322
2323 if (backend.compare(my_max_val_dd) >= 0)
2324 {
2325 *result = (std::numeric_limits<unsigned long long>::max)();
2326 }
2327 else
2328 {
2329 double_float_type source { backend };
2330
2331 *result = detail::extract<unsigned long long>(source);
2332 }
2333 }
2334 }
2335
2336 #ifdef BOOST_HAS_INT128
2337 template <typename FloatingPointType>
2338 constexpr auto eval_convert_to(boost::int128_type* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> typename std::enable_if<(cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits > 24), void>::type
2339 {
2340 const auto fpc = eval_fpclassify(backend);
2341
2342 if (fpc != FP_NORMAL)
2343 {
2344 *result = static_cast<boost::int128_type>(backend.crep().first);
2345 }
2346 else
2347 {
2348 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
2349 using local_float_type = typename double_float_type::float_type;
2350
2351 static_assert(std::is_same<local_float_type, FloatingPointType>::value, "Error something went wrong with the limb type");
2352
2353 constexpr bool
2354 n128_is_longer
2355 {
2356 ((static_cast<int>(sizeof(boost::int128_type) * static_cast<std::size_t>(CHAR_BIT)) - 1) > cpp_df_qf_detail::ccmath::numeric_limits<local_float_type>::digits)
2357 };
2358
2359 using longer_type = typename ::std::conditional<n128_is_longer, boost::int128_type, double_float_type>::type;
2360
2361 constexpr boost::int128_type my_max_val_n128 = (((static_cast<boost::int128_type>(1) << (sizeof(boost::int128_type) * CHAR_BIT - 2)) - 1) << 1) + 1;
2362 constexpr boost::int128_type my_min_val_n128 = static_cast<boost::int128_type>(-my_max_val_n128 - 1);
2363
2364 constexpr longer_type my_max_val(static_cast<longer_type>(my_max_val_n128));
2365 constexpr longer_type my_min_val(static_cast<longer_type>(my_min_val_n128));
2366
2367 constexpr double_float_type my_max_val_dd(static_cast<double_float_type>(my_max_val));
2368 constexpr double_float_type my_min_val_dd(static_cast<double_float_type>(my_min_val));
2369
2370 if (backend.compare(my_max_val_dd) >= 0)
2371 {
2372 *result = my_max_val;
2373 }
2374 else if (backend.compare(my_min_val_dd) <= 0)
2375 {
2376 *result = my_min_val;
2377 }
2378 else
2379 {
2380 double_float_type source { backend };
2381
2382 *result = detail::extract<boost::int128_type>(source);
2383 }
2384 }
2385 }
2386
2387 template <typename FloatingPointType>
2388 constexpr auto eval_convert_to(boost::int128_type* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> typename std::enable_if<!(cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits > 24), void>::type
2389 {
2390 const auto fpc = eval_fpclassify(backend);
2391
2392 if (fpc != FP_NORMAL)
2393 {
2394 *result = static_cast<boost::int128_type>(backend.crep().first);
2395 }
2396 else
2397 {
2398 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
2399
2400 double_float_type source { backend };
2401
2402 *result = detail::extract<boost::int128_type>(source);
2403 }
2404 }
2405
2406 template <typename FloatingPointType>
2407 constexpr auto eval_convert_to(boost::uint128_type* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> typename std::enable_if<(cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits > 24), void>::type
2408 {
2409 const auto fpc = eval_fpclassify(backend);
2410
2411 if (fpc != FP_NORMAL)
2412 {
2413 *result = static_cast<boost::int128_type>(backend.crep().first);
2414 }
2415 else
2416 {
2417 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
2418 using local_float_type = typename double_float_type::float_type;
2419
2420 static_assert(std::is_same<local_float_type, FloatingPointType>::value, "Error something went wrong with the limb type");
2421
2422 constexpr bool
2423 u128_is_longer
2424 {
2425 (static_cast<int>(sizeof(boost::uint128_type) * static_cast<std::size_t>(CHAR_BIT)) > cpp_df_qf_detail::ccmath::numeric_limits<local_float_type>::digits)
2426 };
2427
2428 using longer_type = typename ::std::conditional<u128_is_longer, boost::uint128_type, double_float_type>::type;
2429
2430 constexpr boost::uint128_type my_max_val_u128 = static_cast<boost::uint128_type>(~static_cast<boost::uint128_type>(0));
2431
2432 constexpr longer_type my_max_val(static_cast<longer_type>(my_max_val_u128));
2433
2434 constexpr double_float_type my_max_val_dd(static_cast<double_float_type>(my_max_val));
2435
2436 if (backend.compare(my_max_val_dd) >= 0)
2437 {
2438 *result = my_max_val;
2439 }
2440 else
2441 {
2442 double_float_type source { backend };
2443
2444 *result = detail::extract<boost::uint128_type>(source);
2445 }
2446 }
2447 }
2448
2449 template <typename FloatingPointType>
2450 constexpr auto eval_convert_to(boost::uint128_type* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> typename std::enable_if<!(cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits > 24), void>::type
2451 {
2452 const auto fpc = eval_fpclassify(backend);
2453
2454 if (fpc != FP_NORMAL)
2455 {
2456 *result = static_cast<boost::uint128_type>(backend.crep().first);
2457 }
2458 else
2459 {
2460 using double_float_type = cpp_double_fp_backend<FloatingPointType>;
2461
2462 double_float_type source { backend };
2463
2464 *result = detail::extract<boost::uint128_type>(source);
2465 }
2466 }
2467 #endif
2468
2469 template <typename FloatingPointType,
2470 typename OtherFloatingPointType>
2471 constexpr auto eval_convert_to(OtherFloatingPointType* result, const cpp_double_fp_backend<FloatingPointType>& backend) -> typename ::std::enable_if<cpp_df_qf_detail::is_floating_point<OtherFloatingPointType>::value>::type
2472 {
2473 const auto fpc = eval_fpclassify(backend);
2474
2475
2476
2477 if (fpc != FP_NORMAL)
2478 {
2479 *result = static_cast<OtherFloatingPointType>(backend.my_first());
2480 }
2481 else
2482 {
2483 BOOST_IF_CONSTEXPR(cpp_df_qf_detail::ccmath::numeric_limits<OtherFloatingPointType>::digits > cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits)
2484 {
2485 *result = static_cast<OtherFloatingPointType>(backend.my_first());
2486 *result += static_cast<OtherFloatingPointType>(backend.my_second());
2487 }
2488 else
2489 {
2490 cpp_double_fp_backend<FloatingPointType> source = backend;
2491
2492 *result = 0;
2493
2494 for(auto digit_count = static_cast<int>(0);
2495 digit_count < cpp_double_fp_backend<FloatingPointType>::my_digits;
2496 digit_count += cpp_df_qf_detail::ccmath::numeric_limits<OtherFloatingPointType>::digits)
2497 {
2498 const auto next = static_cast<OtherFloatingPointType>(source.my_first());
2499
2500 *result += next;
2501
2502 eval_subtract(source, cpp_double_fp_backend<FloatingPointType>(next));
2503 }
2504 }
2505 }
2506 }
2507
2508 template <typename FloatingPointType>
2509 constexpr auto hash_value(const cpp_double_fp_backend<FloatingPointType>& a) -> ::std::size_t
2510 {
2511 return a.hash();
2512 }
2513
2514 }
2515
2516 using backends::cpp_double_fp_backend;
2517
2518 using cpp_double_float = number<cpp_double_fp_backend<float>, ::boost::multiprecision::et_off>;
2519 using cpp_double_double = number<cpp_double_fp_backend<double>, ::boost::multiprecision::et_off>;
2520 using cpp_double_long_double = number<cpp_double_fp_backend<long double>, ::boost::multiprecision::et_off>;
2521 #ifdef BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128
2522 using cpp_double_float128 = number<cpp_double_fp_backend<::boost::float128_type>, ::boost::multiprecision::et_off>;
2523 #endif
2524
2525 } }
2526
2527 namespace std {
2528
2529
2530 template <typename FloatingPointType,
2531 const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2532 BOOST_MP_DF_QF_NUM_LIMITS_CLASS_TYPE numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >
2533 {
2534 private:
2535 using local_float_type = FloatingPointType;
2536 using inner_self_type = boost::multiprecision::cpp_double_fp_backend<local_float_type>;
2537
2538 using self_type = boost::multiprecision::number<inner_self_type, ExpressionTemplatesOption>;
2539
2540 public:
2541 static constexpr bool is_specialized = true;
2542 static constexpr bool is_signed = true;
2543 static constexpr bool is_integer = false;
2544 static constexpr bool is_exact = false;
2545 static constexpr bool is_bounded = true;
2546 static constexpr bool is_modulo = false;
2547 static constexpr bool is_iec559 = false;
2548 static constexpr bool has_infinity = true;
2549 static constexpr bool has_quiet_NaN = true;
2550 static constexpr bool has_signaling_NaN = false;
2551
2552
2553 #ifdef BOOST_MSVC
2554 #pragma warning(push)
2555 #pragma warning(disable:4996)
2556 #endif
2557
2558 static constexpr float_denorm_style has_denorm = denorm_absent;
2559 static constexpr bool has_denorm_loss = true;
2560
2561 #ifdef BOOST_MSVC
2562 #pragma warning(pop)
2563 #endif
2564
2565 static constexpr bool traps = false;
2566 static constexpr bool tinyness_before = false;
2567 static constexpr float_round_style round_style = round_to_nearest;
2568
2569 static constexpr int radix = 2;
2570 static constexpr int digits = inner_self_type::my_digits;
2571 static constexpr int digits10 = inner_self_type::my_digits10;
2572 static constexpr int max_digits10 = inner_self_type::my_max_digits10;
2573
2574 static constexpr int max_exponent = inner_self_type::my_max_exponent;
2575 static constexpr int min_exponent = inner_self_type::my_min_exponent;
2576 static constexpr int max_exponent10 = inner_self_type::my_max_exponent10;
2577 static constexpr int min_exponent10 = inner_self_type::my_min_exponent10;
2578
2579 static constexpr auto(min) () noexcept -> self_type { return static_cast<self_type>(inner_self_type::my_value_min()); }
2580 static constexpr auto(max) () noexcept -> self_type { return static_cast<self_type>(inner_self_type::my_value_max()); }
2581 static constexpr auto lowest () noexcept -> self_type { return static_cast<self_type>(-(max)()); }
2582 static constexpr auto epsilon () noexcept -> self_type { return static_cast<self_type>(inner_self_type::my_value_eps()); }
2583 static constexpr auto round_error () noexcept -> self_type { return static_cast<self_type>(static_cast<local_float_type>(0.5)); }
2584 static constexpr auto denorm_min () noexcept -> self_type { return static_cast<self_type>((min)()); }
2585 static constexpr auto infinity () noexcept -> self_type { return static_cast<self_type>(inner_self_type::my_value_inf()); }
2586 static constexpr auto quiet_NaN () noexcept -> self_type { return static_cast<self_type>(inner_self_type::my_value_nan()); }
2587 static constexpr auto signaling_NaN() noexcept -> self_type { return static_cast<self_type>(static_cast<local_float_type>(0.0)); }
2588 };
2589
2590 }
2591
2592 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2593 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::is_specialized;
2594 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2595 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::is_signed;
2596 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2597 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::is_integer;
2598 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2599 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::is_exact;
2600 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2601 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::is_bounded;
2602 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2603 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::is_modulo;
2604 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2605 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::is_iec559;
2606
2607 #ifdef BOOST_MSVC
2608 #pragma warning(push)
2609 #pragma warning(disable:4996)
2610 #endif
2611
2612 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2613 constexpr std::float_denorm_style std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::has_denorm;
2614 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2615 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::has_denorm_loss;
2616
2617 #ifdef BOOST_MSVC
2618 #pragma warning(pop)
2619 #endif
2620
2621 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2622 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::has_infinity;
2623 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2624 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::has_quiet_NaN;
2625 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2626 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::has_signaling_NaN;
2627 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2628 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::traps;
2629 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2630 constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::tinyness_before;
2631 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2632 constexpr std::float_round_style std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::round_style;
2633 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2634 constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::radix;
2635 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2636 constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::digits;
2637 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2638 constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::digits10;
2639 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2640 constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::max_digits10;
2641 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2642 constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::max_exponent;
2643 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2644 constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::min_exponent;
2645 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2646 constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::max_exponent10;
2647 template <typename FloatingPointType, const boost::multiprecision::expression_template_option ExpressionTemplatesOption>
2648 constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplatesOption> >::min_exponent10;
2649
2650 #if defined(BOOST_MP_MATH_AVAILABLE)
2651 namespace boost { namespace math { namespace policies {
2652
2653 template <class FloatingPointType, class Policy, boost::multiprecision::expression_template_option ExpressionTemplates>
2654 struct precision<boost::multiprecision::number<boost::multiprecision::cpp_double_fp_backend<FloatingPointType>, ExpressionTemplates>, Policy>
2655 {
2656 private:
2657 using my_multiprecision_backend_type = boost::multiprecision::cpp_double_fp_backend<FloatingPointType>;
2658
2659 using digits2_type = digits2<my_multiprecision_backend_type::my_digits>;
2660
2661 static constexpr auto use_full_precision() noexcept -> bool
2662 {
2663 return ((digits2_type::value <= precision_type::value) || (precision_type::value <= 0));
2664 }
2665
2666 public:
2667 using precision_type = typename Policy::precision_type;
2668
2669 using type =
2670 typename std::conditional<use_full_precision(),
2671 digits2_type,
2672 precision_type>::type;
2673 };
2674
2675 } } }
2676 #endif
2677
2678 #endif