annotate DEPENDENCIES/generic/include/boost/multiprecision/cpp_int/add.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_ADD_HPP
Chris@16 9 #define BOOST_MP_CPP_INT_ADD_HPP
Chris@16 10
Chris@16 11 namespace boost{ namespace multiprecision{ namespace backends{
Chris@16 12
Chris@16 13 //
Chris@16 14 // This is the key addition routine where all the argument types are non-trivial cpp_int's:
Chris@16 15 //
Chris@16 16 template <class CppInt1, class CppInt2, class CppInt3>
Chris@16 17 inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
Chris@16 18 {
Chris@16 19 using std::swap;
Chris@16 20
Chris@16 21 // Nothing fancy, just let uintmax_t take the strain:
Chris@16 22 double_limb_type carry = 0;
Chris@16 23 unsigned m, x;
Chris@16 24 unsigned as = a.size();
Chris@16 25 unsigned bs = b.size();
Chris@16 26 minmax(as, bs, m, x);
Chris@16 27 if(x == 1)
Chris@16 28 {
Chris@16 29 bool s = a.sign();
Chris@16 30 result = static_cast<double_limb_type>(*a.limbs()) + static_cast<double_limb_type>(*b.limbs());
Chris@16 31 result.sign(s);
Chris@16 32 return;
Chris@16 33 }
Chris@16 34 result.resize(x, x);
Chris@16 35 typename CppInt2::const_limb_pointer pa = a.limbs();
Chris@16 36 typename CppInt3::const_limb_pointer pb = b.limbs();
Chris@16 37 typename CppInt1::limb_pointer pr = result.limbs();
Chris@16 38 typename CppInt1::limb_pointer pr_end = pr + m;
Chris@16 39
Chris@16 40 if(as < bs)
Chris@16 41 swap(pa, pb);
Chris@16 42
Chris@16 43 // First where a and b overlap:
Chris@16 44 while(pr != pr_end)
Chris@16 45 {
Chris@16 46 carry += static_cast<double_limb_type>(*pa) + static_cast<double_limb_type>(*pb);
Chris@16 47 *pr = static_cast<limb_type>(carry);
Chris@16 48 carry >>= CppInt1::limb_bits;
Chris@16 49 ++pr, ++pa, ++pb;
Chris@16 50 }
Chris@16 51 pr_end += x - m;
Chris@16 52 // Now where only a has digits:
Chris@16 53 while(pr != pr_end)
Chris@16 54 {
Chris@16 55 if(!carry)
Chris@16 56 {
Chris@16 57 if(pa != pr)
Chris@16 58 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 59 std::copy(pa, pa + (pr_end - pr), stdext::checked_array_iterator<limb_type*>(pr, result.size()));
Chris@16 60 #else
Chris@16 61 std::copy(pa, pa + (pr_end - pr), pr);
Chris@16 62 #endif
Chris@16 63 break;
Chris@16 64 }
Chris@16 65 carry += static_cast<double_limb_type>(*pa);
Chris@16 66 *pr = static_cast<limb_type>(carry);
Chris@16 67 carry >>= CppInt1::limb_bits;
Chris@16 68 ++pr, ++pa;
Chris@16 69 }
Chris@16 70 if(carry)
Chris@16 71 {
Chris@16 72 // We overflowed, need to add one more limb:
Chris@16 73 result.resize(x + 1, x + 1);
Chris@16 74 if(CppInt1::variable || (result.size() > x))
Chris@16 75 result.limbs()[x] = static_cast<limb_type>(carry);
Chris@16 76 }
Chris@16 77 result.normalize();
Chris@16 78 result.sign(a.sign());
Chris@16 79 }
Chris@16 80 //
Chris@16 81 // As above, but for adding a single limb to a non-trivial cpp_int:
Chris@16 82 //
Chris@16 83 template <class CppInt1, class CppInt2>
Chris@16 84 inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) BOOST_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
Chris@16 85 {
Chris@16 86 // Addition using modular arithmetic.
Chris@16 87 // Nothing fancy, just let uintmax_t take the strain:
Chris@16 88 if(&result != &a)
Chris@16 89 result.resize(a.size(), a.size());
Chris@16 90 double_limb_type carry = o;
Chris@16 91 typename CppInt1::limb_pointer pr = result.limbs();
Chris@16 92 typename CppInt2::const_limb_pointer pa = a.limbs();
Chris@16 93 unsigned i = 0;
Chris@16 94 // Addition with carry until we either run out of digits or carry is zero:
Chris@16 95 for(; carry && (i < result.size()); ++i)
Chris@16 96 {
Chris@16 97 carry += static_cast<double_limb_type>(pa[i]);
Chris@16 98 pr[i] = static_cast<limb_type>(carry);
Chris@16 99 carry >>= CppInt1::limb_bits;
Chris@16 100 }
Chris@16 101 // Just copy any remaining digits:
Chris@16 102 if(&a != &result)
Chris@16 103 {
Chris@16 104 for(; i < result.size(); ++i)
Chris@16 105 pr[i] = pa[i];
Chris@16 106 }
Chris@16 107 if(carry)
Chris@16 108 {
Chris@16 109 // We overflowed, need to add one more limb:
Chris@16 110 unsigned x = result.size();
Chris@16 111 result.resize(x + 1, x + 1);
Chris@16 112 if(CppInt1::variable || (result.size() > x))
Chris@16 113 result.limbs()[x] = static_cast<limb_type>(carry);
Chris@16 114 }
Chris@16 115 result.normalize();
Chris@16 116 result.sign(a.sign());
Chris@16 117 }
Chris@16 118 //
Chris@16 119 // Core subtraction routine for all non-trivial cpp_int's:
Chris@16 120 //
Chris@16 121 template <class CppInt1, class CppInt2, class CppInt3>
Chris@16 122 inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
Chris@16 123 {
Chris@16 124 using std::swap;
Chris@16 125
Chris@16 126 // Nothing fancy, just let uintmax_t take the strain:
Chris@16 127 double_limb_type borrow = 0;
Chris@16 128 unsigned m, x;
Chris@16 129 minmax(a.size(), b.size(), m, x);
Chris@16 130 //
Chris@16 131 // special cases for small limb counts:
Chris@16 132 //
Chris@16 133 if(x == 1)
Chris@16 134 {
Chris@16 135 bool s = a.sign();
Chris@16 136 limb_type al = *a.limbs();
Chris@16 137 limb_type bl = *b.limbs();
Chris@16 138 if(bl > al)
Chris@16 139 {
Chris@16 140 std::swap(al, bl);
Chris@16 141 s = !s;
Chris@16 142 }
Chris@16 143 result = al - bl;
Chris@16 144 result.sign(s);
Chris@16 145 return;
Chris@16 146 }
Chris@16 147 // This isn't used till later, but comparison has to occur before we resize the result,
Chris@16 148 // as that may also resize a or b if this is an inplace operation:
Chris@16 149 int c = a.compare_unsigned(b);
Chris@16 150 // Set up the result vector:
Chris@16 151 result.resize(x, x);
Chris@16 152 // Now that a, b, and result are stable, get pointers to their limbs:
Chris@16 153 typename CppInt2::const_limb_pointer pa = a.limbs();
Chris@16 154 typename CppInt3::const_limb_pointer pb = b.limbs();
Chris@16 155 typename CppInt1::limb_pointer pr = result.limbs();
Chris@16 156 bool swapped = false;
Chris@16 157 if(c < 0)
Chris@16 158 {
Chris@16 159 swap(pa, pb);
Chris@16 160 swapped = true;
Chris@16 161 }
Chris@16 162 else if(c == 0)
Chris@16 163 {
Chris@16 164 result = static_cast<limb_type>(0);
Chris@16 165 return;
Chris@16 166 }
Chris@16 167
Chris@16 168 unsigned i = 0;
Chris@16 169 // First where a and b overlap:
Chris@16 170 while(i < m)
Chris@16 171 {
Chris@16 172 borrow = static_cast<double_limb_type>(pa[i]) - static_cast<double_limb_type>(pb[i]) - borrow;
Chris@16 173 pr[i] = static_cast<limb_type>(borrow);
Chris@16 174 borrow = (borrow >> CppInt1::limb_bits) & 1u;
Chris@16 175 ++i;
Chris@16 176 }
Chris@16 177 // Now where only a has digits, only as long as we've borrowed:
Chris@16 178 while(borrow && (i < x))
Chris@16 179 {
Chris@16 180 borrow = static_cast<double_limb_type>(pa[i]) - borrow;
Chris@16 181 pr[i] = static_cast<limb_type>(borrow);
Chris@16 182 borrow = (borrow >> CppInt1::limb_bits) & 1u;
Chris@16 183 ++i;
Chris@16 184 }
Chris@16 185 // Any remaining digits are the same as those in pa:
Chris@16 186 if((x != i) && (pa != pr))
Chris@16 187 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 188 std::copy(pa + i, pa + x, stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i));
Chris@16 189 #else
Chris@16 190 std::copy(pa + i, pa + x, pr + i);
Chris@16 191 #endif
Chris@16 192 BOOST_ASSERT(0 == borrow);
Chris@16 193
Chris@16 194 //
Chris@16 195 // We may have lost digits, if so update limb usage count:
Chris@16 196 //
Chris@16 197 result.normalize();
Chris@16 198 result.sign(a.sign());
Chris@16 199 if(swapped)
Chris@16 200 result.negate();
Chris@16 201 }
Chris@16 202 //
Chris@16 203 // And again to subtract a single limb:
Chris@16 204 //
Chris@16 205 template <class CppInt1, class CppInt2>
Chris@16 206 inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const limb_type& b) BOOST_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
Chris@16 207 {
Chris@16 208 // Subtract one limb.
Chris@16 209 // Nothing fancy, just let uintmax_t take the strain:
Chris@16 210 BOOST_STATIC_CONSTANT(double_limb_type, borrow = static_cast<double_limb_type>(CppInt1::max_limb_value) + 1);
Chris@16 211 result.resize(a.size(), a.size());
Chris@16 212 typename CppInt1::limb_pointer pr = result.limbs();
Chris@16 213 typename CppInt2::const_limb_pointer pa = a.limbs();
Chris@16 214 if(*pa >= b)
Chris@16 215 {
Chris@16 216 *pr = *pa - b;
Chris@16 217 if(&result != &a)
Chris@16 218 {
Chris@16 219 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 220 std::copy(pa + 1, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + 1, result.size() - 1));
Chris@16 221 #else
Chris@16 222 std::copy(pa + 1, pa + a.size(), pr + 1);
Chris@16 223 #endif
Chris@16 224 result.sign(a.sign());
Chris@16 225 }
Chris@16 226 else if((result.size() == 1) && (*pr == 0))
Chris@16 227 {
Chris@16 228 result.sign(false); // zero is unsigned.
Chris@16 229 }
Chris@16 230 }
Chris@16 231 else if(result.size() == 1)
Chris@16 232 {
Chris@16 233 *pr = b - *pa;
Chris@16 234 result.sign(!a.sign());
Chris@16 235 }
Chris@16 236 else
Chris@16 237 {
Chris@16 238 *pr = static_cast<limb_type>((borrow + *pa) - b);
Chris@16 239 unsigned i = 1;
Chris@16 240 while(!pa[i])
Chris@16 241 {
Chris@16 242 pr[i] = CppInt1::max_limb_value;
Chris@16 243 ++i;
Chris@16 244 }
Chris@16 245 pr[i] = pa[i] - 1;
Chris@16 246 if(&result != &a)
Chris@16 247 {
Chris@16 248 ++i;
Chris@16 249 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 250 std::copy(pa + i, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i));
Chris@16 251 #else
Chris@16 252 std::copy(pa + i, pa + a.size(), pr + i);
Chris@16 253 #endif
Chris@16 254 }
Chris@16 255 result.normalize();
Chris@16 256 result.sign(a.sign());
Chris@16 257 }
Chris@16 258 }
Chris@16 259
Chris@16 260 //
Chris@16 261 // Now the actual functions called by the front end, all of which forward to one of the above:
Chris@16 262 //
Chris@16 263 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 264 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 265 eval_add(
Chris@16 266 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 267 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 268 {
Chris@16 269 eval_add(result, result, o);
Chris@16 270 }
Chris@16 271 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 272 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 273 eval_add(
Chris@16 274 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 275 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
Chris@16 276 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 277 {
Chris@16 278 if(a.sign() != b.sign())
Chris@16 279 {
Chris@16 280 subtract_unsigned(result, a, b);
Chris@16 281 return;
Chris@16 282 }
Chris@16 283 add_unsigned(result, a, b);
Chris@16 284 }
Chris@16 285 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 286 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
Chris@16 287 eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 288 {
Chris@16 289 if(result.sign())
Chris@16 290 {
Chris@16 291 subtract_unsigned(result, result, o);
Chris@16 292 }
Chris@16 293 else
Chris@16 294 add_unsigned(result, result, o);
Chris@16 295 }
Chris@16 296 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 297 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 298 eval_add(
Chris@16 299 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 300 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
Chris@16 301 const limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 302 {
Chris@16 303 if(a.sign())
Chris@16 304 {
Chris@16 305 subtract_unsigned(result, a, o);
Chris@16 306 }
Chris@16 307 else
Chris@16 308 add_unsigned(result, a, o);
Chris@16 309 }
Chris@16 310 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 311 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
Chris@16 312 eval_add(
Chris@16 313 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 314 const signed_limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 315 {
Chris@16 316 if(o < 0)
Chris@101 317 eval_subtract(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
Chris@16 318 else if(o > 0)
Chris@16 319 eval_add(result, static_cast<limb_type>(o));
Chris@16 320 }
Chris@16 321 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 322 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 323 eval_add(
Chris@16 324 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 325 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
Chris@16 326 const signed_limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 327 {
Chris@16 328 if(o < 0)
Chris@101 329 eval_subtract(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
Chris@16 330 else if(o > 0)
Chris@16 331 eval_add(result, a, static_cast<limb_type>(o));
Chris@16 332 else if(&result != &a)
Chris@16 333 result = a;
Chris@16 334 }
Chris@16 335 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 336 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
Chris@16 337 eval_subtract(
Chris@16 338 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 339 const limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 340 {
Chris@16 341 if(result.sign())
Chris@16 342 {
Chris@16 343 add_unsigned(result, result, o);
Chris@16 344 }
Chris@16 345 else
Chris@16 346 subtract_unsigned(result, result, o);
Chris@16 347 }
Chris@16 348 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 349 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 350 eval_subtract(
Chris@16 351 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 352 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
Chris@16 353 const limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 354 {
Chris@16 355 if(a.sign())
Chris@16 356 {
Chris@16 357 add_unsigned(result, a, o);
Chris@16 358 }
Chris@16 359 else
Chris@16 360 {
Chris@16 361 subtract_unsigned(result, a, o);
Chris@16 362 }
Chris@16 363 }
Chris@16 364 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 365 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
Chris@16 366 eval_subtract(
Chris@16 367 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 368 const signed_limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 369 {
Chris@16 370 if(o)
Chris@16 371 {
Chris@16 372 if(o < 0)
Chris@101 373 eval_add(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
Chris@16 374 else
Chris@16 375 eval_subtract(result, static_cast<limb_type>(o));
Chris@16 376 }
Chris@16 377 }
Chris@16 378 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 379 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 380 eval_subtract(
Chris@16 381 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 382 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
Chris@16 383 const signed_limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 384 {
Chris@16 385 if(o)
Chris@16 386 {
Chris@16 387 if(o < 0)
Chris@101 388 eval_add(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
Chris@16 389 else
Chris@16 390 eval_subtract(result, a, static_cast<limb_type>(o));
Chris@16 391 }
Chris@16 392 else if(&result != &a)
Chris@16 393 result = a;
Chris@16 394 }
Chris@16 395
Chris@16 396 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 397 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
Chris@16 398 eval_increment(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 399 {
Chris@16 400 static const limb_type one = 1;
Chris@16 401 if(!result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
Chris@16 402 ++result.limbs()[0];
Chris@16 403 else if(result.sign() && result.limbs()[0])
Chris@16 404 --result.limbs()[0];
Chris@16 405 else
Chris@16 406 eval_add(result, one);
Chris@16 407 }
Chris@16 408 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 409 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
Chris@16 410 eval_decrement(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 411 {
Chris@16 412 static const limb_type one = 1;
Chris@16 413 if(!result.sign() && result.limbs()[0])
Chris@16 414 --result.limbs()[0];
Chris@16 415 else if(result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
Chris@16 416 ++result.limbs()[0];
Chris@16 417 else
Chris@16 418 eval_subtract(result, one);
Chris@16 419 }
Chris@16 420 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 421 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 422 eval_subtract(
Chris@16 423 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 424 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
Chris@16 425 {
Chris@16 426 eval_subtract(result, result, o);
Chris@16 427 }
Chris@16 428 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 429 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 && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value >::type
Chris@16 430 eval_subtract(
Chris@16 431 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 432 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
Chris@16 433 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 434 {
Chris@16 435 if(a.sign() != b.sign())
Chris@16 436 {
Chris@16 437 add_unsigned(result, a, b);
Chris@16 438 return;
Chris@16 439 }
Chris@16 440 subtract_unsigned(result, a, b);
Chris@16 441 }
Chris@16 442
Chris@16 443 //
Chris@16 444 // Simple addition and subtraction routine for trivial cpp_int's come last:
Chris@16 445 //
Chris@16 446 // One of the arguments is signed:
Chris@16 447 //
Chris@16 448 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 449 inline typename enable_if_c<
Chris@16 450 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 451 && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 452 && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
Chris@16 453 >::type
Chris@16 454 eval_add(
Chris@16 455 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 456 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 457 {
Chris@16 458 if(result.sign() != o.sign())
Chris@16 459 {
Chris@16 460 if(*o.limbs() > *result.limbs())
Chris@16 461 {
Chris@16 462 *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
Chris@16 463 result.negate();
Chris@16 464 }
Chris@16 465 else
Chris@16 466 *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
Chris@16 467 }
Chris@16 468 else
Chris@16 469 *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
Chris@16 470 result.normalize();
Chris@16 471 }
Chris@16 472 // Simple version for two unsigned arguments:
Chris@16 473 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 474 BOOST_MP_FORCEINLINE typename enable_if_c<
Chris@16 475 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 476 && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 477 && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 478 && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 479 >::type
Chris@16 480 eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 481 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 482 {
Chris@16 483 *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
Chris@16 484 result.normalize();
Chris@16 485 }
Chris@16 486
Chris@16 487 // signed subtraction:
Chris@16 488 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 489 inline typename enable_if_c<
Chris@16 490 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 491 && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 492 && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
Chris@16 493 >::type
Chris@16 494 eval_subtract(
Chris@16 495 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 496 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 497 {
Chris@16 498 if(result.sign() != o.sign())
Chris@16 499 {
Chris@16 500 *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
Chris@16 501 }
Chris@16 502 else if(*result.limbs() < *o.limbs())
Chris@16 503 {
Chris@16 504 *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
Chris@16 505 result.negate();
Chris@16 506 }
Chris@16 507 else
Chris@16 508 *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
Chris@16 509 result.normalize();
Chris@16 510 }
Chris@16 511
Chris@16 512 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 513 BOOST_MP_FORCEINLINE typename enable_if_c<
Chris@16 514 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 515 && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 516 && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 517 && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 518 >::type
Chris@16 519 eval_subtract(
Chris@16 520 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 521 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 522 {
Chris@16 523 *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
Chris@16 524 result.normalize();
Chris@16 525 }
Chris@16 526
Chris@16 527 }}} // namespaces
Chris@16 528
Chris@16 529 #endif