bitwise.hpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  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. namespace boost{ namespace multiprecision{ namespace backends{
  11. 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>
  12. void is_valid_bitwise_op(
  13. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  14. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::int_<checked>&)
  15. {
  16. if(result.sign() || o.sign())
  17. BOOST_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior."));
  18. }
  19. 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>
  20. void is_valid_bitwise_op(
  21. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&,
  22. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& , const mpl::int_<unchecked>&){}
  23. template <class CppInt1, class CppInt2, class Op>
  24. void bitwise_op(
  25. CppInt1& result,
  26. const CppInt2& o,
  27. Op op) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<CppInt1>::value))
  28. {
  29. //
  30. // There are 4 cases:
  31. // * Both positive.
  32. // * result negative, o positive.
  33. // * o negative, result positive.
  34. // * Both negative.
  35. //
  36. // When one arg is negative we convert to 2's complement form "on the fly",
  37. // and then convert back to signed-magnitude form at the end.
  38. //
  39. // Note however, that if the type is checked, then bitwise ops on negative values
  40. // are not permitted and an exception will result.
  41. //
  42. is_valid_bitwise_op(result, o, typename CppInt1::checked_type());
  43. //
  44. // First figure out how big the result needs to be and set up some data:
  45. //
  46. unsigned rs = result.size();
  47. unsigned os = o.size();
  48. unsigned m, x;
  49. minmax(rs, os, m, x);
  50. result.resize(x, x);
  51. typename CppInt1::limb_pointer pr = result.limbs();
  52. typename CppInt2::const_limb_pointer po = o.limbs();
  53. for(unsigned i = rs; i < x; ++i)
  54. pr[i] = 0;
  55. limb_type next_limb = 0;
  56. if(!result.sign())
  57. {
  58. if(!o.sign())
  59. {
  60. for(unsigned i = 0; i < os; ++i)
  61. pr[i] = op(pr[i], po[i]);
  62. for(unsigned i = os; i < x; ++i)
  63. pr[i] = op(pr[i], limb_type(0));
  64. }
  65. else
  66. {
  67. // "o" is negative:
  68. double_limb_type carry = 1;
  69. for(unsigned i = 0; i < os; ++i)
  70. {
  71. carry += static_cast<double_limb_type>(~po[i]);
  72. pr[i] = op(pr[i], static_cast<limb_type>(carry));
  73. carry >>= CppInt1::limb_bits;
  74. }
  75. for(unsigned i = os; i < x; ++i)
  76. {
  77. carry += static_cast<double_limb_type>(~limb_type(0));
  78. pr[i] = op(pr[i], static_cast<limb_type>(carry));
  79. carry >>= CppInt1::limb_bits;
  80. }
  81. // Set the overflow into the "extra" limb:
  82. carry += static_cast<double_limb_type>(~limb_type(0));
  83. next_limb = op(limb_type(0), static_cast<limb_type>(carry));
  84. }
  85. }
  86. else
  87. {
  88. if(!o.sign())
  89. {
  90. // "result" is negative:
  91. double_limb_type carry = 1;
  92. for(unsigned i = 0; i < os; ++i)
  93. {
  94. carry += static_cast<double_limb_type>(~pr[i]);
  95. pr[i] = op(static_cast<limb_type>(carry), po[i]);
  96. carry >>= CppInt1::limb_bits;
  97. }
  98. for(unsigned i = os; i < x; ++i)
  99. {
  100. carry += static_cast<double_limb_type>(~pr[i]);
  101. pr[i] = op(static_cast<limb_type>(carry), limb_type(0));
  102. carry >>= CppInt1::limb_bits;
  103. }
  104. // Set the overflow into the "extra" limb:
  105. carry += static_cast<double_limb_type>(~limb_type(0));
  106. next_limb = op(static_cast<limb_type>(carry), limb_type(0));
  107. }
  108. else
  109. {
  110. // both are negative:
  111. double_limb_type r_carry = 1;
  112. double_limb_type o_carry = 1;
  113. for(unsigned i = 0; i < os; ++i)
  114. {
  115. r_carry += static_cast<double_limb_type>(~pr[i]);
  116. o_carry += static_cast<double_limb_type>(~po[i]);
  117. pr[i] = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry));
  118. r_carry >>= CppInt1::limb_bits;
  119. o_carry >>= CppInt1::limb_bits;
  120. }
  121. for(unsigned i = os; i < x; ++i)
  122. {
  123. r_carry += static_cast<double_limb_type>(~pr[i]);
  124. o_carry += static_cast<double_limb_type>(~limb_type(0));
  125. pr[i] = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry));
  126. r_carry >>= CppInt1::limb_bits;
  127. o_carry >>= CppInt1::limb_bits;
  128. }
  129. // Set the overflow into the "extra" limb:
  130. r_carry += static_cast<double_limb_type>(~limb_type(0));
  131. o_carry += static_cast<double_limb_type>(~limb_type(0));
  132. next_limb = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry));
  133. }
  134. }
  135. //
  136. // See if the result is negative or not:
  137. //
  138. if(static_cast<signed_limb_type>(next_limb) < 0)
  139. {
  140. result.sign(true);
  141. double_limb_type carry = 1;
  142. for(unsigned i = 0; i < x; ++i)
  143. {
  144. carry += static_cast<double_limb_type>(~pr[i]);
  145. pr[i] = static_cast<limb_type>(carry);
  146. carry >>= CppInt1::limb_bits;
  147. }
  148. }
  149. else
  150. result.sign(false);
  151. result.normalize();
  152. }
  153. struct bit_and{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a & b; } };
  154. struct bit_or { limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a | b; } };
  155. struct bit_xor{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a ^ b; } };
  156. 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>
  157. 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
  158. eval_bitwise_and(
  159. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  160. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  161. {
  162. bitwise_op(result, o, bit_and());
  163. }
  164. 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>
  165. 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
  166. eval_bitwise_or(
  167. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  168. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  169. {
  170. bitwise_op(result, o, bit_or());
  171. }
  172. 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>
  173. 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
  174. eval_bitwise_xor(
  175. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  176. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  177. {
  178. bitwise_op(result, o, bit_xor());
  179. }
  180. 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>
  181. 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
  182. eval_complement(
  183. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  184. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  185. {
  186. BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
  187. // Increment and negate:
  188. result = o;
  189. eval_increment(result);
  190. result.negate();
  191. }
  192. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  193. 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
  194. eval_complement(
  195. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  196. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  197. {
  198. unsigned os = o.size();
  199. result.resize(UINT_MAX, os);
  200. for(unsigned i = 0; i < os; ++i)
  201. result.limbs()[i] = ~o.limbs()[i];
  202. for(unsigned i = os; i < result.size(); ++i)
  203. result.limbs()[i] = ~static_cast<limb_type>(0);
  204. result.normalize();
  205. }
  206. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  207. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  208. eval_left_shift(
  209. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  210. double_limb_type s) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  211. {
  212. if(!s)
  213. return;
  214. limb_type offset = static_cast<limb_type>(s / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits);
  215. limb_type shift = static_cast<limb_type>(s % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits);
  216. unsigned ors = result.size();
  217. if((ors == 1) && (!*result.limbs()))
  218. return; // shifting zero yields zero.
  219. unsigned rs = ors;
  220. if(shift && (result.limbs()[ors - 1] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift)))
  221. ++rs; // Most significant limb will overflow when shifted
  222. rs += offset;
  223. result.resize(rs, rs);
  224. bool truncated = result.size() != rs;
  225. typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pr = result.limbs();
  226. if(offset > rs)
  227. {
  228. // The result is shifted past the end of the result:
  229. result = static_cast<limb_type>(0);
  230. return;
  231. }
  232. unsigned i = rs - result.size();
  233. if(shift)
  234. {
  235. // This code only works when shift is non-zero, otherwise we invoke undefined behaviour!
  236. if(!truncated)
  237. {
  238. if(rs > ors + offset)
  239. {
  240. pr[rs - 1 - i] = pr[ors - 1 - i] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift);
  241. --rs;
  242. }
  243. else
  244. {
  245. pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
  246. if(ors > 1)
  247. pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift);
  248. ++i;
  249. }
  250. }
  251. for(; ors > 1 + i; ++i)
  252. {
  253. pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
  254. pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift);
  255. }
  256. if(ors >= 1 + i)
  257. {
  258. pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
  259. ++i;
  260. }
  261. for(; i < rs; ++i)
  262. pr[rs - 1 - i] = 0;
  263. }
  264. else
  265. {
  266. for(; i < ors; ++i)
  267. pr[rs - 1 - i] = pr[ors - 1 - i];
  268. for(; i < rs; ++i)
  269. pr[rs - 1 - i] = 0;
  270. }
  271. //
  272. // We may have shifted off the end and have leading zeros:
  273. //
  274. result.normalize();
  275. }
  276. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  277. inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  278. eval_right_shift(
  279. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  280. double_limb_type s) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  281. {
  282. if(!s)
  283. return;
  284. limb_type offset = static_cast<limb_type>(s / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits);
  285. limb_type shift = static_cast<limb_type>(s % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits);
  286. unsigned ors = result.size();
  287. unsigned rs = ors;
  288. if(offset >= rs)
  289. {
  290. result = limb_type(0);
  291. return;
  292. }
  293. rs -= offset;
  294. typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pr = result.limbs();
  295. if((pr[ors - 1] >> shift) == 0)
  296. --rs;
  297. if(rs == 0)
  298. {
  299. result = limb_type(0);
  300. return;
  301. }
  302. unsigned i = 0;
  303. if(shift)
  304. {
  305. // This code only works for non-zero shift, otherwise we invoke undefined behaviour!
  306. for(; i + offset + 1 < ors; ++i)
  307. {
  308. pr[i] = pr[i + offset] >> shift;
  309. pr[i] |= pr[i + offset + 1] << (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift);
  310. }
  311. pr[i] = pr[i + offset] >> shift;
  312. }
  313. else
  314. {
  315. for(; i < rs; ++i)
  316. pr[i] = pr[i + offset];
  317. }
  318. result.resize(rs, rs);
  319. }
  320. //
  321. // Over again for trivial cpp_int's:
  322. //
  323. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
  324. BOOST_MP_FORCEINLINE typename enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::type
  325. eval_left_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  326. {
  327. *result.limbs() = detail::checked_left_shift(*result.limbs(), s, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  328. result.normalize();
  329. }
  330. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
  331. BOOST_MP_FORCEINLINE typename enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::type
  332. eval_right_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  333. {
  334. // Nothing to check here... just make sure we don't invoke undefined behavior:
  335. *result.limbs() = (static_cast<unsigned>(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : *result.limbs() >> s;
  336. }
  337. 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>
  338. inline typename enable_if_c<
  339. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  340. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  341. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
  342. >::type
  343. eval_bitwise_and(
  344. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  345. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  346. {
  347. is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  348. using default_ops::eval_bit_test;
  349. using default_ops::eval_increment;
  350. if(result.sign() || o.sign())
  351. {
  352. static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  353. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  354. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  355. eval_bitwise_and(t1, t2);
  356. bool s = eval_bit_test(t1, m + 1);
  357. if(s)
  358. {
  359. eval_complement(t1, t1);
  360. eval_increment(t1);
  361. }
  362. result = t1;
  363. result.sign(s);
  364. }
  365. else
  366. {
  367. *result.limbs() &= *o.limbs();
  368. }
  369. }
  370. 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>
  371. inline typename enable_if_c<
  372. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  373. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  374. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  375. && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  376. >::type
  377. eval_bitwise_and(
  378. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  379. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  380. {
  381. *result.limbs() &= *o.limbs();
  382. }
  383. 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>
  384. inline typename enable_if_c<
  385. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  386. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  387. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
  388. >::type
  389. eval_bitwise_or(
  390. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  391. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  392. {
  393. is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  394. using default_ops::eval_bit_test;
  395. using default_ops::eval_increment;
  396. if(result.sign() || o.sign())
  397. {
  398. static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  399. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  400. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  401. eval_bitwise_or(t1, t2);
  402. bool s = eval_bit_test(t1, m + 1);
  403. if(s)
  404. {
  405. eval_complement(t1, t1);
  406. eval_increment(t1);
  407. }
  408. result = t1;
  409. result.sign(s);
  410. }
  411. else
  412. {
  413. *result.limbs() |= *o.limbs();
  414. result.normalize();
  415. }
  416. }
  417. 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>
  418. inline typename enable_if_c<
  419. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  420. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  421. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  422. && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  423. >::type
  424. eval_bitwise_or(
  425. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  426. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  427. {
  428. *result.limbs() |= *o.limbs();
  429. }
  430. 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>
  431. inline typename enable_if_c<
  432. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  433. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  434. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
  435. >::type
  436. eval_bitwise_xor(
  437. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  438. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  439. {
  440. is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  441. using default_ops::eval_bit_test;
  442. using default_ops::eval_increment;
  443. if(result.sign() || o.sign())
  444. {
  445. static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
  446. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
  447. cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
  448. eval_bitwise_xor(t1, t2);
  449. bool s = eval_bit_test(t1, m + 1);
  450. if(s)
  451. {
  452. eval_complement(t1, t1);
  453. eval_increment(t1);
  454. }
  455. result = t1;
  456. result.sign(s);
  457. }
  458. else
  459. {
  460. *result.limbs() ^= *o.limbs();
  461. }
  462. }
  463. 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>
  464. inline typename enable_if_c<
  465. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  466. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  467. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  468. && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  469. >::type
  470. eval_bitwise_xor(
  471. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  472. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  473. {
  474. *result.limbs() ^= *o.limbs();
  475. }
  476. 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>
  477. inline typename enable_if_c<
  478. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  479. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  480. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
  481. >::type
  482. eval_complement(
  483. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  484. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  485. {
  486. BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
  487. //
  488. // If we're not checked then emulate 2's complement behavior:
  489. //
  490. if(o.sign())
  491. {
  492. *result.limbs() = *o.limbs() - 1;
  493. result.sign(false);
  494. }
  495. else
  496. {
  497. *result.limbs() = 1 + *o.limbs();
  498. result.sign(true);
  499. }
  500. result.normalize();
  501. }
  502. 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>
  503. inline typename enable_if_c<
  504. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  505. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  506. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  507. && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  508. >::type
  509. eval_complement(
  510. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  511. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  512. {
  513. *result.limbs() = ~*o.limbs();
  514. result.normalize();
  515. }
  516. }}} // namespaces
  517. #endif