551 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			551 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | /////////////////////////////////////////////////////////////// | ||
|  | //  Copyright 2012 John Maddock. Distributed under the Boost | ||
|  | //  Software License, Version 1.0. (See accompanying file | ||
|  | //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ | ||
|  | // | ||
|  | // Comparison operators for cpp_int_backend: | ||
|  | // | ||
|  | #ifndef BOOST_MP_CPP_INT_ADD_HPP | ||
|  | #define BOOST_MP_CPP_INT_ADD_HPP | ||
|  | 
 | ||
|  | namespace boost{ namespace multiprecision{ namespace backends{ | ||
|  | 
 | ||
|  | #ifdef _MSC_VER | ||
|  | #pragma warning(push) | ||
|  | #pragma warning(disable:4127) // conditional expression is constant | ||
|  | #endif | ||
|  | 
 | ||
|  | // | ||
|  | // This is the key addition routine where all the argument types are non-trivial cpp_int's: | ||
|  | // | ||
|  | template <class CppInt1, class CppInt2, class CppInt3> | ||
|  | inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value) | ||
|  | { | ||
|  |    using std::swap; | ||
|  | 
 | ||
|  |    // Nothing fancy, just let uintmax_t take the strain: | ||
|  |    double_limb_type carry = 0; | ||
|  |    unsigned m, x; | ||
|  |    unsigned as = a.size(); | ||
|  |    unsigned bs = b.size(); | ||
|  |    minmax(as, bs, m, x); | ||
|  |    if(x == 1) | ||
|  |    { | ||
|  |       bool s = a.sign(); | ||
|  |       result = static_cast<double_limb_type>(*a.limbs()) + static_cast<double_limb_type>(*b.limbs()); | ||
|  |       result.sign(s); | ||
|  |       return; | ||
|  |    } | ||
|  |    result.resize(x, x); | ||
|  |    typename CppInt2::const_limb_pointer pa = a.limbs(); | ||
|  |    typename CppInt3::const_limb_pointer pb = b.limbs(); | ||
|  |    typename CppInt1::limb_pointer pr = result.limbs(); | ||
|  |    typename CppInt1::limb_pointer pr_end = pr + m; | ||
|  | 
 | ||
|  |    if(as < bs) | ||
|  |       swap(pa, pb); | ||
|  |     | ||
|  |    // First where a and b overlap: | ||
|  |    while(pr != pr_end) | ||
|  |    { | ||
|  |       carry += static_cast<double_limb_type>(*pa) + static_cast<double_limb_type>(*pb); | ||
|  | #ifdef __MSVC_RUNTIME_CHECKS | ||
|  |       *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0)); | ||
|  | #else | ||
|  |       *pr = static_cast<limb_type>(carry); | ||
|  | #endif | ||
|  |       carry >>= CppInt1::limb_bits; | ||
|  |       ++pr, ++pa, ++pb; | ||
|  |    } | ||
|  |    pr_end += x - m; | ||
|  |    // Now where only a has digits: | ||
|  |    while(pr != pr_end) | ||
|  |    { | ||
|  |       if(!carry) | ||
|  |       { | ||
|  |          if(pa != pr) | ||
|  | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | ||
|  |             std::copy(pa, pa + (pr_end - pr), stdext::checked_array_iterator<limb_type*>(pr, result.size())); | ||
|  | #else | ||
|  |             std::copy(pa, pa + (pr_end - pr), pr); | ||
|  | #endif | ||
|  |          break; | ||
|  |       } | ||
|  |       carry += static_cast<double_limb_type>(*pa); | ||
|  | #ifdef __MSVC_RUNTIME_CHECKS | ||
|  |       *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0)); | ||
|  | #else | ||
|  |       *pr = static_cast<limb_type>(carry); | ||
|  | #endif | ||
|  |       carry >>= CppInt1::limb_bits; | ||
|  |       ++pr, ++pa; | ||
|  |    } | ||
|  |    if(carry) | ||
|  |    { | ||
|  |       // We overflowed, need to add one more limb: | ||
|  |       result.resize(x + 1, x + 1); | ||
|  |       if(CppInt1::variable || (result.size() > x)) | ||
|  |          result.limbs()[x] = static_cast<limb_type>(carry); | ||
|  |    } | ||
|  |    result.normalize(); | ||
|  |    result.sign(a.sign()); | ||
|  | } | ||
|  | // | ||
|  | // As above, but for adding a single limb to a non-trivial cpp_int: | ||
|  | // | ||
|  | template <class CppInt1, class CppInt2> | ||
|  | inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value) | ||
|  | { | ||
|  |    // Addition using modular arithmetic. | ||
|  |    // Nothing fancy, just let uintmax_t take the strain: | ||
|  |    if(&result != &a) | ||
|  |       result.resize(a.size(), a.size()); | ||
|  |    double_limb_type carry = o; | ||
|  |    typename CppInt1::limb_pointer pr = result.limbs(); | ||
|  |    typename CppInt2::const_limb_pointer pa = a.limbs(); | ||
|  |    unsigned i = 0; | ||
|  |    // Addition with carry until we either run out of digits or carry is zero: | ||
|  |    for(; carry && (i < result.size()); ++i) | ||
|  |    { | ||
|  |       carry += static_cast<double_limb_type>(pa[i]); | ||
|  | #ifdef __MSVC_RUNTIME_CHECKS | ||
|  |       pr[i] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0)); | ||
|  | #else | ||
|  |       pr[i] = static_cast<limb_type>(carry); | ||
|  | #endif | ||
|  |       carry >>= CppInt1::limb_bits; | ||
|  |    } | ||
|  |    // Just copy any remaining digits: | ||
|  |    if(&a != &result) | ||
|  |    { | ||
|  |       for(; i < result.size(); ++i) | ||
|  |          pr[i] = pa[i]; | ||
|  |    } | ||
|  |    if(carry) | ||
|  |    { | ||
|  |       // We overflowed, need to add one more limb: | ||
|  |       unsigned x = result.size(); | ||
|  |       result.resize(x + 1, x + 1); | ||
|  |       if(CppInt1::variable || (result.size() > x)) | ||
|  |          result.limbs()[x] = static_cast<limb_type>(carry); | ||
|  |    } | ||
|  |    result.normalize(); | ||
|  |    result.sign(a.sign()); | ||
|  | } | ||
|  | // | ||
|  | // Core subtraction routine for all non-trivial cpp_int's: | ||
|  | // | ||
|  | template <class CppInt1, class CppInt2, class CppInt3> | ||
|  | inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value) | ||
|  | { | ||
|  |    using std::swap; | ||
|  | 
 | ||
|  |    // Nothing fancy, just let uintmax_t take the strain: | ||
|  |    double_limb_type borrow = 0; | ||
|  |    unsigned m, x; | ||
|  |    minmax(a.size(), b.size(), m, x); | ||
|  |    // | ||
|  |    // special cases for small limb counts: | ||
|  |    // | ||
|  |    if(x == 1) | ||
|  |    { | ||
|  |       bool s = a.sign(); | ||
|  |       limb_type al = *a.limbs(); | ||
|  |       limb_type bl = *b.limbs(); | ||
|  |       if(bl > al) | ||
|  |       { | ||
|  |          std::swap(al, bl); | ||
|  |          s = !s; | ||
|  |       } | ||
|  |       result = al - bl; | ||
|  |       result.sign(s); | ||
|  |       return; | ||
|  |    } | ||
|  |    // This isn't used till later, but comparison has to occur before we resize the result, | ||
|  |    // as that may also resize a or b if this is an inplace operation: | ||
|  |    int c = a.compare_unsigned(b); | ||
|  |    // Set up the result vector: | ||
|  |    result.resize(x, x); | ||
|  |    // Now that a, b, and result are stable, get pointers to their limbs: | ||
|  |    typename CppInt2::const_limb_pointer pa = a.limbs(); | ||
|  |    typename CppInt3::const_limb_pointer pb = b.limbs(); | ||
|  |    typename CppInt1::limb_pointer pr = result.limbs(); | ||
|  |    bool swapped = false; | ||
|  |    if(c < 0) | ||
|  |    { | ||
|  |       swap(pa, pb); | ||
|  |       swapped = true; | ||
|  |    } | ||
|  |    else if(c == 0) | ||
|  |    { | ||
|  |       result = static_cast<limb_type>(0); | ||
|  |       return; | ||
|  |    } | ||
|  |     | ||
|  |    unsigned i = 0; | ||
|  |    // First where a and b overlap: | ||
|  |    while(i < m) | ||
|  |    { | ||
|  |       borrow = static_cast<double_limb_type>(pa[i]) - static_cast<double_limb_type>(pb[i]) - borrow; | ||
|  |       pr[i] = static_cast<limb_type>(borrow); | ||
|  |       borrow = (borrow >> CppInt1::limb_bits) & 1u; | ||
|  |       ++i; | ||
|  |    } | ||
|  |    // Now where only a has digits, only as long as we've borrowed: | ||
|  |    while(borrow && (i < x)) | ||
|  |    { | ||
|  |       borrow = static_cast<double_limb_type>(pa[i]) - borrow; | ||
|  |       pr[i] = static_cast<limb_type>(borrow); | ||
|  |       borrow = (borrow >> CppInt1::limb_bits) & 1u; | ||
|  |       ++i; | ||
|  |    } | ||
|  |    // Any remaining digits are the same as those in pa: | ||
|  |    if((x != i) && (pa != pr)) | ||
|  | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | ||
|  |       std::copy(pa + i, pa + x, stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i)); | ||
|  | #else | ||
|  |       std::copy(pa + i, pa + x, pr + i); | ||
|  | #endif | ||
|  |    BOOST_ASSERT(0 == borrow); | ||
|  | 
 | ||
