add.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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. #include <boost/multiprecision/cpp_int/add_unsigned.hpp>
  12. namespace boost { namespace multiprecision { namespace backends {
  13. //
  14. // As above, but for adding a single limb to a non-trivial cpp_int:
  15. //
  16. template <class CppInt1, class CppInt2>
  17. inline BOOST_MP_CXX14_CONSTEXPR void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) noexcept(is_non_throwing_cpp_int<CppInt1>::value)
  18. {
  19. // Addition using modular arithmetic.
  20. // Nothing fancy, just let uintmax_t take the strain:
  21. if (&result != &a)
  22. result.resize(a.size(), a.size());
  23. double_limb_type carry = o;
  24. typename CppInt1::limb_pointer pr = result.limbs();
  25. typename CppInt2::const_limb_pointer pa = a.limbs();
  26. std::size_t i = 0;
  27. // Addition with carry until we either run out of digits or carry is zero:
  28. for (; carry && (i < result.size()); ++i)
  29. {
  30. carry += static_cast<double_limb_type>(pa[i]);
  31. #ifdef __MSVC_RUNTIME_CHECKS
  32. pr[i] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  33. #else
  34. pr[i] = static_cast<limb_type>(carry);
  35. #endif
  36. carry >>= CppInt1::limb_bits;
  37. }
  38. // Just copy any remaining digits:
  39. if (&a != &result)
  40. {
  41. std_constexpr::copy(pa + i, pa + a.size(), pr + i);
  42. }
  43. if (carry)
  44. {
  45. // We overflowed, need to add one more limb:
  46. std::size_t x = result.size();
  47. result.resize(x + 1, x + 1);
  48. if (result.size() > x)
  49. result.limbs()[x] = static_cast<limb_type>(carry);
  50. }
  51. result.normalize();
  52. result.sign(a.sign());
  53. }
  54. //
  55. // And again to subtract a single limb:
  56. //
  57. template <class CppInt1, class CppInt2>
  58. inline BOOST_MP_CXX14_CONSTEXPR void subtract_unsigned(CppInt1& result, const CppInt2& a, const limb_type& b) noexcept(is_non_throwing_cpp_int<CppInt1>::value)
  59. {
  60. // Subtract one limb.
  61. // Nothing fancy, just let uintmax_t take the strain:
  62. constexpr double_limb_type borrow = static_cast<double_limb_type>(CppInt1::max_limb_value) + 1;
  63. result.resize(a.size(), a.size());
  64. typename CppInt1::limb_pointer pr = result.limbs();
  65. typename CppInt2::const_limb_pointer pa = a.limbs();
  66. if (*pa >= b)
  67. {
  68. *pr = *pa - b;
  69. if (&result != &a)
  70. {
  71. std_constexpr::copy(pa + 1, pa + a.size(), pr + 1);
  72. result.sign(a.sign());
  73. }
  74. else if ((result.size() == 1) && (*pr == 0))
  75. {
  76. result.sign(false); // zero is unsigned.
  77. }
  78. }
  79. else if (result.size() == 1)
  80. {
  81. *pr = b - *pa;
  82. result.sign(!a.sign());
  83. }
  84. else
  85. {
  86. *pr = static_cast<limb_type>((borrow + *pa) - b);
  87. std::size_t i = 1;
  88. while (!pa[i])
  89. {
  90. pr[i] = CppInt1::max_limb_value;
  91. ++i;
  92. }
  93. pr[i] = pa[i] - 1;
  94. if (&result != &a)
  95. {
  96. ++i;
  97. std_constexpr::copy(pa + i, pa + a.size(), pr + i);
  98. }
  99. result.normalize();
  100. result.sign(a.sign());
  101. }
  102. }
  103. //
  104. // Now the actual functions called by the front end, all of which forward to one of the above:
  105. //
  106. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  107. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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
  108. eval_add(
  109. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  110. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  111. {
  112. eval_add(result, result, o);
  113. }
  114. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
  115. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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
  116. eval_add(
  117. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  118. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  119. const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  120. {
  121. if (a.sign() != b.sign())
  122. {
  123. subtract_unsigned(result, a, b);
  124. return;
  125. }
  126. add_unsigned(result, a, b);
  127. }
  128. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  129. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  130. eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  131. {
  132. if (result.sign())
  133. {
  134. subtract_unsigned(result, result, o);
  135. }
  136. else
  137. add_unsigned(result, result, o);
  138. }
  139. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  140. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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
  141. eval_add(
  142. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  143. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  144. const limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  145. {
  146. if (a.sign())
  147. {
  148. subtract_unsigned(result, a, o);
  149. }
  150. else
  151. add_unsigned(result, a, o);
  152. }
  153. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  154. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  155. eval_add(
  156. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  157. const signed_limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  158. {
  159. if (o < 0)
  160. eval_subtract(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
  161. else if (o > 0)
  162. eval_add(result, static_cast<limb_type>(o));
  163. }
  164. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  165. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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_add(
  167. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  168. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  169. const signed_limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  170. {
  171. if (o < 0)
  172. eval_subtract(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
  173. else if (o > 0)
  174. eval_add(result, a, static_cast<limb_type>(o));
  175. else if (&result != &a)
  176. result = a;
  177. }
  178. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  179. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  180. eval_subtract(
  181. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  182. const limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  183. {
  184. if (result.sign())
  185. {
  186. add_unsigned(result, result, o);
  187. }
  188. else
  189. subtract_unsigned(result, result, o);
  190. }
  191. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  192. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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
  193. eval_subtract(
  194. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  195. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  196. const limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  197. {
  198. if (a.sign())
  199. {
  200. add_unsigned(result, a, o);
  201. }
  202. else
  203. {
  204. subtract_unsigned(result, a, o);
  205. }
  206. }
  207. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  208. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  209. eval_subtract(
  210. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  211. const signed_limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  212. {
  213. if (o)
  214. {
  215. if (o < 0)
  216. eval_add(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
  217. else
  218. eval_subtract(result, static_cast<limb_type>(o));
  219. }
  220. }
  221. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  222. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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
  223. eval_subtract(
  224. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  225. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  226. const signed_limb_type& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  227. {
  228. if (o)
  229. {
  230. if (o < 0)
  231. eval_add(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
  232. else
  233. eval_subtract(result, a, static_cast<limb_type>(o));
  234. }
  235. else if (&result != &a)
  236. result = a;
  237. }
  238. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  239. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  240. eval_increment(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  241. {
  242. constexpr limb_type one = 1;
  243. if (!result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
  244. ++result.limbs()[0];
  245. else if (result.sign() && result.limbs()[0])
  246. {
  247. --result.limbs()[0];
  248. if (!result.limbs()[0] && (result.size() == 1))
  249. result.sign(false);
  250. }
  251. else
  252. eval_add(result, one);
  253. }
  254. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  255. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  256. eval_decrement(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  257. {
  258. constexpr limb_type one = 1;
  259. if (!result.sign() && result.limbs()[0])
  260. --result.limbs()[0];
  261. else if (result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
  262. ++result.limbs()[0];
  263. else
  264. eval_subtract(result, one);
  265. }
  266. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  267. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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
  268. eval_subtract(
  269. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  270. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  271. {
  272. eval_subtract(result, result, o);
  273. }
  274. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
  275. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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
  276. eval_subtract(
  277. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  278. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  279. const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  280. {
  281. if (a.sign() != b.sign())
  282. {
  283. add_unsigned(result, a, b);
  284. return;
  285. }
  286. subtract_unsigned(result, a, b);
  287. }
  288. //
  289. // Simple addition and subtraction routine for trivial cpp_int's come last:
  290. //
  291. // One of the arguments is signed:
  292. //
  293. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  294. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  295. 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
  296. eval_add(
  297. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  298. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  299. {
  300. if (result.sign() != o.sign())
  301. {
  302. if (*o.limbs() > *result.limbs())
  303. {
  304. *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  305. result.negate();
  306. }
  307. else
  308. *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  309. }
  310. else
  311. *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  312. result.normalize();
  313. }
  314. // Simple version for two unsigned arguments:
  315. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  316. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  317. 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
  318. eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  319. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  320. {
  321. *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  322. result.normalize();
  323. }
  324. // signed subtraction:
  325. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  326. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  327. 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
  328. eval_subtract(
  329. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  330. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  331. {
  332. if (result.sign() != o.sign())
  333. {
  334. *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  335. }
  336. else if (*result.limbs() < *o.limbs())
  337. {
  338. *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  339. result.negate();
  340. }
  341. else
  342. *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  343. result.normalize();
  344. }
  345. template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  346. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  347. 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
  348. eval_subtract(
  349. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  350. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  351. {
  352. *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  353. result.normalize();
  354. }
  355. }}} // namespace boost::multiprecision::backends
  356. #endif