diff DEPENDENCIES/generic/include/boost/multiprecision/cpp_int/add.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DEPENDENCIES/generic/include/boost/multiprecision/cpp_int/add.hpp	Tue Aug 05 11:11:38 2014 +0100
@@ -0,0 +1,529 @@
+///////////////////////////////////////////////////////////////
+//  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{
+
+//
+// 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_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);
+      *pr = static_cast<limb_type>(carry);
+      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);
+      *pr = static_cast<limb_type>(carry);
+      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_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]);
+      pr[i] = static_cast<limb_type>(carry);
+      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_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_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_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_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_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_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_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>(-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_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>(-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_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_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_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>(-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_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>(-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_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_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_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_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_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_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_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_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();
+}
+
+}}} // namespaces
+
+#endif