123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538 |
- ///////////////////////////////////////////////////////////////
- // Copyright 2012 John Maddock. Distributed under the Boost
- // Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
- //
- // Comparison operators for cpp_int_backend:
- //
- #ifndef BOOST_MP_CPP_INT_ADD_HPP
- #define BOOST_MP_CPP_INT_ADD_HPP
- #include <boost/multiprecision/detail/constexpr.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 BOOST_MP_CXX14_CONSTEXPR void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
- {
- using ::boost::multiprecision::std_constexpr::swap;
- // Nothing fancy, just let uintmax_t take the strain:
- double_limb_type carry = 0;
- unsigned m(0), x(0);
- 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)
- std_constexpr::copy(pa, pa + (pr_end - pr), pr);
- 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 (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 BOOST_MP_CXX14_CONSTEXPR 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 (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 BOOST_MP_CXX14_CONSTEXPR void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
- {
- using ::boost::multiprecision::std_constexpr::swap;
- // Nothing fancy, just let uintmax_t take the strain:
- double_limb_type borrow = 0;
- unsigned m(0), x(0);
- 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)
- {
- ::boost::multiprecision::std_constexpr::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))
- std_constexpr::copy(pa + i, pa + x, pr + i);
- 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 BOOST_MP_CXX14_CONSTEXPR 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:
- #ifdef BOOST_NO_CXX14_CONSTEXPR
- BOOST_STATIC_CONSTANT(double_limb_type, borrow = static_cast<double_limb_type>(CppInt1::max_limb_value) + 1);
- #else
- constexpr double_limb_type borrow = static_cast<double_limb_type>(CppInt1::max_limb_value) + 1;
- #endif
- 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)
- {
- std_constexpr::copy(pa + 1, pa + a.size(), pr + 1);
- 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;
- std_constexpr::copy(pa + i, pa + a.size(), pr + i);
- }
- 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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))
- {
- #ifdef BOOST_NO_CXX14_CONSTEXPR
- static const limb_type one = 1;
- #else
- constexpr const limb_type one = 1;
- #endif
- 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];
- if (!result.limbs()[0])
- result.sign(false);
- }
- else
- eval_add(result, one);
- }
- template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR 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))
- {
- #ifdef BOOST_NO_CXX14_CONSTEXPR
- static const limb_type one = 1;
- #else
- constexpr const limb_type one = 1;
- #endif
- 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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
- }}} // namespace boost::multiprecision::backends
- #endif
|