|  |    // | ||
|  |    // We may have lost digits, if so update limb usage count: | ||
|  |    // | ||
|  |    result.normalize(); | ||
|  |    result.sign(a.sign()); | ||
|  |    if(swapped) | ||
|  |       result.negate(); | ||
|  | } | ||
|  | // | ||
|  | // And again to subtract a single limb: | ||
|  | // | ||
|  | template <class CppInt1, class CppInt2> | ||
|  | inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const limb_type& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value) | ||
|  | { | ||
|  |    // Subtract one limb. | ||
|  |    // Nothing fancy, just let uintmax_t take the strain: | ||
|  |    BOOST_STATIC_CONSTANT(double_limb_type, borrow = static_cast<double_limb_type>(CppInt1::max_limb_value) + 1); | ||
|  |    result.resize(a.size(), a.size()); | ||
|  |    typename CppInt1::limb_pointer pr = result.limbs(); | ||
|  |    typename CppInt2::const_limb_pointer pa = a.limbs(); | ||
|  |    if(*pa >= b) | ||
|  |    { | ||
|  |       *pr = *pa - b; | ||
|  |       if(&result != &a) | ||
|  |       { | ||
|  | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | ||
|  |          std::copy(pa + 1, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + 1, result.size() - 1)); | ||
|  | #else | ||
|  |          std::copy(pa + 1, pa + a.size(), pr + 1); | ||
|  | #endif | ||
|  |          result.sign(a.sign()); | ||
|  |       } | ||
|  |       else if((result.size() == 1) && (*pr == 0)) | ||
|  |       { | ||
|  |          result.sign(false); // zero is unsigned. | ||
|  |       } | ||
|  |    } | ||
|  |    else if(result.size() == 1) | ||
|  |    { | ||
|  |       *pr = b - *pa; | ||
|  |       result.sign(!a.sign()); | ||
|  |    } | ||
|  |    else | ||
|  |    { | ||
|  |       *pr = static_cast<limb_type>((borrow + *pa) - b); | ||
|  |       unsigned i = 1; | ||
|  |       while(!pa[i]) | ||
|  |       { | ||
|  |          pr[i] = CppInt1::max_limb_value; | ||
|  |          ++i; | ||
|  |       } | ||
|  |       pr[i] = pa[i] - 1; | ||
|  |       if(&result != &a) | ||
|  |       { | ||
|  |          ++i; | ||
|  | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | ||
|  |          std::copy(pa + i, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i)); | ||
|  | #else | ||
|  |          std::copy(pa + i, pa + a.size(), pr + i); | ||
|  | #endif | ||
|  |       } | ||
|  |       result.normalize(); | ||
|  |       result.sign(a.sign()); | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | // | ||
|  | // Now the actual functions called by the front end, all of which forward to one of the above: | ||
|  | // | ||
|  | 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> | ||
|  | 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  | ||
|  |    eval_add( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    eval_add(result, result, o); | ||
|  | } | ||
|  | 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> | ||
|  | 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 | ||
|  |    eval_add( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,  | ||
|  |       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)) | ||
|  | { | ||
|  |    if(a.sign() != b.sign()) | ||
|  |    { | ||
|  |       subtract_unsigned(result, a, b); | ||
|  |       return; | ||
|  |    } | ||
|  |    add_unsigned(result, a, b); | ||
|  | } | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type  | ||
|  |    eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    if(result.sign()) | ||
|  |    { | ||
|  |       subtract_unsigned(result, result, o); | ||
|  |    } | ||
|  |    else | ||
|  |       add_unsigned(result, result, o); | ||
|  | } | ||
|  | 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> | ||
|  | 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  | ||
|  |    eval_add( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,  | ||
|  |       const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    if(a.sign()) | ||
|  |    { | ||
|  |       subtract_unsigned(result, a, o); | ||
|  |    } | ||
|  |    else | ||
|  |       add_unsigned(result, a, o); | ||
|  | } | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type  | ||
|  |    eval_add( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    if(o < 0) | ||
|  |       eval_subtract(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o))); | ||
|  |    else if(o > 0) | ||
|  |       eval_add(result, static_cast<limb_type>(o)); | ||
|  | } | ||
|  | 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> | ||
|  | 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  | ||
|  |    eval_add( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,  | ||
|  |       const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    if(o < 0) | ||
|  |       eval_subtract(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o))); | ||
|  |    else if(o > 0) | ||
|  |       eval_add(result, a, static_cast<limb_type>(o)); | ||
|  |    else if(&result != &a) | ||
|  |       result = a; | ||
|  | } | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type  | ||
|  |    eval_subtract( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    if(result.sign()) | ||
|  |    { | ||
|  |       add_unsigned(result, result, o); | ||
|  |    } | ||
|  |    else | ||
|  |       subtract_unsigned(result, result, o); | ||
|  | } | ||
|  | 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> | ||
|  | 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  | ||
|  |    eval_subtract( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,  | ||
|  |       const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    if(a.sign()) | ||
|  |    { | ||
|  |       add_unsigned(result, a, o); | ||
|  |    } | ||
|  |    else | ||
|  |    { | ||
|  |       subtract_unsigned(result, a, o); | ||
|  |    } | ||
|  | } | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type  | ||
|  |    eval_subtract( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    if(o) | ||
|  |    { | ||
|  |       if(o < 0) | ||
|  |          eval_add(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o))); | ||
|  |       else | ||
|  |          eval_subtract(result, static_cast<limb_type>(o)); | ||
|  |    } | ||
|  | } | ||
|  | 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> | ||
|  | 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  | ||
|  |    eval_subtract( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,  | ||
|  |       const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    if(o) | ||
|  |    { | ||
|  |       if(o < 0) | ||
|  |          eval_add(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o))); | ||
|  |       else | ||
|  |          eval_subtract(result, a, static_cast<limb_type>(o)); | ||
|  |    } | ||
|  |    else if(&result != &a) | ||
|  |       result = a; | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type  | ||
|  |    eval_increment(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    static const limb_type one = 1; | ||
|  |    if(!result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value)) | ||
|  |       ++result.limbs()[0]; | ||
|  |    else if(result.sign() && result.limbs()[0]) | ||
|  |       --result.limbs()[0]; | ||
|  |    else | ||
|  |       eval_add(result, one); | ||
|  | } | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type  | ||
|  |    eval_decrement(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    static const limb_type one = 1; | ||
|  |    if(!result.sign() && result.limbs()[0]) | ||
|  |       --result.limbs()[0]; | ||
|  |    else if(result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value)) | ||
|  |       ++result.limbs()[0]; | ||
|  |    else | ||
|  |       eval_subtract(result, one); | ||
|  | } | ||
|  | 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> | ||
|  | 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  | ||
|  |    eval_subtract( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    eval_subtract(result, result, o); | ||
|  | } | ||
|  | 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> | ||
|  | 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 | ||
|  |    eval_subtract( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,  | ||
|  |       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)) | ||
|  | { | ||
|  |    if(a.sign() != b.sign()) | ||
|  |    { | ||
|  |       add_unsigned(result, a, b); | ||
|  |       return; | ||
|  |    } | ||
|  |    subtract_unsigned(result, a, b); | ||
|  | } | ||
|  | 
 | ||
