Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 08:19:29

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