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 namespace boost { namespace multiprecision { namespace backends {
13 template <class CppInt1, class CppInt2, class CppInt3>
14 BOOST_MP_CXX14_CONSTEXPR void divide_unsigned_helper(
20 if (((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
23 divide_unsigned_helper(result, t, y, r);
26 if (((void*)result == (void*)&y) || ((void*)&r == (void*)&y))
29 divide_unsigned_helper(result, x, t, r);
34 Very simple, fairly braindead long division.
35 Start by setting the remainder equal to x, and the
36 result equal to 0. Then in each loop we calculate our
37 "best guess" for how many times y divides into r,
38 add our guess to the result, and subtract guess*y
39 from the remainder r. One wrinkle is that the remainder
40 may go negative, in which case we subtract the current guess
41 from the result rather than adding. The value of the guess
42 is determined by dividing the most-significant-limb of the
43 current remainder by the most-significant-limb of y.
45 Note that there are more efficient algorithms than this
46 available, in particular see Knuth Vol 2. However for small
47 numbers of limbs this generally outperforms the alternatives
48 and avoids the normalisation step which would require extra storage.
51 using default_ops::eval_subtract;
56 divide_unsigned_helper(result, x, y, rem);
62 // Find the most significant words of numerator and denominator.
64 limb_type y_order = y.size() - 1;
69 // Only a single non-zero limb in the denominator, in this case
70 // we can use a specialized divide-by-single-limb routine which is
71 // much faster. This also handles division by zero:
73 divide_unsigned_helper(result, x, y.limbs()[y_order], r);
77 typename CppInt2::const_limb_pointer px = x.limbs();
78 typename CppInt3::const_limb_pointer py = y.limbs();
80 limb_type r_order = x.size() - 1;
81 if ((r_order == 0) && (*px == 0))
83 // x is zero, so is the result:
93 *result = static_cast<limb_type>(0u);
95 // Check if the remainder is already less than the divisor, if so
96 // we already have the result. Note we try and avoid a full compare
99 if (r_order <= y_order)
101 if ((r_order < y_order) || (r.compare_unsigned(y) < 0))
111 // See if we can short-circuit long division, and use basic arithmetic instead:
117 *result = px[0] / py[0];
122 else if (r_order == 1)
124 double_limb_type a = (static_cast<double_limb_type>(px[1]) << CppInt1::limb_bits) | px[0];
125 double_limb_type b = y_order ? (static_cast<double_limb_type>(py[1]) << CppInt1::limb_bits) | py[0]
138 result->resize(1 + r_order - y_order, 1 + r_order - y_order);
139 typename CppInt1::const_limb_pointer prem = r.limbs();
140 // This is initialised just to keep the compiler from emitting useless warnings later on:
141 typename CppInt1::limb_pointer pr = typename CppInt1::limb_pointer();
144 pr = result->limbs();
145 for (unsigned i = 1; i < 1 + r_order - y_order; ++i)
148 bool first_pass = true;
153 // Calculate our best guess for how many times y divides into r:
156 if ((prem[r_order] <= py[y_order]) && (r_order > 0))
158 double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
159 double_limb_type b = py[y_order];
160 double_limb_type v = a / b;
161 if (v <= CppInt1::max_limb_value)
163 guess = static_cast<limb_type>(v);
167 else if (r_order == 0)
169 guess = prem[0] / py[y_order];
173 double_limb_type a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
174 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);
175 double_limb_type v = a / b;
176 guess = static_cast<limb_type>(v);
178 BOOST_ASSERT(guess); // If the guess ever gets to zero we go on forever....
182 limb_type shift = r_order - y_order;
187 if (pr[shift] > guess)
191 t.resize(shift + 1, shift + 1);
192 t.limbs()[shift] = guess;
193 for (unsigned i = 0; i < shift; ++i)
195 eval_subtract(*result, t);
198 else if (CppInt1::max_limb_value - pr[shift] > guess)
202 t.resize(shift + 1, shift + 1);
203 t.limbs()[shift] = guess;
204 for (unsigned i = 0; i < shift; ++i)
206 eval_add(*result, t);
210 // Calculate guess * y, we use a fused mutiply-shift O(N) for this
211 // rather than a full O(N^2) multiply:
213 double_limb_type carry = 0;
214 t.resize(y.size() + shift + 1, y.size() + shift);
215 bool truncated_t = (t.size() != y.size() + shift + 1);
216 typename CppInt1::limb_pointer pt = t.limbs();
217 for (unsigned i = 0; i < shift; ++i)
219 for (unsigned i = 0; i < y.size(); ++i)
221 carry += static_cast<double_limb_type>(py[i]) * static_cast<double_limb_type>(guess);
222 #ifdef __MSVC_RUNTIME_CHECKS
223 pt[i + shift] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
225 pt[i + shift] = static_cast<limb_type>(carry);
227 carry >>= CppInt1::limb_bits;
229 if (carry && !truncated_t)
231 #ifdef __MSVC_RUNTIME_CHECKS
232 pt[t.size() - 1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
234 pt[t.size() - 1] = static_cast<limb_type>(carry);
237 else if (!truncated_t)
239 t.resize(t.size() - 1, t.size() - 1);
242 // Update r in a way that won't actually produce a negative result
243 // in case the argument types are unsigned:
245 if (truncated_t && carry)
247 // We need to calculate 2^n + t - r
248 // where n is the number of bits in this type.
249 // Simplest way is to get 2^n - r by complementing
250 // r, then add t to it. Note that we can't call eval_complement
251 // in case this is a signed checked type:
252 for (unsigned i = 0; i <= r_order; ++i)
253 r.limbs()[i] = ~prem[i];
259 else if (r.compare(t) > 0)
271 // First time through we need to strip any leading zero, otherwise
272 // the termination condition goes belly-up:
274 if (result && first_pass)
277 while (pr[result->size() - 1] == 0)
278 result->resize(result->size() - 1, result->size() - 1);
283 r_order = r.size() - 1;
284 if (r_order < y_order)
287 // Termination condition is really just a check that r > y, but with a common
288 // short-circuit case handled first:
289 while ((r_order > y_order) || (r.compare_unsigned(y) >= 0));
292 // We now just have to normalise the result:
294 if (r_neg && eval_get_sign(r))
296 // We have one too many in the result:
298 eval_decrement(*result);
305 eval_subtract(r, y, r);
308 BOOST_ASSERT(r.compare_unsigned(y) < 0); // remainder must be less than the divisor or our code has failed
311 template <class CppInt1, class CppInt2>
312 BOOST_MP_CXX14_CONSTEXPR void divide_unsigned_helper(
318 if (((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
321 divide_unsigned_helper(result, t, y, r);
328 divide_unsigned_helper(result, x, y, rem);
333 // As above, but simplified for integer divisor:
335 using default_ops::eval_subtract;
339 BOOST_THROW_EXCEPTION(std::overflow_error("Integer Division by zero."));
342 // Find the most significant word of numerator.
344 limb_type r_order = x.size() - 1;
347 // Set remainder and result to their initial values:
351 typename CppInt1::limb_pointer pr = r.limbs();
354 // check for x < y, try to do this without actually having to
355 // do a full comparison:
357 if ((r_order == 0) && (*pr < y))
360 *result = static_cast<limb_type>(0u);
365 // See if we can short-circuit long division, and use basic arithmetic instead:
372 result->sign(x.sign());
378 else if (r_order == 1)
380 double_limb_type a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[0];
384 result->sign(x.sign());
391 // This is initialised just to keep the compiler from emitting useless warnings later on:
392 typename CppInt1::limb_pointer pres = typename CppInt1::limb_pointer();
395 result->resize(r_order + 1, r_order + 1);
396 pres = result->limbs();
397 if (result->size() > r_order)
398 pres[r_order] = 0; // just in case we don't set the most significant limb below.
404 // Calculate our best guess for how many times y divides into r:
406 if ((pr[r_order] < y) && r_order)
408 double_limb_type a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[r_order - 1];
409 double_limb_type b = a % y;
410 r.resize(r.size() - 1, r.size() - 1);
412 pr[r_order] = static_cast<limb_type>(b);
414 pres[r_order] = static_cast<limb_type>(a / y);
415 if (r_order && pr[r_order] == 0)
417 --r_order; // No remainder, division was exact.
418 r.resize(r.size() - 1, r.size() - 1);
420 pres[r_order] = static_cast<limb_type>(0u);
426 pres[r_order] = pr[r_order] / y;
428 if (r_order && pr[r_order] == 0)
430 --r_order; // No remainder, division was exact.
431 r.resize(r.size() - 1, r.size() - 1);
433 pres[r_order] = static_cast<limb_type>(0u);
437 // Termination condition is really just a check that r >= y, but with two common
438 // short-circuit cases handled first:
439 while (r_order || (pr[r_order] >= y));
444 result->sign(x.sign());
449 BOOST_ASSERT(r.compare(y) < 0); // remainder must be less than the divisor or our code has failed
452 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
453 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
455 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
456 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
457 const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
459 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
460 bool s = a.sign() != b.sign();
461 divide_unsigned_helper(&result, a, b, r);
465 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
466 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
468 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
469 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
472 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
474 divide_unsigned_helper(&result, a, b, r);
478 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
479 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
481 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
482 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
485 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
486 bool s = a.sign() != (b < 0);
487 divide_unsigned_helper(&result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(b)), r);
491 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
492 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
494 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
495 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
497 // There is no in place divide:
498 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
499 eval_divide(result, a, b);
502 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
503 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
505 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
508 // There is no in place divide:
509 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
510 eval_divide(result, a, b);
513 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
514 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
516 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
519 // There is no in place divide:
520 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
521 eval_divide(result, a, b);
524 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3>
525 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type
527 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
528 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
529 const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
532 divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>*>(0), a, b, result);
536 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
537 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
539 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
540 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a, limb_type b)
543 divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>*>(0), a, b, result);
547 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
548 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
550 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
551 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
555 divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>*>(0), a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(b)), result);
559 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
560 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type
562 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
563 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
565 // There is no in place divide:
566 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
567 eval_modulus(result, a, b);
570 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
571 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
573 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
576 // There is no in place divide:
577 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
578 eval_modulus(result, a, b);
581 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
582 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
584 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
587 // There is no in place divide:
588 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
589 eval_modulus(result, a, b);
593 // Over again for trivial cpp_int's:
595 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
596 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
597 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
599 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
600 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
603 BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
604 *result.limbs() /= *o.limbs();
605 result.sign(result.sign() != o.sign());
608 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
609 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
610 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
612 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
613 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
616 BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
617 *result.limbs() /= *o.limbs();
620 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
621 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
622 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
624 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
625 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
628 BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
629 *result.limbs() %= *o.limbs();
630 result.sign(result.sign());
633 }}} // namespace boost::multiprecision::backends