123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 |
- ///////////////////////////////////////////////////////////////
- // Copyright 2012 John Maddock. Distributed under the Boost
- // Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
- //
- // Comparison operators for cpp_int_backend:
- //
- #ifndef BOOST_MP_CPP_INT_DIVIDE_HPP
- #define BOOST_MP_CPP_INT_DIVIDE_HPP
- #include <boost/multiprecision/detail/no_exceptions_support.hpp>
- #include <boost/multiprecision/detail/assert.hpp>
- namespace boost { namespace multiprecision { namespace backends {
- template <class CppInt1, class CppInt2, class CppInt3>
- BOOST_MP_CXX14_CONSTEXPR 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.
- //
- std::size_t 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();
- std::size_t 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 = (static_cast<double_limb_type>(px[1]) << CppInt1::limb_bits) | px[0];
- double_limb_type 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 (std::size_t 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 = 1;
- if ((prem[r_order] <= py[y_order]) && (r_order > 0))
- {
- double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
- double_limb_type b = py[y_order];
- double_limb_type v = a / b;
- if (v <= CppInt1::max_limb_value)
- {
- guess = static_cast<limb_type>(v);
- --r_order;
- }
- }
- else if (r_order == 0)
- {
- guess = prem[0] / py[y_order];
- }
- else
- {
- double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
- 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);
- BOOST_MP_ASSERT(b);
- double_limb_type v = a / b;
- guess = static_cast<limb_type>(v);
- }
- BOOST_MP_ASSERT(guess); // If the guess ever gets to zero we go on forever....
- //
- // Update result:
- //
- std::size_t 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 (std::size_t 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 (std::size_t 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 = (t.size() != y.size() + shift + 1);
- typename CppInt1::limb_pointer pt = t.limbs();
- for (std::size_t i = 0; i < shift; ++i)
- pt[i] = 0;
- for (std::size_t i = 0; i < y.size(); ++i)
- {
- carry += static_cast<double_limb_type>(py[i]) * static_cast<double_limb_type>(guess);
- #ifdef __MSVC_RUNTIME_CHECKS
- pt[i + shift] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
- #else
- pt[i + shift] = static_cast<limb_type>(carry);
- #endif
- carry >>= CppInt1::limb_bits;
- }
- if (carry && !truncated_t)
- {
- #ifdef __MSVC_RUNTIME_CHECKS
- pt[t.size() - 1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
- #else
- pt[t.size() - 1] = static_cast<limb_type>(carry);
- #endif
- }
- 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 (truncated_t && carry)
- {
- // We need to calculate 2^n + t - r
- // where n is the number of bits in this type.
- // Simplest way is to get 2^n - r by complementing
- // r, then add t to it. Note that we can't call eval_complement
- // in case this is a signed checked type:
- for (std::size_t i = 0; i <= r_order; ++i)
- r.limbs()[i] = ~prem[i];
- r.normalize();
- eval_increment(r);
- eval_add(r, t);
- r_neg = !r_neg;
- }
- else 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_MP_ASSERT(r.compare_unsigned(y) < 0); // remainder must be less than the divisor or our code has failed
- }
- template <class CppInt1, class CppInt2>
- BOOST_MP_CXX14_CONSTEXPR 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_MP_THROW_EXCEPTION(std::overflow_error("Integer Division by zero."));
- }
- //
- // Find the most significant word of numerator.
- //
- std::size_t 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 = (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 = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[r_order - 1];
- double_limb_type 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_MP_ASSERT(r.compare(y) < 0); // remainder must be less than the divisor or our code has failed
- }
- template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
- eval_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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
- eval_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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
- eval_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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
- eval_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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
- eval_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();
- if (b.size() == 1)
- eval_modulus(result, a, *b.limbs());
- else
- {
- using cpp_int_backend1_type = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>;
- divide_unsigned_helper(static_cast<cpp_int_backend1_type*>(nullptr), a, b, result);
- }
- result.sign(s);
- }
- template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- const limb_type mod)
- {
- const std::ptrdiff_t n = static_cast<std::ptrdiff_t>(a.size());
- const double_limb_type two_n_mod =
- static_cast<double_limb_type>
- (
- static_cast<double_limb_type>(1u) + static_cast<limb_type>(static_cast<limb_type>(~static_cast<limb_type>(0u) - mod) % mod)
- );
- limb_type res = a.limbs()[n - 1] % mod;
- for (std::ptrdiff_t i = n - 2; i >= 0; --i)
- res = static_cast<limb_type>(static_cast<double_limb_type>(static_cast<double_limb_type>(res * two_n_mod) + a.limbs()[i]) % mod);
- //
- // We must not modify result until here in case
- // result and a are the same object:
- //
- result.resize(1, 1);
- *result.limbs() = res;
- result.sign(a.sign());
- }
- template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
- signed_limb_type b)
- {
- const limb_type t = b < 0 ? static_cast<limb_type>(-b) : static_cast<limb_type>(b);
- eval_modulus(result, a, t);
- result.sign(a.sign());
- }
- template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
- eval_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 <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- limb_type b)
- {
- // Single limb modulus is in place:
- eval_modulus(result, result, b);
- }
- template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- signed_limb_type b)
- {
- // Single limb modulus is in place:
- eval_modulus(result, result, b);
- }
- //
- // Over again for trivial cpp_int's:
- //
- template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (is_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_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- *result.limbs() /= *o.limbs();
- result.sign(result.sign() != o.sign());
- }
- template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_divide(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
- {
- if (!*o.limbs())
- BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- *result.limbs() /= *o.limbs();
- }
- template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::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_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- *result.limbs() %= *o.limbs();
- result.sign(result.sign());
- }
- }}} // namespace boost::multiprecision::backends
- #endif
|