misc.hpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright 2012 John Maddock. Distributed under the Boost
  3. // Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
  5. //
  6. // Comparison operators for cpp_int_backend:
  7. //
  8. #ifndef BOOST_MP_CPP_INT_MISC_HPP
  9. #define BOOST_MP_CPP_INT_MISC_HPP
  10. #include <boost/multiprecision/detail/bitscan.hpp> // lsb etc
  11. #include <boost/integer/common_factor_rt.hpp> // gcd/lcm
  12. #include <boost/functional/hash_fwd.hpp>
  13. #ifdef BOOST_MSVC
  14. #pragma warning(push)
  15. #pragma warning(disable:4702)
  16. #pragma warning(disable:4127) // conditional expression is constant
  17. #pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned
  18. #endif
  19. namespace boost{ namespace multiprecision{ namespace backends{
  20. template <class R, class CppInt>
  21. void check_in_range(const CppInt& val, const mpl::int_<checked>&)
  22. {
  23. typedef typename boost::multiprecision::detail::canonical<R, CppInt>::type cast_type;
  24. if(val.sign())
  25. {
  26. if(boost::is_signed<R>::value == false)
  27. BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
  28. if(val.compare(static_cast<cast_type>((std::numeric_limits<R>::min)())) < 0)
  29. BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
  30. }
  31. else
  32. {
  33. if(val.compare(static_cast<cast_type>((std::numeric_limits<R>::max)())) > 0)
  34. BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
  35. }
  36. }
  37. template <class R, class CppInt>
  38. inline void check_in_range(const CppInt& /*val*/, const mpl::int_<unchecked>&) BOOST_NOEXCEPT {}
  39. inline void check_is_negative(const mpl::true_&) BOOST_NOEXCEPT {}
  40. inline void check_is_negative(const mpl::false_&)
  41. {
  42. BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
  43. }
  44. template <class Integer>
  45. inline Integer negate_integer(Integer i, const mpl::true_&) BOOST_NOEXCEPT
  46. {
  47. return -i;
  48. }
  49. template <class Integer>
  50. inline Integer negate_integer(Integer i, const mpl::false_&) BOOST_NOEXCEPT
  51. {
  52. return ~(i-1);
  53. }
  54. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  55. inline typename enable_if_c<is_integral<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
  56. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend)
  57. {
  58. typedef mpl::int_<Checked1> checked_type;
  59. check_in_range<R>(backend, checked_type());
  60. if (std::numeric_limits<R>::digits < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
  61. {
  62. if ((backend.sign() && boost::is_signed<R>::value) && (1 + static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0]))
  63. {
  64. *result = (std::numeric_limits<R>::min)();
  65. return;
  66. }
  67. else if (boost::is_signed<R>::value && !backend.sign() && static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0])
  68. {
  69. *result = (std::numeric_limits<R>::max)();
  70. return;
  71. }
  72. else
  73. *result = static_cast<R>(backend.limbs()[0]);
  74. }
  75. else
  76. *result = static_cast<R>(backend.limbs()[0]);
  77. unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  78. unsigned i = 1;
  79. if (std::numeric_limits<R>::digits > cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
  80. {
  81. while ((i < backend.size()) && (shift < static_cast<unsigned>(std::numeric_limits<R>::digits - cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)))
  82. {
  83. *result += static_cast<R>(backend.limbs()[i]) << shift;
  84. shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  85. ++i;
  86. }
  87. //
  88. // We have one more limb to extract, but may not need all the bits, so treat this as a special case:
  89. //
  90. if (i < backend.size())
  91. {
  92. static const limb_type mask = std::numeric_limits<R>::digits - shift == cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits ?
  93. ~static_cast<limb_type>(0) : (static_cast<limb_type>(1u) << (std::numeric_limits<R>::digits - shift)) - 1;
  94. *result += (static_cast<R>(backend.limbs()[i]) & mask) << shift;
  95. if ((static_cast<R>(backend.limbs()[i]) & static_cast<limb_type>(~mask)) || (i + 1 < backend.size()))
  96. {
  97. // Overflow:
  98. if (backend.sign())
  99. {
  100. check_is_negative(boost::is_signed<R>());
  101. *result = (std::numeric_limits<R>::min)();
  102. }
  103. else if(boost::is_signed<R>::value)
  104. *result = (std::numeric_limits<R>::max)();
  105. return;
  106. }
  107. }
  108. }
  109. else if (backend.size() > 1)
  110. {
  111. // Overflow:
  112. if (backend.sign())
  113. {
  114. check_is_negative(boost::is_signed<R>());
  115. *result = (std::numeric_limits<R>::min)();
  116. }
  117. else if(boost::is_signed<R>::value)
  118. *result = (std::numeric_limits<R>::max)();
  119. return;
  120. }
  121. if(backend.sign())
  122. {
  123. check_is_negative(boost::is_signed<R>());
  124. *result = negate_integer(*result, boost::is_signed<R>());
  125. }
  126. }
  127. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  128. inline typename enable_if_c<is_floating_point<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
  129. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) BOOST_MP_NOEXCEPT_IF(is_arithmetic<R>::value)
  130. {
  131. typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p = backend.limbs();
  132. unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  133. *result = static_cast<R>(*p);
  134. for(unsigned i = 1; i < backend.size(); ++i)
  135. {
  136. *result += static_cast<R>(std::ldexp(static_cast<long double>(p[i]), shift));
  137. shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  138. }
  139. if(backend.sign())
  140. *result = -*result;
  141. }
  142. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  143. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
  144. eval_is_zero(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
  145. {
  146. return (val.size() == 1) && (val.limbs()[0] == 0);
  147. }
  148. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  149. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, int>::type
  150. eval_get_sign(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
  151. {
  152. return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1;
  153. }
  154. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  155. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  156. eval_abs(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  157. {
  158. result = val;
  159. result.sign(false);
  160. }
  161. //
  162. // Get the location of the least-significant-bit:
  163. //
  164. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  165. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  166. eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  167. {
  168. using default_ops::eval_get_sign;
  169. if(eval_get_sign(a) == 0)
  170. {
  171. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  172. }
  173. if(a.sign())
  174. {
  175. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  176. }
  177. //
  178. // Find the index of the least significant limb that is non-zero:
  179. //
  180. unsigned index = 0;
  181. while(!a.limbs()[index] && (index < a.size()))
  182. ++index;
  183. //
  184. // Find the index of the least significant bit within that limb:
  185. //
  186. unsigned result = boost::multiprecision::detail::find_lsb(a.limbs()[index]);
  187. return result + index * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  188. }
  189. //
  190. // Get the location of the most-significant-bit:
  191. //
  192. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  193. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  194. eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  195. {
  196. //
  197. // Find the index of the most significant bit that is non-zero:
  198. //
  199. return (a.size() - 1) * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]);
  200. }
  201. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  202. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  203. eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  204. {
  205. using default_ops::eval_get_sign;
  206. if(eval_get_sign(a) == 0)
  207. {
  208. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  209. }
  210. if(a.sign())
  211. {
  212. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  213. }
  214. return eval_msb_imp(a);
  215. }
  216. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  217. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
  218. eval_bit_test(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT
  219. {
  220. unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  221. unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  222. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  223. if(offset >= val.size())
  224. return false;
  225. return val.limbs()[offset] & mask ? true : false;
  226. }
  227. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  228. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  229. eval_bit_set(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index)
  230. {
  231. unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  232. unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  233. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  234. if(offset >= val.size())
  235. {
  236. unsigned os = val.size();
  237. val.resize(offset + 1, offset + 1);
  238. if(offset >= val.size())
  239. return; // fixed precision overflow
  240. for(unsigned i = os; i <= offset; ++i)
  241. val.limbs()[i] = 0;
  242. }
  243. val.limbs()[offset] |= mask;
  244. }
  245. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  246. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  247. eval_bit_unset(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT
  248. {
  249. unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  250. unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  251. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  252. if(offset >= val.size())
  253. return;
  254. val.limbs()[offset] &= ~mask;
  255. val.normalize();
  256. }
  257. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  258. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  259. eval_bit_flip(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index)
  260. {
  261. unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  262. unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  263. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  264. if(offset >= val.size())
  265. {
  266. unsigned os = val.size();
  267. val.resize(offset + 1, offset + 1);
  268. if(offset >= val.size())
  269. return; // fixed precision overflow
  270. for(unsigned i = os; i <= offset; ++i)
  271. val.limbs()[i] = 0;
  272. }
  273. val.limbs()[offset] ^= mask;
  274. val.normalize();
  275. }
  276. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  277. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  278. eval_qr(
  279. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
  280. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& y,
  281. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
  282. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  283. {
  284. divide_unsigned_helper(&q, x, y, r);
  285. q.sign(x.sign() != y.sign());
  286. r.sign(x.sign());
  287. }
  288. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  289. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  290. eval_qr(
  291. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
  292. limb_type y,
  293. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
  294. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  295. {
  296. divide_unsigned_helper(&q, x, y, r);
  297. q.sign(x.sign());
  298. r.sign(x.sign());
  299. }
  300. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class U>
  301. inline typename enable_if_c<is_integral<U>::value>::type eval_qr(
  302. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
  303. U y,
  304. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
  305. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  306. {
  307. using default_ops::eval_qr;
  308. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
  309. t = y;
  310. eval_qr(x, t, q, r);
  311. }
  312. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  313. inline typename enable_if_c<is_unsigned<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
  314. eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
  315. {
  316. if((sizeof(Integer) <= sizeof(limb_type)) || (val <= (std::numeric_limits<limb_type>::max)()))
  317. {
  318. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> d;
  319. divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>*>(0), x, static_cast<limb_type>(val), d);
  320. return d.limbs()[0];
  321. }
  322. else
  323. {
  324. return default_ops::eval_integer_modulus(x, val);
  325. }
  326. }
  327. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  328. BOOST_MP_FORCEINLINE typename enable_if_c<is_signed<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
  329. eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
  330. {
  331. return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val));
  332. }
  333. inline limb_type integer_gcd_reduce(limb_type u, limb_type v)
  334. {
  335. do
  336. {
  337. if(u > v)
  338. std::swap(u, v);
  339. if(u == v)
  340. break;
  341. v -= u;
  342. v >>= boost::multiprecision::detail::find_lsb(v);
  343. } while(true);
  344. return u;
  345. }
  346. inline double_limb_type integer_gcd_reduce(double_limb_type u, double_limb_type v)
  347. {
  348. do
  349. {
  350. if(u > v)
  351. std::swap(u, v);
  352. if(u == v)
  353. break;
  354. if(v <= ~static_cast<limb_type>(0))
  355. {
  356. u = integer_gcd_reduce(static_cast<limb_type>(v), static_cast<limb_type>(u));
  357. break;
  358. }
  359. v -= u;
  360. #ifdef __MSVC_RUNTIME_CHECKS
  361. while((v & 1u) == 0)
  362. #else
  363. while((static_cast<unsigned>(v) & 1u) == 0)
  364. #endif
  365. v >>= 1;
  366. } while(true);
  367. return u;
  368. }
  369. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  370. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  371. eval_gcd(
  372. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  373. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  374. limb_type v)
  375. {
  376. using default_ops::eval_lsb;
  377. using default_ops::eval_is_zero;
  378. using default_ops::eval_get_sign;
  379. int shift;
  380. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a);
  381. int s = eval_get_sign(u);
  382. /* GCD(0,x) := x */
  383. if(s < 0)
  384. {
  385. u.negate();
  386. }
  387. else if(s == 0)
  388. {
  389. result = v;
  390. return;
  391. }
  392. if(v == 0)
  393. {
  394. result = u;
  395. return;
  396. }
  397. /* Let shift := lg K, where K is the greatest power of 2
  398. dividing both u and v. */
  399. unsigned us = eval_lsb(u);
  400. unsigned vs = boost::multiprecision::detail::find_lsb(v);
  401. shift = (std::min)(us, vs);
  402. eval_right_shift(u, us);
  403. if(vs)
  404. v >>= vs;
  405. do
  406. {
  407. /* Now u and v are both odd, so diff(u, v) is even.
  408. Let u = min(u, v), v = diff(u, v)/2. */
  409. if(u.size() <= 2)
  410. {
  411. if(u.size() == 1)
  412. v = integer_gcd_reduce(*u.limbs(), v);
  413. else
  414. {
  415. double_limb_type i;
  416. i = u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
  417. v = static_cast<limb_type>(integer_gcd_reduce(i, static_cast<double_limb_type>(v)));
  418. }
  419. break;
  420. }
  421. eval_subtract(u, v);
  422. us = eval_lsb(u);
  423. eval_right_shift(u, us);
  424. }
  425. while(true);
  426. result = v;
  427. eval_left_shift(result, shift);
  428. }
  429. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  430. inline typename enable_if_c<is_unsigned<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  431. eval_gcd(
  432. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  433. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  434. const Integer& v)
  435. {
  436. eval_gcd(result, a, static_cast<limb_type>(v));
  437. }
  438. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  439. inline typename enable_if_c<is_signed<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  440. eval_gcd(
  441. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  442. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  443. const Integer& v)
  444. {
  445. eval_gcd(result, a, static_cast<limb_type>(v < 0 ? -v : v));
  446. }
  447. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  448. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  449. eval_gcd(
  450. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  451. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  452. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b)
  453. {
  454. using default_ops::eval_lsb;
  455. using default_ops::eval_is_zero;
  456. using default_ops::eval_get_sign;
  457. if(a.size() == 1)
  458. {
  459. eval_gcd(result, b, *a.limbs());
  460. return;
  461. }
  462. if(b.size() == 1)
  463. {
  464. eval_gcd(result, a, *b.limbs());
  465. return;
  466. }
  467. int shift;
  468. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a), v(b);
  469. int s = eval_get_sign(u);
  470. /* GCD(0,x) := x */
  471. if(s < 0)
  472. {
  473. u.negate();
  474. }
  475. else if(s == 0)
  476. {
  477. result = v;
  478. return;
  479. }
  480. s = eval_get_sign(v);
  481. if(s < 0)
  482. {
  483. v.negate();
  484. }
  485. else if(s == 0)
  486. {
  487. result = u;
  488. return;
  489. }
  490. /* Let shift := lg K, where K is the greatest power of 2
  491. dividing both u and v. */
  492. unsigned us = eval_lsb(u);
  493. unsigned vs = eval_lsb(v);
  494. shift = (std::min)(us, vs);
  495. eval_right_shift(u, us);
  496. eval_right_shift(v, vs);
  497. do
  498. {
  499. /* Now u and v are both odd, so diff(u, v) is even.
  500. Let u = min(u, v), v = diff(u, v)/2. */
  501. s = u.compare(v);
  502. if(s > 0)
  503. u.swap(v);
  504. if(s == 0)
  505. break;
  506. if(v.size() <= 2)
  507. {
  508. if(v.size() == 1)
  509. u = integer_gcd_reduce(*v.limbs(), *u.limbs());
  510. else
  511. {
  512. double_limb_type i, j;
  513. i = v.limbs()[0] | (static_cast<double_limb_type>(v.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
  514. j = (u.size() == 1) ? *u.limbs() : u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
  515. u = integer_gcd_reduce(i, j);
  516. }
  517. break;
  518. }
  519. eval_subtract(v, u);
  520. vs = eval_lsb(v);
  521. eval_right_shift(v, vs);
  522. }
  523. while(true);
  524. result = u;
  525. eval_left_shift(result, shift);
  526. }
  527. //
  528. // Now again for trivial backends:
  529. //
  530. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  531. BOOST_MP_FORCEINLINE typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  532. 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) BOOST_NOEXCEPT
  533. {
  534. *result.limbs() = boost::integer::gcd(*a.limbs(), *b.limbs());
  535. }
  536. // This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version:
  537. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  538. BOOST_MP_FORCEINLINE typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (Checked1 == unchecked)>::type
  539. 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) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  540. {
  541. *result.limbs() = boost::integer::lcm(*a.limbs(), *b.limbs());
  542. result.normalize(); // result may overflow the specified number of bits
  543. }
  544. inline void conversion_overflow(const mpl::int_<checked>&)
  545. {
  546. BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type"));
  547. }
  548. inline void conversion_overflow(const mpl::int_<unchecked>&){}
  549. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  550. inline typename enable_if_c<
  551. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  552. && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  553. && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value
  554. >::type
  555. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
  556. {
  557. typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;
  558. if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
  559. {
  560. if(val.isneg())
  561. {
  562. check_is_negative(mpl::bool_<boost::is_signed<R>::value || (number_category<R>::value == number_kind_floating_point)>());
  563. if(static_cast<common_type>(*val.limbs()) > -static_cast<common_type>((std::numeric_limits<R>::min)()))
  564. conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  565. *result = (std::numeric_limits<R>::min)();
  566. }
  567. else
  568. {
  569. conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  570. *result = boost::is_signed<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());
  571. }
  572. }
  573. else
  574. {
  575. *result = static_cast<R>(*val.limbs());
  576. if(val.isneg())
  577. {
  578. check_is_negative(mpl::bool_<boost::is_signed<R>::value || (number_category<R>::value == number_kind_floating_point)>());
  579. *result = negate_integer(*result, mpl::bool_<is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point)>());
  580. }
  581. }
  582. }
  583. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  584. inline typename enable_if_c<
  585. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  586. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  587. && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value
  588. >::type
  589. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
  590. {
  591. typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;
  592. if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
  593. {
  594. conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  595. *result = boost::is_signed<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());
  596. }
  597. else
  598. *result = static_cast<R>(*val.limbs());
  599. }
  600. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  601. inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  602. eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  603. {
  604. using default_ops::eval_get_sign;
  605. if(eval_get_sign(a) == 0)
  606. {
  607. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  608. }
  609. if(a.sign())
  610. {
  611. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  612. }
  613. //
  614. // Find the index of the least significant bit within that limb:
  615. //
  616. return boost::multiprecision::detail::find_lsb(*a.limbs());
  617. }
  618. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  619. inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  620. eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  621. {
  622. //
  623. // Find the index of the least significant bit within that limb:
  624. //
  625. return boost::multiprecision::detail::find_msb(*a.limbs());
  626. }
  627. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  628. inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  629. eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  630. {
  631. using default_ops::eval_get_sign;
  632. if(eval_get_sign(a) == 0)
  633. {
  634. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  635. }
  636. if(a.sign())
  637. {
  638. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  639. }
  640. return eval_msb_imp(a);
  641. }
  642. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  643. inline std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
  644. {
  645. std::size_t result = 0;
  646. for(unsigned i = 0; i < val.size(); ++i)
  647. {
  648. boost::hash_combine(result, val.limbs()[i]);
  649. }
  650. boost::hash_combine(result, val.sign());
  651. return result;
  652. }
  653. #ifdef BOOST_MSVC
  654. #pragma warning(pop)
  655. #endif
  656. }}} // namespaces
  657. #endif