multiply.hpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  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_MUL_HPP
  9. #define BOOST_MP_CPP_INT_MUL_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. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  16. 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>::type
  17. eval_multiply(
  18. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  19. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  20. const limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  21. {
  22. if (!val)
  23. {
  24. result = static_cast<limb_type>(0);
  25. return;
  26. }
  27. if ((void*)&a != (void*)&result)
  28. result.resize(a.size(), a.size());
  29. double_limb_type carry = 0;
  30. typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer p = result.limbs();
  31. typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pe = result.limbs() + result.size();
  32. typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer pa = a.limbs();
  33. while (p != pe)
  34. {
  35. carry += static_cast<double_limb_type>(*pa) * static_cast<double_limb_type>(val);
  36. #ifdef __MSVC_RUNTIME_CHECKS
  37. *p = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  38. #else
  39. *p = static_cast<limb_type>(carry);
  40. #endif
  41. carry >>= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  42. ++p, ++pa;
  43. }
  44. if (carry)
  45. {
  46. unsigned i = result.size();
  47. result.resize(i + 1, i + 1);
  48. if (result.size() > i)
  49. result.limbs()[i] = static_cast<limb_type>(carry);
  50. }
  51. result.sign(a.sign());
  52. if (!cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::variable)
  53. result.normalize();
  54. }
  55. //
  56. // resize_for_carry forces a resize of the underlying buffer only if a previous request
  57. // for "required" elements could possibly have failed, *and* we have checking enabled.
  58. // This will cause an overflow error inside resize():
  59. //
  60. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  61. inline BOOST_MP_CXX14_CONSTEXPR void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& /*result*/, unsigned /*required*/) {}
  62. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, class Allocator1>
  63. inline BOOST_MP_CXX14_CONSTEXPR void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, checked, Allocator1>& result, unsigned required)
  64. {
  65. if (result.size() < required)
  66. result.resize(required, required);
  67. }
  68. 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>
  69. 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
  70. eval_multiply(
  71. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  72. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  73. 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))
  74. {
  75. // Very simple long multiplication, only usable for small numbers of limb_type's
  76. // but that's the typical use case for this type anyway:
  77. //
  78. // Special cases first:
  79. //
  80. unsigned as = a.size();
  81. unsigned bs = b.size();
  82. typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer pa = a.limbs();
  83. typename cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>::const_limb_pointer pb = b.limbs();
  84. if (as == 1)
  85. {
  86. bool s = b.sign() != a.sign();
  87. if (bs == 1)
  88. {
  89. result = static_cast<double_limb_type>(*pa) * static_cast<double_limb_type>(*pb);
  90. }
  91. else
  92. {
  93. limb_type l = *pa;
  94. eval_multiply(result, b, l);
  95. }
  96. result.sign(s);
  97. return;
  98. }
  99. if (bs == 1)
  100. {
  101. bool s = b.sign() != a.sign();
  102. limb_type l = *pb;
  103. eval_multiply(result, a, l);
  104. result.sign(s);
  105. return;
  106. }
  107. if ((void*)&result == (void*)&a)
  108. {
  109. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(a);
  110. eval_multiply(result, t, b);
  111. return;
  112. }
  113. if ((void*)&result == (void*)&b)
  114. {
  115. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(b);
  116. eval_multiply(result, a, t);
  117. return;
  118. }
  119. result.resize(as + bs, as + bs - 1);
  120. typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pr = result.limbs();
  121. #ifdef BOOST_NO_CXX14_CONSTEXPR
  122. static const double_limb_type limb_max = ~static_cast<limb_type>(0u);
  123. static const double_limb_type double_limb_max = ~static_cast<double_limb_type>(0u);
  124. #else
  125. constexpr const double_limb_type limb_max = ~static_cast<limb_type>(0u);
  126. constexpr const double_limb_type double_limb_max = ~static_cast<double_limb_type>(0u);
  127. #endif
  128. BOOST_STATIC_ASSERT(double_limb_max - 2 * limb_max >= limb_max * limb_max);
  129. double_limb_type carry = 0;
  130. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  131. if (BOOST_MP_IS_CONST_EVALUATED(as))
  132. {
  133. for (unsigned i = 0; i < result.size(); ++i)
  134. pr[i] = 0;
  135. }
  136. else
  137. #endif
  138. std::memset(pr, 0, result.size() * sizeof(limb_type));
  139. for (unsigned i = 0; i < as; ++i)
  140. {
  141. unsigned inner_limit = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::variable ? bs : (std::min)(result.size() - i, bs);
  142. unsigned j = 0;
  143. for (; j < inner_limit; ++j)
  144. {
  145. BOOST_ASSERT(i + j < result.size());
  146. #if (!defined(__GLIBCXX__) && !defined(__GLIBCPP__)) || !BOOST_WORKAROUND(BOOST_GCC_VERSION, <= 50100)
  147. BOOST_ASSERT(!std::numeric_limits<double_limb_type>::is_specialized || ((std::numeric_limits<double_limb_type>::max)() - carry >
  148. static_cast<double_limb_type>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value) * static_cast<double_limb_type>(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value)));
  149. #endif
  150. carry += static_cast<double_limb_type>(pa[i]) * static_cast<double_limb_type>(pb[j]);
  151. BOOST_ASSERT(!std::numeric_limits<double_limb_type>::is_specialized || ((std::numeric_limits<double_limb_type>::max)() - carry >= pr[i + j]));
  152. carry += pr[i + j];
  153. #ifdef __MSVC_RUNTIME_CHECKS
  154. pr[i + j] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  155. #else
  156. pr[i + j] = static_cast<limb_type>(carry);
  157. #endif
  158. carry >>= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  159. BOOST_ASSERT(carry <= (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value));
  160. }
  161. if (carry)
  162. {
  163. resize_for_carry(result, i + j + 1); // May throw if checking is enabled
  164. if (i + j < result.size())
  165. #ifdef __MSVC_RUNTIME_CHECKS
  166. pr[i + j] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  167. #else
  168. pr[i + j] = static_cast<limb_type>(carry);
  169. #endif
  170. }
  171. carry = 0;
  172. }
  173. result.normalize();
  174. //
  175. // Set the sign of the result:
  176. //
  177. result.sign(a.sign() != b.sign());
  178. }
  179. 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>
  180. 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
  181. eval_multiply(
  182. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  183. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  184. {
  185. eval_multiply(result, result, a);
  186. }
  187. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  188. 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
  189. eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  190. {
  191. eval_multiply(result, result, val);
  192. }
  193. 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>
  194. 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
  195. eval_multiply(
  196. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  197. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  198. const double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  199. {
  200. if (val <= (std::numeric_limits<limb_type>::max)())
  201. {
  202. eval_multiply(result, a, static_cast<limb_type>(val));
  203. }
  204. else
  205. {
  206. #if BOOST_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
  207. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(val);
  208. #else
  209. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
  210. t = val;
  211. #endif
  212. eval_multiply(result, a, t);
  213. }
  214. }
  215. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  216. 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
  217. eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  218. {
  219. eval_multiply(result, result, val);
  220. }
  221. 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>
  222. 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
  223. eval_multiply(
  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& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  227. {
  228. if (val > 0)
  229. eval_multiply(result, a, static_cast<limb_type>(val));
  230. else
  231. {
  232. eval_multiply(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(val)));
  233. result.negate();
  234. }
  235. }
  236. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  237. 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
  238. eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const signed_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  239. {
  240. eval_multiply(result, result, val);
  241. }
  242. 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>
  243. 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>::type
  244. eval_multiply(
  245. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  246. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  247. const signed_double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  248. {
  249. if (val > 0)
  250. {
  251. if (val <= (std::numeric_limits<limb_type>::max)())
  252. {
  253. eval_multiply(result, a, static_cast<limb_type>(val));
  254. return;
  255. }
  256. }
  257. else if (val >= -static_cast<signed_double_limb_type>((std::numeric_limits<limb_type>::max)()))
  258. {
  259. eval_multiply(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(val)));
  260. result.negate();
  261. return;
  262. }
  263. #if BOOST_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
  264. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(val);
  265. #else
  266. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
  267. t = val;
  268. #endif
  269. eval_multiply(result, a, t);
  270. }
  271. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  272. 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
  273. eval_multiply(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const signed_double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  274. {
  275. eval_multiply(result, result, val);
  276. }
  277. //
  278. // Now over again for trivial cpp_int's:
  279. //
  280. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  281. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  282. 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
  283. eval_multiply(
  284. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  285. 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))
  286. {
  287. *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  288. result.sign(result.sign() != o.sign());
  289. result.normalize();
  290. }
  291. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  292. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  293. 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>::type
  294. eval_multiply(
  295. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  296. 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))
  297. {
  298. *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  299. result.normalize();
  300. }
  301. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  302. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  303. 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
  304. eval_multiply(
  305. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  306. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  307. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  308. {
  309. *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  310. result.sign(a.sign() != b.sign());
  311. result.normalize();
  312. }
  313. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  314. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  315. 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>::type
  316. eval_multiply(
  317. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  318. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  319. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  320. {
  321. *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  322. result.normalize();
  323. }
  324. //
  325. // Special routines for multiplying two integers to obtain a multiprecision result:
  326. //
  327. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  328. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  329. !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  330. eval_multiply(
  331. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  332. signed_double_limb_type a, signed_double_limb_type b)
  333. {
  334. #ifdef BOOST_NO_CXX14_CONSTEXPR
  335. static const signed_double_limb_type mask = ~static_cast<limb_type>(0);
  336. static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
  337. #else
  338. constexpr const signed_double_limb_type mask = ~static_cast<limb_type>(0);
  339. constexpr const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
  340. #endif
  341. bool s = false;
  342. if (a < 0)
  343. {
  344. a = -a;
  345. s = true;
  346. }
  347. if (b < 0)
  348. {
  349. b = -b;
  350. s = !s;
  351. }
  352. double_limb_type w = a & mask;
  353. double_limb_type x = a >> limb_bits;
  354. double_limb_type y = b & mask;
  355. double_limb_type z = b >> limb_bits;
  356. result.resize(4, 4);
  357. limb_type* pr = result.limbs();
  358. double_limb_type carry = w * y;
  359. #ifdef __MSVC_RUNTIME_CHECKS
  360. pr[0] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  361. carry >>= limb_bits;
  362. carry += w * z + x * y;
  363. pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  364. carry >>= limb_bits;
  365. carry += x * z;
  366. pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  367. pr[3] = static_cast<limb_type>(carry >> limb_bits);
  368. #else
  369. pr[0] = static_cast<limb_type>(carry);
  370. carry >>= limb_bits;
  371. carry += w * z + x * y;
  372. pr[1] = static_cast<limb_type>(carry);
  373. carry >>= limb_bits;
  374. carry += x * z;
  375. pr[2] = static_cast<limb_type>(carry);
  376. pr[3] = static_cast<limb_type>(carry >> limb_bits);
  377. #endif
  378. result.sign(s);
  379. result.normalize();
  380. }
  381. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  382. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  383. !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  384. eval_multiply(
  385. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  386. double_limb_type a, double_limb_type b)
  387. {
  388. #ifdef BOOST_NO_CXX14_CONSTEXPR
  389. static const signed_double_limb_type mask = ~static_cast<limb_type>(0);
  390. static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
  391. #else
  392. constexpr const signed_double_limb_type mask = ~static_cast<limb_type>(0);
  393. constexpr const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
  394. #endif
  395. double_limb_type w = a & mask;
  396. double_limb_type x = a >> limb_bits;
  397. double_limb_type y = b & mask;
  398. double_limb_type z = b >> limb_bits;
  399. result.resize(4, 4);
  400. limb_type* pr = result.limbs();
  401. double_limb_type carry = w * y;
  402. #ifdef __MSVC_RUNTIME_CHECKS
  403. pr[0] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  404. carry >>= limb_bits;
  405. carry += w * z;
  406. pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  407. carry >>= limb_bits;
  408. pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  409. carry = x * y + pr[1];
  410. pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  411. carry >>= limb_bits;
  412. carry += pr[2] + x * z;
  413. pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  414. pr[3] = static_cast<limb_type>(carry >> limb_bits);
  415. #else
  416. pr[0] = static_cast<limb_type>(carry);
  417. carry >>= limb_bits;
  418. carry += w * z;
  419. pr[1] = static_cast<limb_type>(carry);
  420. carry >>= limb_bits;
  421. pr[2] = static_cast<limb_type>(carry);
  422. carry = x * y + pr[1];
  423. pr[1] = static_cast<limb_type>(carry);
  424. carry >>= limb_bits;
  425. carry += pr[2] + x * z;
  426. pr[2] = static_cast<limb_type>(carry);
  427. pr[3] = static_cast<limb_type>(carry >> limb_bits);
  428. #endif
  429. result.sign(false);
  430. result.normalize();
  431. }
  432. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1,
  433. unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  434. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  435. !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<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
  436. eval_multiply(
  437. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  438. cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> const& a,
  439. cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> const& b)
  440. {
  441. typedef typename boost::multiprecision::detail::canonical<typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::local_limb_type, cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::type canonical_type;
  442. eval_multiply(result, static_cast<canonical_type>(*a.limbs()), static_cast<canonical_type>(*b.limbs()));
  443. result.sign(a.sign() != b.sign());
  444. }
  445. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class SI>
  446. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_signed<SI>::value && (sizeof(SI) <= sizeof(signed_double_limb_type) / 2)>::type
  447. eval_multiply(
  448. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  449. SI a, SI b)
  450. {
  451. result = static_cast<signed_double_limb_type>(a) * static_cast<signed_double_limb_type>(b);
  452. }
  453. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class UI>
  454. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_unsigned<UI>::value && (sizeof(UI) <= sizeof(signed_double_limb_type) / 2)>::type
  455. eval_multiply(
  456. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  457. UI a, UI b)
  458. {
  459. result = static_cast<double_limb_type>(a) * static_cast<double_limb_type>(b);
  460. }
  461. #ifdef _MSC_VER
  462. #pragma warning(pop)
  463. #endif
  464. }}} // namespace boost::multiprecision::backends
  465. #endif