misc.hpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  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 https://www.boost.org/LICENSE_1_0.txt
  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/constexpr.hpp>
  11. #include <boost/multiprecision/detail/bitscan.hpp> // lsb etc
  12. #include <boost/integer/common_factor_rt.hpp> // gcd/lcm
  13. #include <boost/functional/hash_fwd.hpp>
  14. #ifdef BOOST_MSVC
  15. #pragma warning(push)
  16. #pragma warning(disable : 4702)
  17. #pragma warning(disable : 4127) // conditional expression is constant
  18. #pragma warning(disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
  19. #endif
  20. namespace boost { namespace multiprecision { namespace backends {
  21. template <class R, class CppInt>
  22. BOOST_MP_CXX14_CONSTEXPR void check_in_range(const CppInt& val, const mpl::int_<checked>&)
  23. {
  24. typedef typename boost::multiprecision::detail::canonical<R, CppInt>::type cast_type;
  25. if (val.sign())
  26. {
  27. if (boost::is_signed<R>::value == false)
  28. BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
  29. if (val.compare(static_cast<cast_type>((std::numeric_limits<R>::min)())) < 0)
  30. BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
  31. }
  32. else
  33. {
  34. if (val.compare(static_cast<cast_type>((std::numeric_limits<R>::max)())) > 0)
  35. BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
  36. }
  37. }
  38. template <class R, class CppInt>
  39. inline BOOST_MP_CXX14_CONSTEXPR void check_in_range(const CppInt& /*val*/, const mpl::int_<unchecked>&) BOOST_NOEXCEPT {}
  40. inline BOOST_MP_CXX14_CONSTEXPR void check_is_negative(const mpl::true_&) BOOST_NOEXCEPT {}
  41. inline void check_is_negative(const mpl::false_&)
  42. {
  43. BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
  44. }
  45. template <class Integer>
  46. inline BOOST_MP_CXX14_CONSTEXPR Integer negate_integer(Integer i, const mpl::true_&) BOOST_NOEXCEPT
  47. {
  48. return -i;
  49. }
  50. template <class Integer>
  51. inline BOOST_MP_CXX14_CONSTEXPR Integer negate_integer(Integer i, const mpl::false_&) BOOST_NOEXCEPT
  52. {
  53. return ~(i - 1);
  54. }
  55. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  56. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
  57. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend)
  58. {
  59. typedef mpl::int_<Checked1> checked_type;
  60. check_in_range<R>(backend, checked_type());
  61. if (std::numeric_limits<R>::digits < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
  62. {
  63. if ((backend.sign() && boost::is_signed<R>::value) && (1 + static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0]))
  64. {
  65. *result = (std::numeric_limits<R>::min)();
  66. return;
  67. }
  68. else if (boost::is_signed<R>::value && !backend.sign() && static_cast<boost::multiprecision::limb_type>((std::numeric_limits<R>::max)()) <= backend.limbs()[0])
  69. {
  70. *result = (std::numeric_limits<R>::max)();
  71. return;
  72. }
  73. else
  74. *result = static_cast<R>(backend.limbs()[0]);
  75. }
  76. else
  77. *result = static_cast<R>(backend.limbs()[0]);
  78. unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  79. unsigned i = 1;
  80. if (std::numeric_limits<R>::digits > cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)
  81. {
  82. while ((i < backend.size()) && (shift < static_cast<unsigned>(std::numeric_limits<R>::digits - cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits)))
  83. {
  84. *result += static_cast<R>(backend.limbs()[i]) << shift;
  85. shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  86. ++i;
  87. }
  88. //
  89. // We have one more limb to extract, but may not need all the bits, so treat this as a special case:
  90. //
  91. if (i < backend.size())
  92. {
  93. const limb_type mask = std::numeric_limits<R>::digits - shift == cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits ? ~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(mpl::bool_<boost::is_signed<R>::value>());
  124. *result = negate_integer(*result, mpl::bool_<boost::is_signed<R>::value>());
  125. }
  126. }
  127. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  128. inline BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR limb_type integer_gcd_reduce(limb_type u, limb_type v)
  334. {
  335. do
  336. {
  337. if (u > v)
  338. std_constexpr::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 BOOST_MP_CXX14_CONSTEXPR double_limb_type integer_gcd_reduce(double_limb_type u, double_limb_type v)
  347. {
  348. do
  349. {
  350. if (u > v)
  351. std_constexpr::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 BOOST_MP_CXX14_CONSTEXPR 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_get_sign;
  377. using default_ops::eval_is_zero;
  378. using default_ops::eval_lsb;
  379. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a);
  380. int s = eval_get_sign(u);
  381. /* GCD(0,x) := x */
  382. if (s < 0)
  383. {
  384. u.negate();
  385. }
  386. else if (s == 0)
  387. {
  388. result = v;
  389. return;
  390. }
  391. if (v == 0)
  392. {
  393. result = u;
  394. return;
  395. }
  396. /* Let shift := lg K, where K is the greatest power of 2
  397. dividing both u and v. */
  398. unsigned us = eval_lsb(u);
  399. unsigned vs = boost::multiprecision::detail::find_lsb(v);
  400. int shift = (std::min)(us, vs);
  401. eval_right_shift(u, us);
  402. if (vs)
  403. v >>= vs;
  404. do
  405. {
  406. /* Now u and v are both odd, so diff(u, v) is even.
  407. Let u = min(u, v), v = diff(u, v)/2. */
  408. if (u.size() <= 2)
  409. {
  410. if (u.size() == 1)
  411. v = integer_gcd_reduce(*u.limbs(), v);
  412. else
  413. {
  414. double_limb_type i = u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
  415. v = static_cast<limb_type>(integer_gcd_reduce(i, static_cast<double_limb_type>(v)));
  416. }
  417. break;
  418. }
  419. eval_subtract(u, v);
  420. us = eval_lsb(u);
  421. eval_right_shift(u, us);
  422. } while (true);
  423. result = v;
  424. eval_left_shift(result, shift);
  425. }
  426. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  427. inline BOOST_MP_CXX14_CONSTEXPR 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
  428. eval_gcd(
  429. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  430. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  431. const Integer& v)
  432. {
  433. eval_gcd(result, a, static_cast<limb_type>(v));
  434. }
  435. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
  436. inline BOOST_MP_CXX14_CONSTEXPR 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
  437. eval_gcd(
  438. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  439. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  440. const Integer& v)
  441. {
  442. eval_gcd(result, a, static_cast<limb_type>(v < 0 ? -v : v));
  443. }
  444. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  445. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  446. eval_gcd(
  447. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  448. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  449. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b)
  450. {
  451. using default_ops::eval_get_sign;
  452. using default_ops::eval_is_zero;
  453. using default_ops::eval_lsb;
  454. if (a.size() == 1)
  455. {
  456. eval_gcd(result, b, *a.limbs());
  457. return;
  458. }
  459. if (b.size() == 1)
  460. {
  461. eval_gcd(result, a, *b.limbs());
  462. return;
  463. }
  464. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a), v(b);
  465. int s = eval_get_sign(u);
  466. /* GCD(0,x) := x */
  467. if (s < 0)
  468. {
  469. u.negate();
  470. }
  471. else if (s == 0)
  472. {
  473. result = v;
  474. return;
  475. }
  476. s = eval_get_sign(v);
  477. if (s < 0)
  478. {
  479. v.negate();
  480. }
  481. else if (s == 0)
  482. {
  483. result = u;
  484. return;
  485. }
  486. /* Let shift := lg K, where K is the greatest power of 2
  487. dividing both u and v. */
  488. unsigned us = eval_lsb(u);
  489. unsigned vs = eval_lsb(v);
  490. int shift = (std::min)(us, vs);
  491. eval_right_shift(u, us);
  492. eval_right_shift(v, vs);
  493. do
  494. {
  495. /* Now u and v are both odd, so diff(u, v) is even.
  496. Let u = min(u, v), v = diff(u, v)/2. */
  497. s = u.compare(v);
  498. if (s > 0)
  499. u.swap(v);
  500. if (s == 0)
  501. break;
  502. if (v.size() <= 2)
  503. {
  504. if (v.size() == 1)
  505. u = integer_gcd_reduce(*v.limbs(), *u.limbs());
  506. else
  507. {
  508. double_limb_type i = v.limbs()[0] | (static_cast<double_limb_type>(v.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
  509. double_limb_type j = (u.size() == 1) ? *u.limbs() : u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
  510. u = integer_gcd_reduce(i, j);
  511. }
  512. break;
  513. }
  514. eval_subtract(v, u);
  515. vs = eval_lsb(v);
  516. eval_right_shift(v, vs);
  517. } while (true);
  518. result = u;
  519. eval_left_shift(result, shift);
  520. }
  521. //
  522. // Now again for trivial backends:
  523. //
  524. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  525. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  526. 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
  527. {
  528. *result.limbs() = boost::integer::gcd(*a.limbs(), *b.limbs());
  529. }
  530. // This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version:
  531. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  532. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (Checked1 == unchecked)>::type
  533. 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))
  534. {
  535. *result.limbs() = boost::integer::lcm(*a.limbs(), *b.limbs());
  536. result.normalize(); // result may overflow the specified number of bits
  537. }
  538. inline void conversion_overflow(const mpl::int_<checked>&)
  539. {
  540. BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type"));
  541. }
  542. inline BOOST_MP_CXX14_CONSTEXPR void conversion_overflow(const mpl::int_<unchecked>&) {}
  543. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  544. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  545. 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 && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value>::type
  546. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
  547. {
  548. typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;
  549. if (std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
  550. {
  551. if (val.isneg())
  552. {
  553. check_is_negative(mpl::bool_ < boost::is_signed<R>::value || (number_category<R>::value == number_kind_floating_point) > ());
  554. if (static_cast<common_type>(*val.limbs()) > -static_cast<common_type>((std::numeric_limits<R>::min)()))
  555. conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  556. *result = (std::numeric_limits<R>::min)();
  557. }
  558. else
  559. {
  560. conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  561. *result = boost::is_signed<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());
  562. }
  563. }
  564. else
  565. {
  566. *result = static_cast<R>(*val.limbs());
  567. if (val.isneg())
  568. {
  569. check_is_negative(mpl::bool_ < boost::is_signed<R>::value || (number_category<R>::value == number_kind_floating_point) > ());
  570. *result = negate_integer(*result, mpl::bool_ < is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point) > ());
  571. }
  572. }
  573. }
  574. template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  575. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  576. 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 && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value>::type
  577. eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
  578. {
  579. typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;
  580. if (std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
  581. {
  582. conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  583. *result = boost::is_signed<R>::value ? (std::numeric_limits<R>::max)() : static_cast<R>(*val.limbs());
  584. }
  585. else
  586. *result = static_cast<R>(*val.limbs());
  587. }
  588. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  589. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  590. eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  591. {
  592. using default_ops::eval_get_sign;
  593. if (eval_get_sign(a) == 0)
  594. {
  595. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  596. }
  597. if (a.sign())
  598. {
  599. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  600. }
  601. //
  602. // Find the index of the least significant bit within that limb:
  603. //
  604. return boost::multiprecision::detail::find_lsb(*a.limbs());
  605. }
  606. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  607. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  608. eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  609. {
  610. //
  611. // Find the index of the least significant bit within that limb:
  612. //
  613. return boost::multiprecision::detail::find_msb(*a.limbs());
  614. }
  615. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  616. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
  617. eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
  618. {
  619. using default_ops::eval_get_sign;
  620. if (eval_get_sign(a) == 0)
  621. {
  622. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  623. }
  624. if (a.sign())
  625. {
  626. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  627. }
  628. return eval_msb_imp(a);
  629. }
  630. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  631. inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
  632. {
  633. std::size_t result = 0;
  634. for (unsigned i = 0; i < val.size(); ++i)
  635. {
  636. boost::hash_combine(result, val.limbs()[i]);
  637. }
  638. boost::hash_combine(result, val.sign());
  639. return result;
  640. }
  641. #ifdef BOOST_MSVC
  642. #pragma warning(pop)
  643. #endif
  644. }}} // namespace boost::multiprecision::backends
  645. #endif