| /////////////////////////////////////////////////////////////// |
| // 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 |