annotate DEPENDENCIES/generic/include/boost/multiprecision/cpp_int/divide.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 ///////////////////////////////////////////////////////////////
Chris@16 2 // Copyright 2012 John Maddock. Distributed under the Boost
Chris@16 3 // Software License, Version 1.0. (See accompanying file
Chris@16 4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
Chris@16 5 //
Chris@16 6 // Comparison operators for cpp_int_backend:
Chris@16 7 //
Chris@16 8 #ifndef BOOST_MP_CPP_INT_DIV_HPP
Chris@16 9 #define BOOST_MP_CPP_INT_DIV_HPP
Chris@16 10
Chris@16 11 namespace boost{ namespace multiprecision{ namespace backends{
Chris@16 12
Chris@16 13 template <class CppInt1, class CppInt2, class CppInt3>
Chris@16 14 void divide_unsigned_helper(
Chris@16 15 CppInt1* result,
Chris@16 16 const CppInt2& x,
Chris@16 17 const CppInt3& y,
Chris@16 18 CppInt1& r)
Chris@16 19 {
Chris@16 20 if(((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
Chris@16 21 {
Chris@16 22 CppInt2 t(x);
Chris@16 23 divide_unsigned_helper(result, t, y, r);
Chris@16 24 return;
Chris@16 25 }
Chris@16 26 if(((void*)result == (void*)&y) || ((void*)&r == (void*)&y))
Chris@16 27 {
Chris@16 28 CppInt3 t(y);
Chris@16 29 divide_unsigned_helper(result, x, t, r);
Chris@16 30 return;
Chris@16 31 }
Chris@16 32
Chris@16 33 /*
Chris@16 34 Very simple, fairly braindead long division.
Chris@16 35 Start by setting the remainder equal to x, and the
Chris@16 36 result equal to 0. Then in each loop we calculate our
Chris@16 37 "best guess" for how many times y divides into r,
Chris@16 38 add our guess to the result, and subtract guess*y
Chris@16 39 from the remainder r. One wrinkle is that the remainder
Chris@16 40 may go negative, in which case we subtract the current guess
Chris@16 41 from the result rather than adding. The value of the guess
Chris@16 42 is determined by dividing the most-significant-limb of the
Chris@16 43 current remainder by the most-significant-limb of y.
Chris@16 44
Chris@16 45 Note that there are more efficient algorithms than this
Chris@16 46 available, in particular see Knuth Vol 2. However for small
Chris@16 47 numbers of limbs this generally outperforms the alternatives
Chris@16 48 and avoids the normalisation step which would require extra storage.
Chris@16 49 */
Chris@16 50
Chris@16 51
Chris@16 52 using default_ops::eval_subtract;
Chris@16 53
Chris@16 54 if(result == &r)
Chris@16 55 {
Chris@16 56 CppInt1 rem;
Chris@16 57 divide_unsigned_helper(result, x, y, rem);
Chris@16 58 r = rem;
Chris@16 59 return;
Chris@16 60 }
Chris@16 61
Chris@16 62 //
Chris@16 63 // Find the most significant words of numerator and denominator.
Chris@16 64 //
Chris@16 65 limb_type y_order = y.size() - 1;
Chris@16 66
Chris@16 67 if(y_order == 0)
Chris@16 68 {
Chris@16 69 //
Chris@16 70 // Only a single non-zero limb in the denominator, in this case
Chris@16 71 // we can use a specialized divide-by-single-limb routine which is
Chris@16 72 // much faster. This also handles division by zero:
Chris@16 73 //
Chris@16 74 divide_unsigned_helper(result, x, y.limbs()[y_order], r);
Chris@16 75 return;
Chris@16 76 }
Chris@16 77
Chris@16 78 typename CppInt2::const_limb_pointer px = x.limbs();
Chris@16 79 typename CppInt3::const_limb_pointer py = y.limbs();
Chris@16 80
Chris@16 81 limb_type r_order = x.size() - 1;
Chris@16 82 if((r_order == 0) && (*px == 0))
Chris@16 83 {
Chris@16 84 // x is zero, so is the result:
Chris@16 85 r = x;
Chris@16 86 if(result)
Chris@16 87 *result = x;
Chris@16 88 return;
Chris@16 89 }
Chris@16 90
Chris@16 91 r = x;
Chris@16 92 r.sign(false);
Chris@16 93 if(result)
Chris@16 94 *result = static_cast<limb_type>(0u);
Chris@16 95 //
Chris@16 96 // Check if the remainder is already less than the divisor, if so
Chris@16 97 // we already have the result. Note we try and avoid a full compare
Chris@16 98 // if we can:
Chris@16 99 //
Chris@16 100 if(r_order <= y_order)
Chris@16 101 {
Chris@16 102 if((r_order < y_order) || (r.compare_unsigned(y) < 0))
Chris@16 103 {
Chris@16 104 return;
Chris@16 105 }
Chris@16 106 }
Chris@16 107
Chris@16 108 CppInt1 t;
Chris@16 109 bool r_neg = false;
Chris@16 110
Chris@16 111 //
Chris@16 112 // See if we can short-circuit long division, and use basic arithmetic instead:
Chris@16 113 //
Chris@16 114 if(r_order == 0)
Chris@16 115 {
Chris@16 116 if(result)
Chris@16 117 {
Chris@16 118 *result = px[0] / py[0];
Chris@16 119 }
Chris@16 120 r = px[0] % py[0];
Chris@16 121 return;
Chris@16 122 }
Chris@16 123 else if(r_order == 1)
Chris@16 124 {
Chris@16 125 double_limb_type a, b;
Chris@16 126 a = (static_cast<double_limb_type>(px[1]) << CppInt1::limb_bits) | px[0];
Chris@16 127 b = y_order ?
Chris@16 128 (static_cast<double_limb_type>(py[1]) << CppInt1::limb_bits) | py[0]
Chris@16 129 : py[0];
Chris@16 130 if(result)
Chris@16 131 {
Chris@16 132 *result = a / b;
Chris@16 133 }
Chris@16 134 r = a % b;
Chris@16 135 return;
Chris@16 136 }
Chris@16 137 //
Chris@16 138 // prepare result:
Chris@16 139 //
Chris@16 140 if(result)
Chris@16 141 result->resize(1 + r_order - y_order, 1 + r_order - y_order);
Chris@16 142 typename CppInt1::const_limb_pointer prem = r.limbs();
Chris@16 143 // This is initialised just to keep the compiler from emitting useless warnings later on:
Chris@16 144 typename CppInt1::limb_pointer pr
Chris@16 145 = typename CppInt1::limb_pointer();
Chris@16 146 if(result)
Chris@16 147 {
Chris@16 148 pr = result->limbs();
Chris@16 149 for(unsigned i = 1; i < 1 + r_order - y_order; ++i)
Chris@16 150 pr[i] = 0;
Chris@16 151 }
Chris@16 152 bool first_pass = true;
Chris@16 153
Chris@16 154 do
Chris@16 155 {
Chris@16 156 //
Chris@16 157 // Calculate our best guess for how many times y divides into r:
Chris@16 158 //
Chris@16 159 limb_type guess;
Chris@16 160 if((prem[r_order] <= py[y_order]) && (r_order > 0))
Chris@16 161 {
Chris@16 162 double_limb_type a, b, v;
Chris@16 163 a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
Chris@16 164 b = py[y_order];
Chris@16 165 v = a / b;
Chris@16 166 if(v > CppInt1::max_limb_value)
Chris@16 167 guess = 1;
Chris@16 168 else
Chris@16 169 {
Chris@16 170 guess = static_cast<limb_type>(v);
Chris@16 171 --r_order;
Chris@16 172 }
Chris@16 173 }
Chris@16 174 else if(r_order == 0)
Chris@16 175 {
Chris@16 176 guess = prem[0] / py[y_order];
Chris@16 177 }
Chris@16 178 else
Chris@16 179 {
Chris@16 180 double_limb_type a, b, v;
Chris@16 181 a = (static_cast<double_limb_type>(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1];
Chris@16 182 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);
Chris@16 183 v = a / b;
Chris@16 184 guess = static_cast<limb_type>(v);
Chris@16 185 }
Chris@16 186 BOOST_ASSERT(guess); // If the guess ever gets to zero we go on forever....
Chris@16 187 //
Chris@16 188 // Update result:
Chris@16 189 //
Chris@16 190 limb_type shift = r_order - y_order;
Chris@16 191 if(result)
Chris@16 192 {
Chris@16 193 if(r_neg)
Chris@16 194 {
Chris@16 195 if(pr[shift] > guess)
Chris@16 196 pr[shift] -= guess;
Chris@16 197 else
Chris@16 198 {
Chris@16 199 t.resize(shift + 1, shift + 1);
Chris@16 200 t.limbs()[shift] = guess;
Chris@16 201 for(unsigned i = 0; i < shift; ++i)
Chris@16 202 t.limbs()[i] = 0;
Chris@16 203 eval_subtract(*result, t);
Chris@16 204 }
Chris@16 205 }
Chris@16 206 else if(CppInt1::max_limb_value - pr[shift] > guess)
Chris@16 207 pr[shift] += guess;
Chris@16 208 else
Chris@16 209 {
Chris@16 210 t.resize(shift + 1, shift + 1);
Chris@16 211 t.limbs()[shift] = guess;
Chris@16 212 for(unsigned i = 0; i < shift; ++i)
Chris@16 213 t.limbs()[i] = 0;
Chris@16 214 eval_add(*result, t);
Chris@16 215 }
Chris@16 216 }
Chris@16 217 //
Chris@16 218 // Calculate guess * y, we use a fused mutiply-shift O(N) for this
Chris@16 219 // rather than a full O(N^2) multiply:
Chris@16 220 //
Chris@16 221 double_limb_type carry = 0;
Chris@16 222 t.resize(y.size() + shift + 1, y.size() + shift);
Chris@16 223 bool truncated_t = !CppInt1::variable && (t.size() != y.size() + shift + 1);
Chris@16 224 typename CppInt1::limb_pointer pt = t.limbs();
Chris@16 225 for(unsigned i = 0; i < shift; ++i)
Chris@16 226 pt[i] = 0;
Chris@16 227 for(unsigned i = 0; i < y.size(); ++i)
Chris@16 228 {
Chris@16 229 carry += static_cast<double_limb_type>(py[i]) * static_cast<double_limb_type>(guess);
Chris@16 230 pt[i + shift] = static_cast<limb_type>(carry);
Chris@16 231 carry >>= CppInt1::limb_bits;
Chris@16 232 }
Chris@16 233 if(carry && !truncated_t)
Chris@16 234 {
Chris@16 235 pt[t.size() - 1] = static_cast<limb_type>(carry);
Chris@16 236 }
Chris@16 237 else if(!truncated_t)
Chris@16 238 {
Chris@16 239 t.resize(t.size() - 1, t.size() - 1);
Chris@16 240 }
Chris@16 241 //
Chris@16 242 // Update r in a way that won't actually produce a negative result
Chris@16 243 // in case the argument types are unsigned:
Chris@16 244 //
Chris@16 245 if(r.compare(t) > 0)
Chris@16 246 {
Chris@16 247 eval_subtract(r, t);
Chris@16 248 }
Chris@16 249 else
Chris@16 250 {
Chris@16 251 r.swap(t);
Chris@16 252 eval_subtract(r, t);
Chris@16 253 prem = r.limbs();
Chris@16 254 r_neg = !r_neg;
Chris@16 255 }
Chris@16 256 //
Chris@16 257 // First time through we need to strip any leading zero, otherwise
Chris@16 258 // the termination condition goes belly-up:
Chris@16 259 //
Chris@16 260 if(result && first_pass)
Chris@16 261 {
Chris@16 262 first_pass = false;
Chris@16 263 while(pr[result->size() - 1] == 0)
Chris@16 264 result->resize(result->size() - 1, result->size() - 1);
Chris@16 265 }
Chris@16 266 //
Chris@16 267 // Update r_order:
Chris@16 268 //
Chris@16 269 r_order = r.size() - 1;
Chris@16 270 if(r_order < y_order)
Chris@16 271 break;
Chris@16 272 }
Chris@16 273 // Termination condition is really just a check that r > y, but with a common
Chris@16 274 // short-circuit case handled first:
Chris@16 275 while((r_order > y_order) || (r.compare_unsigned(y) >= 0));
Chris@16 276
Chris@16 277 //
Chris@16 278 // We now just have to normalise the result:
Chris@16 279 //
Chris@16 280 if(r_neg && eval_get_sign(r))
Chris@16 281 {
Chris@16 282 // We have one too many in the result:
Chris@16 283 if(result)
Chris@16 284 eval_decrement(*result);
Chris@16 285 if(y.sign())
Chris@16 286 {
Chris@16 287 r.negate();
Chris@16 288 eval_subtract(r, y);
Chris@16 289 }
Chris@16 290 else
Chris@16 291 eval_subtract(r, y, r);
Chris@16 292 }
Chris@16 293
Chris@16 294 BOOST_ASSERT(r.compare_unsigned(y) < 0); // remainder must be less than the divisor or our code has failed
Chris@16 295 }
Chris@16 296
Chris@16 297 template <class CppInt1, class CppInt2>
Chris@16 298 void divide_unsigned_helper(
Chris@16 299 CppInt1* result,
Chris@16 300 const CppInt2& x,
Chris@16 301 limb_type y,
Chris@16 302 CppInt1& r)
Chris@16 303 {
Chris@16 304 if(((void*)result == (void*)&x) || ((void*)&r == (void*)&x))
Chris@16 305 {
Chris@16 306 CppInt2 t(x);
Chris@16 307 divide_unsigned_helper(result, t, y, r);
Chris@16 308 return;
Chris@16 309 }
Chris@16 310
Chris@16 311 if(result == &r)
Chris@16 312 {
Chris@16 313 CppInt1 rem;
Chris@16 314 divide_unsigned_helper(result, x, y, rem);
Chris@16 315 r = rem;
Chris@16 316 return;
Chris@16 317 }
Chris@16 318
Chris@16 319 // As above, but simplified for integer divisor:
Chris@16 320
Chris@16 321 using default_ops::eval_subtract;
Chris@16 322
Chris@16 323 if(y == 0)
Chris@16 324 {
Chris@16 325 BOOST_THROW_EXCEPTION(std::overflow_error("Integer Division by zero."));
Chris@16 326 }
Chris@16 327 //
Chris@16 328 // Find the most significant word of numerator.
Chris@16 329 //
Chris@16 330 limb_type r_order = x.size() - 1;
Chris@16 331
Chris@16 332 //
Chris@16 333 // Set remainder and result to their initial values:
Chris@16 334 //
Chris@16 335 r = x;
Chris@16 336 r.sign(false);
Chris@16 337 typename CppInt1::limb_pointer pr = r.limbs();
Chris@16 338
Chris@16 339 //
Chris@16 340 // check for x < y, try to do this without actually having to
Chris@16 341 // do a full comparison:
Chris@16 342 //
Chris@16 343 if((r_order == 0) && (*pr < y))
Chris@16 344 {
Chris@16 345 if(result)
Chris@16 346 *result = static_cast<limb_type>(0u);
Chris@16 347 return;
Chris@16 348 }
Chris@16 349
Chris@16 350 //
Chris@16 351 // See if we can short-circuit long division, and use basic arithmetic instead:
Chris@16 352 //
Chris@16 353 if(r_order == 0)
Chris@16 354 {
Chris@16 355 if(result)
Chris@16 356 {
Chris@16 357 *result = *pr / y;
Chris@16 358 result->sign(x.sign());
Chris@16 359 }
Chris@16 360 *pr %= y;
Chris@16 361 r.sign(x.sign());
Chris@16 362 return;
Chris@16 363 }
Chris@16 364 else if(r_order == 1)
Chris@16 365 {
Chris@16 366 double_limb_type a;
Chris@16 367 a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[0];
Chris@16 368 if(result)
Chris@16 369 {
Chris@16 370 *result = a / y;
Chris@16 371 result->sign(x.sign());
Chris@16 372 }
Chris@16 373 r = a % y;
Chris@16 374 r.sign(x.sign());
Chris@16 375 return;
Chris@16 376 }
Chris@16 377
Chris@16 378 // This is initialised just to keep the compiler from emitting useless warnings later on:
Chris@16 379 typename CppInt1::limb_pointer pres = typename CppInt1::limb_pointer();
Chris@16 380 if(result)
Chris@16 381 {
Chris@16 382 result->resize(r_order + 1, r_order + 1);
Chris@16 383 pres = result->limbs();
Chris@16 384 if(result->size() > r_order)
Chris@16 385 pres[r_order] = 0; // just in case we don't set the most significant limb below.
Chris@16 386 }
Chris@16 387
Chris@16 388 do
Chris@16 389 {
Chris@16 390 //
Chris@16 391 // Calculate our best guess for how many times y divides into r:
Chris@16 392 //
Chris@16 393 if((pr[r_order] < y) && r_order)
Chris@16 394 {
Chris@16 395 double_limb_type a, b;
Chris@16 396 a = (static_cast<double_limb_type>(pr[r_order]) << CppInt1::limb_bits) | pr[r_order - 1];
Chris@16 397 b = a % y;
Chris@16 398 r.resize(r.size() - 1, r.size() - 1);
Chris@16 399 --r_order;
Chris@16 400 pr[r_order] = static_cast<limb_type>(b);
Chris@16 401 if(result)
Chris@16 402 pres[r_order] = static_cast<limb_type>(a / y);
Chris@16 403 if(r_order && pr[r_order] == 0)
Chris@16 404 {
Chris@16 405 --r_order; // No remainder, division was exact.
Chris@16 406 r.resize(r.size() - 1, r.size() - 1);
Chris@16 407 if(result)
Chris@16 408 pres[r_order] = static_cast<limb_type>(0u);
Chris@16 409 }
Chris@16 410 }
Chris@16 411 else
Chris@16 412 {
Chris@16 413 if(result)
Chris@16 414 pres[r_order] = pr[r_order] / y;
Chris@16 415 pr[r_order] %= y;
Chris@16 416 if(r_order && pr[r_order] == 0)
Chris@16 417 {
Chris@16 418 --r_order; // No remainder, division was exact.
Chris@16 419 r.resize(r.size() - 1, r.size() - 1);
Chris@16 420 if(result)
Chris@16 421 pres[r_order] = static_cast<limb_type>(0u);
Chris@16 422 }
Chris@16 423 }
Chris@16 424 }
Chris@16 425 // Termination condition is really just a check that r >= y, but with two common
Chris@16 426 // short-circuit cases handled first:
Chris@16 427 while(r_order || (pr[r_order] >= y));
Chris@16 428
Chris@16 429 if(result)
Chris@16 430 {
Chris@16 431 result->normalize();
Chris@16 432 result->sign(x.sign());
Chris@16 433 }
Chris@16 434 r.normalize();
Chris@16 435 r.sign(x.sign());
Chris@16 436
Chris@16 437 BOOST_ASSERT(r.compare(y) < 0); // remainder must be less than the divisor or our code has failed
Chris@16 438 }
Chris@16 439
Chris@16 440 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>
Chris@16 441 BOOST_MP_FORCEINLINE 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
Chris@16 442 eval_divide(
Chris@16 443 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 444 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
Chris@16 445 const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
Chris@16 446 {
Chris@16 447 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
Chris@16 448 bool s = a.sign() != b.sign();
Chris@16 449 divide_unsigned_helper(&result, a, b, r);
Chris@16 450 result.sign(s);
Chris@16 451 }
Chris@16 452
Chris@16 453 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>
Chris@16 454 BOOST_MP_FORCEINLINE 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
Chris@16 455 eval_divide(
Chris@16 456 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 457 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
Chris@16 458 limb_type& b)
Chris@16 459 {
Chris@16 460 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
Chris@16 461 bool s = a.sign();
Chris@16 462 divide_unsigned_helper(&result, a, b, r);
Chris@16 463 result.sign(s);
Chris@16 464 }
Chris@16 465
Chris@16 466 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>
Chris@16 467 BOOST_MP_FORCEINLINE 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
Chris@16 468 eval_divide(
Chris@16 469 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 470 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
Chris@16 471 signed_limb_type& b)
Chris@16 472 {
Chris@16 473 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
Chris@16 474 bool s = a.sign() != (b < 0);
Chris@101 475 divide_unsigned_helper(&result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(b)), r);
Chris@16 476 result.sign(s);
Chris@16 477 }
Chris@16 478
Chris@16 479 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>
Chris@16 480 BOOST_MP_FORCEINLINE 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
Chris@16 481 eval_divide(
Chris@16 482 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 483 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
Chris@16 484 {
Chris@16 485 // There is no in place divide:
Chris@16 486 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
Chris@16 487 eval_divide(result, a, b);
Chris@16 488 }
Chris@16 489
Chris@16 490 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 491 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
Chris@16 492 eval_divide(
Chris@16 493 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 494 limb_type b)
Chris@16 495 {
Chris@16 496 // There is no in place divide:
Chris@16 497 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
Chris@16 498 eval_divide(result, a, b);
Chris@16 499 }
Chris@16 500
Chris@16 501 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 502 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
Chris@16 503 eval_divide(
Chris@16 504 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 505 signed_limb_type b)
Chris@16 506 {
Chris@16 507 // There is no in place divide:
Chris@16 508 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
Chris@16 509 eval_divide(result, a, b);
Chris@16 510 }
Chris@16 511
Chris@16 512 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>
Chris@16 513 BOOST_MP_FORCEINLINE 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
Chris@16 514 eval_modulus(
Chris@16 515 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 516 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
Chris@16 517 const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
Chris@16 518 {
Chris@16 519 bool s = a.sign();
Chris@16 520 divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, b, result);
Chris@16 521 result.sign(s);
Chris@16 522 }
Chris@16 523
Chris@16 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>
Chris@16 525 BOOST_MP_FORCEINLINE 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
Chris@16 526 eval_modulus(
Chris@16 527 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 528 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a, limb_type b)
Chris@16 529 {
Chris@16 530 bool s = a.sign();
Chris@16 531 divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, b, result);
Chris@16 532 result.sign(s);
Chris@16 533 }
Chris@16 534
Chris@16 535 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>
Chris@16 536 BOOST_MP_FORCEINLINE 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
Chris@16 537 eval_modulus(
Chris@16 538 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 539 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
Chris@16 540 signed_limb_type b)
Chris@16 541 {
Chris@16 542 bool s = a.sign();
Chris@16 543 divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, static_cast<limb_type>(std::abs(b)), result);
Chris@16 544 result.sign(s);
Chris@16 545 }
Chris@16 546
Chris@16 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>
Chris@16 548 BOOST_MP_FORCEINLINE 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
Chris@16 549 eval_modulus(
Chris@16 550 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 551 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b)
Chris@16 552 {
Chris@16 553 // There is no in place divide:
Chris@16 554 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
Chris@16 555 eval_modulus(result, a, b);
Chris@16 556 }
Chris@16 557
Chris@16 558 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 559 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
Chris@16 560 eval_modulus(
Chris@16 561 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 562 limb_type b)
Chris@16 563 {
Chris@16 564 // There is no in place divide:
Chris@16 565 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
Chris@16 566 eval_modulus(result, a, b);
Chris@16 567 }
Chris@16 568
Chris@16 569 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 570 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
Chris@16 571 eval_modulus(
Chris@16 572 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 573 signed_limb_type b)
Chris@16 574 {
Chris@16 575 // There is no in place divide:
Chris@16 576 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> a(result);
Chris@16 577 eval_modulus(result, a, b);
Chris@16 578 }
Chris@16 579
Chris@16 580 //
Chris@16 581 // Over again for trivial cpp_int's:
Chris@16 582 //
Chris@16 583 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 584 BOOST_MP_FORCEINLINE typename enable_if_c<
Chris@16 585 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 586 && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 587 && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 588 || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
Chris@16 589 >::type
Chris@16 590 eval_divide(
Chris@16 591 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 592 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
Chris@16 593 {
Chris@16 594 if(!*o.limbs())
Chris@16 595 BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
Chris@16 596 *result.limbs() /= *o.limbs();
Chris@16 597 result.sign(result.sign() != o.sign());
Chris@16 598 }
Chris@16 599
Chris@16 600 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 601 BOOST_MP_FORCEINLINE typename enable_if_c<
Chris@16 602 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 603 && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 604 && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 605 && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 606 >::type
Chris@16 607 eval_divide(
Chris@16 608 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 609 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
Chris@16 610 {
Chris@16 611 if(!*o.limbs())
Chris@16 612 BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
Chris@16 613 *result.limbs() /= *o.limbs();
Chris@16 614 }
Chris@16 615
Chris@16 616 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
Chris@16 617 BOOST_MP_FORCEINLINE typename enable_if_c<
Chris@16 618 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 619 && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
Chris@16 620 >::type
Chris@16 621 eval_modulus(
Chris@16 622 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
Chris@16 623 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o)
Chris@16 624 {
Chris@16 625 if(!*o.limbs())
Chris@16 626 BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
Chris@16 627 *result.limbs() %= *o.limbs();
Chris@16 628 result.sign(result.sign());
Chris@16 629 }
Chris@16 630
Chris@16 631 }}} // namespaces
Chris@16 632
Chris@16 633 #endif