misc.hpp 62 KB

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