File indexing completed on 2025-01-18 09:42:14
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MP_CPP_INT_DIVIDE_HPP
0009 #define BOOST_MP_CPP_INT_DIVIDE_HPP
0010
0011 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
0012 #include <boost/multiprecision/detail/assert.hpp>
0013
0014 namespace boost { namespace multiprecision { namespace backends {
0015
0016 template <class CppInt1, class CppInt2, class CppInt3>
0017 BOOST_MP_CXX14_CONSTEXPR void divide_unsigned_helper(
0018 CppInt1* result,
0019 const CppInt2& x,
0020 const CppInt3& y,
0021 CppInt1& r)
0022 {
0023 if (((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
0024 {
0025 CppInt2 t(x);
0026 divide_unsigned_helper(result, t, y, r);
0027 return;
0028 }
0029 if (((void*)result == (void*)&y) || ((void*)&r == (void*)&y))
0030 {
0031 CppInt3 t(y);
0032 divide_unsigned_helper(result, x, t, r);
0033 return;
0034 }
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 using default_ops::eval_subtract;
0055
0056 if (result == &r)
0057 {
0058 CppInt1 rem;
0059 divide_unsigned_helper(result, x, y, rem);
0060 r = rem;
0061 return;
0062 }
0063
0064
0065
0066
0067 std::size_t y_order = y.size() - 1;
0068
0069 if (y_order == 0)
0070 {
0071
0072
0073
0074
0075
0076 divide_unsigned_helper(result, x, y.limbs()[y_order], r);
0077 return;
0078 }
0079
0080 typename CppInt2::const_limb_pointer px = x.limbs();
0081 typename CppInt3::const_limb_pointer py = y.limbs();
0082
0083 std::size_t r_order = x.size() - 1;
0084 if ((r_order == 0) && (*px == 0))
0085 {
0086
0087 r = x;
0088 if (result)
0089 *result = x;
0090 return;
0091 }
0092
0093 r = x;
0094 r.sign(false);
0095 if (result)
0096 *result = static_cast<limb_type>(0u);
0097
0098
0099
0100
0101
0102 if (r_order <= y_order)
0103 {
0104 if ((r_order < y_order) || (r.compare_unsigned(y) < 0))
0105 {
0106 return;
0107 }
0108 }
0109
0110 CppInt1 t;
0111 bool r_neg = false;
0112
0113
0114
0115
0116 if (r_order == 0)
0117 {
0118 if (result)
0119 {
0120 *result = px[0] / py[0];
0121 }
0122 r = px[0] % py[0];
0123 return;
0124 }
0125 else if (r_order == 1)
0126 {
0127 double_limb_type a = (static_cast<double_limb_type>(px[1]) << CppInt1::limb_bits) | px[0];
0128 double_limb_type b = y_order ? (static_cast<double_limb_type>(py[1]) << CppInt1::limb_bits) | py[0]
0129 : py[0];
0130 if (result)
0131 {
0132 *result = a / b;
0133 }
0134 r = a % b;
0135 return;
0136 }
0137
0138
0139
0140 if (result)
0141 result->resize(1 + r_order - y_order, 1 + r_order - y_order);
0142 typename CppInt1::const_limb_pointer prem = r.limbs();
0143
0144 typename CppInt1::limb_pointer pr = typename CppInt1::limb_pointer();
0145 if (result)
0146 {
0147 pr = result->limbs();
0148 for (std::size_t i = 1; i < 1 + r_order - y_order; ++i)
0149 pr[i] = 0;
0150 }
0151 bool first_pass = true;
0152
0153 do
0154 {
0155
0156
0157
0158 limb_type guess = 1;
0159 if ((prem[r_order] <= py[y_order]) && (r_order > 0))
0160 {
0161 double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
0162 double_limb_type b = py[y_order];
0163 double_limb_type v = a / b;
0164 if (v <= CppInt1::max_limb_value)
0165 {
0166 guess = static_cast<limb_type>(v);
0167 --r_order;
0168 }
0169 }
0170 else if (r_order == 0)
0171 {
0172 guess = prem[0] / py[y_order];
0173 }
0174 else
0175 {
0176 double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
0177 double_limb_type b = (y_order > 0) ? (static_cast<double_limb_type>(py[y_order]) << CppInt1::limb_bits) | py[y_order - 1] : (static_cast<double_limb_type>(py[y_order]) << CppInt1::limb_bits);
0178 BOOST_MP_ASSERT(b);
0179 double_limb_type v = a / b;
0180 guess = static_cast<limb_type>(v);
0181 }
0182 BOOST_MP_ASSERT(guess);
0183
0184
0185
0186 std::size_t shift = r_order - y_order;
0187 if (result)
0188 {
0189 if (r_neg)
0190 {
0191 if (pr[shift] > guess)
0192 pr[shift] -= guess;
0193 else
0194 {
0195 t.resize(shift + 1, shift + 1);
0196 t.limbs()[shift] = guess;
0197 for (std::size_t i = 0; i < shift; ++i)
0198 t.limbs()[i] = 0;
0199 eval_subtract(*result, t);
0200 }
0201 }
0202 else if (CppInt1::max_limb_value - pr[shift] > guess)
0203 pr[shift] += guess;
0204 else
0205 {
0206 t.resize(shift + 1, shift + 1);
0207 t.limbs()[shift] = guess;
0208 for (std::size_t i = 0; i < shift; ++i)
0209 t.limbs()[i] = 0;
0210 eval_add(*result, t);
0211 }
0212 }
0213
0214
0215
0216
0217 double_limb_type carry = 0;
0218 t.resize(y.size() + shift + 1, y.size() + shift);
0219 bool truncated_t = (t.size() != y.size() + shift + 1);
0220 typename CppInt1::limb_pointer pt = t.limbs();
0221 for (std::size_t i = 0; i < shift; ++i)
0222 pt[i] = 0;
0223 for (std::size_t i = 0; i < y.size(); ++i)
0224 {
0225 carry += static_cast<double_limb_type>(py[i]) * static_cast<double_limb_type>(guess);
0226 #ifdef __MSVC_RUNTIME_CHECKS
0227 pt[i + shift] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
0228 #else
0229 pt[i + shift] = static_cast<limb_type>(carry);
0230 #endif
0231 carry >>= CppInt1::limb_bits;
0232 }
0233 if (carry && !truncated_t)
0234 {
0235 #ifdef __MSVC_RUNTIME_CHECKS
0236 pt[t.size() - 1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
0237 #else
0238 pt[t.size() - 1] = static_cast<limb_type>(carry);
0239 #endif
0240 }
0241 else if (!truncated_t)
0242 {
0243 t.resize(t.size() - 1, t.size() - 1);
0244 }
0245
0246
0247
0248
0249 if (truncated_t && carry)
0250 {
0251
0252
0253
0254
0255
0256 for (std::size_t i = 0; i <= r_order; ++i)
0257 r.limbs()[i] = ~prem[i];
0258 r.normalize();
0259 eval_increment(r);
0260 eval_add(r, t);
0261 r_neg = !r_neg;
0262 }
0263 else if (r.compare(t) > 0)
0264 {
0265 eval_subtract(r, t);
0266 }
0267 else
0268 {
0269 r.swap(t);
0270 eval_subtract(r, t);
0271 prem = r.limbs();
0272 r_neg = !r_neg;
0273 }
0274
0275
0276
0277
0278 if (result && first_pass)
0279 {
0280 first_pass = false;
0281 while (pr[result->size() - 1] == 0)
0282 result->resize(result->size() - 1, result->size() - 1);
0283 }
0284
0285
0286
0287 r_order = r.size() - 1;
0288 if (r_order < y_order)
0289 break;
0290 }
0291
0292
0293 while ((r_order > y_order) || (r.compare_unsigned(y) >= 0));
0294
0295
0296
0297
0298 if (r_neg && eval_get_sign(r))
0299 {
0300
0301 if (result)
0302 eval_decrement(*result);
0303 if (y.sign())
0304 {
0305 r.negate();
0306 eval_subtract(r, y);
0307 }
0308 else
0309 eval_subtract(r, y, r);
0310 }
0311
0312 BOOST_MP_ASSERT(r.compare_unsigned(y) < 0);
0313 }
0314
0315 template <class CppInt1, class CppInt2>
0316 BOOST_MP_CXX14_CONSTEXPR void divide_unsigned_helper(
0317 CppInt1* result,
0318 const CppInt2& x,
0319 limb_type y,
0320 CppInt1& r)
0321 {
0322 if (((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
0323 {
0324 CppInt2 t(x);
0325 divide_unsigned_helper(result, t, y, r);
0326 return;
0327 }
0328
0329 if (result == &r)
0330 {
0331 CppInt1 rem;
0332 divide_unsigned_helper(result, x, y, rem);
0333 r = rem;
0334 return;
0335 }
0336
0337
0338
0339 using default_ops::eval_subtract;
0340
0341 if (y == 0)
0342 {
0343 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer Division by zero."));
0344 }
0345
0346
0347
0348 std::size_t r_order = x.size() - 1;
0349
0350
0351
0352
0353 r = x;
0354 r.sign(false);
0355 typename CppInt1::limb_pointer pr = r.limbs();
0356
0357
0358
0359
0360
0361 if ((r_order == 0) && (*pr < y))
0362 {
0363 if (result)
0364 *result = static_cast<limb_type>(0u);
0365 return;
0366 }
0367
0368
0369
0370
0371 if (r_order == 0)
0372 {
0373 if (result)
0374 {
0375 *result = *pr / y;
0376 result->sign(x.sign());
0377 }
0378 *pr %= y;
0379 r.sign(x.sign());
0380 return;
0381 }
0382 else if (r_order == 1)
0383 {
0384 double_limb_type a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[0];
0385 if (result)
0386 {
0387 *result = a / y;
0388 result->sign(x.sign());
0389 }
0390 r = a % y;
0391 r.sign(x.sign());
0392 return;
0393 }
0394
0395
0396 typename CppInt1::limb_pointer pres = typename CppInt1::limb_pointer();
0397 if (result)
0398 {
0399 result->resize(r_order + 1, r_order + 1);
0400 pres = result->limbs();
0401 if (result->size() > r_order)
0402 pres[r_order] = 0;
0403 }
0404
0405 do
0406 {
0407
0408
0409
0410 if ((pr[r_order] < y) && r_order)
0411 {
0412 double_limb_type a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[r_order - 1];
0413 double_limb_type b = a % y;
0414 r.resize(r.size() - 1, r.size() - 1);
0415 --r_order;
0416 pr[r_order] = static_cast<limb_type>(b);
0417 if (result)
0418 pres[r_order] = static_cast<limb_type>(a / y);
0419 if (r_order && pr[r_order] == 0)
0420 {
0421 --r_order;
0422 r.resize(r.size() - 1, r.size() - 1);
0423 if (result)
0424 pres[r_order] = static_cast<limb_type>(0u);
0425 }
0426 }
0427 else
0428 {
0429 if (result)
0430 pres[r_order] = pr[r_order] / y;
0431 pr[r_order] %= y;
0432 if (r_order && pr[r_order] == 0)
0433 {
0434 --r_order;
0435 r.resize(r.size() - 1, r.size() - 1);
0436 if (result)
0437 pres[r_order] = static_cast<limb_type>(0u);
0438 }
0439 }
0440 }
0441
0442
0443 while (r_order || (pr[r_order] >= y));
0444
0445 if (result)
0446 {
0447 result->normalize();
0448 result->sign(x.sign());
0449 }
0450 r.normalize();
0451 r.sign(x.sign());
0452
0453 BOOST_MP_ASSERT(r.compare(y) < 0);
0454 }
0455
0456 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
0457 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
0458 eval_divide(
0459 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0460 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0461 const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
0462 {
0463 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
0464 bool s = a.sign() != b.sign();
0465 divide_unsigned_helper(&result, a, b, r);
0466 result.sign(s);
0467 }
0468
0469 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0470 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
0471 eval_divide(
0472 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0473 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0474 limb_type& b)
0475 {
0476 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
0477 bool s = a.sign();
0478 divide_unsigned_helper(&result, a, b, r);
0479 result.sign(s);
0480 }
0481
0482 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0483 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
0484 eval_divide(
0485 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0486 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0487 signed_limb_type& b)
0488 {
0489 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
0490 bool s = a.sign() != (b < 0);
0491 divide_unsigned_helper(&result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(b)), r);
0492 result.sign(s);
0493 }
0494
0495 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0496 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
0497 eval_divide(
0498 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0499 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
0500 {
0501
0502 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
0503 eval_divide(result, a, b);
0504 }
0505
0506 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0507 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
0508 eval_divide(
0509 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0510 limb_type b)
0511 {
0512
0513 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
0514 eval_divide(result, a, b);
0515 }
0516
0517 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0518 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
0519 eval_divide(
0520 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0521 signed_limb_type b)
0522 {
0523
0524 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
0525 eval_divide(result, a, b);
0526 }
0527
0528 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, std::size_t MinBits3, std::size_t MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
0529 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
0530 eval_modulus(
0531 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0532 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0533 const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
0534 {
0535 bool s = a.sign();
0536 if (b.size() == 1)
0537 eval_modulus(result, a, *b.limbs());
0538 else
0539 {
0540 using cpp_int_backend1_type = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>;
0541
0542 divide_unsigned_helper(static_cast<cpp_int_backend1_type*>(nullptr), a, b, result);
0543 }
0544 result.sign(s);
0545 }
0546
0547 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0548 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
0549 eval_modulus(
0550 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0551 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0552 const limb_type mod)
0553 {
0554 const std::ptrdiff_t n = static_cast<std::ptrdiff_t>(a.size());
0555
0556 const double_limb_type two_n_mod =
0557 static_cast<double_limb_type>
0558 (
0559 static_cast<double_limb_type>(1u) + static_cast<limb_type>(static_cast<limb_type>(~static_cast<limb_type>(0u) - mod) % mod)
0560 );
0561
0562 limb_type res = a.limbs()[n - 1] % mod;
0563
0564 for (std::ptrdiff_t i = n - 2; i >= 0; --i)
0565 res = static_cast<limb_type>(static_cast<double_limb_type>(static_cast<double_limb_type>(res * two_n_mod) + a.limbs()[i]) % mod);
0566
0567
0568
0569
0570 result.resize(1, 1);
0571 *result.limbs() = res;
0572 result.sign(a.sign());
0573 }
0574
0575 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0576 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
0577 eval_modulus(
0578 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0579 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
0580 signed_limb_type b)
0581 {
0582 const limb_type t = b < 0 ? static_cast<limb_type>(-b) : static_cast<limb_type>(b);
0583 eval_modulus(result, a, t);
0584 result.sign(a.sign());
0585 }
0586
0587 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0588 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
0589 eval_modulus(
0590 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0591 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
0592 {
0593
0594 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
0595 eval_modulus(result, a, b);
0596 }
0597
0598 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0599 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
0600 eval_modulus(
0601 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0602 limb_type b)
0603 {
0604
0605 eval_modulus(result, result, b);
0606 }
0607
0608 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0609 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
0610 eval_modulus(
0611 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0612 signed_limb_type b)
0613 {
0614
0615 eval_modulus(result, result, b);
0616 }
0617
0618
0619
0620
0621 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0622 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0623 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)>::type
0624 eval_divide(
0625 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0626 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
0627 {
0628 if (!*o.limbs())
0629 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
0630 *result.limbs() /= *o.limbs();
0631 result.sign(result.sign() != o.sign());
0632 }
0633
0634 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0635 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0636 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
0637 eval_divide(
0638 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0639 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
0640 {
0641 if (!*o.limbs())
0642 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
0643 *result.limbs() /= *o.limbs();
0644 }
0645
0646 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0647 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0648 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
0649 eval_modulus(
0650 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0651 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
0652 {
0653 if (!*o.limbs())
0654 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
0655 *result.limbs() %= *o.limbs();
0656 result.sign(result.sign());
0657 }
0658
0659 }}}
0660
0661 #endif