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
|