misc.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  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. #ifdef BOOST_MSVC
  12. #pragma warning(push)
  13. #pragma warning(disable:4702)
  14. #endif
  15. namespace boost{ namespace multiprecision{ namespace backends{
  16. template <class R, class CppInt>
  17. void check_in_range(const CppInt& val, const mpl::int_<checked>&)
  18. {
  19. typedef typename boost::multiprecision::detail::canonical<R, CppInt>::type cast_type;
  20. if(val.sign())
  21. {
  22. if(val.compare(static_cast<cast_type>((std::numeric_limits<R>::min)())) < 0)
  23. BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
  24. }
  25. else
  26. {
  27. if(val.compare(static_cast<cast_type>((std::numeric_limits<R>::max)())) > 0)
  28. BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
  29. }
  30. }
  31. template <class R, class CppInt>
  32. inline void check_in_range(const CppInt& /*val*/, const mpl::int_<unchecked>&) BOOST_NOEXCEPT {}
  33. inline void check_is_negative(const mpl::true_&) BOOST_NOEXCEPT {}
  34. inline void check_is_negative(const mpl::false_&)
  35. {
  36. BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
  37. }
  38. template <class Integer>
  39. inline Integer negate_integer(Integer i, const mpl::true_&) BOOST_NOEXCEPT
  40. {
  41. return -i;
  42. }
  43. template <class Integer>
  44. inline Integer negate_integer(Integer i, const mpl::false_&) BOOST_NOEXCEPT
  45. {
  46. return ~(i-1);
  47. }
  48. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  49. inline typename enable_if_c<is_integral<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
  50. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  51. {
  52. typedef mpl::int_<Checked1> checked_type;
  53. check_in_range<R>(backend, checked_type());
  54. *result = static_cast<R>(backend.limbs()[0]);
  55. unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  56. for(unsigned i = 1; (i < backend.size()) && (shift < static_cast<unsigned>(std::numeric_limits<R>::digits)); ++i)
  57. {
  58. *result += static_cast<R>(backend.limbs()[i]) << shift;
  59. shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  60. }
  61. if(backend.sign())
  62. {
  63. check_is_negative(boost::is_signed<R>());
  64. *result = negate_integer(*result, boost::is_signed<R>());
  65. }
  66. }
  67. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  68. 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
  69. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) BOOST_NOEXCEPT_IF(is_arithmetic<R>::value)
  70. {
  71. typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p = backend.limbs();
  72. unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  73. *result = static_cast<R>(*p);
  74. for(unsigned i = 1; i < backend.size(); ++i)
  75. {
  76. *result += static_cast<R>(std::ldexp(static_cast<long double>(p[i]), shift));
  77. shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  78. }
  79. if(backend.sign())
  80. *result = -*result;
  81. }
  82. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  83. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
  84. eval_is_zero(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
  85. {
  86. return (val.size() == 1) && (val.limbs()[0] == 0);
  87. }
  88. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  89. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, int>::type
  90. eval_get_sign(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
  91. {
  92. return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1;
  93. }
  94. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  95. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  96. eval_abs(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  97. {
  98. result = val;
  99. result.sign(false);
  100. }
  101. //
  102. // Get the location of the least-significant-bit:
  103. //
  104. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  105. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  106. eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  107. {
  108. using default_ops::eval_get_sign;
  109. if(eval_get_sign(a) == 0)
  110. {
  111. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  112. }
  113. if(a.sign())
  114. {
  115. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  116. }
  117. //
  118. // Find the index of the least significant limb that is non-zero:
  119. //
  120. unsigned index = 0;
  121. while(!a.limbs()[index] && (index < a.size()))
  122. ++index;
  123. //
  124. // Find the index of the least significant bit within that limb:
  125. //
  126. unsigned result = boost::multiprecision::detail::find_lsb(a.limbs()[index]);
  127. return result + index * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  128. }
  129. //
  130. // Get the location of the most-significant-bit:
  131. //
  132. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  133. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  134. eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  135. {
  136. using default_ops::eval_get_sign;
  137. if(eval_get_sign(a) == 0)
  138. {
  139. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  140. }
  141. if(a.sign())
  142. {
  143. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  144. }
  145. //
  146. // Find the index of the most significant bit that is non-zero:
  147. //
  148. return (a.size() - 1) * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]);
  149. }
  150. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  151. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
  152. eval_bit_test(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT
  153. {
  154. unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  155. unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  156. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  157. if(offset >= val.size())
  158. return false;
  159. return val.limbs()[offset] & mask ? true : false;
  160. }
  161. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  162. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  163. eval_bit_set(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index)
  164. {
  165. unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  166. unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  167. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  168. if(offset >= val.size())
  169. {
  170. unsigned os = val.size();
  171. val.resize(offset + 1, offset + 1);
  172. if(offset >= val.size())
  173. return; // fixed precision overflow
  174. for(unsigned i = os; i <= offset; ++i)
  175. val.limbs()[i] = 0;
  176. }
  177. val.limbs()[offset] |= mask;
  178. }
  179. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  180. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  181. eval_bit_unset(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT
  182. {
  183. unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  184. unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  185. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  186. if(offset >= val.size())
  187. return;
  188. val.limbs()[offset] &= ~mask;
  189. val.normalize();
  190. }
  191. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  192. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  193. eval_bit_flip(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index)
  194. {
  195. unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  196. unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  197. limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
  198. if(offset >= val.size())
  199. {
  200. unsigned os = val.size();
  201. val.resize(offset + 1, offset + 1);
  202. if(offset >= val.size())
  203. return; // fixed precision overflow
  204. for(unsigned i = os; i <= offset; ++i)
  205. val.limbs()[i] = 0;
  206. }
  207. val.limbs()[offset] ^= mask;
  208. val.normalize();
  209. }
  210. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  211. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  212. eval_qr(
  213. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
  214. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& y,
  215. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
  216. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  217. {
  218. divide_unsigned_helper(&q, x, y, r);
  219. q.sign(x.sign() != y.sign());
  220. r.sign(x.sign());
  221. }
  222. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  223. inline typename enable_if_c<is_unsigned<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
  224. eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
  225. {
  226. if((sizeof(Integer) <= sizeof(limb_type)) || (val <= (std::numeric_limits<limb_type>::max)()))
  227. {
  228. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> d;
  229. divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>*>(0), x, static_cast<limb_type>(val), d);
  230. return d.limbs()[0];
  231. }
  232. else
  233. {
  234. return default_ops::eval_integer_modulus(x, val);
  235. }
  236. }
  237. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  238. 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
  239. eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
  240. {
  241. BOOST_MP_USING_ABS
  242. typedef typename make_unsigned<Integer>::type unsigned_type;
  243. return eval_integer_modulus(x, static_cast<unsigned_type>(abs(val)));
  244. }
  245. inline limb_type integer_gcd_reduce(limb_type u, limb_type v)
  246. {
  247. do
  248. {
  249. if(u > v)
  250. std::swap(u, v);
  251. if(u == v)
  252. break;
  253. v -= u;
  254. v >>= boost::multiprecision::detail::find_lsb(v);
  255. } while(true);
  256. return u;
  257. }
  258. inline double_limb_type integer_gcd_reduce(double_limb_type u, double_limb_type v)
  259. {
  260. do
  261. {
  262. if(u > v)
  263. std::swap(u, v);
  264. if(u == v)
  265. break;
  266. if(v <= ~static_cast<limb_type>(0))
  267. {
  268. u = integer_gcd_reduce(static_cast<limb_type>(v), static_cast<limb_type>(u));
  269. break;
  270. }
  271. v -= u;
  272. while((static_cast<unsigned>(v) & 1u) == 0)
  273. v >>= 1;
  274. } while(true);
  275. return u;
  276. }
  277. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  278. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  279. eval_gcd(
  280. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  281. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  282. limb_type v)
  283. {
  284. using default_ops::eval_lsb;
  285. using default_ops::eval_is_zero;
  286. using default_ops::eval_get_sign;
  287. int shift;
  288. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a);
  289. int s = eval_get_sign(u);
  290. /* GCD(0,x) := x */
  291. if(s < 0)
  292. {
  293. u.negate();
  294. }
  295. else if(s == 0)
  296. {
  297. result = v;
  298. return;
  299. }
  300. if(v == 0)
  301. {
  302. result = u;
  303. return;
  304. }
  305. /* Let shift := lg K, where K is the greatest power of 2
  306. dividing both u and v. */
  307. unsigned us = eval_lsb(u);
  308. unsigned vs = boost::multiprecision::detail::find_lsb(v);
  309. shift = (std::min)(us, vs);
  310. eval_right_shift(u, us);
  311. if(vs)
  312. v >>= vs;
  313. do
  314. {
  315. /* Now u and v are both odd, so diff(u, v) is even.
  316. Let u = min(u, v), v = diff(u, v)/2. */
  317. if(u.size() <= 2)
  318. {
  319. if(u.size() == 1)
  320. v = integer_gcd_reduce(*u.limbs(), v);
  321. else
  322. {
  323. double_limb_type i;
  324. i = u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
  325. v = static_cast<limb_type>(integer_gcd_reduce(i, static_cast<double_limb_type>(v)));
  326. }
  327. break;
  328. }
  329. eval_subtract(u, v);
  330. us = eval_lsb(u);
  331. eval_right_shift(u, us);
  332. }
  333. while(true);
  334. result = v;
  335. eval_left_shift(result, shift);
  336. }
  337. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  338. 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
  339. eval_gcd(
  340. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  341. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  342. const Integer& v)
  343. {
  344. eval_gcd(result, a, static_cast<limb_type>(v));
  345. }
  346. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  347. 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
  348. eval_gcd(
  349. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  350. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  351. const Integer& v)
  352. {
  353. eval_gcd(result, a, static_cast<limb_type>(v < 0 ? -v : v));
  354. }
  355. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  356. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  357. eval_gcd(
  358. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  359. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  360. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b)
  361. {
  362. using default_ops::eval_lsb;
  363. using default_ops::eval_is_zero;
  364. using default_ops::eval_get_sign;
  365. if(a.size() == 1)
  366. {
  367. eval_gcd(result, b, *a.limbs());
  368. return;
  369. }
  370. if(b.size() == 1)
  371. {
  372. eval_gcd(result, a, *b.limbs());
  373. return;
  374. }
  375. int shift;
  376. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a), v(b);
  377. int s = eval_get_sign(u);
  378. /* GCD(0,x) := x */
  379. if(s < 0)
  380. {
  381. u.negate();
  382. }
  383. else if(s == 0)
  384. {
  385. result = v;
  386. return;
  387. }
  388. s = eval_get_sign(v);
  389. if(s < 0)
  390. {
  391. v.negate();
  392. }
  393. else if(s == 0)
  394. {
  395. result = u;
  396. return;
  397. }
  398. /* Let shift := lg K, where K is the greatest power of 2
  399. dividing both u and v. */
  400. unsigned us = eval_lsb(u);
  401. unsigned vs = eval_lsb(v);
  402. shift = (std::min)(us, vs);
  403. eval_right_shift(u, us);
  404. eval_right_shift(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. s = u.compare(v);
  410. if(s > 0)
  411. u.swap(v);
  412. if(s == 0)
  413. break;
  414. if(v.size() <= 2)
  415. {
  416. if(v.size() == 1)
  417. u = integer_gcd_reduce(*v.limbs(), *u.limbs());
  418. else
  419. {
  420. double_limb_type i, j;
  421. i = v.limbs()[0] | (static_cast<double_limb_type>(v.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
  422. j = (u.size() == 1) ? *u.limbs() : u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
  423. u = integer_gcd_reduce(i, j);
  424. }
  425. break;
  426. }
  427. eval_subtract(v, u);
  428. vs = eval_lsb(v);
  429. eval_right_shift(v, vs);
  430. }
  431. while(true);
  432. result = u;
  433. eval_left_shift(result, shift);
  434. }
  435. //
  436. // Now again for trivial backends:
  437. //
  438. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  439. BOOST_MP_FORCEINLINE typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  440. 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
  441. {
  442. *result.limbs() = boost::math::gcd(*a.limbs(), *b.limbs());
  443. }
  444. // This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version:
  445. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  446. BOOST_MP_FORCEINLINE typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (Checked1 == unchecked)>::type
  447. 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_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  448. {
  449. *result.limbs() = boost::math::lcm(*a.limbs(), *b.limbs());
  450. result.normalize(); // result may overflow the specified number of bits
  451. }
  452. inline void conversion_overflow(const mpl::int_<checked>&)
  453. {
  454. BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type"));
  455. }
  456. inline void conversion_overflow(const mpl::int_<unchecked>&){}
  457. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  458. inline typename enable_if_c<
  459. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  460. && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  461. >::type
  462. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
  463. {
  464. typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;
  465. if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
  466. {
  467. conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  468. *result = (std::numeric_limits<R>::max)();
  469. }
  470. else
  471. *result = static_cast<R>(*val.limbs());
  472. if(val.isneg())
  473. {
  474. check_is_negative(mpl::bool_<boost::is_signed<R>::value || boost::is_floating_point<R>::value>());
  475. *result = negate_integer(*result, mpl::bool_<boost::is_signed<R>::value || boost::is_floating_point<R>::value>());
  476. }
  477. }
  478. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  479. inline typename enable_if_c<
  480. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  481. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  482. >::type
  483. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
  484. {
  485. typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;
  486. if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
  487. {
  488. conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  489. *result = (std::numeric_limits<R>::max)();
  490. }
  491. else
  492. *result = static_cast<R>(*val.limbs());
  493. }
  494. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  495. inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  496. eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  497. {
  498. using default_ops::eval_get_sign;
  499. if(eval_get_sign(a) == 0)
  500. {
  501. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  502. }
  503. if(a.sign())
  504. {
  505. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  506. }
  507. //
  508. // Find the index of the least significant bit within that limb:
  509. //
  510. return boost::multiprecision::detail::find_lsb(*a.limbs());
  511. }
  512. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  513. inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  514. eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  515. {
  516. using default_ops::eval_get_sign;
  517. if(eval_get_sign(a) == 0)
  518. {
  519. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  520. }
  521. if(a.sign())
  522. {
  523. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  524. }
  525. //
  526. // Find the index of the least significant bit within that limb:
  527. //
  528. return boost::multiprecision::detail::find_msb(*a.limbs());
  529. }
  530. #ifdef BOOST_MSVC
  531. #pragma warning(pop)
  532. #endif
  533. }}} // namespaces
  534. #endif