File indexing completed on 2025-01-30 09:48:39
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MP_CPP_BIN_FLOAT_HPP
0009 #define BOOST_MP_CPP_BIN_FLOAT_HPP
0010
0011 #include <cmath>
0012 #include <cstdint>
0013 #include <limits>
0014 #include <type_traits>
0015 #include <boost/multiprecision/cpp_int.hpp>
0016 #include <boost/multiprecision/integer.hpp>
0017 #include <boost/multiprecision/detail/standalone_config.hpp>
0018 #include <boost/multiprecision/detail/fpclassify.hpp>
0019 #include <boost/multiprecision/detail/float_string_cvt.hpp>
0020 #include <boost/multiprecision/traits/max_digits10.hpp>
0021 #include <boost/multiprecision/detail/hash.hpp>
0022 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
0023 #include <boost/multiprecision/detail/assert.hpp>
0024 #include <boost/multiprecision/detail/float128_functions.hpp>
0025 #include <boost/multiprecision/detail/functions/trunc.hpp>
0026
0027
0028
0029
0030 #ifdef BOOST_MP_MATH_AVAILABLE
0031 #include <boost/math/special_functions/asinh.hpp>
0032 #include <boost/math/special_functions/acosh.hpp>
0033 #include <boost/math/special_functions/atanh.hpp>
0034 #include <boost/math/special_functions/cbrt.hpp>
0035 #include <boost/math/special_functions/expm1.hpp>
0036 #include <boost/math/special_functions/gamma.hpp>
0037 #endif
0038
0039 #ifdef BOOST_HAS_FLOAT128
0040 #include <quadmath.h>
0041 #endif
0042
0043 namespace boost {
0044 namespace multiprecision {
0045 namespace backends {
0046
0047 #ifdef BOOST_MSVC
0048 #pragma warning(push)
0049 #pragma warning(disable : 4522 6326)
0050 #endif
0051
0052 namespace detail {
0053
0054 template <class U>
0055 inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<U>::value, bool>::type is_negative(U) { return false; }
0056 template <class S>
0057 inline typename std::enable_if< !boost::multiprecision::detail::is_unsigned<S>::value, bool>::type is_negative(S s) { return s < 0; }
0058
0059 template <class Float, std::ptrdiff_t, bool = number_category<Float>::value == number_kind_floating_point>
0060 struct is_cpp_bin_float_implicitly_constructible_from_type
0061 {
0062 static constexpr bool value = false;
0063 };
0064
0065 template <class Float, std::ptrdiff_t bit_count>
0066 struct is_cpp_bin_float_implicitly_constructible_from_type<Float, bit_count, true>
0067 {
0068 static constexpr bool value = (std::numeric_limits<Float>::digits <= static_cast<int>(bit_count)) && (std::numeric_limits<Float>::radix == 2) && std::numeric_limits<Float>::is_specialized
0069 #ifdef BOOST_HAS_FLOAT128
0070 && !std::is_same<Float, float128_type>::value
0071 #endif
0072 && (std::is_floating_point<Float>::value || is_number<Float>::value);
0073 };
0074
0075 template <class Float, std::ptrdiff_t, bool = number_category<Float>::value == number_kind_floating_point>
0076 struct is_cpp_bin_float_explicitly_constructible_from_type
0077 {
0078 static constexpr bool value = false;
0079 };
0080
0081 template <class Float, std::ptrdiff_t bit_count>
0082 struct is_cpp_bin_float_explicitly_constructible_from_type<Float, bit_count, true>
0083 {
0084 static constexpr bool value = (std::numeric_limits<Float>::digits > static_cast<int>(bit_count)) && (std::numeric_limits<Float>::radix == 2) && std::numeric_limits<Float>::is_specialized
0085 #ifdef BOOST_HAS_FLOAT128
0086 && !std::is_same<Float, float128_type>::value
0087 #endif
0088 ;
0089 };
0090
0091 }
0092
0093 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent>
0094 class cpp_bin_float
0095 {
0096 public:
0097 static constexpr unsigned bit_count = DigitBase == digit_base_2 ? Digits : (Digits * 1000uL) / 301uL + (((Digits * 1000uL) % 301) ? 2u : 1u);
0098 using rep_type = cpp_int_backend<std::is_void<Allocator>::value ? bit_count : 0, bit_count, std::is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator>;
0099 using double_rep_type = cpp_int_backend<std::is_void<Allocator>::value ? 2 * bit_count : 0, 2 * bit_count, std::is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator>;
0100
0101 using signed_types = typename rep_type::signed_types;
0102 using unsigned_types = typename rep_type::unsigned_types;
0103 using float_types = std::tuple<float, double, long double>;
0104 using exponent_type = Exponent;
0105
0106 static constexpr exponent_type max_exponent_limit = (std::numeric_limits<exponent_type>::max)()- 2 * static_cast<exponent_type>(bit_count);
0107 static constexpr exponent_type min_exponent_limit = (std::numeric_limits<exponent_type>::min)() + 2 * static_cast<exponent_type>(bit_count);
0108
0109 static_assert(MinExponent >= min_exponent_limit, "Template parameter MinExponent is too negative for our internal logic to function correctly, sorry!");
0110 static_assert(MaxExponent <= max_exponent_limit, "Template parameter MaxExponent is too large for our internal logic to function correctly, sorry!");
0111 static_assert(MinExponent <= 0, "Template parameter MinExponent can not be positive!");
0112 static_assert(MaxExponent >= 0, "Template parameter MaxExponent can not be negative!");
0113
0114 static constexpr exponent_type max_exponent = MaxExponent == 0 ? max_exponent_limit : MaxExponent;
0115 static constexpr exponent_type min_exponent = MinExponent == 0 ? min_exponent_limit : MinExponent;
0116
0117 static constexpr exponent_type exponent_zero = max_exponent + 1;
0118 static constexpr exponent_type exponent_infinity = max_exponent + 2;
0119 static constexpr exponent_type exponent_nan = max_exponent + 3;
0120
0121 private:
0122 rep_type m_data;
0123 exponent_type m_exponent;
0124 bool m_sign;
0125
0126 public:
0127 cpp_bin_float() noexcept(noexcept(rep_type())) : m_data(), m_exponent(exponent_zero), m_sign(false) {}
0128
0129 cpp_bin_float(const cpp_bin_float& o) noexcept(noexcept(rep_type(std::declval<const rep_type&>())))
0130 : m_data(o.m_data), m_exponent(o.m_exponent), m_sign(o.m_sign) {}
0131
0132 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
0133 cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE>& o, typename std::enable_if<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = nullptr)
0134 {
0135 *this = o;
0136 }
0137 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
0138 explicit cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE>& o, typename std::enable_if< !(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = nullptr)
0139 : m_exponent(o.exponent()), m_sign(o.sign())
0140 {
0141 *this = o;
0142 }
0143
0144 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
0145 cpp_bin_float(cpp_bin_float<D, B, A, E, MinE, MaxE>&& o, typename std::enable_if<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = nullptr)noexcept(noexcept(rep_type(std::declval<rep_type&&>())))
0146 {
0147 *this = std::move(o);
0148 }
0149 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
0150 explicit cpp_bin_float(cpp_bin_float<D, B, A, E, MinE, MaxE>&& o, typename std::enable_if< !(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = nullptr) noexcept(noexcept(rep_type(std::declval<rep_type&&>())))
0151 : m_exponent(o.exponent()), m_sign(o.sign())
0152 {
0153 *this = std::move(o);
0154 }
0155 template <class Float>
0156 cpp_bin_float(const Float& f,
0157 typename std::enable_if<detail::is_cpp_bin_float_implicitly_constructible_from_type<Float, static_cast<std::ptrdiff_t>(bit_count)>::value>::type const* = nullptr)
0158 : m_data(), m_exponent(0), m_sign(false)
0159 {
0160 this->assign_float(f);
0161 }
0162
0163 template <class Float>
0164 explicit cpp_bin_float(const Float& f,
0165 typename std::enable_if<detail::is_cpp_bin_float_explicitly_constructible_from_type<Float, static_cast<std::ptrdiff_t>(bit_count)>::value>::type const* = nullptr)
0166 : m_data(), m_exponent(0), m_sign(false)
0167 {
0168 this->assign_float(f);
0169 }
0170 #ifdef BOOST_HAS_FLOAT128
0171 template <class Float>
0172 cpp_bin_float(const Float& f,
0173 typename std::enable_if<
0174 std::is_same<Float, float128_type>::value && (static_cast<int>(bit_count) >= 113)>::type const* = nullptr)
0175 : m_data(), m_exponent(0), m_sign(false)
0176 {
0177 this->assign_float(f);
0178 }
0179 template <class Float>
0180 explicit cpp_bin_float(const Float& f,
0181 typename std::enable_if<
0182 std::is_same<Float, float128_type>::value && (static_cast<int>(bit_count) < 113)>::type const* = nullptr)
0183 : m_data(), m_exponent(0), m_sign(false)
0184 {
0185 this->assign_float(f);
0186 }
0187 #endif
0188 cpp_bin_float& operator=(const cpp_bin_float& o) noexcept(noexcept(std::declval<rep_type&>() = std::declval<const rep_type&>()))
0189 {
0190 m_data = o.m_data;
0191 m_exponent = o.m_exponent;
0192 m_sign = o.m_sign;
0193 return *this;
0194 }
0195
0196 template <class A, class E, E MinE, E MaxE>
0197 cpp_bin_float& operator=(const cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>& o) noexcept(noexcept(std::declval<rep_type&>() = std::declval<const rep_type&>()))
0198 {
0199 m_data = o.bits();
0200 m_sign = o.sign();
0201 if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_zero)
0202 m_exponent = exponent_zero;
0203 else if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_nan)
0204 m_exponent = exponent_nan;
0205 else if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_infinity)
0206 m_exponent = exponent_infinity;
0207 else if (o.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
0208 {
0209
0210 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
0211 bits() = static_cast<limb_type>(0u);
0212 }
0213 else if (o.exponent() < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
0214 {
0215
0216 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
0217 bits() = static_cast<limb_type>(0u);
0218 }
0219 else
0220 m_exponent = o.exponent();
0221 return *this;
0222 }
0223
0224 template <class A, class E, E MinE, E MaxE>
0225 cpp_bin_float& operator=(cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>&& o) noexcept(noexcept(std::declval<rep_type&>() = std::declval<rep_type&&>()))
0226 {
0227 m_data = std::move(o.bits());
0228 m_sign = o.sign();
0229 if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_zero)
0230 m_exponent = exponent_zero;
0231 else if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_nan)
0232 m_exponent = exponent_nan;
0233 else if (o.exponent() == cpp_bin_float<Digits, DigitBase, A, E, MinE, MaxE>::exponent_infinity)
0234 m_exponent = exponent_infinity;
0235 else if (o.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
0236 {
0237
0238 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
0239 bits() = static_cast<limb_type>(0u);
0240 }
0241 else if (o.exponent() < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
0242 {
0243
0244 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
0245 bits() = static_cast<limb_type>(0u);
0246 }
0247 else
0248 m_exponent = o.exponent();
0249 return *this;
0250 }
0251 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
0252 cpp_bin_float& operator=(const cpp_bin_float<D, B, A, E, MinE, MaxE>& f)
0253 {
0254 switch (eval_fpclassify(f))
0255 {
0256 case FP_ZERO:
0257 m_data = limb_type(0);
0258 m_sign = f.sign();
0259 m_exponent = exponent_zero;
0260 break;
0261 case FP_NAN:
0262 m_data = limb_type(0);
0263 m_sign = false;
0264 m_exponent = exponent_nan;
0265 break;
0266 ;
0267 case FP_INFINITE:
0268 m_data = limb_type(0);
0269 m_sign = f.sign();
0270 m_exponent = exponent_infinity;
0271 break;
0272 default:
0273 typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(f.bits());
0274 this->exponent() = f.exponent() + (E)bit_count - (E)cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count;
0275 this->sign() = f.sign();
0276 copy_and_round(*this, b);
0277 }
0278 return *this;
0279 }
0280 #ifdef BOOST_HAS_FLOAT128
0281 template <class Float>
0282 typename std::enable_if<
0283 (number_category<Float>::value == number_kind_floating_point)
0284
0285 && ((std::numeric_limits<Float>::radix == 2) || (std::is_same<Float, float128_type>::value)),
0286 cpp_bin_float&>::type
0287 operator=(const Float& f)
0288 #else
0289 template <class Float>
0290 typename std::enable_if<
0291 (number_category<Float>::value == number_kind_floating_point)
0292
0293 && (std::numeric_limits<Float>::radix == 2),
0294 cpp_bin_float&>::type
0295 operator=(const Float& f)
0296 #endif
0297 {
0298 return assign_float(f);
0299 }
0300
0301 #ifdef BOOST_HAS_FLOAT128
0302 template <class Float>
0303 typename std::enable_if<std::is_same<Float, float128_type>::value, cpp_bin_float&>::type assign_float(Float f)
0304 {
0305 using default_ops::eval_add;
0306 using bf_int_type = typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type;
0307 if (f == 0)
0308 {
0309 m_data = limb_type(0);
0310 m_sign = (signbitq(f) > 0);
0311 m_exponent = exponent_zero;
0312 return *this;
0313 }
0314 else if (isnanq(f))
0315 {
0316 m_data = limb_type(0);
0317 m_sign = false;
0318 m_exponent = exponent_nan;
0319 return *this;
0320 }
0321 else if (isinfq(f))
0322 {
0323 m_data = limb_type(0);
0324 m_sign = (f < 0);
0325 m_exponent = exponent_infinity;
0326 return *this;
0327 }
0328 if (f < 0)
0329 {
0330 *this = -f;
0331 this->negate();
0332 return *this;
0333 }
0334
0335 using ui_type = typename std::tuple_element<0, unsigned_types>::type;
0336 m_data = static_cast<ui_type>(0u);
0337 m_sign = false;
0338 m_exponent = 0;
0339
0340 constexpr std::ptrdiff_t bits = sizeof(int) * CHAR_BIT - 1;
0341 int e;
0342 f = frexpq(f, &e);
0343 while (f)
0344 {
0345 f = ldexpq(f, bits);
0346 e -= bits;
0347 int ipart = static_cast<int>(truncq(f));
0348 f -= ipart;
0349 m_exponent += bits;
0350 cpp_bin_float t;
0351 t = static_cast<bf_int_type>(ipart);
0352 eval_add(*this, t);
0353 }
0354 m_exponent += static_cast<Exponent>(e);
0355 return *this;
0356 }
0357 #endif
0358 #ifdef BOOST_HAS_FLOAT128
0359 template <class Float>
0360 typename std::enable_if<std::is_floating_point<Float>::value && !std::is_same<Float, float128_type>::value, cpp_bin_float&>::type assign_float(Float f)
0361 #else
0362 template <class Float>
0363 typename std::enable_if<std::is_floating_point<Float>::value, cpp_bin_float&>::type assign_float(Float f)
0364 #endif
0365 {
0366 using std::frexp;
0367 using std::ldexp;
0368 using std::signbit;
0369 using default_ops::eval_add;
0370 using bf_int_type = typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type;
0371
0372 switch (BOOST_MP_FPCLASSIFY(f))
0373 {
0374 case FP_ZERO:
0375 m_data = limb_type(0);
0376 m_sign = ((signbit)(f));
0377 m_exponent = exponent_zero;
0378 return *this;
0379 case FP_NAN:
0380 m_data = limb_type(0);
0381 m_sign = false;
0382 m_exponent = exponent_nan;
0383 return *this;
0384 case FP_INFINITE:
0385 m_data = limb_type(0);
0386 m_sign = (f < 0);
0387 m_exponent = exponent_infinity;
0388 return *this;
0389 }
0390 if (f < 0)
0391 {
0392 *this = -f;
0393 this->negate();
0394 return *this;
0395 }
0396
0397 using ui_type = typename std::tuple_element<0, unsigned_types>::type;
0398 m_data = static_cast<ui_type>(0u);
0399 m_sign = false;
0400 m_exponent = 0;
0401
0402 constexpr std::ptrdiff_t bits = sizeof(int) * CHAR_BIT - 1;
0403 int e;
0404 f = frexp(f, &e);
0405 while (f != static_cast<Float>(0.0F))
0406 {
0407 f = ldexp(f, bits);
0408 e -= static_cast<int>(bits);
0409 int ipart = boost::multiprecision::detail::itrunc(f);
0410 f -= static_cast<Float>(ipart);
0411 m_exponent += static_cast<exponent_type>(bits);
0412 cpp_bin_float t;
0413 t = static_cast<bf_int_type>(ipart);
0414 eval_add(*this, t);
0415 }
0416 m_exponent += static_cast<Exponent>(e);
0417 return *this;
0418 }
0419
0420 template <class Float>
0421 typename std::enable_if<
0422 (number_category<Float>::value == number_kind_floating_point) && !std::is_floating_point<Float>::value && (number_category<Float>::value == number_kind_floating_point),
0423 cpp_bin_float&>::type
0424 assign_float(Float f)
0425 {
0426 using default_ops::eval_add;
0427 using default_ops::eval_convert_to;
0428 using default_ops::eval_get_sign;
0429 using default_ops::eval_subtract;
0430
0431 using f_int_type = typename boost::multiprecision::detail::canonical<int, Float>::type ;
0432 using bf_int_type = typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type;
0433
0434 switch (eval_fpclassify(f))
0435 {
0436 case FP_ZERO:
0437 m_data = limb_type(0);
0438 m_sign = (eval_get_sign(f) > 0);
0439 m_exponent = exponent_zero;
0440 return *this;
0441 case FP_NAN:
0442 m_data = limb_type(0);
0443 m_sign = false;
0444 m_exponent = exponent_nan;
0445 return *this;
0446 case FP_INFINITE:
0447 m_data = limb_type(0);
0448 m_sign = eval_get_sign(f) < 0;
0449 m_exponent = exponent_infinity;
0450 return *this;
0451 }
0452 if (eval_get_sign(f) < 0)
0453 {
0454 f.negate();
0455 assign_float(f);
0456 this->negate();
0457 return *this;
0458 }
0459
0460 using ui_type = typename std::tuple_element<0, unsigned_types>::type;
0461 m_data = static_cast<ui_type>(0u);
0462 m_sign = false;
0463 m_exponent = 0;
0464
0465 constexpr std::ptrdiff_t bits = sizeof(int) * CHAR_BIT - 1;
0466 int e;
0467 eval_frexp(f, f, &e);
0468 while (eval_get_sign(f) != 0)
0469 {
0470 eval_ldexp(f, f, bits);
0471 e -= bits;
0472 int ipart;
0473 eval_convert_to(&ipart, f);
0474 eval_subtract(f, static_cast<f_int_type>(ipart));
0475 m_exponent += bits;
0476 eval_add(*this, static_cast<bf_int_type>(ipart));
0477 }
0478 m_exponent += e;
0479 if (m_exponent > max_exponent)
0480 m_exponent = exponent_infinity;
0481 if (m_exponent < min_exponent)
0482 {
0483 m_data = limb_type(0u);
0484 m_exponent = exponent_zero;
0485 m_sign = (eval_get_sign(f) > 0);
0486 }
0487 else if (eval_get_sign(m_data) == 0)
0488 {
0489 m_exponent = exponent_zero;
0490 m_sign = (eval_get_sign(f) > 0);
0491 }
0492 return *this;
0493 }
0494 template <class B, expression_template_option et>
0495 cpp_bin_float& assign_float(const number<B, et>& f)
0496 {
0497 return assign_float(f.backend());
0498 }
0499
0500 template <class I>
0501 typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, cpp_bin_float&>::type operator=(const I& i)
0502 {
0503 using default_ops::eval_bit_test;
0504 if (!i)
0505 {
0506 m_data = static_cast<limb_type>(0);
0507 m_exponent = exponent_zero;
0508 m_sign = false;
0509 }
0510 else
0511 {
0512 using ui_type = typename boost::multiprecision::detail::make_unsigned<I>::type ;
0513 ui_type fi = static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(i));
0514 using ar_type = typename boost::multiprecision::detail::canonical<ui_type, rep_type>::type;
0515 m_data = static_cast<ar_type>(fi);
0516 std::size_t shift = msb(fi);
0517 if (shift >= bit_count)
0518 {
0519 m_exponent = static_cast<Exponent>(shift);
0520 m_data = static_cast<ar_type>(fi >> (shift + 1 - bit_count));
0521 }
0522 else
0523 {
0524 m_exponent = static_cast<Exponent>(shift);
0525 eval_left_shift(m_data, bit_count - shift - 1);
0526 }
0527 BOOST_MP_ASSERT(eval_bit_test(m_data, bit_count - 1));
0528 m_sign = detail::is_negative(i);
0529 }
0530 return *this;
0531 }
0532
0533 cpp_bin_float& operator=(const char* s);
0534
0535 void swap(cpp_bin_float& o) noexcept
0536 {
0537 m_data.swap(o.m_data);
0538 std::swap(m_exponent, o.m_exponent);
0539 std::swap(m_sign, o.m_sign);
0540 }
0541
0542 std::string str(std::streamsize dig, std::ios_base::fmtflags f) const;
0543
0544 void negate()
0545 {
0546 if (m_exponent != exponent_nan)
0547 m_sign = !m_sign;
0548 }
0549
0550 int compare(const cpp_bin_float& o) const noexcept
0551 {
0552 if (m_sign != o.m_sign)
0553 return (m_exponent == exponent_zero) && (m_exponent == o.m_exponent) ? 0 : m_sign ? -1 : 1;
0554 int result;
0555 if (m_exponent == exponent_nan)
0556 return -1;
0557 else if (m_exponent != o.m_exponent)
0558 {
0559 if (m_exponent == exponent_zero)
0560 result = -1;
0561 else if (o.m_exponent == exponent_zero)
0562 result = 1;
0563 else
0564 result = m_exponent > o.m_exponent ? 1 : -1;
0565 }
0566 else
0567 result = m_data.compare(o.m_data);
0568 if (m_sign)
0569 result = -result;
0570 return result;
0571 }
0572 template <class A>
0573 int compare(const A& o) const noexcept
0574 {
0575 cpp_bin_float b;
0576 b = o;
0577 return compare(b);
0578 }
0579
0580 rep_type& bits() { return m_data; }
0581 const rep_type& bits() const { return m_data; }
0582 exponent_type& exponent() { return m_exponent; }
0583 const exponent_type& exponent() const { return m_exponent; }
0584 bool& sign() { return m_sign; }
0585 const bool& sign() const { return m_sign; }
0586 void check_invariants()
0587 {
0588 using default_ops::eval_bit_test;
0589 using default_ops::eval_is_zero;
0590 if ((m_exponent <= max_exponent) && (m_exponent >= min_exponent))
0591 {
0592 BOOST_MP_ASSERT(eval_bit_test(m_data, bit_count - 1));
0593 }
0594 else
0595 {
0596 BOOST_MP_ASSERT(m_exponent > max_exponent);
0597 BOOST_MP_ASSERT(m_exponent <= exponent_nan);
0598 BOOST_MP_ASSERT(eval_is_zero(m_data));
0599 }
0600 }
0601
0602 #ifndef BOOST_MP_STANDALONE
0603 template <class Archive>
0604 void serialize(Archive& ar, const unsigned int )
0605 {
0606 ar& boost::make_nvp("data", m_data);
0607 ar& boost::make_nvp("exponent", m_exponent);
0608 ar& boost::make_nvp("sign", m_sign);
0609 }
0610 #endif
0611 };
0612
0613 #ifdef BOOST_MSVC
0614 #pragma warning(pop)
0615 #endif
0616
0617 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class Int>
0618 inline void copy_and_round(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, Int& arg, std::ptrdiff_t bits_to_keep = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
0619 {
0620
0621
0622 using default_ops::eval_bit_test;
0623 using default_ops::eval_get_sign;
0624 using default_ops::eval_increment;
0625 using default_ops::eval_left_shift;
0626 using default_ops::eval_lsb;
0627 using default_ops::eval_msb;
0628 using default_ops::eval_right_shift;
0629
0630
0631 if (eval_get_sign(arg) == 0)
0632 {
0633 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
0634 res.sign() = false;
0635 res.bits() = static_cast<limb_type>(0u);
0636 return;
0637 }
0638 std::ptrdiff_t msb = static_cast<std::ptrdiff_t>(eval_msb(arg));
0639 if (static_cast<std::ptrdiff_t >(bits_to_keep) > msb + 1)
0640 {
0641
0642
0643 res.bits() = arg;
0644 eval_left_shift(res.bits(), static_cast<double_limb_type>(bits_to_keep - msb - 1));
0645 res.exponent() -= static_cast<Exponent>(bits_to_keep - msb - 1);
0646 }
0647 else if (static_cast<std::ptrdiff_t >(bits_to_keep) < msb + 1)
0648 {
0649
0650
0651 bool roundup = eval_bit_test(arg, static_cast<std::size_t>(msb - bits_to_keep));
0652
0653 if (roundup && (msb - bits_to_keep == static_cast<std::ptrdiff_t>(eval_lsb(arg))))
0654 {
0655
0656 if (!eval_bit_test(arg, static_cast<std::size_t>(msb - bits_to_keep + 1)))
0657 roundup = false;
0658 }
0659
0660 eval_right_shift(arg, static_cast<double_limb_type>(msb - bits_to_keep + 1));
0661 res.exponent() += static_cast<Exponent>(msb - bits_to_keep + 1);
0662 if (roundup)
0663 {
0664 eval_increment(arg);
0665 if (bits_to_keep)
0666 {
0667 if (eval_bit_test(arg, static_cast<std::size_t>(bits_to_keep)))
0668 {
0669
0670
0671 eval_right_shift(arg, 1u);
0672 ++res.exponent();
0673 }
0674 }
0675 else
0676 {
0677
0678
0679 ++bits_to_keep;
0680 }
0681 }
0682 if (bits_to_keep != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
0683 {
0684
0685
0686 eval_left_shift(arg, static_cast<double_limb_type>(static_cast<std::ptrdiff_t>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - bits_to_keep));
0687 res.exponent() -= static_cast<Exponent>(static_cast<std::ptrdiff_t>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - bits_to_keep);
0688 }
0689 res.bits() = arg;
0690 }
0691 else
0692 {
0693 res.bits() = arg;
0694 }
0695 if (!bits_to_keep && !res.bits().limbs()[0])
0696 {
0697
0698 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
0699 return;
0700 }
0701
0702 BOOST_MP_ASSERT(((std::ptrdiff_t )eval_msb(res.bits()) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
0703
0704 if (res.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
0705 {
0706
0707 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
0708 res.bits() = static_cast<limb_type>(0u);
0709 }
0710 else if (res.exponent() < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
0711 {
0712
0713 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
0714 res.bits() = static_cast<limb_type>(0u);
0715 }
0716 }
0717
0718 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class BinFloat2, class BinFloat3>
0719 inline void do_eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
0720 const BinFloat2& a, const BinFloat3& b)
0721 {
0722 if (a.exponent() < b.exponent())
0723 {
0724 bool s = a.sign();
0725 do_eval_add(res, b, a);
0726 if (res.sign() != s)
0727 res.negate();
0728 return;
0729 }
0730
0731 using default_ops::eval_add;
0732 using default_ops::eval_bit_test;
0733
0734 using exponent_type = typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type;
0735
0736 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
0737
0738
0739 switch (a.exponent())
0740 {
0741 case BinFloat2::exponent_zero:
0742 {
0743 bool s = a.sign();
0744 res = b;
0745 res.sign() = s;
0746 return;
0747 }
0748 case BinFloat2::exponent_infinity:
0749 if (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
0750 res = b;
0751 else
0752 res = a;
0753 return;
0754 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
0755 res = a;
0756 return;
0757 }
0758 switch (b.exponent())
0759 {
0760 case BinFloat3::exponent_zero:
0761 res = a;
0762 return;
0763 case BinFloat3::exponent_infinity:
0764 res = b;
0765 if (res.sign())
0766 res.negate();
0767 return;
0768 case BinFloat3::exponent_nan:
0769 res = b;
0770 return;
0771 }
0772
0773 static_assert((std::numeric_limits<exponent_type>::max)() - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent, "Exponent range check failed");
0774
0775 bool s = a.sign();
0776 dt = a.bits();
0777 if (a.exponent() > (std::ptrdiff_t )cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent())
0778 {
0779 res.exponent() = a.exponent();
0780 }
0781 else
0782 {
0783 exponent_type e_diff = a.exponent() - b.exponent();
0784 BOOST_MP_ASSERT(e_diff >= 0);
0785 eval_left_shift(dt, static_cast<double_limb_type>(e_diff));
0786 res.exponent() = a.exponent() - e_diff;
0787 eval_add(dt, b.bits());
0788 }
0789
0790 copy_and_round(res, dt);
0791 res.check_invariants();
0792 if (res.sign() != s)
0793 res.negate();
0794 }
0795
0796 template <class BinFloat1, class BinFloat2, class BinFloat3>
0797 inline void do_eval_subtract(BinFloat1& res, const BinFloat2& a, const BinFloat3& b)
0798 {
0799 using default_ops::eval_bit_test;
0800 using default_ops::eval_decrement;
0801 using default_ops::eval_subtract;
0802
0803 typename BinFloat1::double_rep_type dt;
0804
0805
0806 switch (a.exponent())
0807 {
0808 case BinFloat2::exponent_zero:
0809 if (b.exponent() == BinFloat3::exponent_nan)
0810 res = std::numeric_limits<number<BinFloat1> >::quiet_NaN().backend();
0811 else
0812 {
0813 bool s = a.sign();
0814 res = b;
0815 if (res.exponent() == BinFloat1::exponent_zero)
0816 res.sign() = false;
0817 else if (res.sign() == s)
0818 res.negate();
0819 }
0820 return;
0821 case BinFloat2::exponent_infinity:
0822 if ((b.exponent() == BinFloat3::exponent_nan) || (b.exponent() == BinFloat3::exponent_infinity))
0823 res = std::numeric_limits<number<BinFloat1> >::quiet_NaN().backend();
0824 else
0825 res = a;
0826 return;
0827 case BinFloat2::exponent_nan:
0828 res = a;
0829 return;
0830 }
0831 switch (b.exponent())
0832 {
0833 case BinFloat3::exponent_zero:
0834 res = a;
0835 return;
0836 case BinFloat3::exponent_infinity:
0837 res.exponent() = BinFloat1::exponent_infinity;
0838 res.sign() = !a.sign();
0839 res.bits() = static_cast<limb_type>(0u);
0840 return;
0841 case BinFloat3::exponent_nan:
0842 res = b;
0843 return;
0844 }
0845
0846 bool s = a.sign();
0847 if ((a.exponent() > b.exponent()) || ((a.exponent() == b.exponent()) && a.bits().compare(b.bits()) >= 0))
0848 {
0849 dt = a.bits();
0850 if (a.exponent() <= (std::ptrdiff_t )BinFloat1::bit_count + b.exponent())
0851 {
0852 typename BinFloat1::exponent_type e_diff = a.exponent() - b.exponent();
0853 eval_left_shift(dt, static_cast<double_limb_type>(e_diff));
0854 res.exponent() = a.exponent() - e_diff;
0855 eval_subtract(dt, b.bits());
0856 }
0857 else if (a.exponent() == (std::ptrdiff_t )BinFloat1::bit_count + b.exponent() + 1)
0858 {
0859 if ((eval_lsb(a.bits()) == BinFloat1::bit_count - 1)
0860 && (eval_lsb(b.bits()) != BinFloat1::bit_count - 1))
0861 {
0862 eval_left_shift(dt, 1);
0863 eval_decrement(dt);
0864 res.exponent() = a.exponent() - 1;
0865 }
0866 else
0867 res.exponent() = a.exponent();
0868 }
0869 else
0870 res.exponent() = a.exponent();
0871 }
0872 else
0873 {
0874 dt = b.bits();
0875 if (b.exponent() <= (std::ptrdiff_t )BinFloat1::bit_count + a.exponent())
0876 {
0877 typename BinFloat1::exponent_type e_diff = a.exponent() - b.exponent();
0878 eval_left_shift(dt, static_cast<double_limb_type>(-e_diff));
0879 res.exponent() = b.exponent() + e_diff;
0880 eval_subtract(dt, a.bits());
0881 }
0882 else if (b.exponent() == (std::ptrdiff_t )BinFloat1::bit_count + a.exponent() + 1)
0883 {
0884 if ((eval_lsb(a.bits()) != BinFloat1::bit_count - 1)
0885 && eval_lsb(b.bits()))
0886 {
0887 eval_left_shift(dt, 1);
0888 eval_decrement(dt);
0889 res.exponent() = b.exponent() - 1;
0890 }
0891 else
0892 res.exponent() = b.exponent();
0893 }
0894 else
0895 res.exponent() = b.exponent();
0896 s = !s;
0897 }
0898
0899 copy_and_round(res, dt);
0900 if (res.exponent() == BinFloat1::exponent_zero)
0901 res.sign() = false;
0902 else if (res.sign() != s)
0903 res.negate();
0904 res.check_invariants();
0905 }
0906
0907 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
0908 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2,
0909 class Allocator3, class Exponent3, Exponent MinE3, Exponent MaxE3>
0910 inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
0911 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a,
0912 const cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>& b)
0913 {
0914 if (a.sign() == b.sign())
0915 do_eval_add(res, a, b);
0916 else
0917 do_eval_subtract(res, a, b);
0918 }
0919
0920 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
0921 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
0922 inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
0923 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a)
0924 {
0925 return eval_add(res, res, a);
0926 }
0927
0928 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
0929 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2,
0930 class Allocator3, class Exponent3, Exponent MinE3, Exponent MaxE3>
0931 inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
0932 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a,
0933 const cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>& b)
0934 {
0935 if (a.sign() != b.sign())
0936 do_eval_add(res, a, b);
0937 else
0938 do_eval_subtract(res, a, b);
0939 }
0940
0941 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
0942 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
0943 inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
0944 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a)
0945 {
0946 return eval_subtract(res, res, a);
0947 }
0948
0949 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
0950 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2,
0951 class Allocator3, class Exponent3, Exponent MinE3, Exponent MaxE3>
0952 inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
0953 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a,
0954 const cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>& b)
0955 {
0956 using default_ops::eval_bit_test;
0957 using default_ops::eval_multiply;
0958
0959
0960 switch (a.exponent())
0961 {
0962 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_zero:
0963 {
0964 if (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_nan)
0965 res = b;
0966 else if (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_infinity)
0967 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
0968 else
0969 {
0970 bool s = a.sign() != b.sign();
0971 res = a;
0972 res.sign() = s;
0973 }
0974 return;
0975 }
0976 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_infinity:
0977 switch (b.exponent())
0978 {
0979 case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_zero:
0980 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
0981 break;
0982 case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_nan:
0983 res = b;
0984 break;
0985 default:
0986 bool s = a.sign() != b.sign();
0987 res = a;
0988 res.sign() = s;
0989 break;
0990 }
0991 return;
0992 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_nan:
0993 res = a;
0994 return;
0995 }
0996 if (b.exponent() > cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::max_exponent)
0997 {
0998 bool s = a.sign() != b.sign();
0999 res = b;
1000 res.sign() = s;
1001 return;
1002 }
1003 if ((a.exponent() > 0) && (b.exponent() > 0))
1004 {
1005 if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + 2 - a.exponent() < b.exponent())
1006 {
1007
1008 bool s = a.sign() != b.sign();
1009 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
1010 res.sign() = s;
1011 res.bits() = static_cast<limb_type>(0u);
1012 return;
1013 }
1014 }
1015 if ((a.exponent() < 0) && (b.exponent() < 0))
1016 {
1017 if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - 2 - a.exponent() > b.exponent())
1018 {
1019
1020 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
1021 res.sign() = a.sign() != b.sign();
1022 res.bits() = static_cast<limb_type>(0u);
1023 return;
1024 }
1025 }
1026
1027 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
1028 eval_multiply(dt, a.bits(), b.bits());
1029 res.exponent() = a.exponent() + b.exponent() - (Exponent)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
1030 copy_and_round(res, dt);
1031 res.check_invariants();
1032 res.sign() = a.sign() != b.sign();
1033 }
1034
1035 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
1036 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
1037 inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
1038 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a)
1039 {
1040 eval_multiply(res, res, a);
1041 }
1042
1043 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
1044 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2, class U>
1045 inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
1046 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a, const U& b)
1047 {
1048 using default_ops::eval_bit_test;
1049 using default_ops::eval_multiply;
1050
1051 bool s = a.sign();
1052
1053
1054 switch (a.exponent())
1055 {
1056 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_zero:
1057 {
1058 res = a;
1059 res.sign() = s;
1060 return;
1061 }
1062 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_infinity:
1063 if (b == 0)
1064 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1065 else
1066 res = a;
1067 return;
1068 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_nan:
1069 res = a;
1070 return;
1071 }
1072
1073 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
1074 using canon_ui_type = typename boost::multiprecision::detail::canonical<U, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::type;
1075 eval_multiply(dt, a.bits(), static_cast<canon_ui_type>(b));
1076 res.exponent() = a.exponent();
1077 copy_and_round(res, dt);
1078 res.check_invariants();
1079 res.sign() = s;
1080 }
1081
1082 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
1083 inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const U& b)
1084 {
1085 eval_multiply(res, res, b);
1086 }
1087
1088 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
1089 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2, class S>
1090 inline typename std::enable_if<boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
1091 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& a, const S& b)
1092 {
1093 using ui_type = typename boost::multiprecision::detail::make_unsigned<S>::type;
1094 eval_multiply(res, a, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(b)));
1095 if (b < 0)
1096 res.negate();
1097 }
1098
1099 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
1100 inline typename std::enable_if<boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const S& b)
1101 {
1102 eval_multiply(res, res, b);
1103 }
1104
1105 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
1106 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2,
1107 class Allocator3, class Exponent3, Exponent MinE3, Exponent MaxE3>
1108 inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
1109 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& u,
1110 const cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>& v)
1111 {
1112 #ifdef BOOST_MSVC
1113 #pragma warning(push)
1114 #pragma warning(disable : 6326)
1115 #endif
1116 using default_ops::eval_bit_test;
1117 using default_ops::eval_get_sign;
1118 using default_ops::eval_increment;
1119 using default_ops::eval_qr;
1120 using default_ops::eval_subtract;
1121
1122
1123
1124
1125 switch (u.exponent())
1126 {
1127 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_zero:
1128 {
1129 switch (v.exponent())
1130 {
1131 case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_zero:
1132 case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_nan:
1133 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1134 return;
1135 }
1136 bool s = u.sign() != v.sign();
1137 res = u;
1138 res.sign() = s;
1139 return;
1140 }
1141 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_infinity:
1142 {
1143 switch (v.exponent())
1144 {
1145 case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_infinity:
1146 case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_nan:
1147 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1148 return;
1149 }
1150 bool s = u.sign() != v.sign();
1151 res = u;
1152 res.sign() = s;
1153 return;
1154 }
1155 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_nan:
1156 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1157 return;
1158 }
1159 switch (v.exponent())
1160 {
1161 case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_zero:
1162 {
1163 bool s = u.sign() != v.sign();
1164 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
1165 res.sign() = s;
1166 return;
1167 }
1168 case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_infinity:
1169 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
1170 res.bits() = limb_type(0);
1171 res.sign() = u.sign() != v.sign();
1172 return;
1173 case cpp_bin_float<Digits, DigitBase, Allocator3, Exponent3, MinE3, MaxE3>::exponent_nan:
1174 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1175 return;
1176 }
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194 if ((v.exponent() < 0) && (u.exponent() > 0))
1195 {
1196
1197 if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + v.exponent() < u.exponent() - 1)
1198 {
1199 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
1200 res.sign() = u.sign() != v.sign();
1201 res.bits() = static_cast<limb_type>(0u);
1202 return;
1203 }
1204 }
1205 else if ((v.exponent() > 0) && (u.exponent() < 0))
1206 {
1207
1208 if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent + v.exponent() > u.exponent())
1209 {
1210
1211 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
1212 res.sign() = u.sign() != v.sign();
1213 res.bits() = static_cast<limb_type>(0u);
1214 return;
1215 }
1216 }
1217 res.exponent() = u.exponent() - v.exponent() - 1;
1218 res.sign() = u.sign() != v.sign();
1219
1220
1221
1222 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), t2(v.bits()), q, r;
1223 eval_left_shift(t, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count);
1224 eval_qr(t, t2, q, r);
1225
1226
1227
1228
1229
1230 constexpr unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
1231 if (eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
1232 {
1233
1234
1235
1236
1237
1238
1239
1240 BOOST_MP_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count));
1241 if ((q.limbs()[0] & 1u) && (eval_get_sign(r) || (q.limbs()[0] & 2u)))
1242 {
1243 eval_increment(q);
1244 }
1245 }
1246 else
1247 {
1248
1249
1250
1251
1252
1253
1254
1255 using local_exponent_type = typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type;
1256
1257 BOOST_MP_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
1258 constexpr unsigned lshift = (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits) ? 2 : limb_bits;
1259 eval_left_shift(q, lshift);
1260 res.exponent() -= static_cast<local_exponent_type>(lshift);
1261 eval_left_shift(r, 1u);
1262 int c = r.compare(v.bits());
1263 if (c == 0)
1264 q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1);
1265 else if (c > 0)
1266 q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u);
1267 }
1268 copy_and_round(res, q);
1269 #ifdef BOOST_MSVC
1270 #pragma warning(pop)
1271 #endif
1272 }
1273
1274 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
1275 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
1276 inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
1277 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& arg)
1278 {
1279 eval_divide(res, res, arg);
1280 }
1281
1282 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
1283 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2, class U>
1284 inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<U>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
1285 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& u, const U& v)
1286 {
1287 #ifdef BOOST_MSVC
1288 #pragma warning(push)
1289 #pragma warning(disable : 6326)
1290 #endif
1291 using default_ops::eval_bit_test;
1292 using default_ops::eval_get_sign;
1293 using default_ops::eval_increment;
1294 using default_ops::eval_qr;
1295 using default_ops::eval_subtract;
1296
1297
1298
1299
1300 switch (u.exponent())
1301 {
1302 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_zero:
1303 {
1304 if (v == 0)
1305 {
1306 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1307 return;
1308 }
1309 bool s = u.sign() != (v < 0);
1310 res = u;
1311 res.sign() = s;
1312 return;
1313 }
1314 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_infinity:
1315 res = u;
1316 return;
1317 case cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>::exponent_nan:
1318 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1319 return;
1320 }
1321 if (v == 0)
1322 {
1323 bool s = u.sign();
1324 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
1325 res.sign() = s;
1326 return;
1327 }
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344 std::ptrdiff_t gb = static_cast<std::ptrdiff_t>(msb(v));
1345 res.exponent() = u.exponent() - static_cast<Exponent>(gb) - static_cast<Exponent>(1);
1346 res.sign() = u.sign();
1347
1348
1349
1350 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), q, r;
1351 eval_left_shift(t, static_cast<double_limb_type>(gb + 1));
1352 eval_qr(t, number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v), q, r);
1353
1354
1355
1356 constexpr unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
1357 if (eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
1358 {
1359
1360
1361
1362
1363
1364 BOOST_MP_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count));
1365 if ((q.limbs()[0] & 1u) && eval_get_sign(r))
1366 {
1367 eval_increment(q);
1368 }
1369 }
1370 else
1371 {
1372
1373
1374
1375
1376
1377
1378
1379 using local_exponent_type = typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type;
1380
1381 BOOST_MP_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
1382 constexpr unsigned lshift = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits ? 2 : limb_bits;
1383 eval_left_shift(q, lshift);
1384 res.exponent() -= static_cast<local_exponent_type>(lshift);
1385 eval_left_shift(r, 1u);
1386 int c = r.compare(number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v));
1387 if (c == 0)
1388 q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1);
1389 else if (c > 0)
1390 q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u);
1391 }
1392 copy_and_round(res, q);
1393 #ifdef BOOST_MSVC
1394 #pragma warning(pop)
1395 #endif
1396 }
1397
1398 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
1399 inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<U>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const U& v)
1400 {
1401 eval_divide(res, res, v);
1402 }
1403
1404 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
1405 class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2, class S>
1406 inline typename std::enable_if<boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res,
1407 const cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2>& u, const S& v)
1408 {
1409 using ui_type = typename boost::multiprecision::detail::make_unsigned<S>::type;
1410 eval_divide(res, u, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(v)));
1411 if (v < 0)
1412 res.negate();
1413 }
1414
1415 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
1416 inline typename std::enable_if<boost::multiprecision::detail::is_signed<S>::value && boost::multiprecision::detail::is_integral<S>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const S& v)
1417 {
1418 eval_divide(res, res, v);
1419 }
1420
1421 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1422 inline int eval_get_sign(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1423 {
1424 return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero ? 0 : arg.sign() ? -1 : 1;
1425 }
1426
1427 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1428 inline bool eval_is_zero(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1429 {
1430 return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
1431 }
1432
1433 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1434 inline bool eval_eq(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& a, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& b)
1435 {
1436 if (a.exponent() == b.exponent())
1437 {
1438 if (a.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero)
1439 return true;
1440 return (a.sign() == b.sign()) && (a.bits().compare(b.bits()) == 0) && (a.exponent() != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan);
1441 }
1442 return false;
1443 }
1444
1445 template <class I, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1446 inline void convert_to_signed_int(I* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1447 {
1448 static constexpr int digits = std::numeric_limits<I>::is_specialized ? std::numeric_limits<I>::digits : sizeof(I) * CHAR_BIT - 1;
1449 static constexpr I max_val = std::numeric_limits<I>::is_specialized ? (std::numeric_limits<I>::max)() : (((I(1) << (sizeof(I) * CHAR_BIT - 2)) - 1) << 1) + 1;
1450 static constexpr I min_val = std::numeric_limits<I>::is_specialized ? (std::numeric_limits<I>::min)() : -max_val - 1;
1451
1452
1453 switch (arg.exponent())
1454 {
1455 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1456 *res = 0;
1457 return;
1458 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1459 BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1460 return;
1461 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1462 *res = max_val;
1463 if (arg.sign())
1464 *res = -*res;
1465 return;
1466 }
1467 using shift_type = typename std::conditional<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type;
1468 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits());
1469 shift_type shift = (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent();
1470 if (shift > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
1471 {
1472 *res = 0;
1473 return;
1474 }
1475 if (arg.sign() && (arg.compare(min_val) <= 0))
1476 {
1477 *res = min_val;
1478 return;
1479 }
1480 else if (!arg.sign() && (arg.compare(max_val) >= 0))
1481 {
1482 *res = max_val;
1483 return;
1484 }
1485
1486 if (shift < 0)
1487 {
1488 if (static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - static_cast<int>(shift) <= digits)
1489 {
1490
1491 eval_convert_to(res, man);
1492 *res <<= -shift;
1493 }
1494 else
1495 {
1496 *res = (std::numeric_limits<I>::max)();
1497 return;
1498 }
1499 }
1500 else
1501 {
1502 eval_right_shift(man, static_cast<double_limb_type>(shift));
1503 eval_convert_to(res, man);
1504 }
1505 if (arg.sign())
1506 {
1507 *res = -*res;
1508 }
1509 }
1510
1511 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1512 inline void eval_convert_to(long long* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1513 {
1514 convert_to_signed_int(res, arg);
1515 }
1516
1517 #ifdef BOOST_HAS_INT128
1518 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1519 inline void eval_convert_to(int128_type* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1520 {
1521 convert_to_signed_int(res, arg);
1522 }
1523 #endif
1524
1525 template <class I, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1526 inline void convert_to_unsigned_int(I* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1527 {
1528 static constexpr int digits = std::numeric_limits<I>::is_specialized ? std::numeric_limits<I>::digits : sizeof(I) * CHAR_BIT;
1529 static constexpr I max_val = std::numeric_limits<I>::is_specialized ? (std::numeric_limits<I>::max)() : ~static_cast<I>(0);
1530
1531 switch (arg.exponent())
1532 {
1533 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1534 *res = 0;
1535 return;
1536 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1537 BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1538 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1539 *res = max_val;
1540 return;
1541 }
1542 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits());
1543 using shift_type = typename std::conditional<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type;
1544 shift_type shift = (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent();
1545 if (shift > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
1546 {
1547 *res = 0;
1548 return;
1549 }
1550 else if (shift < 0)
1551 {
1552 if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - shift <= digits)
1553 {
1554
1555 eval_convert_to(res, man);
1556 *res <<= -shift;
1557 return;
1558 }
1559 *res = max_val;
1560 return;
1561 }
1562 eval_right_shift(man, shift);
1563 eval_convert_to(res, man);
1564 }
1565
1566 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1567 inline void eval_convert_to(unsigned long long* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1568 {
1569 convert_to_unsigned_int(res, arg);
1570 }
1571
1572 #ifdef BOOST_HAS_INT128
1573 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1574 inline void eval_convert_to(uint128_type* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1575 {
1576 convert_to_unsigned_int(res, arg);
1577 }
1578 #endif
1579
1580 template <class Float, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1581 inline typename std::enable_if<std::is_floating_point<Float>::value>::type eval_convert_to(Float* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& original_arg)
1582 {
1583 using conv_type = cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE>;
1584 using common_exp_type = typename std::common_type<typename conv_type::exponent_type, int>::type;
1585
1586 static constexpr int float_digits = boost::multiprecision::detail::is_float128<Float>::value ? 113 : std::numeric_limits<Float>::digits;
1587
1588 BOOST_MP_FLOAT128_USING using std::ldexp;
1589
1590
1591
1592 switch (original_arg.exponent())
1593 {
1594 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1595 *res = 0;
1596 if (original_arg.sign())
1597 *res = -*res;
1598 return;
1599 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1600 BOOST_IF_CONSTEXPR(boost::multiprecision::detail::is_float128<Float>::value)
1601 {
1602 *res = static_cast<Float>(std::numeric_limits<double>::quiet_NaN());
1603 }
1604 else
1605 {
1606 *res = std::numeric_limits<Float>::quiet_NaN();
1607 }
1608 return;
1609 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1610 BOOST_IF_CONSTEXPR(boost::multiprecision::detail::is_float128<Float>::value)
1611 {
1612 *res = static_cast<Float>((std::numeric_limits<double>::infinity)());
1613 }
1614 else
1615 {
1616 *res = (std::numeric_limits<Float>::infinity)();
1617 }
1618 if (original_arg.sign())
1619 *res = -*res;
1620 return;
1621 }
1622
1623
1624
1625 if (original_arg.exponent() > (boost::multiprecision::detail::is_float128<Float>::value ? 16384 : std::numeric_limits<Float>::max_exponent))
1626 {
1627 BOOST_IF_CONSTEXPR(boost::multiprecision::detail::is_float128<Float>::value)
1628 {
1629 *res = static_cast<Float>(std::numeric_limits<double>::infinity());
1630 }
1631 else
1632 {
1633 *res = std::numeric_limits<Float>::has_infinity ? std::numeric_limits<Float>::infinity() : (std::numeric_limits<Float>::max)();
1634 }
1635 if (original_arg.sign())
1636 *res = -*res;
1637 return;
1638 }
1639
1640
1641
1642
1643 common_exp_type digits_to_round_to = float_digits;
1644 if (original_arg.exponent() < std::numeric_limits<Float>::min_exponent - 1)
1645 {
1646 common_exp_type diff = original_arg.exponent();
1647 diff -= boost::multiprecision::detail::is_float128<Float>::value ? -16382 : std::numeric_limits<Float>::min_exponent - 1;
1648 digits_to_round_to += diff;
1649 }
1650 if (digits_to_round_to < 0)
1651 {
1652
1653 *res = 0;
1654 if (original_arg.sign())
1655 *res = -*res;
1656 return;
1657 }
1658
1659
1660
1661 cpp_bin_float<static_cast<unsigned>(float_digits), digit_base_2, Allocator, Exponent, MinE, MaxE> arg;
1662 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type bits(original_arg.bits());
1663 arg.exponent() = original_arg.exponent();
1664 copy_and_round(arg, bits, (std::ptrdiff_t)digits_to_round_to);
1665 common_exp_type e = arg.exponent();
1666 e -= static_cast<common_exp_type>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - 1;
1667 constexpr std::size_t limbs_needed = static_cast<std::size_t>(float_digits) / (sizeof(*arg.bits().limbs()) * CHAR_BIT) + (static_cast<std::size_t>(float_digits) % (sizeof(*arg.bits().limbs()) * CHAR_BIT) ? 1 : 0);
1668 std::size_t first_limb_needed = arg.bits().size() - limbs_needed;
1669 *res = 0;
1670 e += static_cast<common_exp_type>(first_limb_needed * sizeof(*arg.bits().limbs()) * CHAR_BIT);
1671 while (first_limb_needed < arg.bits().size())
1672 {
1673 *res += ldexp(static_cast<Float>(arg.bits().limbs()[first_limb_needed]), static_cast<int>(e));
1674 ++first_limb_needed;
1675 e += static_cast<common_exp_type>(sizeof(*arg.bits().limbs()) * CHAR_BIT);
1676 }
1677 if (original_arg.sign())
1678 *res = -*res;
1679 }
1680
1681 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1682 inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, Exponent* e)
1683 {
1684 switch (arg.exponent())
1685 {
1686 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1687 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1688 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1689 *e = 0;
1690 res = arg;
1691 return;
1692 }
1693 res = arg;
1694 *e = arg.exponent() + 1;
1695 res.exponent() = -1;
1696 }
1697
1698 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
1699 inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, I* pe)
1700 {
1701 Exponent e;
1702 eval_frexp(res, arg, &e);
1703 if ((e > (std::numeric_limits<I>::max)()) || (e < (std::numeric_limits<I>::min)()))
1704 {
1705 BOOST_MP_THROW_EXCEPTION(std::runtime_error("Exponent was outside of the range of the argument type to frexp."));
1706 }
1707 *pe = static_cast<I>(e);
1708 }
1709
1710 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1711 inline void eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, Exponent e)
1712 {
1713 switch (arg.exponent())
1714 {
1715 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1716 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1717 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1718 res = arg;
1719 return;
1720 }
1721 if ((e > 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent - e < arg.exponent()))
1722 {
1723
1724 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
1725 res.sign() = arg.sign();
1726 }
1727 else if ((e < 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - e > arg.exponent()))
1728 {
1729
1730 res = limb_type(0);
1731 }
1732 else
1733 {
1734 res = arg;
1735 res.exponent() += e;
1736 }
1737 }
1738
1739 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
1740 inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<I>::value>::type eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, I e)
1741 {
1742 using si_type = typename boost::multiprecision::detail::make_signed<I>::type;
1743 if (e > static_cast<I>((std::numeric_limits<si_type>::max)()))
1744 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
1745 else
1746 eval_ldexp(res, arg, static_cast<si_type>(e));
1747 }
1748
1749 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
1750 inline typename std::enable_if<boost::multiprecision::detail::is_signed<I>::value && boost::multiprecision::detail::is_integral<I>::value>::type eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, I e)
1751 {
1752 if ((e > (std::numeric_limits<Exponent>::max)()) || (e < (std::numeric_limits<Exponent>::min)()))
1753 {
1754 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
1755 if (e < 0)
1756 res.negate();
1757 }
1758 else
1759 eval_ldexp(res, arg, static_cast<Exponent>(e));
1760 }
1761
1762
1763
1764
1765
1766 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
1767 unsigned Digits2, digit_base_type DigitBase2, class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
1768 inline void eval_abs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits2, DigitBase2, Allocator2, Exponent2, MinE2, MaxE2>& arg)
1769 {
1770 res = arg;
1771 res.sign() = false;
1772 }
1773 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1774 inline void eval_abs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1775 {
1776 res = arg;
1777 res.sign() = false;
1778 }
1779
1780 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE,
1781 unsigned Digits2, digit_base_type DigitBase2, class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
1782 inline void eval_fabs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits2, DigitBase2, Allocator2, Exponent2, MinE2, MaxE2>& arg)
1783 {
1784 res = arg;
1785 res.sign() = false;
1786 }
1787 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1788 inline void eval_fabs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1789 {
1790 res = arg;
1791 res.sign() = false;
1792 }
1793
1794 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1795 inline int eval_fpclassify(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1796 {
1797 switch (arg.exponent())
1798 {
1799 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1800 return FP_ZERO;
1801 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1802 return FP_INFINITE;
1803 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1804 return FP_NAN;
1805 }
1806 return FP_NORMAL;
1807 }
1808
1809 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1810 inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1811 {
1812 using default_ops::eval_bit_test;
1813 using default_ops::eval_increment;
1814 using default_ops::eval_integer_sqrt;
1815 switch (arg.exponent())
1816 {
1817 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1818 errno = EDOM;
1819
1820 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1821 res = arg;
1822 return;
1823 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1824 if (arg.sign())
1825 {
1826 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1827 errno = EDOM;
1828 }
1829 else
1830 res = arg;
1831 return;
1832 }
1833 if (arg.sign())
1834 {
1835 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1836 errno = EDOM;
1837 return;
1838 }
1839
1840 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(arg.bits()), r, s;
1841 eval_left_shift(t, arg.exponent() & 1 ? cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count : cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1);
1842 eval_integer_sqrt(s, r, t);
1843
1844 if (!eval_bit_test(s, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
1845 {
1846
1847 if (s.compare(r) < 0)
1848 {
1849 eval_increment(s);
1850 }
1851 }
1852 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type ae = arg.exponent();
1853 res.exponent() = ae / 2;
1854 res.sign() = false;
1855 if ((ae & 1) && (ae < 0))
1856 --res.exponent();
1857 copy_and_round(res, s);
1858 }
1859
1860 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1861 inline void eval_floor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1862 {
1863 using default_ops::eval_increment;
1864 switch (arg.exponent())
1865 {
1866 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1867 errno = EDOM;
1868
1869 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1870 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1871 res = arg;
1872 return;
1873 }
1874 using shift_type = typename std::conditional<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type;
1875 shift_type shift =
1876 (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1;
1877 if ((arg.exponent() > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0))
1878 {
1879
1880 res = arg;
1881 return;
1882 }
1883 if (shift >= (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
1884 {
1885 res = static_cast<signed_limb_type>(arg.sign() ? -1 : 0);
1886 return;
1887 }
1888 bool fractional = (shift_type)eval_lsb(arg.bits()) < shift;
1889 res = arg;
1890 eval_right_shift(res.bits(), static_cast<double_limb_type>(shift));
1891 if (fractional && res.sign())
1892 {
1893 eval_increment(res.bits());
1894
1895 const std::ptrdiff_t shift_check =
1896 static_cast<std::ptrdiff_t>(static_cast<std::ptrdiff_t>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - 1 - static_cast<std::ptrdiff_t>(shift));
1897
1898 if (static_cast<std::ptrdiff_t>(eval_msb(res.bits())) != shift_check)
1899 {
1900
1901 --shift;
1902 ++res.exponent();
1903 }
1904 }
1905 eval_left_shift(res.bits(), static_cast<double_limb_type>(shift));
1906 }
1907
1908 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
1909 inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
1910 {
1911 using default_ops::eval_increment;
1912 switch (arg.exponent())
1913 {
1914 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1915 errno = EDOM;
1916
1917 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1918 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1919 res = arg;
1920 return;
1921 }
1922 using shift_type = typename std::conditional<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type;
1923 shift_type shift = (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1;
1924 if ((arg.exponent() > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0))
1925 {
1926
1927 res = arg;
1928 return;
1929 }
1930 if (shift >= (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
1931 {
1932 bool s = arg.sign();
1933 res = static_cast<signed_limb_type>(arg.sign() ? 0 : 1);
1934 res.sign() = s;
1935 return;
1936 }
1937 bool fractional = (shift_type)eval_lsb(arg.bits()) < shift;
1938 res = arg;
1939 eval_right_shift(res.bits(), shift);
1940 if (fractional && !res.sign())
1941 {
1942 eval_increment(res.bits());
1943 if ((std::ptrdiff_t)eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift)
1944 {
1945
1946 --shift;
1947 ++res.exponent();
1948 }
1949 }
1950 eval_left_shift(res.bits(), shift);
1951 }
1952
1953 template <unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2>
1954 int eval_signbit(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val)
1955 {
1956 return val.sign();
1957 }
1958
1959 template <unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2>
1960 inline std::size_t hash_value(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val)
1961 {
1962 std::size_t result = hash_value(val.bits());
1963 boost::multiprecision::detail::hash_combine(result, val.exponent(), val.sign());
1964 return result;
1965 }
1966
1967 }
1968
1969 namespace detail {
1970
1971 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent>
1972 struct transcendental_reduction_type<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> >
1973 {
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983 using type = boost::multiprecision::backends::cpp_bin_float<
1984 boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent>::bit_count * 3,
1985 boost::multiprecision::backends::digit_base_2,
1986 Allocator, Exponent, MinExponent, MaxExponent>;
1987 };
1988 #ifdef BOOST_HAS_INT128
1989 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent>
1990 struct is_convertible_arithmetic<int128_type, boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> > : public std::true_type
1991 {};
1992 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent>
1993 struct is_convertible_arithmetic<uint128_type, boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> > : public std::true_type
1994 {};
1995 #endif
1996
1997 }
1998
1999 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
2000 inline boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>
2001 copysign BOOST_PREVENT_MACRO_SUBSTITUTION(
2002 const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& a,
2003 const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& b)
2004 {
2005 boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> res(a);
2006 res.backend().sign() = b.backend().sign();
2007 return res;
2008 }
2009
2010 template <unsigned Digits, backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator>
2011 struct number_category<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > : public std::integral_constant<int, boost::multiprecision::number_kind_floating_point>
2012 {};
2013
2014 template <unsigned Digits, backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2>
2015 struct is_equivalent_number_type<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, cpp_bin_float<Digits, DigitBase, Allocator2, Exponent2, MinE2, MaxE2> >
2016 : public std::integral_constant<bool, true> {};
2017
2018 }
2019
2020 namespace math {
2021
2022 using boost::multiprecision::copysign;
2023 using boost::multiprecision::signbit;
2024
2025 }
2026
2027 }
2028
2029 #include <boost/multiprecision/cpp_bin_float/io.hpp>
2030 #include <boost/multiprecision/cpp_bin_float/transcendental.hpp>
2031
2032 namespace std {
2033
2034
2035
2036
2037 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2038 class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >
2039 {
2040 using number_type = boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>;
2041
2042 private:
2043
2044
2045
2046 static number_type get_min()
2047 {
2048 using ui_type = typename std::tuple_element<0, typename number_type::backend_type::unsigned_types>::type;
2049 number_type value(ui_type(1u));
2050 value.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
2051 return value;
2052 }
2053 #ifdef BOOST_MSVC
2054 #pragma warning(push)
2055 #pragma warning(disable : 4127)
2056 #endif
2057 static number_type get_max()
2058 {
2059 number_type value;
2060 BOOST_IF_CONSTEXPR(std::is_void<Allocator>::value)
2061 eval_complement(value.backend().bits(), value.backend().bits());
2062 else
2063 {
2064
2065
2066 using boost::multiprecision::default_ops::eval_add;
2067 using boost::multiprecision::default_ops::eval_decrement;
2068 using boost::multiprecision::default_ops::eval_left_shift;
2069 using int_backend_type = typename number_type::backend_type::rep_type;
2070 using ui_type = typename std::tuple_element<0, typename int_backend_type::unsigned_types>::type;
2071 int_backend_type i;
2072 i = ui_type(1u);
2073 eval_left_shift(i, boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1);
2074 int_backend_type j(i);
2075 eval_decrement(i);
2076 eval_add(j, i);
2077 value.backend().bits() = j;
2078 }
2079 value.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
2080 return value;
2081 }
2082 #ifdef BOOST_MSVC
2083 #pragma warning(pop)
2084 #endif
2085 static number_type get_epsilon()
2086 {
2087 using ui_type = typename std::tuple_element<0, typename number_type::backend_type::unsigned_types>::type;
2088 number_type value(ui_type(1u));
2089 return ldexp(value, 1 - static_cast<int>(digits));
2090 }
2091
2092 static number_type get_round_error()
2093 {
2094
2095 return ldexp(number_type(1u), -1);
2096 }
2097 static number_type get_infinity()
2098 {
2099 number_type value;
2100 value.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
2101 return value;
2102 }
2103 static number_type get_quiet_NaN()
2104 {
2105 number_type value;
2106 value.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan;
2107 return value;
2108 }
2109
2110 public:
2111 static constexpr bool is_specialized = true;
2112 static number_type(min)()
2113 {
2114
2115 static number_type value = get_min();
2116 return value;
2117 }
2118 static number_type(max)()
2119 {
2120
2121 static number_type value = get_max();
2122 return value;
2123 }
2124 static constexpr number_type lowest()
2125 {
2126 return -(max)();
2127 }
2128 static constexpr int digits = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count;
2129 static constexpr int digits10 = boost::multiprecision::detail::calc_digits10<static_cast<unsigned>(digits)>::value;
2130
2131 static constexpr int max_digits10 = boost::multiprecision::detail::calc_max_digits10<static_cast<unsigned>(digits)>::value;
2132 static constexpr bool is_signed = true;
2133 static constexpr bool is_integer = false;
2134 static constexpr bool is_exact = false;
2135 static constexpr int radix = 2;
2136 static number_type epsilon()
2137 {
2138
2139 static number_type value = get_epsilon();
2140 return value;
2141 }
2142
2143 static number_type round_error()
2144 {
2145
2146
2147 static number_type value = get_round_error();
2148 return value;
2149 }
2150 static constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
2151 static constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent10 = (min_exponent / 1000) * 301L;
2152 static constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
2153 static constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent10 = (max_exponent / 1000) * 301L;
2154 static constexpr bool has_infinity = true;
2155 static constexpr bool has_quiet_NaN = true;
2156 static constexpr bool has_signaling_NaN = false;
2157 static constexpr float_denorm_style has_denorm = denorm_absent;
2158 static constexpr bool has_denorm_loss = false;
2159 static number_type infinity()
2160 {
2161
2162 static number_type value = get_infinity();
2163 return value;
2164 }
2165 static number_type quiet_NaN()
2166 {
2167
2168 static number_type value = get_quiet_NaN();
2169 return value;
2170 }
2171 static constexpr number_type signaling_NaN()
2172 {
2173 return number_type(0);
2174 }
2175 static constexpr number_type denorm_min() { return get_min(); }
2176 static constexpr bool is_iec559 = false;
2177 static constexpr bool is_bounded = true;
2178 static constexpr bool is_modulo = false;
2179 static constexpr bool traps = true;
2180 static constexpr bool tinyness_before = false;
2181 static constexpr float_round_style round_style = round_to_nearest;
2182 };
2183
2184 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2185 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits;
2186 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2187 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits10;
2188 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2189 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_digits10;
2190 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2191 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_signed;
2192 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2193 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_integer;
2194 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2195 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_exact;
2196 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2197 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::radix;
2198 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2199 constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::min_exponent;
2200 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2201 constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::min_exponent10;
2202 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2203 constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_exponent;
2204 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2205 constexpr typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_exponent10;
2206 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2207 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_infinity;
2208 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2209 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_quiet_NaN;
2210 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2211 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_signaling_NaN;
2212 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2213 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm;
2214 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2215 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm_loss;
2216 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2217 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_iec559;
2218 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2219 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_bounded;
2220 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2221 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_modulo;
2222 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2223 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::traps;
2224 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2225 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::tinyness_before;
2226 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2227 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::round_style;
2228
2229
2230 }
2231
2232 #endif