| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698 | /////////////////////////////////////////////////////////////////  Copyright 2012 John Maddock. Distributed under the Boost//  Software License, Version 1.0. (See accompanying file//  LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt//// Comparison operators for cpp_int_backend://#ifndef BOOST_MP_CPP_INT_MISC_HPP#define BOOST_MP_CPP_INT_MISC_HPP#include <boost/multiprecision/detail/constexpr.hpp>#include <boost/multiprecision/detail/bitscan.hpp> // lsb etc#include <boost/integer/common_factor_rt.hpp>      // gcd/lcm#include <boost/functional/hash_fwd.hpp>#ifdef BOOST_MSVC#pragma warning(push)#pragma warning(disable : 4702)#pragma warning(disable : 4127) // conditional expression is constant#pragma warning(disable : 4146) // unary minus operator applied to unsigned type, result still unsigned#endifnamespace boost { namespace multiprecision { namespace backends {template <class R, class CppInt>BOOST_MP_CXX14_CONSTEXPR void check_in_range(const CppInt& val, const mpl::int_<checked>&){   typedef typename boost::multiprecision::detail::canonical<R, CppInt>::type cast_type;   if (val.sign())   {      if (boost::is_signed<R>::value == false)         BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));      if (val.compare(static_cast<cast_type>((std::numeric_limits<R>::min)())) < 0)         BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));   }   else   {      if (val.compare(static_cast<cast_type>((std::numeric_limits<R>::max)())) > 0)         BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));   }}template <class R, class CppInt>inline BOOST_MP_CXX14_CONSTEXPR void check_in_range(const CppInt& /*val*/, const mpl::int_<unchecked>&) BOOST_NOEXCEPT {}inline BOOST_MP_CXX14_CONSTEXPR void check_is_negative(const mpl::true_&) BOOST_NOEXCEPT {}inline void check_is_negative(const mpl::false_&){   BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));}template <class Integer>inline BOOST_MP_CXX14_CONSTEXPR Integer negate_integer(Integer i, const mpl::true_&) BOOST_NOEXCEPT{   return -i;}template <class Integer>inline BOOST_MP_CXX14_CONSTEXPR Integer negate_integer(Integer i, const mpl::false_&) BOOST_NOEXCEPT{   return ~(i - 1);}template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::typeeval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend){   typedef mpl::int_<Checked1> checked_type;   check_in_range<R>(backend, checked_type());   if (std::numeric_limits<R>::digits < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)   {      if ((backend.sign() && boost::is_signed<R>::value) && (1 + static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0]))      {         *result = (std::numeric_limits<R>::min)();         return;      }      else if (boost::is_signed<R>::value && !backend.sign() && static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0])      {         *result = (std::numeric_limits<R>::max)();         return;      }      else         *result = static_cast<R>(backend.limbs()[0]);   }   else      *result = static_cast<R>(backend.limbs()[0]);   unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;   unsigned i     = 1;   if (std::numeric_limits<R>::digits > cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)   {      while ((i < backend.size()) && (shift < static_cast<unsigned>(std::numeric_limits<R>::digits - cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)))      {         *result += static_cast<R>(backend.limbs()[i]) << shift;         shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;         ++i;      }      //      // We have one more limb to extract, but may not need all the bits, so treat this as a special case:      //      if (i < backend.size())      {         const limb_type mask = std::numeric_limits<R>::digits - shift == cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits ? ~static_cast<limb_type>(0) : (static_cast<limb_type>(1u) << (std::numeric_limits<R>::digits - shift)) - 1;         *result += (static_cast<R>(backend.limbs()[i]) & mask) << shift;         if ((static_cast<R>(backend.limbs()[i]) & static_cast<limb_type>(~mask)) || (i + 1 < backend.size()))         {            // Overflow:            if (backend.sign())            {               check_is_negative(boost::is_signed<R>());               *result = (std::numeric_limits<R>::min)();            }            else if (boost::is_signed<R>::value)               *result = (std::numeric_limits<R>::max)();            return;         }      }   }   else if (backend.size() > 1)   {      // Overflow:      if (backend.sign())      {         check_is_negative(boost::is_signed<R>());         *result = (std::numeric_limits<R>::min)();      }      else if (boost::is_signed<R>::value)         *result = (std::numeric_limits<R>::max)();      return;   }   if (backend.sign())   {      check_is_negative(mpl::bool_<boost::is_signed<R>::value>());      *result = negate_integer(*result, mpl::bool_<boost::is_signed<R>::value>());   }}template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_floating_point<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::typeeval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) BOOST_MP_NOEXCEPT_IF(is_arithmetic<R>::value){   typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p     = backend.limbs();   unsigned                                                                                          shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;   *result                                                                                                 = static_cast<R>(*p);   for (unsigned i = 1; i < backend.size(); ++i)   {      *result += static_cast<R>(std::ldexp(static_cast<long double>(p[i]), shift));      shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;   }   if (backend.sign())      *result = -*result;}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::typeeval_is_zero(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT{   return (val.size() == 1) && (val.limbs()[0] == 0);}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, int>::typeeval_get_sign(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT{   return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1;}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::typeeval_abs(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)){   result = val;   result.sign(false);}//// Get the location of the least-significant-bit://template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::typeeval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a){   using default_ops::eval_get_sign;   if (eval_get_sign(a) == 0)   {      BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));   }   if (a.sign())   {      BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));   }   //   // Find the index of the least significant limb that is non-zero:   //   unsigned index = 0;   while (!a.limbs()[index] && (index < a.size()))      ++index;   //   // Find the index of the least significant bit within that limb:   //   unsigned result = boost::multiprecision::detail::find_lsb(a.limbs()[index]);   return result + index * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;}//// Get the location of the most-significant-bit://template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::typeeval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a){   //   // Find the index of the most significant bit that is non-zero:   //   return (a.size() - 1) * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]);}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::typeeval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a){   using default_ops::eval_get_sign;   if (eval_get_sign(a) == 0)   {      BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));   }   if (a.sign())   {      BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));   }   return eval_msb_imp(a);}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::typeeval_bit_test(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT{   unsigned  offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;   unsigned  shift  = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;   limb_type mask   = shift ? limb_type(1u) << shift : limb_type(1u);   if (offset >= val.size())      return false;   return val.limbs()[offset] & mask ? true : false;}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::typeeval_bit_set(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index){   unsigned  offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;   unsigned  shift  = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;   limb_type mask   = shift ? limb_type(1u) << shift : limb_type(1u);   if (offset >= val.size())   {      unsigned os = val.size();      val.resize(offset + 1, offset + 1);      if (offset >= val.size())         return; // fixed precision overflow      for (unsigned i = os; i <= offset; ++i)         val.limbs()[i] = 0;   }   val.limbs()[offset] |= mask;}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::typeeval_bit_unset(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT{   unsigned  offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;   unsigned  shift  = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;   limb_type mask   = shift ? limb_type(1u) << shift : limb_type(1u);   if (offset >= val.size())      return;   val.limbs()[offset] &= ~mask;   val.normalize();}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::typeeval_bit_flip(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index){   unsigned  offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;   unsigned  shift  = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;   limb_type mask   = shift ? limb_type(1u) << shift : limb_type(1u);   if (offset >= val.size())   {      unsigned os = val.size();      val.resize(offset + 1, offset + 1);      if (offset >= val.size())         return; // fixed precision overflow      for (unsigned i = os; i <= offset; ++i)         val.limbs()[i] = 0;   }   val.limbs()[offset] ^= mask;   val.normalize();}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::typeeval_qr(    const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,    const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& y,    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       q,    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)){   divide_unsigned_helper(&q, x, y, r);   q.sign(x.sign() != y.sign());   r.sign(x.sign());}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::typeeval_qr(    const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,    limb_type                                                                   y,    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       q,    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)){   divide_unsigned_helper(&q, x, y, r);   q.sign(x.sign());   r.sign(x.sign());}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class U>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<U>::value>::type eval_qr(    const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,    U                                                                           y,    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       q,    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)){   using default_ops::eval_qr;   cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;   t = y;   eval_qr(x, t, q, r);}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_unsigned<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::typeeval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val){   if ((sizeof(Integer) <= sizeof(limb_type)) || (val <= (std::numeric_limits<limb_type>::max)()))   {      cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> d;      divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>*>(0), x, static_cast<limb_type>(val), d);      return d.limbs()[0];   }   else   {      return default_ops::eval_integer_modulus(x, val);   }}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_signed<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::typeeval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val){   return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val));}inline BOOST_MP_CXX14_CONSTEXPR limb_type integer_gcd_reduce(limb_type u, limb_type v){   do   {      if (u > v)         std_constexpr::swap(u, v);      if (u == v)         break;      v -= u;      v >>= boost::multiprecision::detail::find_lsb(v);   } while (true);   return u;}inline BOOST_MP_CXX14_CONSTEXPR double_limb_type integer_gcd_reduce(double_limb_type u, double_limb_type v){   do   {      if (u > v)         std_constexpr::swap(u, v);      if (u == v)         break;      if (v <= ~static_cast<limb_type>(0))      {         u = integer_gcd_reduce(static_cast<limb_type>(v), static_cast<limb_type>(u));         break;      }      v -= u;#ifdef __MSVC_RUNTIME_CHECKS      while ((v & 1u) == 0)#else      while ((static_cast<unsigned>(v) & 1u) == 0)#endif         v >>= 1;   } while (true);   return u;}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::typeeval_gcd(    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,    const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,    limb_type                                                                   v){   using default_ops::eval_get_sign;   using default_ops::eval_is_zero;   using default_ops::eval_lsb;   cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a);   int s = eval_get_sign(u);   /* GCD(0,x) := x */   if (s < 0)   {      u.negate();   }   else if (s == 0)   {      result = v;      return;   }   if (v == 0)   {      result = u;      return;   }   /* Let shift := lg K, where K is the greatest power of 2   dividing both u and v. */   unsigned us = eval_lsb(u);   unsigned vs = boost::multiprecision::detail::find_lsb(v);   int shift   = (std::min)(us, vs);   eval_right_shift(u, us);   if (vs)      v >>= vs;   do   {      /* Now u and v are both odd, so diff(u, v) is even.      Let u = min(u, v), v = diff(u, v)/2. */      if (u.size() <= 2)      {         if (u.size() == 1)            v = integer_gcd_reduce(*u.limbs(), v);         else         {            double_limb_type i = u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);            v = static_cast<limb_type>(integer_gcd_reduce(i, static_cast<double_limb_type>(v)));         }         break;      }      eval_subtract(u, v);      us = eval_lsb(u);      eval_right_shift(u, us);   } while (true);   result = v;   eval_left_shift(result, shift);}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_unsigned<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::typeeval_gcd(    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,    const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,    const Integer&                                                              v){   eval_gcd(result, a, static_cast<limb_type>(v));}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_signed<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::typeeval_gcd(    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,    const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,    const Integer&                                                              v){   eval_gcd(result, a, static_cast<limb_type>(v < 0 ? -v : v));}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::typeeval_gcd(    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,    const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,    const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b){   using default_ops::eval_get_sign;   using default_ops::eval_is_zero;   using default_ops::eval_lsb;   if (a.size() == 1)   {      eval_gcd(result, b, *a.limbs());      return;   }   if (b.size() == 1)   {      eval_gcd(result, a, *b.limbs());      return;   }   cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a), v(b);   int s = eval_get_sign(u);   /* GCD(0,x) := x */   if (s < 0)   {      u.negate();   }   else if (s == 0)   {      result = v;      return;   }   s = eval_get_sign(v);   if (s < 0)   {      v.negate();   }   else if (s == 0)   {      result = u;      return;   }   /* Let shift := lg K, where K is the greatest power of 2   dividing both u and v. */   unsigned us = eval_lsb(u);   unsigned vs = eval_lsb(v);   int shift   = (std::min)(us, vs);   eval_right_shift(u, us);   eval_right_shift(v, vs);   do   {      /* Now u and v are both odd, so diff(u, v) is even.      Let u = min(u, v), v = diff(u, v)/2. */      s = u.compare(v);      if (s > 0)         u.swap(v);      if (s == 0)         break;      if (v.size() <= 2)      {         if (v.size() == 1)            u = integer_gcd_reduce(*v.limbs(), *u.limbs());         else         {            double_limb_type i = v.limbs()[0] | (static_cast<double_limb_type>(v.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);            double_limb_type j = (u.size() == 1) ? *u.limbs() : u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);            u = integer_gcd_reduce(i, j);         }         break;      }      eval_subtract(v, u);      vs = eval_lsb(v);      eval_right_shift(v, vs);   } while (true);   result = u;   eval_left_shift(result, shift);}//// Now again for trivial backends://template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::typeeval_gcd(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_NOEXCEPT{   *result.limbs() = boost::integer::gcd(*a.limbs(), *b.limbs());}// This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version:template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (Checked1 == unchecked)>::typeeval_lcm(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)){   *result.limbs() = boost::integer::lcm(*a.limbs(), *b.limbs());   result.normalize(); // result may overflow the specified number of bits}inline void conversion_overflow(const mpl::int_<checked>&){   BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type"));}inline BOOST_MP_CXX14_CONSTEXPR void conversion_overflow(const mpl::int_<unchecked>&) {}template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<    is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value>::typeeval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val){   typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;   if (std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))   {      if (val.isneg())      {         check_is_negative(mpl::bool_ < boost::is_signed<R>::value || (number_category<R>::value == number_kind_floating_point) > ());         if (static_cast<common_type>(*val.limbs()) > -static_cast<common_type>((std::numeric_limits<R>::min)()))            conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());         *result = (std::numeric_limits<R>::min)();      }      else      {         conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());         *result = boost::is_signed<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());      }   }   else   {      *result = static_cast<R>(*val.limbs());      if (val.isneg())      {         check_is_negative(mpl::bool_ < boost::is_signed<R>::value || (number_category<R>::value == number_kind_floating_point) > ());         *result = negate_integer(*result, mpl::bool_ < is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point) > ());      }   }}template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<    is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value>::typeeval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val){   typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;   if (std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))   {      conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());      *result = boost::is_signed<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());   }   else      *result = static_cast<R>(*val.limbs());}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::typeeval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a){   using default_ops::eval_get_sign;   if (eval_get_sign(a) == 0)   {      BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));   }   if (a.sign())   {      BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));   }   //   // Find the index of the least significant bit within that limb:   //   return boost::multiprecision::detail::find_lsb(*a.limbs());}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::typeeval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a){   //   // Find the index of the least significant bit within that limb:   //   return boost::multiprecision::detail::find_msb(*a.limbs());}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::typeeval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a){   using default_ops::eval_get_sign;   if (eval_get_sign(a) == 0)   {      BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));   }   if (a.sign())   {      BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));   }   return eval_msb_imp(a);}template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT{   std::size_t result = 0;   for (unsigned i = 0; i < val.size(); ++i)   {      boost::hash_combine(result, val.limbs()[i]);   }   boost::hash_combine(result, val.sign());   return result;}#ifdef BOOST_MSVC#pragma warning(pop)#endif}}} // namespace boost::multiprecision::backends#endif
 |