123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703 |
- #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;
- }
-
- using default_ops::eval_subtract;
- if (result == &r)
- {
- CppInt1 rem;
- divide_unsigned_helper(result, x, y, rem);
- r = rem;
- return;
- }
-
-
-
- std::size_t y_order = y.size() - 1;
- if (y_order == 0)
- {
-
-
-
-
-
- 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))
- {
-
- r = x;
- if (result)
- *result = x;
- return;
- }
- r = x;
- r.sign(false);
- if (result)
- *result = static_cast<limb_type>(0u);
-
-
-
-
-
- if (r_order <= y_order)
- {
- if ((r_order < y_order) || (r.compare_unsigned(y) < 0))
- {
- return;
- }
- }
- CppInt1 t;
- bool r_neg = false;
-
-
-
- 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;
- }
-
-
-
- if (result)
- result->resize(1 + r_order - y_order, 1 + r_order - y_order);
- typename CppInt1::const_limb_pointer prem = r.limbs();
-
- 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
- {
-
-
-
- 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);
-
-
-
- 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);
- }
- }
-
-
-
-
- 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);
- }
-
-
-
-
- if (truncated_t && carry)
- {
-
-
-
-
-
- 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;
- }
-
-
-
-
- if (result && first_pass)
- {
- first_pass = false;
- while (pr[result->size() - 1] == 0)
- result->resize(result->size() - 1, result->size() - 1);
- }
-
-
-
- r_order = r.size() - 1;
- if (r_order < y_order)
- break;
- }
-
-
- while ((r_order > y_order) || (r.compare_unsigned(y) >= 0));
-
-
-
- if (r_neg && eval_get_sign(r))
- {
-
- 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);
- }
- 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;
- }
-
- using default_ops::eval_subtract;
- if (y == 0)
- {
- BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer Division by zero."));
- }
-
-
-
- std::size_t r_order = x.size() - 1;
-
-
-
- r = x;
- r.sign(false);
- typename CppInt1::limb_pointer pr = r.limbs();
-
-
-
-
- if ((r_order == 0) && (*pr < y))
- {
- if (result)
- *result = static_cast<limb_type>(0u);
- return;
- }
-
-
-
- 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;
- }
-
- 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;
- }
- do
- {
-
-
-
- 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;
- 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;
- r.resize(r.size() - 1, r.size() - 1);
- if (result)
- pres[r_order] = static_cast<limb_type>(0u);
- }
- }
- }
-
-
- 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);
- }
- 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)
- {
-
- 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)
- {
-
- 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)
- {
-
- 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)
- {
- if(mod == 0)
- BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- 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);
-
-
-
-
- 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)
- {
-
- 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)
- {
-
- 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)
- {
-
- 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 && 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());
- }
- template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class V>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_unsigned<V>::value>::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
- V o)
- {
- using local_limb_type = typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type;
- BOOST_IF_CONSTEXPR(std::numeric_limits<V>::digits > MaxBits1)
- {
- if (o >= (static_cast<V>(1u) << MaxBits1))
- {
-
-
- result = a;
- return;
- }
- }
- if (!o)
- BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
- *result.limbs() = *a.limbs() % static_cast<local_limb_type>(o);
- result.sign(a.sign());
- }
- template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class V>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && std::is_signed<V>::value>::type
- eval_modulus(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
- V o)
- {
- using unsigned_type = typename std::make_unsigned<V>::type;
- eval_modulus(result, a, static_cast<unsigned_type>(o < 0 ? -o : o));
- }
- }}}
- #endif
|