annotate DEPENDENCIES/generic/include/boost/multiprecision/cpp_int/multiply.hpp @ 125:34e428693f5d vext

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