multiply.hpp 23 KB

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