multiply.hpp 25 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 http://www.boost.org/LICENSE_1_
  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 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 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 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 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. static const double_limb_type limb_max = ~static_cast<limb_type>(0u);
  122. static const double_limb_type double_limb_max = ~static_cast<double_limb_type>(0u);
  123. BOOST_STATIC_ASSERT(double_limb_max - 2 * limb_max >= limb_max * limb_max);
  124. double_limb_type carry = 0;
  125. std::memset(pr, 0, result.size() * sizeof(limb_type));
  126. for(unsigned i = 0; i < as; ++i)
  127. {
  128. unsigned inner_limit = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::variable ? bs : (std::min)(result.size() - i, bs);
  129. unsigned j;
  130. for(j = 0; j < inner_limit; ++j)
  131. {
  132. BOOST_ASSERT(i+j < result.size());
  133. #if (!defined(__GLIBCXX__) && !defined(__GLIBCPP__)) || !BOOST_WORKAROUND(BOOST_GCC_VERSION, <= 50100)
  134. BOOST_ASSERT(!std::numeric_limits<double_limb_type>::is_specialized
  135. || ((std::numeric_limits<double_limb_type>::max)() - carry
  136. >
  137. 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)));
  138. #endif
  139. carry += static_cast<double_limb_type>(pa[i]) * static_cast<double_limb_type>(pb[j]);
  140. BOOST_ASSERT(!std::numeric_limits<double_limb_type>::is_specialized || ((std::numeric_limits<double_limb_type>::max)() - carry >= pr[i+j]));
  141. carry += pr[i + j];
  142. #ifdef __MSVC_RUNTIME_CHECKS
  143. pr[i + j] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  144. #else
  145. pr[i + j] = static_cast<limb_type>(carry);
  146. #endif
  147. carry >>= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
  148. BOOST_ASSERT(carry <= (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value));
  149. }
  150. if(carry)
  151. {
  152. resize_for_carry(result, i + j + 1); // May throw if checking is enabled
  153. if(i + j < result.size())
  154. #ifdef __MSVC_RUNTIME_CHECKS
  155. pr[i + j] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  156. #else
  157. pr[i + j] = static_cast<limb_type>(carry);
  158. #endif
  159. }
  160. carry = 0;
  161. }
  162. result.normalize();
  163. //
  164. // Set the sign of the result:
  165. //
  166. result.sign(a.sign() != b.sign());
  167. }
  168. 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>
  169. 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
  170. eval_multiply(
  171. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  172. 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))
  173. {
  174. eval_multiply(result, result, a);
  175. }
  176. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  177. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  178. 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))
  179. {
  180. eval_multiply(result, result, val);
  181. }
  182. 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>
  183. 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
  184. eval_multiply(
  185. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  186. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  187. const double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  188. {
  189. if(val <= (std::numeric_limits<limb_type>::max)())
  190. {
  191. eval_multiply(result, a, static_cast<limb_type>(val));
  192. }
  193. else
  194. {
  195. #if BOOST_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
  196. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(val);
  197. #else
  198. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
  199. t = val;
  200. #endif
  201. eval_multiply(result, a, t);
  202. }
  203. }
  204. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  205. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  206. 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))
  207. {
  208. eval_multiply(result, result, val);
  209. }
  210. 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>
  211. 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
  212. eval_multiply(
  213. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  214. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  215. const signed_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  216. {
  217. if(val > 0)
  218. eval_multiply(result, a, static_cast<limb_type>(val));
  219. else
  220. {
  221. eval_multiply(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(val)));
  222. result.negate();
  223. }
  224. }
  225. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  226. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  227. 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))
  228. {
  229. eval_multiply(result, result, val);
  230. }
  231. 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>
  232. 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 >::type
  233. eval_multiply(
  234. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  235. const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
  236. const signed_double_limb_type& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
  237. {
  238. if(val > 0)
  239. {
  240. if(val <= (std::numeric_limits<limb_type>::max)())
  241. {
  242. eval_multiply(result, a, static_cast<limb_type>(val));
  243. return;
  244. }
  245. }
  246. else if(val >= -static_cast<signed_double_limb_type>((std::numeric_limits<limb_type>::max)()))
  247. {
  248. eval_multiply(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(val)));
  249. result.negate();
  250. return;
  251. }
  252. #if BOOST_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
  253. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(val);
  254. #else
  255. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
  256. t = val;
  257. #endif
  258. eval_multiply(result, a, t);
  259. }
  260. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  261. BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
  262. 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))
  263. {
  264. eval_multiply(result, result, val);
  265. }
  266. //
  267. // Now over again for trivial cpp_int's:
  268. //
  269. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  270. BOOST_MP_FORCEINLINE typename enable_if_c<
  271. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  272. && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  273. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  274. || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
  275. >::type
  276. eval_multiply(
  277. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  278. 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))
  279. {
  280. *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  281. result.sign(result.sign() != o.sign());
  282. result.normalize();
  283. }
  284. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  285. BOOST_MP_FORCEINLINE typename enable_if_c<
  286. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  287. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  288. >::type
  289. eval_multiply(
  290. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  291. 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))
  292. {
  293. *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  294. result.normalize();
  295. }
  296. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  297. BOOST_MP_FORCEINLINE typename enable_if_c<
  298. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  299. && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  300. && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  301. || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
  302. >::type
  303. eval_multiply(
  304. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  305. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  306. 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))
  307. {
  308. *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  309. result.sign(a.sign() != b.sign());
  310. result.normalize();
  311. }
  312. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  313. BOOST_MP_FORCEINLINE typename enable_if_c<
  314. is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  315. && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  316. >::type
  317. eval_multiply(
  318. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  319. const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
  320. 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))
  321. {
  322. *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
  323. result.normalize();
  324. }
  325. //
  326. // Special routines for multiplying two integers to obtain a multiprecision result:
  327. //
  328. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  329. BOOST_MP_FORCEINLINE typename enable_if_c<
  330. !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  331. >::type
  332. eval_multiply(
  333. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  334. signed_double_limb_type a, signed_double_limb_type b)
  335. {
  336. static const signed_double_limb_type mask = ~static_cast<limb_type>(0);
  337. static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
  338. bool s = false;
  339. double_limb_type w, x, y, z;
  340. if(a < 0)
  341. {
  342. a = -a;
  343. s = true;
  344. }
  345. if(b < 0)
  346. {
  347. b = -b;
  348. s = !s;
  349. }
  350. w = a & mask;
  351. x = a >> limb_bits;
  352. y = b & mask;
  353. z = b >> limb_bits;
  354. result.resize(4, 4);
  355. limb_type* pr = result.limbs();
  356. double_limb_type carry = w * y;
  357. #ifdef __MSVC_RUNTIME_CHECKS
  358. pr[0] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  359. carry >>= limb_bits;
  360. carry += w * z + x * y;
  361. pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  362. carry >>= limb_bits;
  363. carry += x * z;
  364. pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  365. pr[3] = static_cast<limb_type>(carry >> limb_bits);
  366. #else
  367. pr[0] = static_cast<limb_type>(carry);
  368. carry >>= limb_bits;
  369. carry += w * z + x * y;
  370. pr[1] = static_cast<limb_type>(carry);
  371. carry >>= limb_bits;
  372. carry += x * z;
  373. pr[2] = static_cast<limb_type>(carry);
  374. pr[3] = static_cast<limb_type>(carry >> limb_bits);
  375. #endif
  376. result.sign(s);
  377. result.normalize();
  378. }
  379. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
  380. BOOST_MP_FORCEINLINE typename enable_if_c<
  381. !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  382. >::type
  383. eval_multiply(
  384. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  385. double_limb_type a, double_limb_type b)
  386. {
  387. static const signed_double_limb_type mask = ~static_cast<limb_type>(0);
  388. static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
  389. double_limb_type w, x, y, z;
  390. w = a & mask;
  391. x = a >> limb_bits;
  392. y = b & mask;
  393. z = b >> limb_bits;
  394. result.resize(4, 4);
  395. limb_type* pr = result.limbs();
  396. double_limb_type carry = w * y;
  397. #ifdef __MSVC_RUNTIME_CHECKS
  398. pr[0] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  399. carry >>= limb_bits;
  400. carry += w * z;
  401. pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  402. carry >>= limb_bits;
  403. pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  404. carry = x * y + pr[1];
  405. pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  406. carry >>= limb_bits;
  407. carry += pr[2] + x * z;
  408. pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
  409. pr[3] = static_cast<limb_type>(carry >> limb_bits);
  410. #else
  411. pr[0] = static_cast<limb_type>(carry);
  412. carry >>= limb_bits;
  413. carry += w * z;
  414. pr[1] = static_cast<limb_type>(carry);
  415. carry >>= limb_bits;
  416. pr[2] = static_cast<limb_type>(carry);
  417. carry = x * y + pr[1];
  418. pr[1] = static_cast<limb_type>(carry);
  419. carry >>= limb_bits;
  420. carry += pr[2] + x * z;
  421. pr[2] = static_cast<limb_type>(carry);
  422. pr[3] = static_cast<limb_type>(carry >> limb_bits);
  423. #endif
  424. result.sign(false);
  425. result.normalize();
  426. }
  427. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1,
  428. unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
  429. BOOST_MP_FORCEINLINE typename enable_if_c<
  430. !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
  431. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  432. && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
  433. >::type
  434. eval_multiply(
  435. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  436. cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> const& a,
  437. cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> const& b)
  438. {
  439. 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;
  440. eval_multiply(result, static_cast<canonical_type>(*a.limbs()), static_cast<canonical_type>(*b.limbs()));
  441. result.sign(a.sign() != b.sign());
  442. }
  443. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class SI>
  444. BOOST_MP_FORCEINLINE typename enable_if_c<is_signed<SI>::value && (sizeof(SI) <= sizeof(signed_double_limb_type) / 2)>::type
  445. eval_multiply(
  446. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  447. SI a, SI b)
  448. {
  449. result = static_cast<signed_double_limb_type>(a) * static_cast<signed_double_limb_type>(b);
  450. }
  451. template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class UI>
  452. BOOST_MP_FORCEINLINE typename enable_if_c<is_unsigned<UI>::value && (sizeof(UI) <= sizeof(signed_double_limb_type) / 2)>::type
  453. eval_multiply(
  454. cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
  455. UI a, UI b)
  456. {
  457. result = static_cast<double_limb_type>(a) * static_cast<double_limb_type>(b);
  458. }
  459. #ifdef _MSC_VER
  460. #pragma warning(pop)
  461. #endif
  462. }}} // namespaces
  463. #endif