add.hpp 27 KB

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