Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:12

0001 ///////////////////////////////////////////////////////////////
0002 //  Copyright 2012 John Maddock. Distributed under the Boost
0003 //  Software License, Version 1.0. (See accompanying file
0004 //  LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
0005 //
0006 // Comparison operators for cpp_int_backend:
0007 //
0008 #ifndef BOOST_MP_CPP_INT_ADD_HPP
0009 #define BOOST_MP_CPP_INT_ADD_HPP
0010 
0011 #include <boost/multiprecision/detail/constexpr.hpp>
0012 #include <boost/multiprecision/cpp_int/add_unsigned.hpp>
0013 
0014 namespace boost { namespace multiprecision { namespace backends {
0015 
0016 //
0017 // As above, but for adding a single limb to a non-trivial cpp_int:
0018 //
0019 template <class CppInt1, class CppInt2>
0020 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)
0021 {
0022    // Addition using modular arithmetic.
0023    // Nothing fancy, just let uintmax_t take the strain:
0024    if (&result != &a)
0025       result.resize(a.size(), a.size());
0026    double_limb_type                     carry = o;
0027    typename CppInt1::limb_pointer       pr    = result.limbs();
0028    typename CppInt2::const_limb_pointer pa    = a.limbs();
0029    std::size_t                             i     = 0;
0030    // Addition with carry until we either run out of digits or carry is zero:
0031    for (; carry && (i < result.size()); ++i)
0032    {
0033       carry += static_cast<double_limb_type>(pa[i]);
0034 #ifdef __MSVC_RUNTIME_CHECKS
0035       pr[i] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
0036 #else
0037       pr[i] = static_cast<limb_type>(carry);
0038 #endif
0039       carry >>= CppInt1::limb_bits;
0040    }
0041    // Just copy any remaining digits:
0042    if (&a != &result)
0043    {
0044       std_constexpr::copy(pa + i, pa + a.size(), pr + i);
0045    }
0046    if (carry)
0047    {
0048       // We overflowed, need to add one more limb:
0049       std::size_t x = result.size();
0050       result.resize(x + 1, x + 1);
0051       if (result.size() > x)
0052          result.limbs()[x] = static_cast<limb_type>(carry);
0053    }
0054    result.normalize();
0055    result.sign(a.sign());
0056 }
0057 //
0058 // And again to subtract a single limb:
0059 //
0060 template <class CppInt1, class CppInt2>
0061 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)
0062 {
0063    // Subtract one limb.
0064    // Nothing fancy, just let uintmax_t take the strain:
0065    constexpr double_limb_type borrow = static_cast<double_limb_type>(CppInt1::max_limb_value) + 1;
0066    result.resize(a.size(), a.size());
0067    typename CppInt1::limb_pointer       pr = result.limbs();
0068    typename CppInt2::const_limb_pointer pa = a.limbs();
0069    if (*pa >= b)
0070    {
0071       *pr = *pa - b;
0072       if (&result != &a)
0073       {
0074          std_constexpr::copy(pa + 1, pa + a.size(), pr + 1);
0075          result.sign(a.sign());
0076       }
0077       else if ((result.size() == 1) && (*pr == 0))
0078       {
0079          result.sign(false); // zero is unsigned.
0080       }
0081    }
0082    else if (result.size() == 1)
0083    {
0084       *pr = b - *pa;
0085       result.sign(!a.sign());
0086    }
0087    else
0088    {
0089       *pr        = static_cast<limb_type>((borrow + *pa) - b);
0090       std::size_t i = 1;
0091       while (!pa[i])
0092       {
0093          pr[i] = CppInt1::max_limb_value;
0094          ++i;
0095       }
0096       pr[i] = pa[i] - 1;
0097       if (&result != &a)
0098       {
0099          ++i;
0100          std_constexpr::copy(pa + i, pa + a.size(), pr + i);
0101       }
0102       result.normalize();
0103       result.sign(a.sign());
0104    }
0105 }
0106 
0107 //
0108 // Now the actual functions called by the front end, all of which forward to one of the above:
0109 //
0110 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>
0111 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
0112 eval_add(
0113     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0114     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))
0115 {
0116    eval_add(result, result, o);
0117 }
0118 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>
0119 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
0120 eval_add(
0121     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0122     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0123     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))
0124 {
0125    if (a.sign() != b.sign())
0126    {
0127       subtract_unsigned(result, a, b);
0128       return;
0129    }
0130    add_unsigned(result, a, b);
0131 }
0132 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0133 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
0134 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))
0135 {
0136    if (result.sign())
0137    {
0138       subtract_unsigned(result, result, o);
0139    }
0140    else
0141       add_unsigned(result, result, o);
0142 }
0143 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>
0144 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
0145 eval_add(
0146     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0147     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0148     const limb_type&                                                            o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0149 {
0150    if (a.sign())
0151    {
0152       subtract_unsigned(result, a, o);
0153    }
0154    else
0155       add_unsigned(result, a, o);
0156 }
0157 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0158 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
0159 eval_add(
0160     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0161     const signed_limb_type&                                               o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0162 {
0163    if (o < 0)
0164       eval_subtract(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
0165    else if (o > 0)
0166       eval_add(result, static_cast<limb_type>(o));
0167 }
0168 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>
0169 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
0170 eval_add(
0171     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0172     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0173     const signed_limb_type&                                                     o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0174 {
0175    if (o < 0)
0176       eval_subtract(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
0177    else if (o > 0)
0178       eval_add(result, a, static_cast<limb_type>(o));
0179    else if (&result != &a)
0180       result = a;
0181 }
0182 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0183 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
0184 eval_subtract(
0185     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0186     const limb_type&                                                      o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0187 {
0188    if (result.sign())
0189    {
0190       add_unsigned(result, result, o);
0191    }
0192    else
0193       subtract_unsigned(result, result, o);
0194 }
0195 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>
0196 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
0197 eval_subtract(
0198     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0199     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0200     const limb_type&                                                            o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0201 {
0202    if (a.sign())
0203    {
0204       add_unsigned(result, a, o);
0205    }
0206    else
0207    {
0208       subtract_unsigned(result, a, o);
0209    }
0210 }
0211 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0212 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
0213 eval_subtract(
0214     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0215     const signed_limb_type&                                               o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0216 {
0217    if (o)
0218    {
0219       if (o < 0)
0220          eval_add(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
0221       else
0222          eval_subtract(result, static_cast<limb_type>(o));
0223    }
0224 }
0225 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>
0226 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
0227 eval_subtract(
0228     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0229     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0230     const signed_limb_type&                                                     o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0231 {
0232    if (o)
0233    {
0234       if (o < 0)
0235          eval_add(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
0236       else
0237          eval_subtract(result, a, static_cast<limb_type>(o));
0238    }
0239    else if (&result != &a)
0240       result = a;
0241 }
0242 
0243 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0244 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
0245 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))
0246 {
0247    constexpr limb_type one = 1;
0248 
0249    if (!result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
0250       ++result.limbs()[0];
0251    else if (result.sign() && result.limbs()[0])
0252    {
0253       --result.limbs()[0];
0254       if (!result.limbs()[0] && (result.size() == 1))
0255          result.sign(false);
0256    }
0257    else
0258       eval_add(result, one);
0259 }
0260 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0261 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
0262 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))
0263 {
0264    constexpr limb_type one = 1;
0265 
0266    if (!result.sign() && result.limbs()[0])
0267       --result.limbs()[0];
0268    else if (result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
0269       ++result.limbs()[0];
0270    else
0271       eval_subtract(result, one);
0272 }
0273 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>
0274 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
0275 eval_subtract(
0276     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0277     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))
0278 {
0279    eval_subtract(result, result, o);
0280 }
0281 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>
0282 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
0283 eval_subtract(
0284     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0285     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0286     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))
0287 {
0288    if (a.sign() != b.sign())
0289    {
0290       add_unsigned(result, a, b);
0291       return;
0292    }
0293    subtract_unsigned(result, a, b);
0294 }
0295 
0296 //
0297 // Simple addition and subtraction routine for trivial cpp_int's come last:
0298 //
0299 // One of the arguments is signed:
0300 //
0301 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0302 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0303     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
0304 eval_add(
0305     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0306     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))
0307 {
0308    if (result.sign() != o.sign())
0309    {
0310       if (*o.limbs() > *result.limbs())
0311       {
0312          *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0313          result.negate();
0314       }
0315       else
0316          *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0317    }
0318    else
0319       *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0320    result.normalize();
0321 }
0322 // Simple version for two unsigned arguments:
0323 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0324 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0325     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
0326 eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0327          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))
0328 {
0329    *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0330    result.normalize();
0331 }
0332 
0333 // signed subtraction:
0334 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0335 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0336     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
0337 eval_subtract(
0338     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0339     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))
0340 {
0341    if (result.sign() != o.sign())
0342    {
0343       *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0344    }
0345    else if (*result.limbs() < *o.limbs())
0346    {
0347       *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0348       result.negate();
0349    }
0350    else
0351       *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0352    result.normalize();
0353 }
0354 
0355 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0356 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0357     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
0358 eval_subtract(
0359     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0360     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))
0361 {
0362    *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0363    result.normalize();
0364 }
0365 
0366 }}} // namespace boost::multiprecision::backends
0367 
0368 #endif