bitwise.hpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  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_BIT_HPP
  9. #define BOOST_MP_CPP_INT_BIT_HPP
  10. #ifdef _MSC_VER
  11. #pragma warning(push)
  12. #pragma warning(disable : 4319)
  13. #endif
  14. namespace boost { namespace multiprecision { namespace backends {
  15. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  16. BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
  17. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  18. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const std::integral_constant<int, checked>&)
  19. {
  20. if (result.sign() || o.sign())
  21. BOOST_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior."));
  22. }
  23. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  24. BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
  25. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&,
  26. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&, const std::integral_constant<int, unchecked>&) {}
  27. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  28. BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
  29. const cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result, const std::integral_constant<int, checked>&)
  30. {
  31. if (result.sign())
  32. BOOST_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior."));
  33. }
  34. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  35. BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
  36. const cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>&, const std::integral_constant<int, checked>&) {}
  37. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  38. BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
  39. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&, const std::integral_constant<int, unchecked>&) {}
  40. template <class CppInt1, class CppInt2, class Op>
  41. BOOST_MP_CXX14_CONSTEXPR void bitwise_op(
  42. CppInt1& result,
  43. const CppInt2& o,
  44. Op op, const std::integral_constant<bool, true>&) noexcept((is_non_throwing_cpp_int<CppInt1>::value))
  45. {
  46. //
  47. // There are 4 cases:
  48. // * Both positive.
  49. // * result negative, o positive.
  50. // * o negative, result positive.
  51. // * Both negative.
  52. //
  53. // When one arg is negative we convert to 2's complement form "on the fly",
  54. // and then convert back to signed-magnitude form at the end.
  55. //
  56. // Note however, that if the type is checked, then bitwise ops on negative values
  57. // are not permitted and an exception will result.
  58. //
  59. is_valid_bitwise_op(result, o, typename CppInt1::checked_type());
  60. //
  61. // First figure out how big the result needs to be and set up some data:
  62. //
  63. unsigned rs = result.size();
  64. unsigned os = o.size();
  65. unsigned m(0), x(0);
  66. minmax(rs, os, m, x);
  67. result.resize(x, x);
  68. typename CppInt1::limb_pointer pr = result.limbs();
  69. typename CppInt2::const_limb_pointer po = o.limbs();
  70. for (unsigned i = rs; i < x; ++i)
  71. pr[i] = 0;
  72. limb_type next_limb = 0;
  73. if (!result.sign())
  74. {
  75. if (!o.sign())
  76. {
  77. for (unsigned i = 0; i < os; ++i)
  78. pr[i] = op(pr[i], po[i]);
  79. for (unsigned i = os; i < x; ++i)
  80. pr[i] = op(pr[i], limb_type(0));
  81. }
  82. else
  83. {
  84. // "o" is negative:
  85. double_limb_type carry = 1;
  86. for (unsigned i = 0; i < os; ++i)
  87. {
  88. carry += static_cast<double_limb_type>(~po[i]);
  89. pr[i] = op(pr[i], static_cast<limb_type>(carry));
  90. carry >>= CppInt1::limb_bits;
  91. }
  92. for (unsigned i = os; i < x; ++i)
  93. {
  94. carry += static_cast<double_limb_type>(~limb_type(0));
  95. pr[i] = op(pr[i], static_cast<limb_type>(carry));
  96. carry >>= CppInt1::limb_bits;
  97. }
  98. // Set the overflow into the "extra" limb:
  99. carry += static_cast<double_limb_type>(~limb_type(0));
  100. next_limb = op(limb_type(0), static_cast<limb_type>(carry));
  101. }
  102. }
  103. else
  104. {
  105. if (!o.sign())
  106. {
  107. // "result" is negative:
  108. double_limb_type carry = 1;
  109. for (unsigned i = 0; i < os; ++i)
  110. {
  111. carry += static_cast<double_limb_type>(~pr[i]);
  112. pr[i] = op(static_cast<limb_type>(carry), po[i]);
  113. carry >>= CppInt1::limb_bits;
  114. }
  115. for (unsigned i = os; i < x; ++i)
  116. {
  117. carry += static_cast<double_limb_type>(~pr[i]);
  118. pr[i] = op(static_cast<limb_type>(carry), limb_type(0));
  119. carry >>= CppInt1::limb_bits;
  120. }
  121. // Set the overflow into the "extra" limb:
  122. carry += static_cast<double_limb_type>(~limb_type(0));
  123. next_limb = op(static_cast<limb_type>(carry), limb_type(0));
  124. }
  125. else
  126. {
  127. // both are negative:
  128. double_limb_type r_carry = 1;
  129. double_limb_type o_carry = 1;
  130. for (unsigned i = 0; i < os; ++i)
  131. {
  132. r_carry += static_cast<double_limb_type>(~pr[i]);
  133. o_carry += static_cast<double_limb_type>(~po[i]);
  134. pr[i] = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry));
  135. r_carry >>= CppInt1::limb_bits;
  136. o_carry >>= CppInt1::limb_bits;
  137. }
  138. for (unsigned i = os; i < x; ++i)
  139. {
  140. r_carry += static_cast<double_limb_type>(~pr[i]);
  141. o_carry += static_cast<double_limb_type>(~limb_type(0));
  142. pr[i] = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry));
  143. r_carry >>= CppInt1::limb_bits;
  144. o_carry >>= CppInt1::limb_bits;
  145. }
  146. // Set the overflow into the "extra" limb:
  147. r_carry += static_cast<double_limb_type>(~limb_type(0));
  148. o_carry += static_cast<double_limb_type>(~limb_type(0));
  149. next_limb = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry));
  150. }
  151. }
  152. //
  153. // See if the result is negative or not:
  154. //
  155. if (static_cast<signed_limb_type>(next_limb) < 0)
  156. {
  157. double_limb_type carry = 1;
  158. for (unsigned i = 0; i < x; ++i)
  159. {
  160. carry += static_cast<double_limb_type>(~pr[i]);
  161. pr[i] = static_cast<limb_type>(carry);
  162. carry >>= CppInt1::limb_bits;
  163. }
  164. if (carry)
  165. {
  166. result.resize(x + 1, x);
  167. if (result.size() > x)
  168. result.limbs()[x] = static_cast<limb_type>(carry);
  169. }
  170. result.sign(true);
  171. }
  172. else
  173. result.sign(false);
  174. result.normalize();
  175. }
  176. template <class CppInt1, class CppInt2, class Op>
  177. BOOST_MP_CXX14_CONSTEXPR void bitwise_op(
  178. CppInt1& result,
  179. const CppInt2& o,
  180. Op op, const std::integral_constant<bool, false>&) noexcept((is_non_throwing_cpp_int<CppInt1>::value))
  181. {
  182. //
  183. // Both arguments are unsigned types, very simple case handled as a special case.
  184. //
  185. // First figure out how big the result needs to be and set up some data:
  186. //
  187. unsigned rs = result.size();
  188. unsigned os = o.size();
  189. unsigned m(0), x(0);
  190. minmax(rs, os, m, x);
  191. result.resize(x, x);
  192. typename CppInt1::limb_pointer pr = result.limbs();
  193. typename CppInt2::const_limb_pointer po = o.limbs();
  194. for (unsigned i = rs; i < x; ++i)
  195. pr[i] = 0;
  196. for (unsigned i = 0; i < os; ++i)
  197. pr[i] = op(pr[i], po[i]);
  198. for (unsigned i = os; i < x; ++i)
  199. pr[i] = op(pr[i], limb_type(0));
  200. result.normalize();
  201. }
  202. struct bit_and
  203. {
  204. BOOST_MP_CXX14_CONSTEXPR limb_type operator()(limb_type a, limb_type b) const noexcept { return a & b; }
  205. };
  206. struct bit_or
  207. {
  208. BOOST_MP_CXX14_CONSTEXPR limb_type operator()(limb_type a, limb_type b) const noexcept { return a | b; }
  209. };
  210. struct bit_xor
  211. {
  212. BOOST_MP_CXX14_CONSTEXPR limb_type operator()(limb_type a, limb_type b) const noexcept { return a ^ b; }
  213. };
  214. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  215. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
  216. eval_bitwise_and(
  217. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  218. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  219. {
  220. bitwise_op(result, o, bit_and(),
  221. std::integral_constant<bool, std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed > ());
  222. }
  223. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  224. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
  225. eval_bitwise_or(
  226. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  227. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  228. {
  229. bitwise_op(result, o, bit_or(),
  230. std::integral_constant<bool, std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed > ());
  231. }
  232. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  233. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
  234. eval_bitwise_xor(
  235. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  236. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  237. {
  238. bitwise_op(result, o, bit_xor(),
  239. std::integral_constant<bool, std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed > ());
  240. }
  241. //
  242. // Again for operands which are single limbs:
  243. //
  244. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  245. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
  246. eval_bitwise_and(
  247. cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
  248. limb_type l) noexcept
  249. {
  250. result.limbs()[0] &= l;
  251. result.resize(1, 1);
  252. }
  253. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  254. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
  255. eval_bitwise_or(
  256. cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
  257. limb_type l) noexcept
  258. {
  259. result.limbs()[0] |= l;
  260. }
  261. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  262. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
  263. eval_bitwise_xor(
  264. cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
  265. limb_type l) noexcept
  266. {
  267. result.limbs()[0] ^= l;
  268. }
  269. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  270. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
  271. eval_complement(
  272. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  273. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  274. {
  275. static_assert(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
  276. // Increment and negate:
  277. result = o;
  278. eval_increment(result);
  279. result.negate();
  280. }
  281. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  282. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  283. eval_complement(
  284. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  285. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  286. {
  287. unsigned os = o.size();
  288. result.resize(UINT_MAX, os);
  289. for (unsigned i = 0; i < os; ++i)
  290. result.limbs()[i] = ~o.limbs()[i];
  291. for (unsigned i = os; i < result.size(); ++i)
  292. result.limbs()[i] = ~static_cast<limb_type>(0);
  293. result.normalize();
  294. }
  295. template <class Int>
  296. inline void left_shift_byte(Int& result, double_limb_type s)
  297. {
  298. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  299. limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
  300. unsigned ors = result.size();
  301. if ((ors == 1) && (!*result.limbs()))
  302. return; // shifting zero yields zero.
  303. unsigned rs = ors;
  304. if (shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
  305. ++rs; // Most significant limb will overflow when shifted
  306. rs += offset;
  307. result.resize(rs, rs);
  308. rs = result.size();
  309. typename Int::limb_pointer pr = result.limbs();
  310. if (rs != ors)
  311. pr[rs - 1] = 0u;
  312. std::size_t bytes = static_cast<std::size_t>(s / CHAR_BIT);
  313. std::size_t len = (std::min)(ors * sizeof(limb_type), rs * sizeof(limb_type) - bytes);
  314. if (bytes >= rs * sizeof(limb_type))
  315. result = static_cast<limb_type>(0u);
  316. else
  317. {
  318. unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
  319. std::memmove(pc + bytes, pc, len);
  320. std::memset(pc, 0, bytes);
  321. }
  322. }
  323. template <class Int>
  324. inline BOOST_MP_CXX14_CONSTEXPR void left_shift_limb(Int& result, double_limb_type s)
  325. {
  326. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  327. limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
  328. unsigned ors = result.size();
  329. if ((ors == 1) && (!*result.limbs()))
  330. return; // shifting zero yields zero.
  331. unsigned rs = ors;
  332. if (shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
  333. ++rs; // Most significant limb will overflow when shifted
  334. rs += offset;
  335. result.resize(rs, rs);
  336. typename Int::limb_pointer pr = result.limbs();
  337. if (offset > rs)
  338. {
  339. // The result is shifted past the end of the result:
  340. result = static_cast<limb_type>(0);
  341. return;
  342. }
  343. unsigned i = rs - result.size();
  344. for (; i < ors; ++i)
  345. pr[rs - 1 - i] = pr[ors - 1 - i];
  346. for (; i < rs; ++i)
  347. pr[rs - 1 - i] = 0;
  348. }
  349. template <class Int>
  350. inline BOOST_MP_CXX14_CONSTEXPR void left_shift_generic(Int& result, double_limb_type s)
  351. {
  352. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  353. limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
  354. unsigned ors = result.size();
  355. if ((ors == 1) && (!*result.limbs()))
  356. return; // shifting zero yields zero.
  357. unsigned rs = ors;
  358. if (shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
  359. ++rs; // Most significant limb will overflow when shifted
  360. rs += offset;
  361. result.resize(rs, rs);
  362. bool truncated = result.size() != rs;
  363. typename Int::limb_pointer pr = result.limbs();
  364. if (offset > rs)
  365. {
  366. // The result is shifted past the end of the result:
  367. result = static_cast<limb_type>(0);
  368. return;
  369. }
  370. unsigned i = rs - result.size();
  371. // This code only works when shift is non-zero, otherwise we invoke undefined behaviour!
  372. BOOST_ASSERT(shift);
  373. if (!truncated)
  374. {
  375. if (rs > ors + offset)
  376. {
  377. pr[rs - 1 - i] = pr[ors - 1 - i] >> (Int::limb_bits - shift);
  378. --rs;
  379. }
  380. else
  381. {
  382. pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
  383. if (ors > 1)
  384. pr[rs - 1 - i] |= pr[ors - 2 - i] >> (Int::limb_bits - shift);
  385. ++i;
  386. }
  387. }
  388. for (; rs - i >= 2 + offset; ++i)
  389. {
  390. pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift;
  391. pr[rs - 1 - i] |= pr[rs - 2 - i - offset] >> (Int::limb_bits - shift);
  392. }
  393. if (rs - i >= 1 + offset)
  394. {
  395. pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift;
  396. ++i;
  397. }
  398. for (; i < rs; ++i)
  399. pr[rs - 1 - i] = 0;
  400. }
  401. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  402. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  403. eval_left_shift(
  404. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  405. double_limb_type s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  406. {
  407. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  408. if (!s)
  409. return;
  410. #if BOOST_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
  411. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
  412. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  413. if ((s & limb_shift_mask) == 0)
  414. {
  415. left_shift_limb(result, s);
  416. }
  417. #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
  418. else if ((s & byte_shift_mask) == 0)
  419. #else
  420. else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
  421. #endif
  422. {
  423. left_shift_byte(result, s);
  424. }
  425. #elif BOOST_ENDIAN_LITTLE_BYTE
  426. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  427. #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
  428. if ((s & byte_shift_mask) == 0)
  429. #else
  430. constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
  431. if (BOOST_MP_IS_CONST_EVALUATED(s) && ((s & limb_shift_mask) == 0))
  432. left_shift_limb(result, s);
  433. else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
  434. #endif
  435. {
  436. left_shift_byte(result, s);
  437. }
  438. #else
  439. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
  440. if ((s & limb_shift_mask) == 0)
  441. {
  442. left_shift_limb(result, s);
  443. }
  444. #endif
  445. else
  446. {
  447. left_shift_generic(result, s);
  448. }
  449. //
  450. // We may have shifted off the end and have leading zeros:
  451. //
  452. result.normalize();
  453. }
  454. template <class Int>
  455. inline void right_shift_byte(Int& result, double_limb_type s)
  456. {
  457. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  458. BOOST_ASSERT((s % CHAR_BIT) == 0);
  459. unsigned ors = result.size();
  460. unsigned rs = ors;
  461. if (offset >= rs)
  462. {
  463. result = limb_type(0);
  464. return;
  465. }
  466. rs -= offset;
  467. typename Int::limb_pointer pr = result.limbs();
  468. unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
  469. limb_type shift = static_cast<limb_type>(s / CHAR_BIT);
  470. std::memmove(pc, pc + shift, ors * sizeof(pr[0]) - shift);
  471. shift = (sizeof(limb_type) - shift % sizeof(limb_type)) * CHAR_BIT;
  472. if (shift < Int::limb_bits)
  473. {
  474. pr[ors - offset - 1] &= (static_cast<limb_type>(1u) << shift) - 1;
  475. if (!pr[ors - offset - 1] && (rs > 1))
  476. --rs;
  477. }
  478. result.resize(rs, rs);
  479. }
  480. template <class Int>
  481. inline BOOST_MP_CXX14_CONSTEXPR void right_shift_limb(Int& result, double_limb_type s)
  482. {
  483. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  484. BOOST_ASSERT((s % Int::limb_bits) == 0);
  485. unsigned ors = result.size();
  486. unsigned rs = ors;
  487. if (offset >= rs)
  488. {
  489. result = limb_type(0);
  490. return;
  491. }
  492. rs -= offset;
  493. typename Int::limb_pointer pr = result.limbs();
  494. unsigned i = 0;
  495. for (; i < rs; ++i)
  496. pr[i] = pr[i + offset];
  497. result.resize(rs, rs);
  498. }
  499. template <class Int>
  500. inline BOOST_MP_CXX14_CONSTEXPR void right_shift_generic(Int& result, double_limb_type s)
  501. {
  502. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  503. limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
  504. unsigned ors = result.size();
  505. unsigned rs = ors;
  506. if (offset >= rs)
  507. {
  508. result = limb_type(0);
  509. return;
  510. }
  511. rs -= offset;
  512. typename Int::limb_pointer pr = result.limbs();
  513. if ((pr[ors - 1] >> shift) == 0)
  514. {
  515. if (--rs == 0)
  516. {
  517. result = limb_type(0);
  518. return;
  519. }
  520. }
  521. unsigned i = 0;
  522. // This code only works for non-zero shift, otherwise we invoke undefined behaviour!
  523. BOOST_ASSERT(shift);
  524. for (; i + offset + 1 < ors; ++i)
  525. {
  526. pr[i] = pr[i + offset] >> shift;
  527. pr[i] |= pr[i + offset + 1] << (Int::limb_bits - shift);
  528. }
  529. pr[i] = pr[i + offset] >> shift;
  530. result.resize(rs, rs);
  531. }
  532. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  533. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
  534. eval_right_shift(
  535. cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
  536. double_limb_type s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value))
  537. {
  538. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>::checked_type());
  539. if (!s)
  540. return;
  541. #if BOOST_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
  542. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  543. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  544. if ((s & limb_shift_mask) == 0)
  545. right_shift_limb(result, s);
  546. #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
  547. else if ((s & byte_shift_mask) == 0)
  548. #else
  549. else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
  550. #endif
  551. right_shift_byte(result, s);
  552. #elif BOOST_ENDIAN_LITTLE_BYTE
  553. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  554. #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
  555. if ((s & byte_shift_mask) == 0)
  556. #else
  557. constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  558. if (BOOST_MP_IS_CONST_EVALUATED(s) && ((s & limb_shift_mask) == 0))
  559. right_shift_limb(result, s);
  560. else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
  561. #endif
  562. right_shift_byte(result, s);
  563. #else
  564. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  565. if ((s & limb_shift_mask) == 0)
  566. right_shift_limb(result, s);
  567. #endif
  568. else
  569. right_shift_generic(result, s);
  570. }
  571. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  572. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value>::type
  573. eval_right_shift(
  574. cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result,
  575. double_limb_type s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value))
  576. {
  577. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::checked_type());
  578. if (!s)
  579. return;
  580. bool is_neg = result.sign();
  581. if (is_neg)
  582. eval_increment(result);
  583. #if BOOST_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
  584. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  585. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  586. if ((s & limb_shift_mask) == 0)
  587. right_shift_limb(result, s);
  588. else if ((s & byte_shift_mask) == 0)
  589. right_shift_byte(result, s);
  590. #elif BOOST_ENDIAN_LITTLE_BYTE
  591. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  592. if ((s & byte_shift_mask) == 0)
  593. right_shift_byte(result, s);
  594. #else
  595. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  596. if ((s & limb_shift_mask) == 0)
  597. right_shift_limb(result, s);
  598. #endif
  599. else
  600. right_shift_generic(result, s);
  601. if (is_neg)
  602. eval_decrement(result);
  603. }
  604. //
  605. // Over again for trivial cpp_int's:
  606. //
  607. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
  608. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value >::type
  609. eval_left_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  610. {
  611. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  612. *result.limbs() = detail::checked_left_shift(*result.limbs(), s, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  613. result.normalize();
  614. }
  615. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
  616. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value >::type
  617. eval_right_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  618. {
  619. // Nothing to check here... just make sure we don't invoke undefined behavior:
  620. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  621. *result.limbs() = (static_cast<unsigned>(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : (result.sign() ? ((--*result.limbs()) >> s) + 1 : *result.limbs() >> s);
  622. if (result.sign() && (*result.limbs() == 0))
  623. result = static_cast<signed_limb_type>(-1);
  624. }
  625. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  626. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  627. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)>::type
  628. eval_complement(
  629. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  630. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  631. {
  632. static_assert(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
  633. //
  634. // If we're not checked then emulate 2's complement behavior:
  635. //
  636. if (o.sign())
  637. {
  638. *result.limbs() = *o.limbs() - 1;
  639. result.sign(false);
  640. }
  641. else
  642. {
  643. *result.limbs() = 1 + *o.limbs();
  644. result.sign(true);
  645. }
  646. result.normalize();
  647. }
  648. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  649. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  650. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
  651. eval_complement(
  652. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  653. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  654. {
  655. *result.limbs() = ~*o.limbs();
  656. result.normalize();
  657. }
  658. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  659. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  660. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
  661. eval_bitwise_and(
  662. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  663. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  664. {
  665. *result.limbs() &= *o.limbs();
  666. }
  667. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  668. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  669. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)>::type
  670. eval_bitwise_and(
  671. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  672. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  673. {
  674. is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  675. using default_ops::eval_bit_test;
  676. using default_ops::eval_increment;
  677. if (result.sign() || o.sign())
  678. {
  679. constexpr const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  680. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  681. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  682. eval_bitwise_and(t1, t2);
  683. bool s = eval_bit_test(t1, m + 1);
  684. if (s)
  685. {
  686. eval_complement(t1, t1);
  687. eval_increment(t1);
  688. }
  689. result = t1;
  690. result.sign(s);
  691. }
  692. else
  693. {
  694. *result.limbs() &= *o.limbs();
  695. }
  696. }
  697. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  698. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  699. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
  700. eval_bitwise_or(
  701. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  702. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  703. {
  704. *result.limbs() |= *o.limbs();
  705. }
  706. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  707. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  708. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)>::type
  709. eval_bitwise_or(
  710. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  711. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  712. {
  713. is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  714. using default_ops::eval_bit_test;
  715. using default_ops::eval_increment;
  716. if (result.sign() || o.sign())
  717. {
  718. constexpr const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  719. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  720. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  721. eval_bitwise_or(t1, t2);
  722. bool s = eval_bit_test(t1, m + 1);
  723. if (s)
  724. {
  725. eval_complement(t1, t1);
  726. eval_increment(t1);
  727. }
  728. result = t1;
  729. result.sign(s);
  730. }
  731. else
  732. {
  733. *result.limbs() |= *o.limbs();
  734. result.normalize();
  735. }
  736. }
  737. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  738. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  739. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
  740. eval_bitwise_xor(
  741. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  742. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  743. {
  744. *result.limbs() ^= *o.limbs();
  745. }
  746. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  747. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  748. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)>::type
  749. eval_bitwise_xor(
  750. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  751. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  752. {
  753. is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  754. using default_ops::eval_bit_test;
  755. using default_ops::eval_increment;
  756. if (result.sign() || o.sign())
  757. {
  758. constexpr const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  759. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  760. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  761. eval_bitwise_xor(t1, t2);
  762. bool s = eval_bit_test(t1, m + 1);
  763. if (s)
  764. {
  765. eval_complement(t1, t1);
  766. eval_increment(t1);
  767. }
  768. result = t1;
  769. result.sign(s);
  770. }
  771. else
  772. {
  773. *result.limbs() ^= *o.limbs();
  774. }
  775. }
  776. }}} // namespace boost::multiprecision::backends
  777. #ifdef _MSC_VER
  778. #pragma warning(pop)
  779. #endif
  780. #endif