bitwise.hpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright 2012 John Maddock. Distributed under the Boost
  3. // Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
  5. //
  6. // Comparison operators for cpp_int_backend:
  7. //
  8. #ifndef BOOST_MP_CPP_INT_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. 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. 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. 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. 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. 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. 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, x;
  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. 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, x;
  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{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a & b; } };
  203. struct bit_or { limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a | b; } };
  204. struct bit_xor{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a ^ b; } };
  205. 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>
  206. BOOST_MP_FORCEINLINE 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
  207. eval_bitwise_and(
  208. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  209. 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))
  210. {
  211. bitwise_op(result, o, bit_and(),
  212. 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>());
  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 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_or(
  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_or(),
  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 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_xor(
  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_xor(),
  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. //
  233. // Again for operands which are single limbs:
  234. //
  235. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  236. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
  237. eval_bitwise_and(
  238. cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
  239. limb_type l) BOOST_NOEXCEPT
  240. {
  241. result.limbs()[0] &= l;
  242. result.resize(1, 1);
  243. }
  244. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  245. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
  246. eval_bitwise_or(
  247. cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
  248. limb_type l) BOOST_NOEXCEPT
  249. {
  250. result.limbs()[0] |= l;
  251. }
  252. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  253. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
  254. eval_bitwise_xor(
  255. cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
  256. limb_type l) BOOST_NOEXCEPT
  257. {
  258. result.limbs()[0] ^= l;
  259. }
  260. 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>
  261. BOOST_MP_FORCEINLINE 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
  262. eval_complement(
  263. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  264. 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))
  265. {
  266. BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
  267. // Increment and negate:
  268. result = o;
  269. eval_increment(result);
  270. result.negate();
  271. }
  272. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  273. BOOST_MP_FORCEINLINE 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
  274. eval_complement(
  275. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  276. 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))
  277. {
  278. unsigned os = o.size();
  279. result.resize(UINT_MAX, os);
  280. for(unsigned i = 0; i < os; ++i)
  281. result.limbs()[i] = ~o.limbs()[i];
  282. for(unsigned i = os; i < result.size(); ++i)
  283. result.limbs()[i] = ~static_cast<limb_type>(0);
  284. result.normalize();
  285. }
  286. template <class Int>
  287. inline void left_shift_byte(Int& result, double_limb_type s)
  288. {
  289. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  290. limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
  291. unsigned ors = result.size();
  292. if((ors == 1) && (!*result.limbs()))
  293. return; // shifting zero yields zero.
  294. unsigned rs = ors;
  295. if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
  296. ++rs; // Most significant limb will overflow when shifted
  297. rs += offset;
  298. result.resize(rs, rs);
  299. rs = result.size();
  300. typename Int::limb_pointer pr = result.limbs();
  301. if(rs != ors)
  302. pr[rs - 1] = 0u;
  303. std::size_t bytes = static_cast<std::size_t>(s / CHAR_BIT);
  304. std::size_t len = (std::min)(ors * sizeof(limb_type), rs * sizeof(limb_type) - bytes);
  305. if(bytes >= rs * sizeof(limb_type))
  306. result = static_cast<limb_type>(0u);
  307. else
  308. {
  309. unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
  310. std::memmove(pc + bytes, pc, len);
  311. std::memset(pc, 0, bytes);
  312. }
  313. }
  314. template <class Int>
  315. inline void left_shift_limb(Int& result, double_limb_type s)
  316. {
  317. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  318. limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
  319. unsigned ors = result.size();
  320. if((ors == 1) && (!*result.limbs()))
  321. return; // shifting zero yields zero.
  322. unsigned rs = ors;
  323. if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
  324. ++rs; // Most significant limb will overflow when shifted
  325. rs += offset;
  326. result.resize(rs, rs);
  327. typename Int::limb_pointer pr = result.limbs();
  328. if(offset > rs)
  329. {
  330. // The result is shifted past the end of the result:
  331. result = static_cast<limb_type>(0);
  332. return;
  333. }
  334. unsigned i = rs - result.size();
  335. for(; i < ors; ++i)
  336. pr[rs - 1 - i] = pr[ors - 1 - i];
  337. for(; i < rs; ++i)
  338. pr[rs - 1 - i] = 0;
  339. }
  340. template <class Int>
  341. inline void left_shift_generic(Int& result, double_limb_type s)
  342. {
  343. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  344. limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
  345. unsigned ors = result.size();
  346. if((ors == 1) && (!*result.limbs()))
  347. return; // shifting zero yields zero.
  348. unsigned rs = ors;
  349. if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
  350. ++rs; // Most significant limb will overflow when shifted
  351. rs += offset;
  352. result.resize(rs, rs);
  353. bool truncated = result.size() != rs;
  354. typename Int::limb_pointer pr = result.limbs();
  355. if(offset > rs)
  356. {
  357. // The result is shifted past the end of the result:
  358. result = static_cast<limb_type>(0);
  359. return;
  360. }
  361. unsigned i = rs - result.size();
  362. // This code only works when shift is non-zero, otherwise we invoke undefined behaviour!
  363. BOOST_ASSERT(shift);
  364. if(!truncated)
  365. {
  366. if(rs > ors + offset)
  367. {
  368. pr[rs - 1 - i] = pr[ors - 1 - i] >> (Int::limb_bits - shift);
  369. --rs;
  370. }
  371. else
  372. {
  373. pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
  374. if(ors > 1)
  375. pr[rs - 1 - i] |= pr[ors - 2 - i] >> (Int::limb_bits - shift);
  376. ++i;
  377. }
  378. }
  379. for(; rs - i >= 2 + offset; ++i)
  380. {
  381. pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift;
  382. pr[rs - 1 - i] |= pr[rs - 2 - i - offset] >> (Int::limb_bits - shift);
  383. }
  384. if(rs - i >= 1 + offset)
  385. {
  386. pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift;
  387. ++i;
  388. }
  389. for(; i < rs; ++i)
  390. pr[rs - 1 - i] = 0;
  391. }
  392. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  393. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  394. eval_left_shift(
  395. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  396. double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  397. {
  398. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  399. if(!s)
  400. return;
  401. #if BOOST_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
  402. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
  403. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  404. if((s & limb_shift_mask) == 0)
  405. {
  406. left_shift_limb(result, s);
  407. }
  408. else if((s & byte_shift_mask) == 0)
  409. {
  410. left_shift_byte(result, s);
  411. }
  412. #elif BOOST_ENDIAN_LITTLE_BYTE
  413. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  414. if((s & byte_shift_mask) == 0)
  415. {
  416. left_shift_byte(result, s);
  417. }
  418. #else
  419. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
  420. if((s & limb_shift_mask) == 0)
  421. {
  422. left_shift_limb(result, s);
  423. }
  424. #endif
  425. else
  426. {
  427. left_shift_generic(result, s);
  428. }
  429. //
  430. // We may have shifted off the end and have leading zeros:
  431. //
  432. result.normalize();
  433. }
  434. template <class Int>
  435. inline void right_shift_byte(Int& result, double_limb_type s)
  436. {
  437. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  438. limb_type shift;
  439. BOOST_ASSERT((s % CHAR_BIT) == 0);
  440. unsigned ors = result.size();
  441. unsigned rs = ors;
  442. if(offset >= rs)
  443. {
  444. result = limb_type(0);
  445. return;
  446. }
  447. rs -= offset;
  448. typename Int::limb_pointer pr = result.limbs();
  449. unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
  450. shift = static_cast<limb_type>(s / CHAR_BIT);
  451. std::memmove(pc, pc + shift, ors * sizeof(pr[0]) - shift);
  452. shift = (sizeof(limb_type) - shift % sizeof(limb_type)) * CHAR_BIT;
  453. if(shift < Int::limb_bits)
  454. {
  455. pr[ors - offset - 1] &= (static_cast<limb_type>(1u) << shift) - 1;
  456. if(!pr[ors - offset - 1] && (rs > 1))
  457. --rs;
  458. }
  459. result.resize(rs, rs);
  460. }
  461. template <class Int>
  462. inline void right_shift_limb(Int& result, double_limb_type s)
  463. {
  464. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  465. BOOST_ASSERT((s % Int::limb_bits) == 0);
  466. unsigned ors = result.size();
  467. unsigned rs = ors;
  468. if(offset >= rs)
  469. {
  470. result = limb_type(0);
  471. return;
  472. }
  473. rs -= offset;
  474. typename Int::limb_pointer pr = result.limbs();
  475. unsigned i = 0;
  476. for(; i < rs; ++i)
  477. pr[i] = pr[i + offset];
  478. result.resize(rs, rs);
  479. }
  480. template <class Int>
  481. inline void right_shift_generic(Int& result, double_limb_type s)
  482. {
  483. limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
  484. limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
  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. if((pr[ors - 1] >> shift) == 0)
  495. {
  496. if(--rs == 0)
  497. {
  498. result = limb_type(0);
  499. return;
  500. }
  501. }
  502. unsigned i = 0;
  503. // This code only works for non-zero shift, otherwise we invoke undefined behaviour!
  504. BOOST_ASSERT(shift);
  505. for(; i + offset + 1 < ors; ++i)
  506. {
  507. pr[i] = pr[i + offset] >> shift;
  508. pr[i] |= pr[i + offset + 1] << (Int::limb_bits - shift);
  509. }
  510. pr[i] = pr[i + offset] >> shift;
  511. result.resize(rs, rs);
  512. }
  513. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  514. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
  515. eval_right_shift(
  516. cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
  517. double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value))
  518. {
  519. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>::checked_type());
  520. if(!s)
  521. return;
  522. #if BOOST_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
  523. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  524. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  525. if((s & limb_shift_mask) == 0)
  526. right_shift_limb(result, s);
  527. else if((s & byte_shift_mask) == 0)
  528. right_shift_byte(result, s);
  529. #elif BOOST_ENDIAN_LITTLE_BYTE
  530. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  531. if((s & byte_shift_mask) == 0)
  532. right_shift_byte(result, s);
  533. #else
  534. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  535. if((s & limb_shift_mask) == 0)
  536. right_shift_limb(result, s);
  537. #endif
  538. else
  539. right_shift_generic(result, s);
  540. }
  541. template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
  542. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value>::type
  543. eval_right_shift(
  544. cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result,
  545. double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value))
  546. {
  547. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::checked_type());
  548. if(!s)
  549. return;
  550. bool is_neg = result.sign();
  551. if(is_neg)
  552. eval_increment(result);
  553. #if BOOST_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
  554. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  555. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  556. if((s & limb_shift_mask) == 0)
  557. right_shift_limb(result, s);
  558. else if((s & byte_shift_mask) == 0)
  559. right_shift_byte(result, s);
  560. #elif BOOST_ENDIAN_LITTLE_BYTE
  561. static const limb_type byte_shift_mask = CHAR_BIT - 1;
  562. if((s & byte_shift_mask) == 0)
  563. right_shift_byte(result, s);
  564. #else
  565. static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
  566. if((s & limb_shift_mask) == 0)
  567. right_shift_limb(result, s);
  568. #endif
  569. else
  570. right_shift_generic(result, s);
  571. if(is_neg)
  572. eval_decrement(result);
  573. }
  574. //
  575. // Over again for trivial cpp_int's:
  576. //
  577. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
  578. BOOST_MP_FORCEINLINE typename enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::type
  579. 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))
  580. {
  581. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  582. *result.limbs() = detail::checked_left_shift(*result.limbs(), s, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  583. result.normalize();
  584. }
  585. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
  586. BOOST_MP_FORCEINLINE typename enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::type
  587. 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))
  588. {
  589. // Nothing to check here... just make sure we don't invoke undefined behavior:
  590. is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  591. *result.limbs() = (static_cast<unsigned>(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : (result.sign() ? ((--*result.limbs()) >> s) + 1 : *result.limbs() >> s);
  592. if(result.sign() && (*result.limbs() == 0))
  593. result = static_cast<signed_limb_type>(-1);
  594. }
  595. 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>
  596. inline typename enable_if_c<
  597. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  598. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  599. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
  600. >::type
  601. eval_complement(
  602. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  603. 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))
  604. {
  605. BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
  606. //
  607. // If we're not checked then emulate 2's complement behavior:
  608. //
  609. if(o.sign())
  610. {
  611. *result.limbs() = *o.limbs() - 1;
  612. result.sign(false);
  613. }
  614. else
  615. {
  616. *result.limbs() = 1 + *o.limbs();
  617. result.sign(true);
  618. }
  619. result.normalize();
  620. }
  621. 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>
  622. inline typename enable_if_c<
  623. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  624. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  625. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  626. && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  627. >::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) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  631. {
  632. *result.limbs() = ~*o.limbs();
  633. result.normalize();
  634. }
  635. 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>
  636. inline typename enable_if_c<
  637. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  638. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  639. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  640. && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  641. >::type
  642. eval_bitwise_and(
  643. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  644. 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))
  645. {
  646. *result.limbs() &= *o.limbs();
  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 typename enable_if_c<
  650. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  651. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  652. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
  653. >::type
  654. eval_bitwise_and(
  655. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  656. 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))
  657. {
  658. is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  659. using default_ops::eval_bit_test;
  660. using default_ops::eval_increment;
  661. if(result.sign() || o.sign())
  662. {
  663. static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  664. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  665. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  666. eval_bitwise_and(t1, t2);
  667. bool s = eval_bit_test(t1, m + 1);
  668. if(s)
  669. {
  670. eval_complement(t1, t1);
  671. eval_increment(t1);
  672. }
  673. result = t1;
  674. result.sign(s);
  675. }
  676. else
  677. {
  678. *result.limbs() &= *o.limbs();
  679. }
  680. }
  681. 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>
  682. inline typename enable_if_c<
  683. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  684. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  685. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  686. && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  687. >::type
  688. eval_bitwise_or(
  689. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  690. 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))
  691. {
  692. *result.limbs() |= *o.limbs();
  693. }
  694. 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>
  695. inline typename enable_if_c<
  696. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  697. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  698. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
  699. >::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) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  703. {
  704. is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  705. using default_ops::eval_bit_test;
  706. using default_ops::eval_increment;
  707. if(result.sign() || o.sign())
  708. {
  709. static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  710. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  711. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  712. eval_bitwise_or(t1, t2);
  713. bool s = eval_bit_test(t1, m + 1);
  714. if(s)
  715. {
  716. eval_complement(t1, t1);
  717. eval_increment(t1);
  718. }
  719. result = t1;
  720. result.sign(s);
  721. }
  722. else
  723. {
  724. *result.limbs() |= *o.limbs();
  725. result.normalize();
  726. }
  727. }
  728. 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>
  729. inline typename enable_if_c<
  730. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  731. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  732. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  733. && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  734. >::type
  735. eval_bitwise_xor(
  736. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  737. 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))
  738. {
  739. *result.limbs() ^= *o.limbs();
  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 typename enable_if_c<
  743. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  744. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  745. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
  746. >::type
  747. eval_bitwise_xor(
  748. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  749. 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))
  750. {
  751. is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  752. using default_ops::eval_bit_test;
  753. using default_ops::eval_increment;
  754. if(result.sign() || o.sign())
  755. {
  756. static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  757. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  758. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  759. eval_bitwise_xor(t1, t2);
  760. bool s = eval_bit_test(t1, m + 1);
  761. if(s)
  762. {
  763. eval_complement(t1, t1);
  764. eval_increment(t1);
  765. }
  766. result = t1;
  767. result.sign(s);
  768. }
  769. else
  770. {
  771. *result.limbs() ^= *o.limbs();
  772. }
  773. }
  774. }}} // namespaces
  775. #ifdef _MSC_VER
  776. #pragma warning(pop)
  777. #endif
  778. #endif