369 lines
22 KiB
C++
369 lines
22 KiB
C++
///////////////////////////////////////////////////////////////
|
|
// 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>
|
|
#include <boost/multiprecision/cpp_int/add_unsigned.hpp>
|
|
|
|
namespace boost { namespace multiprecision { namespace backends {
|
|
|
|
//
|
|
// 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) noexcept(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();
|
|
std::size_t 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)
|
|
{
|
|
std_constexpr::copy(pa + i, pa + a.size(), pr + i);
|
|
}
|
|
if (carry)
|
|
{
|
|
// We overflowed, need to add one more limb:
|
|
std::size_t 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());
|
|
}
|
|
//
|
|
// 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) noexcept(is_non_throwing_cpp_int<CppInt1>::value)
|
|
{
|
|
// Subtract one limb.
|
|
// Nothing fancy, just let uintmax_t take the strain:
|
|
constexpr 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)
|
|
{
|
|
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);
|
|
std::size_t 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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
|
|
{
|
|
eval_add(result, result, o);
|
|
}
|
|
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
|
|
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
|
|
{
|
|
constexpr 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];
|
|
if (!result.limbs()[0] && (result.size() == 1))
|
|
result.sign(false);
|
|
}
|
|
else
|
|
eval_add(result, one);
|
|
}
|
|
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
|
|
{
|
|
constexpr 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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
|
|
{
|
|
eval_subtract(result, result, o);
|
|
}
|
|
template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
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) noexcept((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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
|
|
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
|
|
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) noexcept((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();
|
|
}
|
|
|
|
}}} // namespace boost::multiprecision::backends
|
|
|
|
#endif
|