bitwise.hpp 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898
  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 mpl::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 mpl::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 mpl::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 mpl::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 mpl::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 mpl::true_&) BOOST_MP_NOEXCEPT_IF((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 mpl::false_&) BOOST_MP_NOEXCEPT_IF((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 BOOST_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 BOOST_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 BOOST_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 enable_if_c<!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) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  219. {
  220. bitwise_op(result, o, bit_and(),
  221. mpl::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 enable_if_c<!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) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  228. {
  229. bitwise_op(result, o, bit_or(),
  230. mpl::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 enable_if_c<!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) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  237. {
  238. bitwise_op(result, o, bit_xor(),
  239. mpl::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 enable_if_c<!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) BOOST_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 enable_if_c<!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) BOOST_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 enable_if_c<!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) BOOST_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 enable_if_c<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) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  274. {
  275. BOOST_STATIC_ASSERT_MSG(((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 enable_if_c<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) BOOST_MP_NOEXCEPT_IF((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 BOOST_MP_CXX14_CONSTEXPR 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 enable_if_c<!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) BOOST_MP_NOEXCEPT_IF((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. #ifdef BOOST_NO_CXX14_CONSTEXPR
  412. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
  413. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  414. #else
  415. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
  416. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  417. #endif
  418. if ((s & limb_shift_mask) == 0)
  419. {
  420. left_shift_limb(result, s);
  421. }
  422. #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
  423. else if ((s & byte_shift_mask) == 0)
  424. #else
  425. else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
  426. #endif
  427. {
  428. left_shift_byte(result, s);
  429. }
  430. #elif BOOST_ENDIAN_LITTLE_BYTE
  431. #ifdef BOOST_NO_CXX14_CONSTEXPR
  432. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  433. #else
  434. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  435. #endif
  436. #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
  437. if ((s & byte_shift_mask) == 0)
  438. #else
  439. constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
  440. if (BOOST_MP_IS_CONST_EVALUATED(s) && ((s & limb_shift_mask) == 0))
  441. left_shift_limb(result, s);
  442. else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
  443. #endif
  444. {
  445. left_shift_byte(result, s);
  446. }
  447. #else
  448. #ifdef BOOST_NO_CXX14_CONSTEXPR
  449. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
  450. #else
  451. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
  452. #endif
  453. if ((s & limb_shift_mask) == 0)
  454. {
  455. left_shift_limb(result, s);
  456. }
  457. #endif
  458. else
  459. {
  460. left_shift_generic(result, s);
  461. }
  462. //
  463. // We may have shifted off the end and have leading zeros:
  464. //
  465. result.normalize();
  466. }
  467. template <class Int>
  468. inline BOOST_MP_CXX14_CONSTEXPR void right_shift_byte(Int& result, double_limb_type s)
  469. {
  470. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  471. BOOST_ASSERT((s % CHAR_BIT) == 0);
  472. unsigned ors = result.size();
  473. unsigned rs = ors;
  474. if (offset >= rs)
  475. {
  476. result = limb_type(0);
  477. return;
  478. }
  479. rs -= offset;
  480. typename Int::limb_pointer pr = result.limbs();
  481. unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
  482. limb_type shift = static_cast<limb_type>(s / CHAR_BIT);
  483. std::memmove(pc, pc + shift, ors * sizeof(pr[0]) - shift);
  484. shift = (sizeof(limb_type) - shift % sizeof(limb_type)) * CHAR_BIT;
  485. if (shift < Int::limb_bits)
  486. {
  487. pr[ors - offset - 1] &= (static_cast<limb_type>(1u) << shift) - 1;
  488. if (!pr[ors - offset - 1] && (rs > 1))
  489. --rs;
  490. }
  491. result.resize(rs, rs);
  492. }
  493. template <class Int>
  494. inline BOOST_MP_CXX14_CONSTEXPR void right_shift_limb(Int& result, double_limb_type s)
  495. {
  496. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  497. BOOST_ASSERT((s % Int::limb_bits) == 0);
  498. unsigned ors = result.size();
  499. unsigned rs = ors;
  500. if (offset >= rs)
  501. {
  502. result = limb_type(0);
  503. return;
  504. }
  505. rs -= offset;
  506. typename Int::limb_pointer pr = result.limbs();
  507. unsigned i = 0;
  508. for (; i < rs; ++i)
  509. pr[i] = pr[i + offset];
  510. result.resize(rs, rs);
  511. }
  512. template <class Int>
  513. inline BOOST_MP_CXX14_CONSTEXPR void right_shift_generic(Int& result, double_limb_type s)
  514. {
  515. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  516. limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
  517. unsigned ors = result.size();
  518. unsigned rs = ors;
  519. if (offset >= rs)
  520. {
  521. result = limb_type(0);
  522. return;
  523. }
  524. rs -= offset;
  525. typename Int::limb_pointer pr = result.limbs();
  526. if ((pr[ors - 1] >> shift) == 0)
  527. {
  528. if (--rs == 0)
  529. {
  530. result = limb_type(0);
  531. return;
  532. }
  533. }
  534. unsigned i = 0;
  535. // This code only works for non-zero shift, otherwise we invoke undefined behaviour!
  536. BOOST_ASSERT(shift);
  537. for (; i + offset + 1 < ors; ++i)
  538. {
  539. pr[i] = pr[i + offset] >> shift;
  540. pr[i] |= pr[i + offset + 1] << (Int::limb_bits - shift);
  541. }
  542. pr[i] = pr[i + offset] >> shift;
  543. result.resize(rs, rs);
  544. }
  545. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  546. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
  547. eval_right_shift(
  548. cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
  549. double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value))
  550. {
  551. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>::checked_type());
  552. if (!s)
  553. return;
  554. #if BOOST_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
  555. #ifdef BOOST_NO_CXX14_CONSTEXPR
  556. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  557. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  558. #else
  559. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  560. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  561. #endif
  562. if ((s & limb_shift_mask) == 0)
  563. right_shift_limb(result, s);
  564. #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
  565. else if ((s & byte_shift_mask) == 0)
  566. #else
  567. else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
  568. #endif
  569. right_shift_byte(result, s);
  570. #elif BOOST_ENDIAN_LITTLE_BYTE
  571. #ifdef BOOST_NO_CXX14_CONSTEXPR
  572. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  573. #else
  574. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  575. #endif
  576. #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
  577. if ((s & byte_shift_mask) == 0)
  578. #else
  579. constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  580. if (BOOST_MP_IS_CONST_EVALUATED(s) && ((s & limb_shift_mask) == 0))
  581. right_shift_limb(result, s);
  582. else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
  583. #endif
  584. right_shift_byte(result, s);
  585. #else
  586. #ifdef BOOST_NO_CXX14_CONSTEXPR
  587. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  588. #else
  589. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  590. #endif
  591. if ((s & limb_shift_mask) == 0)
  592. right_shift_limb(result, s);
  593. #endif
  594. else
  595. right_shift_generic(result, s);
  596. }
  597. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  598. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value>::type
  599. eval_right_shift(
  600. cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result,
  601. double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value))
  602. {
  603. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::checked_type());
  604. if (!s)
  605. return;
  606. bool is_neg = result.sign();
  607. if (is_neg)
  608. eval_increment(result);
  609. #if BOOST_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
  610. #ifdef BOOST_NO_CXX14_CONSTEXPR
  611. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  612. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  613. #else
  614. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  615. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  616. #endif
  617. if ((s & limb_shift_mask) == 0)
  618. right_shift_limb(result, s);
  619. else if ((s & byte_shift_mask) == 0)
  620. right_shift_byte(result, s);
  621. #elif BOOST_ENDIAN_LITTLE_BYTE
  622. #ifdef BOOST_NO_CXX14_CONSTEXPR
  623. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  624. #else
  625. constexpr const limb_type byte_shift_mask = CHAR_BIT - 1;
  626. #endif
  627. if ((s & byte_shift_mask) == 0)
  628. right_shift_byte(result, s);
  629. #else
  630. #ifdef BOOST_NO_CXX14_CONSTEXPR
  631. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  632. #else
  633. constexpr const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  634. #endif
  635. if ((s & limb_shift_mask) == 0)
  636. right_shift_limb(result, s);
  637. #endif
  638. else
  639. right_shift_generic(result, s);
  640. if (is_neg)
  641. eval_decrement(result);
  642. }
  643. //
  644. // Over again for trivial cpp_int's:
  645. //
  646. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
  647. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::type
  648. eval_left_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  649. {
  650. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  651. *result.limbs() = detail::checked_left_shift(*result.limbs(), s, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  652. result.normalize();
  653. }
  654. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
  655. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::type
  656. eval_right_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  657. {
  658. // Nothing to check here... just make sure we don't invoke undefined behavior:
  659. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  660. *result.limbs() = (static_cast<unsigned>(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : (result.sign() ? ((--*result.limbs()) >> s) + 1 : *result.limbs() >> s);
  661. if (result.sign() && (*result.limbs() == 0))
  662. result = static_cast<signed_limb_type>(-1);
  663. }
  664. 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>
  665. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  666. 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
  667. eval_complement(
  668. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  669. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  670. {
  671. BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
  672. //
  673. // If we're not checked then emulate 2's complement behavior:
  674. //
  675. if (o.sign())
  676. {
  677. *result.limbs() = *o.limbs() - 1;
  678. result.sign(false);
  679. }
  680. else
  681. {
  682. *result.limbs() = 1 + *o.limbs();
  683. result.sign(true);
  684. }
  685. result.normalize();
  686. }
  687. 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>
  688. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  689. 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
  690. eval_complement(
  691. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  692. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  693. {
  694. *result.limbs() = ~*o.limbs();
  695. result.normalize();
  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 enable_if_c<
  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_and(
  701. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  702. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((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 enable_if_c<
  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_and(
  710. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  711. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((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. #ifdef BOOST_NO_CXX14_CONSTEXPR
  719. static
  720. #else
  721. constexpr
  722. #endif
  723. const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  724. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  725. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  726. eval_bitwise_and(t1, t2);
  727. bool s = eval_bit_test(t1, m + 1);
  728. if (s)
  729. {
  730. eval_complement(t1, t1);
  731. eval_increment(t1);
  732. }
  733. result = t1;
  734. result.sign(s);
  735. }
  736. else
  737. {
  738. *result.limbs() &= *o.limbs();
  739. }
  740. }
  741. 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>
  742. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  743. 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
  744. eval_bitwise_or(
  745. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  746. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  747. {
  748. *result.limbs() |= *o.limbs();
  749. }
  750. 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>
  751. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  752. 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
  753. eval_bitwise_or(
  754. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  755. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  756. {
  757. is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  758. using default_ops::eval_bit_test;
  759. using default_ops::eval_increment;
  760. if (result.sign() || o.sign())
  761. {
  762. #ifdef BOOST_NO_CXX14_CONSTEXPR
  763. static
  764. #else
  765. constexpr
  766. #endif
  767. const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  768. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  769. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  770. eval_bitwise_or(t1, t2);
  771. bool s = eval_bit_test(t1, m + 1);
  772. if (s)
  773. {
  774. eval_complement(t1, t1);
  775. eval_increment(t1);
  776. }
  777. result = t1;
  778. result.sign(s);
  779. }
  780. else
  781. {
  782. *result.limbs() |= *o.limbs();
  783. result.normalize();
  784. }
  785. }
  786. 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>
  787. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  788. 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
  789. eval_bitwise_xor(
  790. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  791. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  792. {
  793. *result.limbs() ^= *o.limbs();
  794. }
  795. 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>
  796. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  797. 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
  798. eval_bitwise_xor(
  799. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  800. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  801. {
  802. is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  803. using default_ops::eval_bit_test;
  804. using default_ops::eval_increment;
  805. if (result.sign() || o.sign())
  806. {
  807. #ifdef BOOST_NO_CXX14_CONSTEXPR
  808. static
  809. #else
  810. constexpr
  811. #endif
  812. const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  813. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  814. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  815. eval_bitwise_xor(t1, t2);
  816. bool s = eval_bit_test(t1, m + 1);
  817. if (s)
  818. {
  819. eval_complement(t1, t1);
  820. eval_increment(t1);
  821. }
  822. result = t1;
  823. result.sign(s);
  824. }
  825. else
  826. {
  827. *result.limbs() ^= *o.limbs();
  828. }
  829. }
  830. }}} // namespace boost::multiprecision::backends
  831. #ifdef _MSC_VER
  832. #pragma warning(pop)
  833. #endif
  834. #endif