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