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