summaryrefslogtreecommitdiff
path: root/boost/multiprecision/cpp_int/divide.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/multiprecision/cpp_int/divide.hpp')
-rw-r--r--boost/multiprecision/cpp_int/divide.hpp633
1 files changed, 633 insertions, 0 deletions
diff --git a/boost/multiprecision/cpp_int/divide.hpp b/boost/multiprecision/cpp_int/divide.hpp
new file mode 100644
index 0000000000..b5c9b5e220
--- /dev/null
+++ b/boost/multiprecision/cpp_int/divide.hpp
@@ -0,0 +1,633 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2012 John Maddock. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+//
+// Comparison operators for cpp_int_backend:
+//
+#ifndef BOOST_MP_CPP_INT_DIV_HPP
+#define BOOST_MP_CPP_INT_DIV_HPP
+
+namespace boost{ namespace multiprecision{ namespace backends{
+
+template <class CppInt1, class CppInt2, class CppInt3>
+void divide_unsigned_helper(
+ CppInt1* result,
+ const CppInt2& x,
+ const CppInt3& y,
+ CppInt1& r)
+{
+ if(((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
+ {
+ CppInt2 t(x);
+ divide_unsigned_helper(result, t, y, r);
+ return;
+ }
+ if(((void*)result == (void*)&y) || ((void*)&r == (void*)&y))
+ {
+ CppInt3 t(y);
+ divide_unsigned_helper(result, x, t, r);
+ return;
+ }
+
+ /*
+ Very simple, fairly braindead long division.
+ Start by setting the remainder equal to x, and the
+ result equal to 0. Then in each loop we calculate our
+ "best guess" for how many times y divides into r,
+ add our guess to the result, and subtract guess*y
+ from the remainder r. One wrinkle is that the remainder
+ may go negative, in which case we subtract the current guess
+ from the result rather than adding. The value of the guess
+ is determined by dividing the most-significant-limb of the
+ current remainder by the most-significant-limb of y.
+
+ Note that there are more efficient algorithms than this
+ available, in particular see Knuth Vol 2. However for small
+ numbers of limbs this generally outperforms the alternatives
+ and avoids the normalisation step which would require extra storage.
+ */
+
+
+ using default_ops::eval_subtract;
+
+ if(result == &r)
+ {
+ CppInt1 rem;
+ divide_unsigned_helper(result, x, y, rem);
+ r = rem;
+ return;
+ }
+
+ //
+ // Find the most significant words of numerator and denominator.
+ //
+ limb_type y_order = y.size() - 1;
+
+ if(y_order == 0)
+ {
+ //
+ // Only a single non-zero limb in the denominator, in this case
+ // we can use a specialized divide-by-single-limb routine which is
+ // much faster. This also handles division by zero:
+ //
+ divide_unsigned_helper(result, x, y.limbs()[y_order], r);
+ return;
+ }
+
+ typename CppInt2::const_limb_pointer px = x.limbs();
+ typename CppInt3::const_limb_pointer py = y.limbs();
+
+ limb_type r_order = x.size() - 1;
+ if((r_order == 0) && (*px == 0))
+ {
+ // x is zero, so is the result:
+ r = x;
+ if(result)
+ *result = x;
+ return;
+ }
+
+ r = x;
+ r.sign(false);
+ if(result)
+ *result = static_cast<limb_type>(0u);
+ //
+ // Check if the remainder is already less than the divisor, if so
+ // we already have the result. Note we try and avoid a full compare
+ // if we can:
+ //
+ if(r_order <= y_order)
+ {
+ if((r_order < y_order) || (r.compare_unsigned(y) < 0))
+ {
+ return;
+ }
+ }
+
+ CppInt1 t;
+ bool r_neg = false;
+
+ //
+ // See if we can short-circuit long division, and use basic arithmetic instead:
+ //
+ if(r_order == 0)
+ {
+ if(result)
+ {
+ *result = px[0] / py[0];
+ }
+ r = px[0] % py[0];
+ return;
+ }
+ else if(r_order == 1)
+ {
+ double_limb_type a, b;
+ a = (static_cast<double_limb_type>(px[1]) << CppInt1::limb_bits) | px[0];
+ b = y_order ?
+ (static_cast<double_limb_type>(py[1]) << CppInt1::limb_bits) | py[0]
+ : py[0];
+ if(result)
+ {
+ *result = a / b;
+ }
+ r = a % b;
+ return;
+ }
+ //
+ // prepare result:
+ //
+ if(result)
+ result->resize(1 + r_order - y_order, 1 + r_order - y_order);
+ typename CppInt1::const_limb_pointer prem = r.limbs();
+ // This is initialised just to keep the compiler from emitting useless warnings later on:
+ typename CppInt1::limb_pointer pr
+ = typename CppInt1::limb_pointer();
+ if(result)
+ {
+ pr = result->limbs();
+ for(unsigned i = 1; i < 1 + r_order - y_order; ++i)
+ pr[i] = 0;
+ }
+ bool first_pass = true;
+
+ do
+ {
+ //
+ // Calculate our best guess for how many times y divides into r:
+ //
+ limb_type guess;
+ if((prem[r_order] <= py[y_order]) && (r_order > 0))
+ {
+ double_limb_type a, b, v;
+ a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
+ b = py[y_order];
+ v = a / b;
+ if(v > CppInt1::max_limb_value)
+ guess = 1;
+ else
+ {
+ guess = static_cast<limb_type>(v);
+ --r_order;
+ }
+ }
+ else if(r_order == 0)
+ {
+ guess = prem[0] / py[y_order];
+ }
+ else
+ {
+ double_limb_type a, b, v;
+ a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
+ 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);
+ v = a / b;
+ guess = static_cast<limb_type>(v);
+ }
+ BOOST_ASSERT(guess); // If the guess ever gets to zero we go on forever....
+ //
+ // Update result:
+ //
+ limb_type shift = r_order - y_order;
+ if(result)
+ {
+ if(r_neg)
+ {
+ if(pr[shift] > guess)
+ pr[shift] -= guess;
+ else
+ {
+ t.resize(shift + 1, shift + 1);
+ t.limbs()[shift] = guess;
+ for(unsigned i = 0; i < shift; ++i)
+ t.limbs()[i] = 0;
+ eval_subtract(*result, t);
+ }
+ }
+ else if(CppInt1::max_limb_value - pr[shift] > guess)
+ pr[shift] += guess;
+ else
+ {
+ t.resize(shift + 1, shift + 1);
+ t.limbs()[shift] = guess;
+ for(unsigned i = 0; i < shift; ++i)
+ t.limbs()[i] = 0;
+ eval_add(*result, t);
+ }
+ }
+ //
+ // Calculate guess * y, we use a fused mutiply-shift O(N) for this
+ // rather than a full O(N^2) multiply:
+ //
+ double_limb_type carry = 0;
+ t.resize(y.size() + shift + 1, y.size() + shift);
+ bool truncated_t = !CppInt1::variable && (t.size() != y.size() + shift + 1);
+ typename CppInt1::limb_pointer pt = t.limbs();
+ for(unsigned i = 0; i < shift; ++i)
+ pt[i] = 0;
+ for(unsigned i = 0; i < y.size(); ++i)
+ {
+ carry += static_cast<double_limb_type>(py[i]) * static_cast<double_limb_type>(guess);
+ pt[i + shift] = static_cast<limb_type>(carry);
+ carry >>= CppInt1::limb_bits;
+ }
+ if(carry && !truncated_t)
+ {
+ pt[t.size() - 1] = static_cast<limb_type>(carry);
+ }
+ else if(!truncated_t)
+ {
+ t.resize(t.size() - 1, t.size() - 1);
+ }
+ //
+ // Update r in a way that won't actually produce a negative result
+ // in case the argument types are unsigned:
+ //
+ if(r.compare(t) > 0)
+ {
+ eval_subtract(r, t);
+ }
+ else
+ {
+ r.swap(t);
+ eval_subtract(r, t);
+ prem = r.limbs();
+ r_neg = !r_neg;
+ }
+ //
+ // First time through we need to strip any leading zero, otherwise
+ // the termination condition goes belly-up:
+ //
+ if(result && first_pass)
+ {
+ first_pass = false;
+ while(pr[result->size() - 1] == 0)
+ result->resize(result->size() - 1, result->size() - 1);
+ }
+ //
+ // Update r_order:
+ //
+ r_order = r.size() - 1;
+ if(r_order < y_order)
+ break;
+ }
+ // Termination condition is really just a check that r > y, but with a common
+ // short-circuit case handled first:
+ while((r_order > y_order) || (r.compare_unsigned(y) >= 0));
+
+ //
+ // We now just have to normalise the result:
+ //
+ if(r_neg && eval_get_sign(r))
+ {
+ // We have one too many in the result:
+ if(result)
+ eval_decrement(*result);
+ if(y.sign())
+ {
+ r.negate();
+ eval_subtract(r, y);
+ }
+ else
+ eval_subtract(r, y, r);
+ }
+
+ BOOST_ASSERT(r.compare_unsigned(y) < 0); // remainder must be less than the divisor or our code has failed
+}
+
+template <class CppInt1, class CppInt2>
+void divide_unsigned_helper(
+ CppInt1* result,
+ const CppInt2& x,
+ limb_type y,
+ CppInt1& r)
+{
+ if(((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
+ {
+ CppInt2 t(x);
+ divide_unsigned_helper(result, t, y, r);
+ return;
+ }
+
+ if(result == &r)
+ {
+ CppInt1 rem;
+ divide_unsigned_helper(result, x, y, rem);
+ r = rem;
+ return;
+ }
+
+ // As above, but simplified for integer divisor:
+
+ using default_ops::eval_subtract;
+
+ if(y == 0)
+ {
+ BOOST_THROW_EXCEPTION(std::overflow_error("Integer Division by zero."));
+ }
+ //
+ // Find the most significant word of numerator.
+ //
+ limb_type r_order = x.size() - 1;
+
+ //
+ // Set remainder and result to their initial values:
+ //
+ r = x;
+ r.sign(false);
+ typename CppInt1::limb_pointer pr = r.limbs();
+
+ //
+ // check for x < y, try to do this without actually having to
+ // do a full comparison:
+ //
+ if((r_order == 0) && (*pr < y))
+ {
+ if(result)
+ *result = static_cast<limb_type>(0u);
+ return;
+ }
+
+ //
+ // See if we can short-circuit long division, and use basic arithmetic instead:
+ //
+ if(r_order == 0)
+ {
+ if(result)
+ {
+ *result = *pr / y;
+ result->sign(x.sign());
+ }
+ *pr %= y;
+ r.sign(x.sign());
+ return;
+ }
+ else if(r_order == 1)
+ {
+ double_limb_type a;
+ a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[0];
+ if(result)
+ {
+ *result = a / y;
+ result->sign(x.sign());
+ }
+ r = a % y;
+ r.sign(x.sign());
+ return;
+ }
+
+ // This is initialised just to keep the compiler from emitting useless warnings later on:
+ typename CppInt1::limb_pointer pres = typename CppInt1::limb_pointer();
+ if(result)
+ {
+ result->resize(r_order + 1, r_order + 1);
+ pres = result->limbs();
+ if(result->size() > r_order)
+ pres[r_order] = 0; // just in case we don't set the most significant limb below.
+ }
+
+ do
+ {
+ //
+ // Calculate our best guess for how many times y divides into r:
+ //
+ if((pr[r_order] < y) && r_order)
+ {
+ double_limb_type a, b;
+ a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[r_order - 1];
+ b = a % y;
+ r.resize(r.size() - 1, r.size() - 1);
+ --r_order;
+ pr[r_order] = static_cast<limb_type>(b);
+ if(result)
+ pres[r_order] = static_cast<limb_type>(a / y);
+ if(r_order && pr[r_order] == 0)
+ {
+ --r_order; // No remainder, division was exact.
+ r.resize(r.size() - 1, r.size() - 1);
+ if(result)
+ pres[r_order] = static_cast<limb_type>(0u);
+ }
+ }
+ else
+ {
+ if(result)
+ pres[r_order] = pr[r_order] / y;
+ pr[r_order] %= y;
+ if(r_order && pr[r_order] == 0)
+ {
+ --r_order; // No remainder, division was exact.
+ r.resize(r.size() - 1, r.size() - 1);
+ if(result)
+ pres[r_order] = static_cast<limb_type>(0u);
+ }
+ }
+ }
+ // Termination condition is really just a check that r >= y, but with two common
+ // short-circuit cases handled first:
+ while(r_order || (pr[r_order] >= y));
+
+ if(result)
+ {
+ result->normalize();
+ result->sign(x.sign());
+ }
+ r.normalize();
+ r.sign(x.sign());
+
+ BOOST_ASSERT(r.compare(y) < 0); // remainder must be less than the divisor or our code has failed
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value >::type
+ eval_divide(
+ 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)
+{
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
+ bool s = a.sign() != b.sign();
+ divide_unsigned_helper(&result, a, b, r);
+ result.sign(s);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
+ eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ limb_type& b)
+{
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
+ bool s = a.sign();
+ divide_unsigned_helper(&result, a, b, r);
+ result.sign(s);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
+ eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ signed_limb_type& b)
+{
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
+ bool s = a.sign() != (b < 0);
+ divide_unsigned_helper(&result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(b)), r);
+ result.sign(s);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
+ eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
+{
+ // There is no in place divide:
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
+ eval_divide(result, a, b);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+ eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ limb_type b)
+{
+ // There is no in place divide:
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
+ eval_divide(result, a, b);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+ eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ signed_limb_type b)
+{
+ // There is no in place divide:
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
+ eval_divide(result, a, b);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value >::type
+ eval_modulus(
+ 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)
+{
+ bool s = a.sign();
+ divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, b, result);
+ result.sign(s);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
+ eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a, limb_type b)
+{
+ bool s = a.sign();
+ divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, b, result);
+ result.sign(s);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
+ eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
+ signed_limb_type b)
+{
+ bool s = a.sign();
+ divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, static_cast<limb_type>(std::abs(b)), result);
+ result.sign(s);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
+ eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
+{
+ // There is no in place divide:
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
+ eval_modulus(result, a, b);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+ eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ limb_type b)
+{
+ // There is no in place divide:
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
+ eval_modulus(result, a, b);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
+ eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ signed_limb_type b)
+{
+ // There is no in place divide:
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
+ eval_modulus(result, a, b);
+}
+
+//
+// Over again for trivial cpp_int's:
+//
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE typename enable_if_c<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ && (is_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_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
+{
+ if(!*o.limbs())
+ BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
+ *result.limbs() /= *o.limbs();
+ result.sign(result.sign() != o.sign());
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE typename enable_if_c<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ >::type
+ eval_divide(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
+{
+ if(!*o.limbs())
+ BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
+ *result.limbs() /= *o.limbs();
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE typename enable_if_c<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ >::type
+ eval_modulus(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
+{
+ if(!*o.limbs())
+ BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
+ *result.limbs() %= *o.limbs();
+ result.sign(result.sign());
+}
+
+}}} // namespaces
+
+#endif