misc.hpp 61 KB

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