misc.hpp 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright 2012-2020 John Maddock.
  3. // Copyright 2020 Madhur Chauhan.
  4. // Copyright 2021 Matt Borland.
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // https://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // Comparison operators for cpp_int_backend:
  10. //
  11. #ifndef BOOST_MP_CPP_INT_MISC_HPP
  12. #define BOOST_MP_CPP_INT_MISC_HPP
  13. #include <boost/multiprecision/detail/standalone_config.hpp>
  14. #include <boost/multiprecision/detail/number_base.hpp>
  15. #include <boost/multiprecision/cpp_int/cpp_int_config.hpp>
  16. #include <boost/multiprecision/detail/float128_functions.hpp>
  17. #include <boost/multiprecision/detail/assert.hpp>
  18. #include <boost/multiprecision/detail/constexpr.hpp>
  19. #include <boost/multiprecision/detail/bitscan.hpp> // lsb etc
  20. #include <boost/multiprecision/detail/hash.hpp>
  21. #include <boost/multiprecision/detail/no_exceptions_support.hpp>
  22. #include <numeric> // std::gcd
  23. #include <type_traits>
  24. #include <stdexcept>
  25. #include <cmath>
  26. #ifndef BOOST_MP_STANDALONE
  27. #include <boost/integer/common_factor_rt.hpp>
  28. #endif
  29. #ifdef BOOST_MP_MATH_AVAILABLE
  30. #include <boost/math/special_functions/next.hpp>
  31. #endif
  32. #ifdef BOOST_MSVC
  33. #pragma warning(push)
  34. #pragma warning(disable : 4702)
  35. #pragma warning(disable : 4127) // conditional expression is constant
  36. #pragma warning(disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
  37. #endif
  38. // Forward decleration of gcd and lcm functions
  39. namespace boost { namespace multiprecision { namespace detail {
  40. template <typename T>
  41. inline BOOST_CXX14_CONSTEXPR T constexpr_gcd(T a, T b) noexcept;
  42. template <typename T>
  43. inline BOOST_CXX14_CONSTEXPR T constexpr_lcm(T a, T b) noexcept;
  44. }}} // namespace boost::multiprecision::detail
  45. namespace boost { namespace multiprecision { namespace backends {
  46. template <class T, bool has_limits = std::numeric_limits<T>::is_specialized>
  47. struct numeric_limits_workaround : public std::numeric_limits<T>
  48. {
  49. };
  50. template <class R>
  51. struct numeric_limits_workaround<R, false>
  52. {
  53. static constexpr unsigned digits = ~static_cast<R>(0) < 0 ? sizeof(R) * CHAR_BIT - 1 : sizeof(R) * CHAR_BIT;
  54. static constexpr R (min)(){ return (static_cast<R>(-1) < 0) ? static_cast<R>(1) << digits : 0; }
  55. static constexpr R (max)() { return (static_cast<R>(-1) < 0) ? ~(static_cast<R>(1) << digits) : ~static_cast<R>(0); }
  56. };
  57. template <class R, class CppInt>
  58. BOOST_MP_CXX14_CONSTEXPR void check_in_range(const CppInt& val, const std::integral_constant<int, checked>&)
  59. {
  60. using cast_type = typename boost::multiprecision::detail::canonical<R, CppInt>::type;
  61. if (val.sign())
  62. {
  63. BOOST_IF_CONSTEXPR (boost::multiprecision::detail::is_signed<R>::value == false)
  64. BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
  65. if (val.compare(static_cast<cast_type>((numeric_limits_workaround<R>::min)())) < 0)
  66. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
  67. }
  68. else
  69. {
  70. if (val.compare(static_cast<cast_type>((numeric_limits_workaround<R>::max)())) > 0)
  71. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
  72. }
  73. }
  74. template <class R, class CppInt>
  75. inline BOOST_MP_CXX14_CONSTEXPR void check_in_range(const CppInt& /*val*/, const std::integral_constant<int, unchecked>&) noexcept {}
  76. inline BOOST_MP_CXX14_CONSTEXPR void check_is_negative(const std::integral_constant<bool, true>&) noexcept {}
  77. inline void check_is_negative(const std::integral_constant<bool, false>&)
  78. {
  79. BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
  80. }
  81. template <class Integer>
  82. inline BOOST_MP_CXX14_CONSTEXPR Integer negate_integer(Integer i, const std::integral_constant<bool, true>&) noexcept
  83. {
  84. return -i;
  85. }
  86. template <class Integer>
  87. inline BOOST_MP_CXX14_CONSTEXPR Integer negate_integer(Integer i, const std::integral_constant<bool, false>&) noexcept
  88. {
  89. return ~(i - 1);
  90. }
  91. template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  92. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
  93. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend)
  94. {
  95. using checked_type = std::integral_constant<int, Checked1>;
  96. check_in_range<R>(backend, checked_type());
  97. BOOST_IF_CONSTEXPR(numeric_limits_workaround<R>::digits < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
  98. {
  99. if ((backend.sign() && boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) && (1 + static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0]))
  100. {
  101. *result = (numeric_limits_workaround<R>::min)();
  102. return;
  103. }
  104. else if (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value && !backend.sign() && static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0])
  105. {
  106. *result = (numeric_limits_workaround<R>::max)();
  107. return;
  108. }
  109. else
  110. *result = static_cast<R>(backend.limbs()[0]);
  111. }
  112. else
  113. *result = static_cast<R>(backend.limbs()[0]);
  114. BOOST_IF_CONSTEXPR(numeric_limits_workaround<R>::digits > cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
  115. {
  116. std::size_t shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  117. std::size_t i = 1u;
  118. while ((i < backend.size()) && (shift < static_cast<unsigned>(numeric_limits_workaround<R>::digits - cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)))
  119. {
  120. *result += static_cast<R>(backend.limbs()[i]) << shift;
  121. shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  122. ++i;
  123. }
  124. //
  125. // We have one more limb to extract, but may not need all the bits, so treat this as a special case:
  126. //
  127. if (i < backend.size())
  128. {
  129. const limb_type mask = ((numeric_limits_workaround<R>::digits - shift) == cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits) ? ~static_cast<limb_type>(0) : static_cast<limb_type>(static_cast<limb_type>(1u) << (numeric_limits_workaround<R>::digits - shift)) - 1u;
  130. const limb_type limb_at_index_masked = static_cast<limb_type>(backend.limbs()[i] & mask);
  131. *result = static_cast<R>(*result + static_cast<R>(static_cast<R>(limb_at_index_masked) << shift));
  132. if ((backend.limbs()[i] & static_cast<limb_type>(~mask)) || (i + 1 < backend.size()))
  133. {
  134. // Overflow:
  135. if (backend.sign())
  136. {
  137. check_is_negative(boost::multiprecision::detail::is_signed<R>());
  138. *result = (numeric_limits_workaround<R>::min)();
  139. }
  140. else if (boost::multiprecision::detail::is_signed<R>::value)
  141. *result = (numeric_limits_workaround<R>::max)();
  142. return;
  143. }
  144. }
  145. }
  146. else if (backend.size() > 1)
  147. {
  148. // Overflow:
  149. if (backend.sign())
  150. {
  151. check_is_negative(boost::multiprecision::detail::is_signed<R>());
  152. *result = (numeric_limits_workaround<R>::min)();
  153. }
  154. else if (boost::multiprecision::detail::is_signed<R>::value)
  155. *result = (numeric_limits_workaround<R>::max)();
  156. return;
  157. }
  158. if (backend.sign())
  159. {
  160. check_is_negative(std::integral_constant<bool, boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value>());
  161. *result = negate_integer(*result, std::integral_constant<bool, boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value>());
  162. }
  163. }
  164. template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  165. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_floating_point<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
  166. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) noexcept(boost::multiprecision::detail::is_arithmetic<R>::value && std::numeric_limits<R>::has_infinity)
  167. {
  168. BOOST_MP_FLOAT128_USING using std::ldexp;
  169. if (eval_is_zero(backend))
  170. {
  171. *result = 0.0f;
  172. return;
  173. }
  174. #ifdef BOOST_HAS_FLOAT128
  175. std::ptrdiff_t bits_to_keep = static_cast<std::ptrdiff_t>(std::is_same<R, float128_type>::value ? 113 : std::numeric_limits<R>::digits);
  176. #else
  177. std::ptrdiff_t bits_to_keep = static_cast<std::ptrdiff_t>(std::numeric_limits<R>::digits);
  178. #endif
  179. std::ptrdiff_t bits = static_cast<std::ptrdiff_t>(eval_msb_imp(backend) + 1);
  180. if (bits > bits_to_keep)
  181. {
  182. // Extract the bits we need, and then manually round the result:
  183. *result = 0.0f;
  184. typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p = backend.limbs();
  185. limb_type mask = ~static_cast<limb_type>(0u);
  186. std::size_t index = backend.size() - 1;
  187. std::size_t shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits * index;
  188. while (bits_to_keep > 0)
  189. {
  190. if (bits_to_keep < (std::ptrdiff_t)cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
  191. {
  192. if(index != backend.size() - 1)
  193. {
  194. const std::ptrdiff_t left_shift_amount = static_cast<std::ptrdiff_t>(static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits) - bits_to_keep);
  195. mask <<= left_shift_amount;
  196. }
  197. else
  198. {
  199. std::ptrdiff_t bits_in_first_limb = static_cast<std::ptrdiff_t>(bits % static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits));
  200. if (bits_in_first_limb == 0)
  201. bits_in_first_limb = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  202. if (bits_in_first_limb > bits_to_keep)
  203. mask <<= bits_in_first_limb - bits_to_keep;
  204. }
  205. }
  206. *result += ldexp(static_cast<R>(p[index] & mask), static_cast<int>(shift));
  207. shift -= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  208. const bool bits_has_non_zero_remainder = (bits % static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits) != 0);
  209. bits_to_keep -= ((index == backend.size() - 1) && bits_has_non_zero_remainder)
  210. ? bits % static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
  211. : static_cast<std::ptrdiff_t>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits);
  212. --index;
  213. }
  214. // Perform rounding:
  215. bits -= 1 + std::numeric_limits<R>::digits;
  216. if (eval_bit_test(backend, static_cast<unsigned>(bits)))
  217. {
  218. if ((eval_lsb_imp(backend) < static_cast<std::size_t>(bits)) || eval_bit_test(backend, static_cast<std::size_t>(bits + 1)))
  219. {
  220. #ifdef BOOST_MP_MATH_AVAILABLE
  221. BOOST_IF_CONSTEXPR(std::numeric_limits<R>::has_infinity)
  222. {
  223. // Must NOT throw:
  224. *result = boost::math::float_next(*result, boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::ignore_error>()));
  225. }
  226. else
  227. {
  228. *result = boost::math::float_next(*result);
  229. }
  230. #else
  231. using std::nextafter; BOOST_MP_FLOAT128_USING
  232. *result = nextafter(*result, *result * 2);
  233. #endif
  234. }
  235. }
  236. }
  237. else
  238. {
  239. typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p = backend.limbs();
  240. std::size_t shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  241. *result = static_cast<R>(*p);
  242. for (std::size_t i = 1; i < backend.size(); ++i)
  243. {
  244. *result += static_cast<R>(ldexp(static_cast<long double>(p[i]), static_cast<int>(shift)));
  245. shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  246. }
  247. }
  248. if (backend.sign())
  249. *result = -*result;
  250. }
  251. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  252. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
  253. eval_is_zero(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept
  254. {
  255. return (val.size() == 1) && (val.limbs()[0] == 0);
  256. }
  257. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  258. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, int>::type
  259. eval_get_sign(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept
  260. {
  261. return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1;
  262. }
  263. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  264. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  265. eval_abs(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  266. {
  267. result = val;
  268. result.sign(false);
  269. }
  270. //
  271. // Get the location of the least-significant-bit:
  272. //
  273. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  274. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
  275. eval_lsb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  276. {
  277. //
  278. // Find the index of the least significant limb that is non-zero:
  279. //
  280. std::size_t index = 0;
  281. while (!a.limbs()[index] && (index < a.size()))
  282. ++index;
  283. //
  284. // Find the index of the least significant bit within that limb:
  285. //
  286. std::size_t result = boost::multiprecision::detail::find_lsb(a.limbs()[index]);
  287. return result + index * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  288. }
  289. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  290. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
  291. eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  292. {
  293. using default_ops::eval_get_sign;
  294. if (eval_get_sign(a) == 0)
  295. {
  296. BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
  297. }
  298. if (a.sign())
  299. {
  300. BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
  301. }
  302. return eval_lsb_imp(a);
  303. }
  304. //
  305. // Get the location of the most-significant-bit:
  306. //
  307. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  308. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
  309. eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  310. {
  311. //
  312. // Find the index of the most significant bit that is non-zero:
  313. //
  314. return (a.size() - 1) * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]);
  315. }
  316. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  317. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
  318. eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  319. {
  320. using default_ops::eval_get_sign;
  321. if (eval_get_sign(a) == 0)
  322. {
  323. BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
  324. }
  325. if (a.sign())
  326. {
  327. BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
  328. }
  329. return eval_msb_imp(a);
  330. }
  331. #ifdef BOOST_GCC
  332. //
  333. // We really shouldn't need to be disabling this warning, but it really does appear to be
  334. // spurious. The warning appears only when in release mode, and asserts are on.
  335. //
  336. #pragma GCC diagnostic push
  337. #pragma GCC diagnostic ignored "-Warray-bounds"
  338. #endif
  339. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  340. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
  341. eval_bit_test(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index) noexcept
  342. {
  343. std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  344. std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  345. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  346. if (offset >= val.size())
  347. return false;
  348. return val.limbs()[offset] & mask ? true : false;
  349. }
  350. #ifdef BOOST_GCC
  351. #pragma GCC diagnostic pop
  352. #endif
  353. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  354. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  355. eval_bit_set(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index)
  356. {
  357. std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  358. std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  359. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  360. if (offset >= val.size())
  361. {
  362. std::size_t os = val.size();
  363. val.resize(offset + 1, offset + 1);
  364. if (offset >= val.size())
  365. return; // fixed precision overflow
  366. for (std::size_t i = os; i <= offset; ++i)
  367. val.limbs()[i] = 0;
  368. }
  369. val.limbs()[offset] |= mask;
  370. }
  371. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  372. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  373. eval_bit_unset(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index) noexcept
  374. {
  375. std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  376. std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  377. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  378. if (offset >= val.size())
  379. return;
  380. val.limbs()[offset] &= ~mask;
  381. val.normalize();
  382. }
  383. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  384. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  385. eval_bit_flip(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, std::size_t index)
  386. {
  387. std::size_t offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  388. std::size_t shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  389. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  390. if (offset >= val.size())
  391. {
  392. std::size_t os = val.size();
  393. val.resize(offset + 1, offset + 1);
  394. if (offset >= val.size())
  395. return; // fixed precision overflow
  396. for (std::size_t i = os; i <= offset; ++i)
  397. val.limbs()[i] = 0;
  398. }
  399. val.limbs()[offset] ^= mask;
  400. val.normalize();
  401. }
  402. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  403. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  404. eval_qr(
  405. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
  406. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& y,
  407. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
  408. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  409. {
  410. divide_unsigned_helper(&q, x, y, r);
  411. q.sign(x.sign() != y.sign());
  412. r.sign(x.sign());
  413. }
  414. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  415. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  416. eval_qr(
  417. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
  418. limb_type y,
  419. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
  420. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  421. {
  422. divide_unsigned_helper(&q, x, y, r);
  423. q.sign(x.sign());
  424. r.sign(x.sign());
  425. }
  426. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class U>
  427. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<U>::value>::type eval_qr(
  428. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
  429. U y,
  430. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
  431. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  432. {
  433. using default_ops::eval_qr;
  434. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
  435. t = y;
  436. eval_qr(x, t, q, r);
  437. }
  438. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  439. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
  440. eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, Integer mod)
  441. {
  442. BOOST_IF_CONSTEXPR (sizeof(Integer) <= sizeof(limb_type))
  443. {
  444. if (mod <= (std::numeric_limits<limb_type>::max)())
  445. {
  446. const std::ptrdiff_t n = a.size();
  447. const double_limb_type two_n_mod = static_cast<limb_type>(1u) + (~static_cast<limb_type>(0u) - mod) % mod;
  448. limb_type res = a.limbs()[n - 1] % mod;
  449. for (std::ptrdiff_t i = n - 2; i >= 0; --i)
  450. res = static_cast<limb_type>((res * two_n_mod + a.limbs()[i]) % mod);
  451. return res;
  452. }
  453. else
  454. return default_ops::eval_integer_modulus(a, mod);
  455. }
  456. else
  457. {
  458. return default_ops::eval_integer_modulus(a, mod);
  459. }
  460. }
  461. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  462. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_signed<Integer>::value && boost::multiprecision::detail::is_integral<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
  463. eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
  464. {
  465. return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val));
  466. }
  467. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR limb_type eval_gcd(limb_type u, limb_type v)
  468. {
  469. // boundary cases
  470. if (!u || !v)
  471. return u | v;
  472. #if (defined(__cpp_lib_gcd_lcm) && (__cpp_lib_gcd_lcm >= 201606L))
  473. return std::gcd(u, v);
  474. #else
  475. std::size_t shift = boost::multiprecision::detail::find_lsb(u | v);
  476. u >>= boost::multiprecision::detail::find_lsb(u);
  477. do
  478. {
  479. v >>= boost::multiprecision::detail::find_lsb(v);
  480. if (u > v)
  481. std_constexpr::swap(u, v);
  482. v -= u;
  483. } while (v);
  484. return u << shift;
  485. #endif
  486. }
  487. inline BOOST_MP_CXX14_CONSTEXPR double_limb_type eval_gcd(double_limb_type u, double_limb_type v)
  488. {
  489. #if (defined(__cpp_lib_gcd_lcm) && (__cpp_lib_gcd_lcm >= 201606L)) && (!defined(BOOST_HAS_INT128) || !defined(__STRICT_ANSI__))
  490. return std::gcd(u, v);
  491. #else
  492. if (u == 0)
  493. return v;
  494. std::size_t shift = boost::multiprecision::detail::find_lsb(u | v);
  495. u >>= boost::multiprecision::detail::find_lsb(u);
  496. do
  497. {
  498. v >>= boost::multiprecision::detail::find_lsb(v);
  499. if (u > v)
  500. std_constexpr::swap(u, v);
  501. v -= u;
  502. } while (v);
  503. return u << shift;
  504. #endif
  505. }
  506. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  507. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  508. eval_gcd(
  509. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  510. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  511. limb_type b)
  512. {
  513. int s = eval_get_sign(a);
  514. if (!b || !s)
  515. {
  516. result = a;
  517. *result.limbs() |= b;
  518. }
  519. else
  520. {
  521. eval_modulus(result, a, b);
  522. limb_type& res = *result.limbs();
  523. res = eval_gcd(res, b);
  524. }
  525. result.sign(false);
  526. }
  527. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  528. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  529. eval_gcd(
  530. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  531. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  532. double_limb_type b)
  533. {
  534. int s = eval_get_sign(a);
  535. if (!b || !s)
  536. {
  537. if (!s)
  538. result = b;
  539. else
  540. result = a;
  541. return;
  542. }
  543. double_limb_type res = 0;
  544. if(a.sign() == 0)
  545. res = eval_integer_modulus(a, b);
  546. else
  547. {
  548. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(a);
  549. t.negate();
  550. res = eval_integer_modulus(t, b);
  551. }
  552. res = eval_gcd(res, b);
  553. result = res;
  554. result.sign(false);
  555. }
  556. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  557. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  558. eval_gcd(
  559. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  560. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  561. signed_double_limb_type v)
  562. {
  563. eval_gcd(result, a, static_cast<double_limb_type>(v < 0 ? -v : v));
  564. }
  565. //
  566. // These 2 overloads take care of gcd against an (unsigned) short etc:
  567. //
  568. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  569. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  570. eval_gcd(
  571. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  572. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  573. const Integer& v)
  574. {
  575. eval_gcd(result, a, static_cast<limb_type>(v));
  576. }
  577. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  578. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_signed<Integer>::value && boost::multiprecision::detail::is_integral<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  579. eval_gcd(
  580. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  581. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  582. const Integer& v)
  583. {
  584. eval_gcd(result, a, static_cast<limb_type>(v < 0 ? -v : v));
  585. }
  586. //
  587. // What follows is Lehmer's GCD algorithm:
  588. // Essentially this uses the leading digit(s) of U and V
  589. // only to run a "simulated" Euclid algorithm. It stops
  590. // when the calculated quotient differs from what would have been
  591. // the true quotient. At that point the cosequences are used to
  592. // calculate the new U and V. A nice lucid description appears
  593. // in "An Analysis of Lehmer's Euclidean GCD Algorithm",
  594. // by Jonathan Sorenson. https://www.researchgate.net/publication/2424634_An_Analysis_of_Lehmer%27s_Euclidean_GCD_Algorithm
  595. // DOI: 10.1145/220346.220378.
  596. //
  597. // There are two versions of this algorithm here, and both are "double digit"
  598. // variations: which is to say if there are k bits per limb, then they extract
  599. // 2k bits into a double_limb_type and then run the algorithm on that. The first
  600. // version is a straightforward version of the algorithm, and is designed for
  601. // situations where double_limb_type is a native integer (for example where
  602. // limb_type is a 32-bit integer on a 64-bit machine). For 32-bit limbs it
  603. // reduces the size of U by about 30 bits per call. The second is a more complex
  604. // version for situations where double_limb_type is a synthetic type: for example
  605. // __int128. For 64 bit limbs it reduces the size of U by about 62 bits per call.
  606. //
  607. // The complexity of the algorithm given by Sorenson is roughly O(ln^2(N)) for
  608. // two N bit numbers.
  609. //
  610. // The original double-digit version of the algorithm is described in:
  611. //
  612. // "A Double Digit Lehmer-Euclid Algorithm for Finding the GCD of Long Integers",
  613. // Tudor Jebelean, J Symbolic Computation, 1995 (19), 145.
  614. //
  615. #ifndef BOOST_HAS_INT128
  616. //
  617. // When double_limb_type is a native integer type then we should just use it and not worry about the consequences.
  618. // This can eliminate approximately a full limb with each call.
  619. //
  620. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Storage>
  621. void eval_gcd_lehmer(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& U, cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& V, std::size_t lu, Storage& storage)
  622. {
  623. //
  624. // Extract the leading 2 * bits_per_limb bits from U and V:
  625. //
  626. std::size_t h = lu % bits_per_limb;
  627. double_limb_type u = (static_cast<double_limb_type>((U.limbs()[U.size() - 1])) << bits_per_limb) | U.limbs()[U.size() - 2];
  628. double_limb_type v = (static_cast<double_limb_type>((V.size() < U.size() ? 0 : V.limbs()[V.size() - 1])) << bits_per_limb) | V.limbs()[U.size() - 2];
  629. if (h)
  630. {
  631. u <<= bits_per_limb - h;
  632. u |= U.limbs()[U.size() - 3] >> h;
  633. v <<= bits_per_limb - h;
  634. v |= V.limbs()[U.size() - 3] >> h;
  635. }
  636. //
  637. // Co-sequences x an y: we need only the last 3 values of these,
  638. // the first 2 values are known correct, the third gets checked
  639. // in each loop operation, and we terminate when they go wrong.
  640. //
  641. // x[i+0] is positive for even i.
  642. // y[i+0] is positive for odd i.
  643. //
  644. // However we track only absolute values here:
  645. //
  646. double_limb_type x[3] = {1, 0};
  647. double_limb_type y[3] = {0, 1};
  648. std::size_t i = 0;
  649. #ifdef BOOST_MP_GCD_DEBUG
  650. cpp_int UU, VV;
  651. UU = U;
  652. VV = V;
  653. #endif
  654. while (true)
  655. {
  656. double_limb_type q = u / v;
  657. x[2] = x[0] + q * x[1];
  658. y[2] = y[0] + q * y[1];
  659. double_limb_type tu = u;
  660. u = v;
  661. v = tu - q * v;
  662. ++i;
  663. //
  664. // We must make sure that y[2] occupies a single limb otherwise
  665. // the multiprecision multiplications below would be much more expensive.
  666. // This can sometimes lose us one iteration, but is worth it for improved
  667. // calculation efficiency.
  668. //
  669. if (y[2] >> bits_per_limb)
  670. break;
  671. //
  672. // These are Jebelean's exact termination conditions:
  673. //
  674. if ((i & 1u) == 0)
  675. {
  676. BOOST_MP_ASSERT(u > v);
  677. if ((v < x[2]) || ((u - v) < (y[2] + y[1])))
  678. break;
  679. }
  680. else
  681. {
  682. BOOST_MP_ASSERT(u > v);
  683. if ((v < y[2]) || ((u - v) < (x[2] + x[1])))
  684. break;
  685. }
  686. #ifdef BOOST_MP_GCD_DEBUG
  687. BOOST_MP_ASSERT(q == UU / VV);
  688. UU %= VV;
  689. UU.swap(VV);
  690. #endif
  691. x[0] = x[1];
  692. x[1] = x[2];
  693. y[0] = y[1];
  694. y[1] = y[2];
  695. }
  696. if (i == 1)
  697. {
  698. // No change to U and V we've stalled!
  699. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
  700. eval_modulus(t, U, V);
  701. U.swap(V);
  702. V.swap(t);
  703. return;
  704. }
  705. //
  706. // Update U and V.
  707. // We have:
  708. //
  709. // U = x[0]U + y[0]V and
  710. // V = x[1]U + y[1]V.
  711. //
  712. // But since we track only absolute values of x and y
  713. // we have to take account of the implied signs and perform
  714. // the appropriate subtraction depending on the whether i is
  715. // even or odd:
  716. //
  717. std::size_t ts = U.size() + 1;
  718. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t1(storage, ts), t2(storage, ts), t3(storage, ts);
  719. eval_multiply(t1, U, static_cast<limb_type>(x[0]));
  720. eval_multiply(t2, V, static_cast<limb_type>(y[0]));
  721. eval_multiply(t3, U, static_cast<limb_type>(x[1]));
  722. if ((i & 1u) == 0)
  723. {
  724. if (x[0] == 0)
  725. U = t2;
  726. else
  727. {
  728. BOOST_MP_ASSERT(t2.compare(t1) >= 0);
  729. eval_subtract(U, t2, t1);
  730. BOOST_MP_ASSERT(U.sign() == false);
  731. }
  732. }
  733. else
  734. {
  735. BOOST_MP_ASSERT(t1.compare(t2) >= 0);
  736. eval_subtract(U, t1, t2);
  737. BOOST_MP_ASSERT(U.sign() == false);
  738. }
  739. eval_multiply(t2, V, static_cast<limb_type>(y[1]));
  740. if (i & 1u)
  741. {
  742. if (x[1] == 0)
  743. V = t2;
  744. else
  745. {
  746. BOOST_MP_ASSERT(t2.compare(t3) >= 0);
  747. eval_subtract(V, t2, t3);
  748. BOOST_MP_ASSERT(V.sign() == false);
  749. }
  750. }
  751. else
  752. {
  753. BOOST_MP_ASSERT(t3.compare(t2) >= 0);
  754. eval_subtract(V, t3, t2);
  755. BOOST_MP_ASSERT(V.sign() == false);
  756. }
  757. BOOST_MP_ASSERT(U.compare(V) >= 0);
  758. BOOST_MP_ASSERT(lu > eval_msb(U));
  759. #ifdef BOOST_MP_GCD_DEBUG
  760. BOOST_MP_ASSERT(UU == U);
  761. BOOST_MP_ASSERT(VV == V);
  762. extern std::size_t total_lehmer_gcd_calls;
  763. extern std::size_t total_lehmer_gcd_bits_saved;
  764. extern std::size_t total_lehmer_gcd_cycles;
  765. ++total_lehmer_gcd_calls;
  766. total_lehmer_gcd_bits_saved += lu - eval_msb(U);
  767. total_lehmer_gcd_cycles += i;
  768. #endif
  769. if (lu < 2048)
  770. {
  771. //
  772. // Since we have stripped all common powers of 2 from U and V at the start
  773. // if either are even at this point, we can remove stray powers of 2 now.
  774. // Note that it is not possible for *both* U and V to be even at this point.
  775. //
  776. // This has an adverse effect on performance for high bit counts, but has
  777. // a significant positive effect for smaller counts.
  778. //
  779. if ((U.limbs()[0] & 1u) == 0)
  780. {
  781. eval_right_shift(U, eval_lsb(U));
  782. if (U.compare(V) < 0)
  783. U.swap(V);
  784. }
  785. else if ((V.limbs()[0] & 1u) == 0)
  786. {
  787. eval_right_shift(V, eval_lsb(V));
  788. }
  789. }
  790. storage.deallocate(ts * 3);
  791. }
  792. #else
  793. //
  794. // This branch is taken when double_limb_type is a synthetic type with no native hardware support.
  795. // For example __int128. The assumption is that add/subtract/multiply of double_limb_type are efficient,
  796. // but that division is very slow.
  797. //
  798. // We begin with a specialized routine for division.
  799. // We know that most of the time this is called the result will be 1.
  800. // For small limb counts, this almost doubles the performance of Lehmer's routine!
  801. //
  802. BOOST_FORCEINLINE void divide_subtract(double_limb_type& q, double_limb_type& u, const double_limb_type& v)
  803. {
  804. BOOST_MP_ASSERT(q == 1); // precondition on entry.
  805. u -= v;
  806. while (u >= v)
  807. {
  808. u -= v;
  809. if (++q > 30)
  810. {
  811. double_limb_type t = u / v;
  812. u -= t * v;
  813. q += t;
  814. }
  815. }
  816. }
  817. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Storage>
  818. void eval_gcd_lehmer(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& U, cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& V, std::size_t lu, Storage& storage)
  819. {
  820. //
  821. // Extract the leading 2*bits_per_limb bits from U and V:
  822. //
  823. std::size_t h = lu % bits_per_limb;
  824. double_limb_type u, v;
  825. if (h)
  826. {
  827. u = (static_cast<double_limb_type>((U.limbs()[U.size() - 1])) << bits_per_limb) | U.limbs()[U.size() - 2];
  828. v = (static_cast<double_limb_type>((V.size() < U.size() ? 0 : V.limbs()[V.size() - 1])) << bits_per_limb) | V.limbs()[U.size() - 2];
  829. u <<= bits_per_limb - h;
  830. u |= U.limbs()[U.size() - 3] >> h;
  831. v <<= bits_per_limb - h;
  832. v |= V.limbs()[U.size() - 3] >> h;
  833. }
  834. else
  835. {
  836. u = (static_cast<double_limb_type>(U.limbs()[U.size() - 1]) << bits_per_limb) | U.limbs()[U.size() - 2];
  837. v = (static_cast<double_limb_type>(V.limbs()[U.size() - 1]) << bits_per_limb) | V.limbs()[U.size() - 2];
  838. }
  839. //
  840. // Cosequences are stored as limb_types, we take care not to overflow these:
  841. //
  842. // x[i+0] is positive for even i.
  843. // y[i+0] is positive for odd i.
  844. //
  845. // However we track only absolute values here:
  846. //
  847. limb_type x[3] = { 1, 0 };
  848. limb_type y[3] = { 0, 1 };
  849. std::size_t i = 0;
  850. #ifdef BOOST_MP_GCD_DEBUG
  851. cpp_int UU, VV;
  852. UU = U;
  853. VV = V;
  854. #endif
  855. //
  856. // We begine by running a single digit version of Lehmer's algorithm, we still have
  857. // to track u and v at double precision, but this adds only a tiny performance penalty.
  858. // What we gain is fast division, and fast termination testing.
  859. // When you see static_cast<limb_type>(u >> bits_per_limb) here, this is really just
  860. // a direct access to the upper bits_per_limb of the double limb type. For __int128
  861. // this is simple a load of the upper 64 bits and the "shift" is optimised away.
  862. //
  863. double_limb_type old_u, old_v;
  864. while (true)
  865. {
  866. limb_type q = static_cast<limb_type>(u >> bits_per_limb) / static_cast<limb_type>(v >> bits_per_limb);
  867. x[2] = x[0] + q * x[1];
  868. y[2] = y[0] + q * y[1];
  869. double_limb_type tu = u;
  870. old_u = u;
  871. old_v = v;
  872. u = v;
  873. double_limb_type t = q * v;
  874. if (tu < t)
  875. {
  876. ++i;
  877. break;
  878. }
  879. v = tu - t;
  880. ++i;
  881. BOOST_MP_ASSERT((u <= v) || (t / q == old_v));
  882. if (u <= v)
  883. {
  884. // We've gone terribly wrong, probably numeric overflow:
  885. break;
  886. }
  887. if ((i & 1u) == 0)
  888. {
  889. if ((static_cast<limb_type>(v >> bits_per_limb) < x[2]) || ((static_cast<limb_type>(u >> bits_per_limb) - static_cast<limb_type>(v >> bits_per_limb)) < (y[2] + y[1])))
  890. break;
  891. }
  892. else
  893. {
  894. if ((static_cast<limb_type>(v >> bits_per_limb) < y[2]) || ((static_cast<limb_type>(u >> bits_per_limb) - static_cast<limb_type>(v >> bits_per_limb)) < (x[2] + x[1])))
  895. break;
  896. }
  897. #ifdef BOOST_MP_GCD_DEBUG
  898. BOOST_MP_ASSERT(q == UU / VV);
  899. UU %= VV;
  900. UU.swap(VV);
  901. #endif
  902. x[0] = x[1];
  903. x[1] = x[2];
  904. y[0] = y[1];
  905. y[1] = y[2];
  906. }
  907. //
  908. // We get here when the single digit algorithm has gone wrong, back up i, u and v:
  909. //
  910. --i;
  911. u = old_u;
  912. v = old_v;
  913. //
  914. // Now run the full double-digit algorithm:
  915. //
  916. while (true)
  917. {
  918. double_limb_type q = 1u;
  919. double_limb_type tt = u;
  920. divide_subtract(q, u, v);
  921. std::swap(u, v);
  922. tt = y[0] + q * static_cast<double_limb_type>(y[1]);
  923. //
  924. // If calculation of y[2] would overflow a single limb, then we *must* terminate.
  925. // Note that x[2] < y[2] so there is no need to check that as well:
  926. //
  927. if (tt >> bits_per_limb)
  928. {
  929. ++i;
  930. break;
  931. }
  932. x[2] = static_cast<limb_type>(x[0] + static_cast<double_limb_type>(q * x[1]));
  933. y[2] = static_cast<limb_type>(tt);
  934. ++i;
  935. if ((i & 1u) == 0)
  936. {
  937. BOOST_MP_ASSERT(u > v);
  938. if ((v < x[2]) || ((u - v) < (static_cast<double_limb_type>(y[2]) + y[1])))
  939. break;
  940. }
  941. else
  942. {
  943. BOOST_MP_ASSERT(u > v);
  944. if ((v < y[2]) || ((u - v) < (static_cast<double_limb_type>(x[2]) + x[1])))
  945. break;
  946. }
  947. #ifdef BOOST_MP_GCD_DEBUG
  948. BOOST_MP_ASSERT(q == UU / VV);
  949. UU %= VV;
  950. UU.swap(VV);
  951. #endif
  952. x[0] = x[1];
  953. x[1] = x[2];
  954. y[0] = y[1];
  955. y[1] = y[2];
  956. }
  957. if (i == 1)
  958. {
  959. // No change to U and V we've stalled!
  960. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
  961. eval_modulus(t, U, V);
  962. U.swap(V);
  963. V.swap(t);
  964. return;
  965. }
  966. //
  967. // Update U and V.
  968. // We have:
  969. //
  970. // U = x[0]U + y[0]V and
  971. // V = x[1]U + y[1]V.
  972. //
  973. // But since we track only absolute values of x and y
  974. // we have to take account of the implied signs and perform
  975. // the appropriate subtraction depending on the whether i is
  976. // even or odd:
  977. //
  978. std::size_t ts = U.size() + 1;
  979. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t1(storage, ts), t2(storage, ts), t3(storage, ts);
  980. eval_multiply(t1, U, x[0]);
  981. eval_multiply(t2, V, y[0]);
  982. eval_multiply(t3, U, x[1]);
  983. if ((i & 1u) == 0)
  984. {
  985. if (x[0] == 0)
  986. U = t2;
  987. else
  988. {
  989. BOOST_MP_ASSERT(t2.compare(t1) >= 0);
  990. eval_subtract(U, t2, t1);
  991. BOOST_MP_ASSERT(U.sign() == false);
  992. }
  993. }
  994. else
  995. {
  996. BOOST_MP_ASSERT(t1.compare(t2) >= 0);
  997. eval_subtract(U, t1, t2);
  998. BOOST_MP_ASSERT(U.sign() == false);
  999. }
  1000. eval_multiply(t2, V, y[1]);
  1001. if (i & 1u)
  1002. {
  1003. if (x[1] == 0)
  1004. V = t2;
  1005. else
  1006. {
  1007. BOOST_MP_ASSERT(t2.compare(t3) >= 0);
  1008. eval_subtract(V, t2, t3);
  1009. BOOST_MP_ASSERT(V.sign() == false);
  1010. }
  1011. }
  1012. else
  1013. {
  1014. BOOST_MP_ASSERT(t3.compare(t2) >= 0);
  1015. eval_subtract(V, t3, t2);
  1016. BOOST_MP_ASSERT(V.sign() == false);
  1017. }
  1018. BOOST_MP_ASSERT(U.compare(V) >= 0);
  1019. BOOST_MP_ASSERT(lu > eval_msb(U));
  1020. #ifdef BOOST_MP_GCD_DEBUG
  1021. BOOST_MP_ASSERT(UU == U);
  1022. BOOST_MP_ASSERT(VV == V);
  1023. extern std::size_t total_lehmer_gcd_calls;
  1024. extern std::size_t total_lehmer_gcd_bits_saved;
  1025. extern std::size_t total_lehmer_gcd_cycles;
  1026. ++total_lehmer_gcd_calls;
  1027. total_lehmer_gcd_bits_saved += lu - eval_msb(U);
  1028. total_lehmer_gcd_cycles += i;
  1029. #endif
  1030. if (lu < 2048)
  1031. {
  1032. //
  1033. // Since we have stripped all common powers of 2 from U and V at the start
  1034. // if either are even at this point, we can remove stray powers of 2 now.
  1035. // Note that it is not possible for *both* U and V to be even at this point.
  1036. //
  1037. // This has an adverse effect on performance for high bit counts, but has
  1038. // a significant positive effect for smaller counts.
  1039. //
  1040. if ((U.limbs()[0] & 1u) == 0)
  1041. {
  1042. eval_right_shift(U, eval_lsb(U));
  1043. if (U.compare(V) < 0)
  1044. U.swap(V);
  1045. }
  1046. else if ((V.limbs()[0] & 1u) == 0)
  1047. {
  1048. eval_right_shift(V, eval_lsb(V));
  1049. }
  1050. }
  1051. storage.deallocate(ts * 3);
  1052. }
  1053. #endif
  1054. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1055. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  1056. eval_gcd(
  1057. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  1058. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  1059. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b)
  1060. {
  1061. using default_ops::eval_get_sign;
  1062. using default_ops::eval_is_zero;
  1063. using default_ops::eval_lsb;
  1064. if (a.size() == 1)
  1065. {
  1066. eval_gcd(result, b, *a.limbs());
  1067. return;
  1068. }
  1069. if (b.size() == 1)
  1070. {
  1071. eval_gcd(result, a, *b.limbs());
  1072. return;
  1073. }
  1074. std::size_t temp_size = (std::max)(a.size(), b.size()) + 1;
  1075. typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::scoped_shared_storage storage(a, temp_size * 6);
  1076. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> U(storage, temp_size);
  1077. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> V(storage, temp_size);
  1078. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(storage, temp_size);
  1079. U = a;
  1080. V = b;
  1081. int s = eval_get_sign(U);
  1082. /* GCD(0,x) := x */
  1083. if (s < 0)
  1084. {
  1085. U.negate();
  1086. }
  1087. else if (s == 0)
  1088. {
  1089. result = V;
  1090. return;
  1091. }
  1092. s = eval_get_sign(V);
  1093. if (s < 0)
  1094. {
  1095. V.negate();
  1096. }
  1097. else if (s == 0)
  1098. {
  1099. result = U;
  1100. return;
  1101. }
  1102. //
  1103. // Remove common factors of 2:
  1104. //
  1105. std::size_t us = eval_lsb(U);
  1106. std::size_t vs = eval_lsb(V);
  1107. std::size_t shift = (std::min)(us, vs);
  1108. if (us)
  1109. eval_right_shift(U, us);
  1110. if (vs)
  1111. eval_right_shift(V, vs);
  1112. if (U.compare(V) < 0)
  1113. U.swap(V);
  1114. while (!eval_is_zero(V))
  1115. {
  1116. if (U.size() <= 2)
  1117. {
  1118. //
  1119. // Special case: if V has no more than 2 limbs
  1120. // then we can reduce U and V to a pair of integers and perform
  1121. // direct integer gcd:
  1122. //
  1123. if (U.size() == 1)
  1124. U = eval_gcd(*V.limbs(), *U.limbs());
  1125. else
  1126. {
  1127. double_limb_type i = U.limbs()[0] | (static_cast<double_limb_type>(U.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
  1128. double_limb_type j = (V.size() == 1) ? *V.limbs() : V.limbs()[0] | (static_cast<double_limb_type>(V.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
  1129. U = eval_gcd(i, j);
  1130. }
  1131. break;
  1132. }
  1133. std::size_t lu = eval_msb(U) + 1;
  1134. std::size_t lv = eval_msb(V) + 1;
  1135. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  1136. if (!BOOST_MP_IS_CONST_EVALUATED(lu) && (lu - lv <= bits_per_limb / 2))
  1137. #else
  1138. if (lu - lv <= bits_per_limb / 2)
  1139. #endif
  1140. {
  1141. eval_gcd_lehmer(U, V, lu, storage);
  1142. }
  1143. else
  1144. {
  1145. eval_modulus(t, U, V);
  1146. U.swap(V);
  1147. V.swap(t);
  1148. }
  1149. }
  1150. result = U;
  1151. if (shift)
  1152. eval_left_shift(result, shift);
  1153. }
  1154. //
  1155. // Now again for trivial backends:
  1156. //
  1157. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1158. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  1159. eval_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) noexcept
  1160. {
  1161. *result.limbs() = boost::multiprecision::detail::constexpr_gcd(*a.limbs(), *b.limbs());
  1162. result.sign(false);
  1163. }
  1164. // This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version:
  1165. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1166. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (Checked1 == unchecked)>::type
  1167. eval_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) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  1168. {
  1169. *result.limbs() = boost::multiprecision::detail::constexpr_lcm(*a.limbs(), *b.limbs());
  1170. result.normalize(); // result may overflow the specified number of bits
  1171. result.sign(false);
  1172. }
  1173. inline void conversion_overflow(const std::integral_constant<int, checked>&)
  1174. {
  1175. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type"));
  1176. }
  1177. inline BOOST_MP_CXX14_CONSTEXPR void conversion_overflow(const std::integral_constant<int, unchecked>&) {}
  1178. #if defined(__clang__) && defined(__MINGW32__)
  1179. //
  1180. // clang-11 on Mingw segfaults on conversion of __int128 -> float.
  1181. // See: https://bugs.llvm.org/show_bug.cgi?id=48941
  1182. // These workarounds pass everything through an intermediate uint64_t.
  1183. //
  1184. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1185. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1186. 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 && std::is_same<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, double_limb_type>::value>::type
  1187. eval_convert_to(float* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
  1188. {
  1189. float f = static_cast<std::uint64_t>((*val.limbs()) >> 64);
  1190. *result = std::ldexp(f, 64);
  1191. *result += static_cast<std::uint64_t>((*val.limbs()));
  1192. if(val.sign())
  1193. *result = -*result;
  1194. }
  1195. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1196. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1197. 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 && std::is_same<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, double_limb_type>::value>::type
  1198. eval_convert_to(double* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
  1199. {
  1200. float f = static_cast<std::uint64_t>((*val.limbs()) >> 64);
  1201. *result = std::ldexp(f, 64);
  1202. *result += static_cast<std::uint64_t>((*val.limbs()));
  1203. if(val.sign())
  1204. *result = -*result;
  1205. }
  1206. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1207. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1208. 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 && std::is_same<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, double_limb_type>::value>::type
  1209. eval_convert_to(long double* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
  1210. {
  1211. float f = static_cast<std::uint64_t>((*val.limbs()) >> 64);
  1212. *result = std::ldexp(f, 64);
  1213. *result += static_cast<std::uint64_t>((*val.limbs()));
  1214. if(val.sign())
  1215. *result = -*result;
  1216. }
  1217. #endif
  1218. template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1219. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1220. 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 && std::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value>::type
  1221. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
  1222. {
  1223. BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized)
  1224. {
  1225. using common_type = typename std::common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type;
  1226. if (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)()))
  1227. {
  1228. if (val.isneg())
  1229. {
  1230. check_is_negative(std::integral_constant < bool, (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) || (number_category<R>::value == number_kind_floating_point) > ());
  1231. if (static_cast<common_type>(*val.limbs()) > -static_cast<common_type>((std::numeric_limits<R>::min)()))
  1232. conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  1233. *result = (std::numeric_limits<R>::min)();
  1234. }
  1235. else
  1236. {
  1237. conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  1238. *result = boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());
  1239. }
  1240. }
  1241. else
  1242. {
  1243. *result = static_cast<R>(*val.limbs());
  1244. if (val.isneg())
  1245. {
  1246. check_is_negative(std::integral_constant < bool, (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) || (number_category<R>::value == number_kind_floating_point) > ());
  1247. *result = negate_integer(*result, std::integral_constant < bool, is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point) > ());
  1248. }
  1249. }
  1250. }
  1251. else
  1252. {
  1253. *result = static_cast<R>(*val.limbs());
  1254. if (val.isneg())
  1255. {
  1256. check_is_negative(std::integral_constant<bool, (boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value) || (number_category<R>::value == number_kind_floating_point) > ());
  1257. *result = negate_integer(*result, std::integral_constant<bool, is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point) > ());
  1258. }
  1259. }
  1260. }
  1261. template <class R, std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1262. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1263. 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 && std::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value>::type
  1264. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
  1265. {
  1266. BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized)
  1267. {
  1268. using common_type = typename std::common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type;
  1269. if(static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)()))
  1270. {
  1271. conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  1272. *result = boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());
  1273. }
  1274. else
  1275. *result = static_cast<R>(*val.limbs());
  1276. }
  1277. else
  1278. *result = static_cast<R>(*val.limbs());
  1279. }
  1280. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1281. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
  1282. eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  1283. {
  1284. using default_ops::eval_get_sign;
  1285. if (eval_get_sign(a) == 0)
  1286. {
  1287. BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
  1288. }
  1289. if (a.sign())
  1290. {
  1291. BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
  1292. }
  1293. //
  1294. // Find the index of the least significant bit within that limb:
  1295. //
  1296. return boost::multiprecision::detail::find_lsb(*a.limbs());
  1297. }
  1298. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1299. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
  1300. eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  1301. {
  1302. //
  1303. // Find the index of the least significant bit within that limb:
  1304. //
  1305. return boost::multiprecision::detail::find_msb(*a.limbs());
  1306. }
  1307. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1308. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, std::size_t>::type
  1309. eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  1310. {
  1311. using default_ops::eval_get_sign;
  1312. if (eval_get_sign(a) == 0)
  1313. {
  1314. BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
  1315. }
  1316. if (a.sign())
  1317. {
  1318. BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
  1319. }
  1320. return eval_msb_imp(a);
  1321. }
  1322. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  1323. inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) noexcept
  1324. {
  1325. std::size_t result = 0;
  1326. for (std::size_t i = 0; i < val.size(); ++i)
  1327. {
  1328. boost::multiprecision::detail::hash_combine(result, val.limbs()[i]);
  1329. }
  1330. boost::multiprecision::detail::hash_combine(result, val.sign());
  1331. return result;
  1332. }
  1333. #ifdef BOOST_MSVC
  1334. #pragma warning(pop)
  1335. #endif
  1336. } // Namespace backends
  1337. namespace detail {
  1338. #ifndef BOOST_MP_STANDALONE
  1339. template <typename T>
  1340. inline BOOST_CXX14_CONSTEXPR T constexpr_gcd(T a, T b) noexcept
  1341. {
  1342. return boost::integer::gcd(a, b);
  1343. }
  1344. template <typename T>
  1345. inline BOOST_CXX14_CONSTEXPR T constexpr_lcm(T a, T b) noexcept
  1346. {
  1347. return boost::integer::lcm(a, b);
  1348. }
  1349. #else
  1350. template <typename T>
  1351. inline BOOST_CXX14_CONSTEXPR T constexpr_gcd(T a, T b) noexcept
  1352. {
  1353. return boost::multiprecision::backends::eval_gcd(a, b);
  1354. }
  1355. template <typename T>
  1356. inline BOOST_CXX14_CONSTEXPR T constexpr_lcm(T a, T b) noexcept
  1357. {
  1358. const T ab_gcd = boost::multiprecision::detail::constexpr_gcd(a, b);
  1359. return (a * b) / ab_gcd;
  1360. }
  1361. #endif // BOOST_MP_STANDALONE
  1362. }
  1363. }} // Namespace boost::multiprecision
  1364. #endif