add.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  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_ADD_HPP
  9. #define BOOST_MP_CPP_INT_ADD_HPP
  10. namespace boost{ namespace multiprecision{ namespace backends{
  11. #ifdef _MSC_VER
  12. #pragma warning(push)
  13. #pragma warning(disable:4127) // conditional expression is constant
  14. #endif
  15. //
  16. // This is the key addition routine where all the argument types are non-trivial cpp_int's:
  17. //
  18. template <class CppInt1, class CppInt2, class CppInt3>
  19. inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
  20. {
  21. using std::swap;
  22. // Nothing fancy, just let uintmax_t take the strain:
  23. double_limb_type carry = 0;
  24. unsigned m, x;
  25. unsigned as = a.size();
  26. unsigned bs = b.size();
  27. minmax(as, bs, m, x);
  28. if(x == 1)
  29. {
  30. bool s = a.sign();
  31. result = static_cast<double_limb_type>(*a.limbs()) + static_cast<double_limb_type>(*b.limbs());
  32. result.sign(s);
  33. return;
  34. }
  35. result.resize(x, x);
  36. typename CppInt2::const_limb_pointer pa = a.limbs();
  37. typename CppInt3::const_limb_pointer pb = b.limbs();
  38. typename CppInt1::limb_pointer pr = result.limbs();
  39. typename CppInt1::limb_pointer pr_end = pr + m;
  40. if(as < bs)
  41. swap(pa, pb);
  42. // First where a and b overlap:
  43. while(pr != pr_end)
  44. {
  45. carry += static_cast<double_limb_type>(*pa) + static_cast<double_limb_type>(*pb);
  46. #ifdef __MSVC_RUNTIME_CHECKS
  47. *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  48. #else
  49. *pr = static_cast<limb_type>(carry);
  50. #endif
  51. carry >>= CppInt1::limb_bits;
  52. ++pr, ++pa, ++pb;
  53. }
  54. pr_end += x - m;
  55. // Now where only a has digits:
  56. while(pr != pr_end)
  57. {
  58. if(!carry)
  59. {
  60. if(pa != pr)
  61. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
  62. std::copy(pa, pa + (pr_end - pr), stdext::checked_array_iterator<limb_type*>(pr, result.size()));
  63. #else
  64. std::copy(pa, pa + (pr_end - pr), pr);
  65. #endif
  66. break;
  67. }
  68. carry += static_cast<double_limb_type>(*pa);
  69. #ifdef __MSVC_RUNTIME_CHECKS
  70. *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  71. #else
  72. *pr = static_cast<limb_type>(carry);
  73. #endif
  74. carry >>= CppInt1::limb_bits;
  75. ++pr, ++pa;
  76. }
  77. if(carry)
  78. {
  79. // We overflowed, need to add one more limb:
  80. result.resize(x + 1, x + 1);
  81. if(result.size() > x)
  82. result.limbs()[x] = static_cast<limb_type>(carry);
  83. }
  84. result.normalize();
  85. result.sign(a.sign());
  86. }
  87. //
  88. // As above, but for adding a single limb to a non-trivial cpp_int:
  89. //
  90. template <class CppInt1, class CppInt2>
  91. inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
  92. {
  93. // Addition using modular arithmetic.
  94. // Nothing fancy, just let uintmax_t take the strain:
  95. if(&result != &a)
  96. result.resize(a.size(), a.size());
  97. double_limb_type carry = o;
  98. typename CppInt1::limb_pointer pr = result.limbs();
  99. typename CppInt2::const_limb_pointer pa = a.limbs();
  100. unsigned i = 0;
  101. // Addition with carry until we either run out of digits or carry is zero:
  102. for(; carry && (i < result.size()); ++i)
  103. {
  104. carry += static_cast<double_limb_type>(pa[i]);
  105. #ifdef __MSVC_RUNTIME_CHECKS
  106. pr[i] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  107. #else
  108. pr[i] = static_cast<limb_type>(carry);
  109. #endif
  110. carry >>= CppInt1::limb_bits;
  111. }
  112. // Just copy any remaining digits:
  113. if(&a != &result)
  114. {
  115. for(; i < result.size(); ++i)
  116. pr[i] = pa[i];
  117. }
  118. if(carry)
  119. {
  120. // We overflowed, need to add one more limb:
  121. unsigned x = result.size();
  122. result.resize(x + 1, x + 1);
  123. if(result.size() > x)
  124. result.limbs()[x] = static_cast<limb_type>(carry);
  125. }
  126. result.normalize();
  127. result.sign(a.sign());
  128. }
  129. //
  130. // Core subtraction routine for all non-trivial cpp_int's:
  131. //
  132. template <class CppInt1, class CppInt2, class CppInt3>
  133. inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
  134. {
  135. using std::swap;
  136. // Nothing fancy, just let uintmax_t take the strain:
  137. double_limb_type borrow = 0;
  138. unsigned m, x;
  139. minmax(a.size(), b.size(), m, x);
  140. //
  141. // special cases for small limb counts:
  142. //
  143. if(x == 1)
  144. {
  145. bool s = a.sign();
  146. limb_type al = *a.limbs();
  147. limb_type bl = *b.limbs();
  148. if(bl > al)
  149. {
  150. std::swap(al, bl);
  151. s = !s;
  152. }
  153. result = al - bl;
  154. result.sign(s);
  155. return;
  156. }
  157. // This isn't used till later, but comparison has to occur before we resize the result,
  158. // as that may also resize a or b if this is an inplace operation:
  159. int c = a.compare_unsigned(b);
  160. // Set up the result vector:
  161. result.resize(x, x);
  162. // Now that a, b, and result are stable, get pointers to their limbs:
  163. typename CppInt2::const_limb_pointer pa = a.limbs();
  164. typename CppInt3::const_limb_pointer pb = b.limbs();
  165. typename CppInt1::limb_pointer pr = result.limbs();
  166. bool swapped = false;
  167. if(c < 0)
  168. {
  169. swap(pa, pb);
  170. swapped = true;
  171. }
  172. else if(c == 0)
  173. {
  174. result = static_cast<limb_type>(0);
  175. return;
  176. }
  177. unsigned i = 0;
  178. // First where a and b overlap:
  179. while(i < m)
  180. {
  181. borrow = static_cast<double_limb_type>(pa[i]) - static_cast<double_limb_type>(pb[i]) - borrow;
  182. pr[i] = static_cast<limb_type>(borrow);
  183. borrow = (borrow >> CppInt1::limb_bits) & 1u;
  184. ++i;
  185. }
  186. // Now where only a has digits, only as long as we've borrowed:
  187. while(borrow && (i < x))
  188. {
  189. borrow = static_cast<double_limb_type>(pa[i]) - borrow;
  190. pr[i] = static_cast<limb_type>(borrow);
  191. borrow = (borrow >> CppInt1::limb_bits) & 1u;
  192. ++i;
  193. }
  194. // Any remaining digits are the same as those in pa:
  195. if((x != i) && (pa != pr))
  196. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
  197. std::copy(pa + i, pa + x, stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i));
  198. #else
  199. std::copy(pa + i, pa + x, pr + i);
  200. #endif
  201. BOOST_ASSERT(0 == borrow);
  202. //
  203. // We may have lost digits, if so update limb usage count:
  204. //
  205. result.normalize();
  206. result.sign(a.sign());
  207. if(swapped)
  208. result.negate();
  209. }
  210. //
  211. // And again to subtract a single limb:
  212. //
  213. template <class CppInt1, class CppInt2>
  214. inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const limb_type& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
  215. {
  216. // Subtract one limb.
  217. // Nothing fancy, just let uintmax_t take the strain:
  218. BOOST_STATIC_CONSTANT(double_limb_type, borrow = static_cast<double_limb_type>(CppInt1::max_limb_value) + 1);
  219. result.resize(a.size(), a.size());
  220. typename CppInt1::limb_pointer pr = result.limbs();
  221. typename CppInt2::const_limb_pointer pa = a.limbs();
  222. if(*pa >= b)
  223. {
  224. *pr = *pa - b;
  225. if(&result != &a)
  226. {
  227. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
  228. std::copy(pa + 1, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + 1, result.size() - 1));
  229. #else
  230. std::copy(pa + 1, pa + a.size(), pr + 1);
  231. #endif
  232. result.sign(a.sign());
  233. }
  234. else if((result.size() == 1) && (*pr == 0))
  235. {
  236. result.sign(false); // zero is unsigned.
  237. }
  238. }
  239. else if(result.size() == 1)
  240. {
  241. *pr = b - *pa;
  242. result.sign(!a.sign());
  243. }
  244. else
  245. {
  246. *pr = static_cast<limb_type>((borrow + *pa) - b);
  247. unsigned i = 1;
  248. while(!pa[i])
  249. {
  250. pr[i] = CppInt1::max_limb_value;
  251. ++i;
  252. }
  253. pr[i] = pa[i] - 1;
  254. if(&result != &a)
  255. {
  256. ++i;
  257. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
  258. std::copy(pa + i, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i));
  259. #else
  260. std::copy(pa + i, pa + a.size(), pr + i);
  261. #endif
  262. }
  263. result.normalize();
  264. result.sign(a.sign());
  265. }
  266. }
  267. //
  268. // Now the actual functions called by the front end, all of which forward to one of the above:
  269. //
  270. 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>
  271. 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
  272. eval_add(
  273. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  274. 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))
  275. {
  276. eval_add(result, result, o);
  277. }
  278. 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, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
  279. inline 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 && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value >::type
  280. eval_add(
  281. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  282. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  283. const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  284. {
  285. if(a.sign() != b.sign())
  286. {
  287. subtract_unsigned(result, a, b);
  288. return;
  289. }
  290. add_unsigned(result, a, b);
  291. }
  292. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  293. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  294. eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  295. {
  296. if(result.sign())
  297. {
  298. subtract_unsigned(result, result, o);
  299. }
  300. else
  301. add_unsigned(result, result, o);
  302. }
  303. 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>
  304. 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
  305. eval_add(
  306. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  307. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  308. const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  309. {
  310. if(a.sign())
  311. {
  312. subtract_unsigned(result, a, o);
  313. }
  314. else
  315. add_unsigned(result, a, o);
  316. }
  317. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  318. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  319. eval_add(
  320. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  321. const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  322. {
  323. if(o < 0)
  324. eval_subtract(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
  325. else if(o > 0)
  326. eval_add(result, static_cast<limb_type>(o));
  327. }
  328. 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>
  329. 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
  330. eval_add(
  331. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  332. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  333. const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  334. {
  335. if(o < 0)
  336. eval_subtract(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
  337. else if(o > 0)
  338. eval_add(result, a, static_cast<limb_type>(o));
  339. else if(&result != &a)
  340. result = a;
  341. }
  342. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  343. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  344. eval_subtract(
  345. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  346. const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  347. {
  348. if(result.sign())
  349. {
  350. add_unsigned(result, result, o);
  351. }
  352. else
  353. subtract_unsigned(result, result, o);
  354. }
  355. 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>
  356. 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
  357. eval_subtract(
  358. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  359. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  360. const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  361. {
  362. if(a.sign())
  363. {
  364. add_unsigned(result, a, o);
  365. }
  366. else
  367. {
  368. subtract_unsigned(result, a, o);
  369. }
  370. }
  371. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  372. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  373. eval_subtract(
  374. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  375. const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  376. {
  377. if(o)
  378. {
  379. if(o < 0)
  380. eval_add(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
  381. else
  382. eval_subtract(result, static_cast<limb_type>(o));
  383. }
  384. }
  385. 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>
  386. 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
  387. eval_subtract(
  388. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  389. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  390. const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  391. {
  392. if(o)
  393. {
  394. if(o < 0)
  395. eval_add(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
  396. else
  397. eval_subtract(result, a, static_cast<limb_type>(o));
  398. }
  399. else if(&result != &a)
  400. result = a;
  401. }
  402. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  403. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  404. eval_increment(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  405. {
  406. static const limb_type one = 1;
  407. if(!result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
  408. ++result.limbs()[0];
  409. else if (result.sign() && result.limbs()[0])
  410. {
  411. --result.limbs()[0];
  412. if (!result.limbs()[0])
  413. result.sign(false);
  414. }
  415. else
  416. eval_add(result, one);
  417. }
  418. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  419. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  420. eval_decrement(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  421. {
  422. static const limb_type one = 1;
  423. if(!result.sign() && result.limbs()[0])
  424. --result.limbs()[0];
  425. else if (result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
  426. ++result.limbs()[0];
  427. else
  428. eval_subtract(result, one);
  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. 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
  432. eval_subtract(
  433. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  434. 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))
  435. {
  436. eval_subtract(result, result, o);
  437. }
  438. 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, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
  439. 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 && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value >::type
  440. eval_subtract(
  441. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  442. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  443. const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  444. {
  445. if(a.sign() != b.sign())
  446. {
  447. add_unsigned(result, a, b);
  448. return;
  449. }
  450. subtract_unsigned(result, a, b);
  451. }
  452. //
  453. // Simple addition and subtraction routine for trivial cpp_int's come last:
  454. //
  455. // One of the arguments is signed:
  456. //
  457. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  458. inline typename enable_if_c<
  459. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  460. && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  461. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
  462. >::type
  463. eval_add(
  464. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  465. 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))
  466. {
  467. if(result.sign() != o.sign())
  468. {
  469. if(*o.limbs() > *result.limbs())
  470. {
  471. *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  472. result.negate();
  473. }
  474. else
  475. *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  476. }
  477. else
  478. *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  479. result.normalize();
  480. }
  481. // Simple version for two unsigned arguments:
  482. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  483. BOOST_MP_FORCEINLINE typename enable_if_c<
  484. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  485. && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  486. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  487. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  488. >::type
  489. eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  490. 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))
  491. {
  492. *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  493. result.normalize();
  494. }
  495. // signed subtraction:
  496. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  497. inline typename enable_if_c<
  498. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  499. && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  500. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
  501. >::type
  502. eval_subtract(
  503. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  504. 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))
  505. {
  506. if(result.sign() != o.sign())
  507. {
  508. *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  509. }
  510. else if(*result.limbs() < *o.limbs())
  511. {
  512. *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  513. result.negate();
  514. }
  515. else
  516. *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  517. result.normalize();
  518. }
  519. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  520. BOOST_MP_FORCEINLINE typename enable_if_c<
  521. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  522. && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  523. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  524. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  525. >::type
  526. eval_subtract(
  527. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  528. 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))
  529. {
  530. *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  531. result.normalize();
  532. }
  533. #ifdef _MSC_VER
  534. #pragma warning(pop)
  535. #endif
  536. }}} // namespaces
  537. #endif