|  | // | ||
|  | // Simple addition and subtraction routine for trivial cpp_int's come last: | ||
|  | // | ||
|  | // One of the arguments is signed: | ||
|  | // | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | 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<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value) | ||
|  |          >::type  | ||
|  |    eval_add( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       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)) | ||
|  | { | ||
|  |    if(result.sign() != o.sign()) | ||
|  |    { | ||
|  |       if(*o.limbs() > *result.limbs()) | ||
|  |       { | ||
|  |          *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |          result.negate(); | ||
|  |       } | ||
|  |       else | ||
|  |          *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |    } | ||
|  |    else | ||
|  |       *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |    result.normalize(); | ||
|  | } | ||
|  | // Simple version for two unsigned arguments: | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | 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<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value  | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          >::type  | ||
|  |    eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       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)) | ||
|  | { | ||
|  |    *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |    result.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | // signed subtraction: | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | 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<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value) | ||
|  |          >::type  | ||
|  |    eval_subtract( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       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)) | ||
|  | { | ||
|  |    if(result.sign() != o.sign()) | ||
|  |    { | ||
|  |       *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |    } | ||
|  |    else if(*result.limbs() < *o.limbs()) | ||
|  |    { | ||
|  |       *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |       result.negate(); | ||
|  |    } | ||
|  |    else | ||
|  |       *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |    result.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | 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<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value  | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          >::type  | ||
|  |    eval_subtract( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       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)) | ||
|  | { | ||
|  |    *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |    result.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef _MSC_VER | ||
|  | #pragma warning(pop) | ||
|  | #endif | ||
|  | 
 | ||
|  | }}} // namespaces | ||
|  | 
 | ||
|  | #endif |