Back to home page

EIC code displayed by LXR

 
 

    


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

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_DIVIDE_HPP
0009 #define BOOST_MP_CPP_INT_DIVIDE_HPP
0010 
0011 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
0012 #include <boost/multiprecision/detail/assert.hpp>
0013 
0014 namespace boost { namespace multiprecision { namespace backends {
0015 
0016 template <class CppInt1, class CppInt2, class CppInt3>
0017 BOOST_MP_CXX14_CONSTEXPR void divide_unsigned_helper(
0018     CppInt1*       result,
0019     const CppInt2& x,
0020     const CppInt3& y,
0021     CppInt1&       r)
0022 {
0023    if (((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
0024    {
0025       CppInt2 t(x);
0026       divide_unsigned_helper(result, t, y, r);
0027       return;
0028    }
0029    if (((void*)result == (void*)&y) || ((void*)&r == (void*)&y))
0030    {
0031       CppInt3 t(y);
0032       divide_unsigned_helper(result, x, t, r);
0033       return;
0034    }
0035 
0036    /*
0037     Very simple, fairly braindead long division.
0038     Start by setting the remainder equal to x, and the
0039     result equal to 0.  Then in each loop we calculate our
0040     "best guess" for how many times y divides into r,
0041     add our guess to the result, and subtract guess*y
0042     from the remainder r.  One wrinkle is that the remainder
0043     may go negative, in which case we subtract the current guess
0044     from the result rather than adding.  The value of the guess
0045     is determined by dividing the most-significant-limb of the
0046     current remainder by the most-significant-limb of y.
0047 
0048     Note that there are more efficient algorithms than this
0049     available, in particular see Knuth Vol 2.  However for small
0050     numbers of limbs this generally outperforms the alternatives
0051     and avoids the normalisation step which would require extra storage.
0052     */
0053 
0054    using default_ops::eval_subtract;
0055 
0056    if (result == &r)
0057    {
0058       CppInt1 rem;
0059       divide_unsigned_helper(result, x, y, rem);
0060       r = rem;
0061       return;
0062    }
0063 
0064    //
0065    // Find the most significant words of numerator and denominator.
0066    //
0067    std::size_t y_order = y.size() - 1;
0068 
0069    if (y_order == 0)
0070    {
0071       //
0072       // Only a single non-zero limb in the denominator, in this case
0073       // we can use a specialized divide-by-single-limb routine which is
0074       // much faster.  This also handles division by zero:
0075       //
0076       divide_unsigned_helper(result, x, y.limbs()[y_order], r);
0077       return;
0078    }
0079 
0080    typename CppInt2::const_limb_pointer px = x.limbs();
0081    typename CppInt3::const_limb_pointer py = y.limbs();
0082 
0083    std::size_t r_order = x.size() - 1;
0084    if ((r_order == 0) && (*px == 0))
0085    {
0086       // x is zero, so is the result:
0087       r = x;
0088       if (result)
0089          *result = x;
0090       return;
0091    }
0092 
0093    r = x;
0094    r.sign(false);
0095    if (result)
0096       *result = static_cast<limb_type>(0u);
0097    //
0098    // Check if the remainder is already less than the divisor, if so
0099    // we already have the result.  Note we try and avoid a full compare
0100    // if we can:
0101    //
0102    if (r_order <= y_order)
0103    {
0104       if ((r_order < y_order) || (r.compare_unsigned(y) < 0))
0105       {
0106          return;
0107       }
0108    }
0109 
0110    CppInt1 t;
0111    bool    r_neg = false;
0112 
0113    //
0114    // See if we can short-circuit long division, and use basic arithmetic instead:
0115    //
0116    if (r_order == 0)
0117    {
0118       if (result)
0119       {
0120          *result = px[0] / py[0];
0121       }
0122       r = px[0] % py[0];
0123       return;
0124    }
0125    else if (r_order == 1)
0126    {
0127       double_limb_type a = (static_cast<double_limb_type>(px[1]) << CppInt1::limb_bits) | px[0];
0128       double_limb_type b = y_order ? (static_cast<double_limb_type>(py[1]) << CppInt1::limb_bits) | py[0]
0129                                    : py[0];
0130       if (result)
0131       {
0132          *result = a / b;
0133       }
0134       r = a % b;
0135       return;
0136    }
0137    //
0138    // prepare result:
0139    //
0140    if (result)
0141       result->resize(1 + r_order - y_order, 1 + r_order - y_order);
0142    typename CppInt1::const_limb_pointer prem = r.limbs();
0143    // This is initialised just to keep the compiler from emitting useless warnings later on:
0144    typename CppInt1::limb_pointer pr = typename CppInt1::limb_pointer();
0145    if (result)
0146    {
0147       pr = result->limbs();
0148       for (std::size_t i = 1; i < 1 + r_order - y_order; ++i)
0149          pr[i] = 0;
0150    }
0151    bool first_pass = true;
0152 
0153    do
0154    {
0155       //
0156       // Calculate our best guess for how many times y divides into r:
0157       //
0158       limb_type guess = 1;
0159       if ((prem[r_order] <= py[y_order]) && (r_order > 0))
0160       {
0161          double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
0162          double_limb_type b = py[y_order];
0163          double_limb_type v = a / b;
0164          if (v <= CppInt1::max_limb_value)
0165          {
0166             guess = static_cast<limb_type>(v);
0167             --r_order;
0168          }
0169       }
0170       else if (r_order == 0)
0171       {
0172          guess = prem[0] / py[y_order];
0173       }
0174       else
0175       {
0176          double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
0177          double_limb_type b = (y_order > 0) ? (static_cast<double_limb_type>(py[y_order]) << CppInt1::limb_bits) | py[y_order - 1] : (static_cast<double_limb_type>(py[y_order]) << CppInt1::limb_bits);
0178          BOOST_MP_ASSERT(b);
0179          double_limb_type v = a / b;
0180          guess              = static_cast<limb_type>(v);
0181       }
0182       BOOST_MP_ASSERT(guess); // If the guess ever gets to zero we go on forever....
0183       //
0184       // Update result:
0185       //
0186       std::size_t shift = r_order - y_order;
0187       if (result)
0188       {
0189          if (r_neg)
0190          {
0191             if (pr[shift] > guess)
0192                pr[shift] -= guess;
0193             else
0194             {
0195                t.resize(shift + 1, shift + 1);
0196                t.limbs()[shift] = guess;
0197                for (std::size_t i = 0; i < shift; ++i)
0198                   t.limbs()[i] = 0;
0199                eval_subtract(*result, t);
0200             }
0201          }
0202          else if (CppInt1::max_limb_value - pr[shift] > guess)
0203             pr[shift] += guess;
0204          else
0205          {
0206             t.resize(shift + 1, shift + 1);
0207             t.limbs()[shift] = guess;
0208             for (std::size_t i = 0; i < shift; ++i)
0209                t.limbs()[i] = 0;
0210             eval_add(*result, t);
0211          }
0212       }
0213       //
0214       // Calculate guess * y, we use a fused mutiply-shift O(N) for this
0215       // rather than a full O(N^2) multiply:
0216       //
0217       double_limb_type carry = 0;
0218       t.resize(y.size() + shift + 1, y.size() + shift);
0219       bool                           truncated_t = (t.size() != y.size() + shift + 1);
0220       typename CppInt1::limb_pointer pt          = t.limbs();
0221       for (std::size_t i = 0; i < shift; ++i)
0222          pt[i] = 0;
0223       for (std::size_t i = 0; i < y.size(); ++i)
0224       {
0225          carry += static_cast<double_limb_type>(py[i]) * static_cast<double_limb_type>(guess);
0226 #ifdef __MSVC_RUNTIME_CHECKS
0227          pt[i + shift] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
0228 #else
0229          pt[i + shift]    = static_cast<limb_type>(carry);
0230 #endif
0231          carry >>= CppInt1::limb_bits;
0232       }
0233       if (carry && !truncated_t)
0234       {
0235 #ifdef __MSVC_RUNTIME_CHECKS
0236          pt[t.size() - 1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
0237 #else
0238          pt[t.size() - 1] = static_cast<limb_type>(carry);
0239 #endif
0240       }
0241       else if (!truncated_t)
0242       {
0243          t.resize(t.size() - 1, t.size() - 1);
0244       }
0245       //
0246       // Update r in a way that won't actually produce a negative result
0247       // in case the argument types are unsigned:
0248       //
0249       if (truncated_t && carry)
0250       {
0251          // We need to calculate 2^n + t - r
0252          // where n is the number of bits in this type.
0253          // Simplest way is to get 2^n - r by complementing
0254          // r, then add t to it.  Note that we can't call eval_complement
0255          // in case this is a signed checked type:
0256          for (std::size_t i = 0; i <= r_order; ++i)
0257             r.limbs()[i] = ~prem[i];
0258          r.normalize();
0259          eval_increment(r);
0260          eval_add(r, t);
0261          r_neg = !r_neg;
0262       }
0263       else if (r.compare(t) > 0)
0264       {
0265          eval_subtract(r, t);
0266       }
0267       else
0268       {
0269          r.swap(t);
0270          eval_subtract(r, t);
0271          prem  = r.limbs();
0272          r_neg = !r_neg;
0273       }
0274       //
0275       // First time through we need to strip any leading zero, otherwise
0276       // the termination condition goes belly-up:
0277       //
0278       if (result && first_pass)
0279       {
0280          first_pass = false;
0281          while (pr[result->size() - 1] == 0)
0282             result->resize(result->size() - 1, result->size() - 1);
0283       }
0284       //
0285       // Update r_order:
0286       //
0287       r_order = r.size() - 1;
0288       if (r_order < y_order)
0289          break;
0290    }
0291    // Termination condition is really just a check that r > y, but with a common
0292    // short-circuit case handled first:
0293    while ((r_order > y_order) || (r.compare_unsigned(y) >= 0));
0294 
0295    //
0296    // We now just have to normalise the result:
0297    //
0298    if (r_neg && eval_get_sign(r))
0299    {
0300       // We have one too many in the result:
0301       if (result)
0302          eval_decrement(*result);
0303       if (y.sign())
0304       {
0305          r.negate();
0306          eval_subtract(r, y);
0307       }
0308       else
0309          eval_subtract(r, y, r);
0310    }
0311 
0312    BOOST_MP_ASSERT(r.compare_unsigned(y) < 0); // remainder must be less than the divisor or our code has failed
0313 }
0314 
0315 template <class CppInt1, class CppInt2>
0316 BOOST_MP_CXX14_CONSTEXPR void divide_unsigned_helper(
0317     CppInt1*       result,
0318     const CppInt2& x,
0319     limb_type      y,
0320     CppInt1&       r)
0321 {
0322    if (((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
0323    {
0324       CppInt2 t(x);
0325       divide_unsigned_helper(result, t, y, r);
0326       return;
0327    }
0328 
0329    if (result == &r)
0330    {
0331       CppInt1 rem;
0332       divide_unsigned_helper(result, x, y, rem);
0333       r = rem;
0334       return;
0335    }
0336 
0337    // As above, but simplified for integer divisor:
0338 
0339    using default_ops::eval_subtract;
0340 
0341    if (y == 0)
0342    {
0343       BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer Division by zero."));
0344    }
0345    //
0346    // Find the most significant word of numerator.
0347    //
0348    std::size_t r_order = x.size() - 1;
0349 
0350    //
0351    // Set remainder and result to their initial values:
0352    //
0353    r = x;
0354    r.sign(false);
0355    typename CppInt1::limb_pointer pr = r.limbs();
0356 
0357    //
0358    // check for x < y, try to do this without actually having to
0359    // do a full comparison:
0360    //
0361    if ((r_order == 0) && (*pr < y))
0362    {
0363       if (result)
0364          *result = static_cast<limb_type>(0u);
0365       return;
0366    }
0367 
0368    //
0369    // See if we can short-circuit long division, and use basic arithmetic instead:
0370    //
0371    if (r_order == 0)
0372    {
0373       if (result)
0374       {
0375          *result = *pr / y;
0376          result->sign(x.sign());
0377       }
0378       *pr %= y;
0379       r.sign(x.sign());
0380       return;
0381    }
0382    else if (r_order == 1)
0383    {
0384       double_limb_type a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[0];
0385       if (result)
0386       {
0387          *result = a / y;
0388          result->sign(x.sign());
0389       }
0390       r = a % y;
0391       r.sign(x.sign());
0392       return;
0393    }
0394 
0395    // This is initialised just to keep the compiler from emitting useless warnings later on:
0396    typename CppInt1::limb_pointer pres = typename CppInt1::limb_pointer();
0397    if (result)
0398    {
0399       result->resize(r_order + 1, r_order + 1);
0400       pres = result->limbs();
0401       if (result->size() > r_order)
0402          pres[r_order] = 0; // just in case we don't set the most significant limb below.
0403    }
0404 
0405    do
0406    {
0407       //
0408       // Calculate our best guess for how many times y divides into r:
0409       //
0410       if ((pr[r_order] < y) && r_order)
0411       {
0412          double_limb_type a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[r_order - 1];
0413          double_limb_type b = a % y;
0414          r.resize(r.size() - 1, r.size() - 1);
0415          --r_order;
0416          pr[r_order] = static_cast<limb_type>(b);
0417          if (result)
0418             pres[r_order] = static_cast<limb_type>(a / y);
0419          if (r_order && pr[r_order] == 0)
0420          {
0421             --r_order; // No remainder, division was exact.
0422             r.resize(r.size() - 1, r.size() - 1);
0423             if (result)
0424                pres[r_order] = static_cast<limb_type>(0u);
0425          }
0426       }
0427       else
0428       {
0429          if (result)
0430             pres[r_order] = pr[r_order] / y;
0431          pr[r_order] %= y;
0432          if (r_order && pr[r_order] == 0)
0433          {
0434             --r_order; // No remainder, division was exact.
0435             r.resize(r.size() - 1, r.size() - 1);
0436             if (result)
0437                pres[r_order] = static_cast<limb_type>(0u);
0438          }
0439       }
0440    }
0441    // Termination condition is really just a check that r >= y, but with two common
0442    // short-circuit cases handled first:
0443    while (r_order || (pr[r_order] >= y));
0444 
0445    if (result)
0446    {
0447       result->normalize();
0448       result->sign(x.sign());
0449    }
0450    r.normalize();
0451    r.sign(x.sign());
0452 
0453    BOOST_MP_ASSERT(r.compare(y) < 0); // remainder must be less than the divisor or our code has failed
0454 }
0455 
0456 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>
0457 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
0458 eval_divide(
0459     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0460     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0461     const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
0462 {
0463    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
0464    bool                                                                 s = a.sign() != b.sign();
0465    divide_unsigned_helper(&result, a, b, r);
0466    result.sign(s);
0467 }
0468 
0469 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>
0470 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
0471 eval_divide(
0472     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0473     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0474     limb_type&                                                                  b)
0475 {
0476    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
0477    bool                                                                 s = a.sign();
0478    divide_unsigned_helper(&result, a, b, r);
0479    result.sign(s);
0480 }
0481 
0482 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>
0483 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
0484 eval_divide(
0485     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0486     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0487     signed_limb_type&                                                           b)
0488 {
0489    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
0490    bool                                                                 s = a.sign() != (b < 0);
0491    divide_unsigned_helper(&result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(b)), r);
0492    result.sign(s);
0493 }
0494 
0495 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>
0496 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
0497 eval_divide(
0498     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0499     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
0500 {
0501    // There is no in place divide:
0502    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
0503    eval_divide(result, a, b);
0504 }
0505 
0506 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0507 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
0508 eval_divide(
0509     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0510     limb_type                                                             b)
0511 {
0512    // There is no in place divide:
0513    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
0514    eval_divide(result, a, b);
0515 }
0516 
0517 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0518 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
0519 eval_divide(
0520     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0521     signed_limb_type                                                      b)
0522 {
0523    // There is no in place divide:
0524    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
0525    eval_divide(result, a, b);
0526 }
0527 
0528 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>
0529 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
0530 eval_modulus(
0531     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0532     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0533     const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
0534 {
0535    bool s = a.sign();
0536    if (b.size() == 1)
0537       eval_modulus(result, a, *b.limbs());
0538    else
0539    {
0540       using cpp_int_backend1_type = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>;
0541 
0542       divide_unsigned_helper(static_cast<cpp_int_backend1_type*>(nullptr), a, b, result);
0543    }
0544    result.sign(s);
0545 }
0546 
0547 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>
0548 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
0549 eval_modulus(
0550     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0551     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0552     const limb_type                                                             mod)
0553 {
0554    const std::ptrdiff_t n = static_cast<std::ptrdiff_t>(a.size());
0555 
0556    const double_limb_type two_n_mod =
0557       static_cast<double_limb_type>
0558       (
0559          static_cast<double_limb_type>(1u) + static_cast<limb_type>(static_cast<limb_type>(~static_cast<limb_type>(0u) - mod) % mod)
0560       );
0561 
0562    limb_type res = a.limbs()[n - 1] % mod;
0563 
0564    for (std::ptrdiff_t i = n - 2; i >= 0; --i)
0565       res = static_cast<limb_type>(static_cast<double_limb_type>(static_cast<double_limb_type>(res * two_n_mod) + a.limbs()[i]) % mod);
0566    //
0567    // We must not modify result until here in case
0568    // result and a are the same object:
0569    //
0570    result.resize(1, 1);
0571    *result.limbs() = res;
0572    result.sign(a.sign());
0573 }
0574 
0575 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>
0576 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
0577 eval_modulus(
0578    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0579    const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0580    signed_limb_type                                                            b)
0581 {
0582    const limb_type t = b < 0 ? static_cast<limb_type>(-b) : static_cast<limb_type>(b);
0583    eval_modulus(result, a, t);
0584    result.sign(a.sign());
0585 }
0586 
0587 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>
0588 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
0589 eval_modulus(
0590     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0591     const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
0592 {
0593    // There is no in place divide:
0594    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
0595    eval_modulus(result, a, b);
0596 }
0597 
0598 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0599 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
0600 eval_modulus(
0601     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0602     limb_type                                                             b)
0603 {
0604    // Single limb modulus is in place:
0605    eval_modulus(result, result, b);
0606 }
0607 
0608 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0609 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
0610 eval_modulus(
0611     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0612     signed_limb_type                                                      b)
0613 {
0614    // Single limb modulus is in place:
0615    eval_modulus(result, result, b);
0616 }
0617 
0618 //
0619 // Over again for trivial cpp_int's:
0620 //
0621 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0622 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0623     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
0624 eval_divide(
0625     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0626     const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
0627 {
0628    if (!*o.limbs())
0629       BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
0630    *result.limbs() /= *o.limbs();
0631    result.sign(result.sign() != o.sign());
0632 }
0633 
0634 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0635 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0636     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
0637 eval_divide(
0638     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0639     const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
0640 {
0641    if (!*o.limbs())
0642       BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
0643    *result.limbs() /= *o.limbs();
0644 }
0645 
0646 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0647 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0648     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>::type
0649 eval_modulus(
0650     cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&       result,
0651     const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
0652 {
0653    if (!*o.limbs())
0654       BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
0655    *result.limbs() %= *o.limbs();
0656    result.sign(result.sign());
0657 }
0658 
0659 }}} // namespace boost::multiprecision::backends
0660 
0661 #endif