1 ///////////////////////////////////////////////////////////////
2 // Copyright 2012 John Maddock. Distributed under the Boost
3 // Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
6 // Comparison operators for cpp_int_backend:
8 #ifndef BOOST_MP_CPP_INT_DIV_HPP
9 #define BOOST_MP_CPP_INT_DIV_HPP
11 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
12 #include <boost/multiprecision/detail/assert.hpp>
14 namespace boost { namespace multiprecision { namespace backends {
16 template <class CppInt1, class CppInt2, class CppInt3>
17 BOOST_MP_CXX14_CONSTEXPR void divide_unsigned_helper(
23 if (((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
26 divide_unsigned_helper(result, t, y, r);
29 if (((void*)result == (void*)&y) || ((void*)&r == (void*)&y))
32 divide_unsigned_helper(result, x, t, r);
37 Very simple, fairly braindead long division.
38 Start by setting the remainder equal to x, and the
39 result equal to 0. Then in each loop we calculate our
40 "best guess" for how many times y divides into r,
41 add our guess to the result, and subtract guess*y
42 from the remainder r. One wrinkle is that the remainder
43 may go negative, in which case we subtract the current guess
44 from the result rather than adding. The value of the guess
45 is determined by dividing the most-significant-limb of the
46 current remainder by the most-significant-limb of y.
48 Note that there are more efficient algorithms than this
49 available, in particular see Knuth Vol 2. However for small
50 numbers of limbs this generally outperforms the alternatives
51 and avoids the normalisation step which would require extra storage.
54 using default_ops::eval_subtract;
59 divide_unsigned_helper(result, x, y, rem);
65 // Find the most significant words of numerator and denominator.
67 std::size_t y_order = y.size() - 1;
72 // Only a single non-zero limb in the denominator, in this case
73 // we can use a specialized divide-by-single-limb routine which is
74 // much faster. This also handles division by zero:
76 divide_unsigned_helper(result, x, y.limbs()[y_order], r);
80 typename CppInt2::const_limb_pointer px = x.limbs();
81 typename CppInt3::const_limb_pointer py = y.limbs();
83 std::size_t r_order = x.size() - 1;
84 if ((r_order == 0) && (*px == 0))
86 // x is zero, so is the result:
96 *result = static_cast<limb_type>(0u);
98 // Check if the remainder is already less than the divisor, if so
99 // we already have the result. Note we try and avoid a full compare
102 if (r_order <= y_order)
104 if ((r_order < y_order) || (r.compare_unsigned(y) < 0))
114 // See if we can short-circuit long division, and use basic arithmetic instead:
120 *result = px[0] / py[0];
125 else if (r_order == 1)
127 double_limb_type a = (static_cast<double_limb_type>(px[1]) << CppInt1::limb_bits) | px[0];
128 double_limb_type b = y_order ? (static_cast<double_limb_type>(py[1]) << CppInt1::limb_bits) | py[0]
141 result->resize(1 + r_order - y_order, 1 + r_order - y_order);
142 typename CppInt1::const_limb_pointer prem = r.limbs();
143 // This is initialised just to keep the compiler from emitting useless warnings later on:
144 typename CppInt1::limb_pointer pr = typename CppInt1::limb_pointer();
147 pr = result->limbs();
148 for (std::size_t i = 1; i < 1 + r_order - y_order; ++i)
151 bool first_pass = true;
156 // Calculate our best guess for how many times y divides into r:
159 if ((prem[r_order] <= py[y_order]) && (r_order > 0))
161 double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
162 double_limb_type b = py[y_order];
163 double_limb_type v = a / b;
164 if (v <= CppInt1::max_limb_value)
166 guess = static_cast<limb_type>(v);
170 else if (r_order == 0)
172 guess = prem[0] / py[y_order];
176 double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
177 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);
179 double_limb_type v = a / b;
180 guess = static_cast<limb_type>(v);
182 BOOST_MP_ASSERT(guess); // If the guess ever gets to zero we go on forever....
186 std::size_t shift = r_order - y_order;
191 if (pr[shift] > guess)
195 t.resize(shift + 1, shift + 1);
196 t.limbs()[shift] = guess;
197 for (std::size_t i = 0; i < shift; ++i)
199 eval_subtract(*result, t);
202 else if (CppInt1::max_limb_value - pr[shift] > guess)
206 t.resize(shift + 1, shift + 1);
207 t.limbs()[shift] = guess;
208 for (std::size_t i = 0; i < shift; ++i)
210 eval_add(*result, t);
214 // Calculate guess * y, we use a fused mutiply-shift O(N) for this
215 // rather than a full O(N^2) multiply:
217 double_limb_type carry = 0;
218 t.resize(y.size() + shift + 1, y.size() + shift);
219 bool truncated_t = (t.size() != y.size() + shift + 1);
220 typename CppInt1::limb_pointer pt = t.limbs();
221 for (std::size_t i = 0; i < shift; ++i)
223 for (std::size_t i = 0; i < y.size(); ++i)
225 carry += static_cast<double_limb_type>(py[i]) * static_cast<double_limb_type>(guess);
226 #ifdef __MSVC_RUNTIME_CHECKS
227 pt[i + shift] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
229 pt[i + shift] = static_cast<limb_type>(carry);
231 carry >>= CppInt1::limb_bits;
233 if (carry && !truncated_t)
235 #ifdef __MSVC_RUNTIME_CHECKS
236 pt[t.size() - 1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
238 pt[t.size() - 1] = static_cast<limb_type>(carry);
241 else if (!truncated_t)
243 t.resize(t.size() - 1, t.size() - 1);
246 // Update r in a way that won't actually produce a negative result
247 // in case the argument types are unsigned:
249 if (truncated_t && carry)
251 // We need to calculate 2^n + t - r
252 // where n is the number of bits in this type.
253 // Simplest way is to get 2^n - r by complementing
254 // r, then add t to it. Note that we can't call eval_complement
255 // in case this is a signed checked type:
256 for (std::size_t i = 0; i <= r_order; ++i)
257 r.limbs()[i] = ~prem[i];
263 else if (r.compare(t) > 0)
275 // First time through we need to strip any leading zero, otherwise
276 // the termination condition goes belly-up:
278 if (result && first_pass)
281 while (pr[result->size() - 1] == 0)
282 result->resize(result->size() - 1, result->size() - 1);
287 r_order = r.size() - 1;
288 if (r_order < y_order)
291 // Termination condition is really just a check that r > y, but with a common
292 // short-circuit case handled first:
293 while ((r_order > y_order) || (r.compare_unsigned(y) >= 0));
296 // We now just have to normalise the result:
298 if (r_neg && eval_get_sign(r))
300 // We have one too many in the result:
302 eval_decrement(*result);
309 eval_subtract(r, y, r);
312 BOOST_MP_ASSERT(r.compare_unsigned(y) < 0); // remainder must be less than the divisor or our code has failed
315 template <class CppInt1, class CppInt2>
316 BOOST_MP_CXX14_CONSTEXPR void divide_unsigned_helper(
322 if (((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
325 divide_unsigned_helper(result, t, y, r);
332 divide_unsigned_helper(result, x, y, rem);
337 // As above, but simplified for integer divisor:
339 using default_ops::eval_subtract;
343 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer Division by zero."));
346 // Find the most significant word of numerator.
348 std::size_t r_order = x.size() - 1;
351 // Set remainder and result to their initial values:
355 typename CppInt1::limb_pointer pr = r.limbs();
358 // check for x < y, try to do this without actually having to
359 // do a full comparison:
361 if ((r_order == 0) && (*pr < y))
364 *result = static_cast<limb_type>(0u);
369 // See if we can short-circuit long division, and use basic arithmetic instead:
376 result->sign(x.sign());
382 else if (r_order == 1)
384 double_limb_type a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[0];
388 result->sign(x.sign());
395 // This is initialised just to keep the compiler from emitting useless warnings later on:
396 typename CppInt1::limb_pointer pres = typename CppInt1::limb_pointer();
399 result->resize(r_order + 1, r_order + 1);
400 pres = result->limbs();
401 if (result->size() > r_order)
402 pres[r_order] = 0; // just in case we don't set the most significant limb below.
408 // Calculate our best guess for how many times y divides into r:
410 if ((pr[r_order] < y) && r_order)
412 double_limb_type a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[r_order - 1];
413 double_limb_type b = a % y;
414 r.resize(r.size() - 1, r.size() - 1);
416 pr[r_order] = static_cast<limb_type>(b);
418 pres[r_order] = static_cast<limb_type>(a / y);
419 if (r_order && pr[r_order] == 0)
421 --r_order; // No remainder, division was exact.
422 r.resize(r.size() - 1, r.size() - 1);
424 pres[r_order] = static_cast<limb_type>(0u);
430 pres[r_order] = pr[r_order] / y;
432 if (r_order && pr[r_order] == 0)
434 --r_order; // No remainder, division was exact.
435 r.resize(r.size() - 1, r.size() - 1);
437 pres[r_order] = static_cast<limb_type>(0u);
441 // Termination condition is really just a check that r >= y, but with two common
442 // short-circuit cases handled first:
443 while (r_order || (pr[r_order] >= y));
448 result->sign(x.sign());
453 BOOST_MP_ASSERT(r.compare(y) < 0); // remainder must be less than the divisor or our code has failed
456 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>
457 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
459 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
460 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
461 const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
463 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
464 bool s = a.sign() != b.sign();
465 divide_unsigned_helper(&result, a, b, r);
469 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>
470 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
472 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
473 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
476 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
478 divide_unsigned_helper(&result, a, b, r);
482 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>
483 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
485 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
486 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
489 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
490 bool s = a.sign() != (b < 0);
491 divide_unsigned_helper(&result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(b)), r);
495 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>
496 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
498 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
499 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
501 // There is no in place divide:
502 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
503 eval_divide(result, a, b);
506 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
507 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
509 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
512 // There is no in place divide:
513 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
514 eval_divide(result, a, b);
517 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
518 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
520 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
523 // There is no in place divide:
524 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
525 eval_divide(result, a, b);
528 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>
529 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
531 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
532 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
533 const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
537 eval_modulus(result, a, *b.limbs());
539 divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>*>(0), a, b, result);
543 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>
544 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
546 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
547 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
550 const std::ptrdiff_t n = a.size();
551 const double_limb_type two_n_mod = static_cast<limb_type>(1u) + (~static_cast<limb_type>(0u) - mod) % mod;
552 limb_type res = a.limbs()[n - 1] % mod;
554 for (std::ptrdiff_t i = n - 2; i >= 0; --i)
555 res = (res * two_n_mod + a.limbs()[i]) % mod;
557 // We must not modify result until here in case
558 // result and a are the same object:
561 *result.limbs() = res;
562 result.sign(a.sign());
565 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>
566 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
568 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
569 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
572 const limb_type t = b < 0 ? -b : b;
573 eval_modulus(result, a, t);
574 result.sign(a.sign());
577 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>
578 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
580 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
581 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
583 // There is no in place divide:
584 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
585 eval_modulus(result, a, b);
588 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
589 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
591 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
594 // Single limb modulus is in place:
595 eval_modulus(result, result, b);
598 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
599 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
601 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
604 // Single limb modulus is in place:
605 eval_modulus(result, result, b);
609 // Over again for trivial cpp_int's:
611 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
612 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
613 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
615 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
616 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
619 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
620 *result.limbs() /= *o.limbs();
621 result.sign(result.sign() != o.sign());
624 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
625 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
626 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
628 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
629 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
632 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
633 *result.limbs() /= *o.limbs();
636 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
637 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
638 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
640 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
641 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
644 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
645 *result.limbs() %= *o.limbs();
646 result.sign(result.sign());
649 }}} // namespace boost::multiprecision::backends