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