]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/multiprecision/cpp_int/add.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / multiprecision / cpp_int / add.hpp
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_ADD_HPP
9 #define BOOST_MP_CPP_INT_ADD_HPP
10
11 namespace boost{ namespace multiprecision{ namespace backends{
12
13 #ifdef _MSC_VER
14 #pragma warning(push)
15 #pragma warning(disable:4127) // conditional expression is constant
16 #endif
17
18 //
19 // This is the key addition routine where all the argument types are non-trivial cpp_int's:
20 //
21 template <class CppInt1, class CppInt2, class CppInt3>
22 inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
23 {
24 using std::swap;
25
26 // Nothing fancy, just let uintmax_t take the strain:
27 double_limb_type carry = 0;
28 unsigned m, x;
29 unsigned as = a.size();
30 unsigned bs = b.size();
31 minmax(as, bs, m, x);
32 if(x == 1)
33 {
34 bool s = a.sign();
35 result = static_cast<double_limb_type>(*a.limbs()) + static_cast<double_limb_type>(*b.limbs());
36 result.sign(s);
37 return;
38 }
39 result.resize(x, x);
40 typename CppInt2::const_limb_pointer pa = a.limbs();
41 typename CppInt3::const_limb_pointer pb = b.limbs();
42 typename CppInt1::limb_pointer pr = result.limbs();
43 typename CppInt1::limb_pointer pr_end = pr + m;
44
45 if(as < bs)
46 swap(pa, pb);
47
48 // First where a and b overlap:
49 while(pr != pr_end)
50 {
51 carry += static_cast<double_limb_type>(*pa) + static_cast<double_limb_type>(*pb);
52 #ifdef __MSVC_RUNTIME_CHECKS
53 *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
54 #else
55 *pr = static_cast<limb_type>(carry);
56 #endif
57 carry >>= CppInt1::limb_bits;
58 ++pr, ++pa, ++pb;
59 }
60 pr_end += x - m;
61 // Now where only a has digits:
62 while(pr != pr_end)
63 {
64 if(!carry)
65 {
66 if(pa != pr)
67 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
68 std::copy(pa, pa + (pr_end - pr), stdext::checked_array_iterator<limb_type*>(pr, result.size()));
69 #else
70 std::copy(pa, pa + (pr_end - pr), pr);
71 #endif
72 break;
73 }
74 carry += static_cast<double_limb_type>(*pa);
75 #ifdef __MSVC_RUNTIME_CHECKS
76 *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
77 #else
78 *pr = static_cast<limb_type>(carry);
79 #endif
80 carry >>= CppInt1::limb_bits;
81 ++pr, ++pa;
82 }
83 if(carry)
84 {
85 // We overflowed, need to add one more limb:
86 result.resize(x + 1, x + 1);
87 if(result.size() > x)
88 result.limbs()[x] = static_cast<limb_type>(carry);
89 }
90 result.normalize();
91 result.sign(a.sign());
92 }
93 //
94 // As above, but for adding a single limb to a non-trivial cpp_int:
95 //
96 template <class CppInt1, class CppInt2>
97 inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
98 {
99 // Addition using modular arithmetic.
100 // Nothing fancy, just let uintmax_t take the strain:
101 if(&result != &a)
102 result.resize(a.size(), a.size());
103 double_limb_type carry = o;
104 typename CppInt1::limb_pointer pr = result.limbs();
105 typename CppInt2::const_limb_pointer pa = a.limbs();
106 unsigned i = 0;
107 // Addition with carry until we either run out of digits or carry is zero:
108 for(; carry && (i < result.size()); ++i)
109 {
110 carry += static_cast<double_limb_type>(pa[i]);
111 #ifdef __MSVC_RUNTIME_CHECKS
112 pr[i] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
113 #else
114 pr[i] = static_cast<limb_type>(carry);
115 #endif
116 carry >>= CppInt1::limb_bits;
117 }
118 // Just copy any remaining digits:
119 if(&a != &result)
120 {
121 for(; i < result.size(); ++i)
122 pr[i] = pa[i];
123 }
124 if(carry)
125 {
126 // We overflowed, need to add one more limb:
127 unsigned x = result.size();
128 result.resize(x + 1, x + 1);
129 if(result.size() > x)
130 result.limbs()[x] = static_cast<limb_type>(carry);
131 }
132 result.normalize();
133 result.sign(a.sign());
134 }
135 //
136 // Core subtraction routine for all non-trivial cpp_int's:
137 //
138 template <class CppInt1, class CppInt2, class CppInt3>
139 inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
140 {
141 using std::swap;
142
143 // Nothing fancy, just let uintmax_t take the strain:
144 double_limb_type borrow = 0;
145 unsigned m, x;
146 minmax(a.size(), b.size(), m, x);
147 //
148 // special cases for small limb counts:
149 //
150 if(x == 1)
151 {
152 bool s = a.sign();
153 limb_type al = *a.limbs();
154 limb_type bl = *b.limbs();
155 if(bl > al)
156 {
157 std::swap(al, bl);
158 s = !s;
159 }
160 result = al - bl;
161 result.sign(s);
162 return;
163 }
164 // This isn't used till later, but comparison has to occur before we resize the result,
165 // as that may also resize a or b if this is an inplace operation:
166 int c = a.compare_unsigned(b);
167 // Set up the result vector:
168 result.resize(x, x);
169 // Now that a, b, and result are stable, get pointers to their limbs:
170 typename CppInt2::const_limb_pointer pa = a.limbs();
171 typename CppInt3::const_limb_pointer pb = b.limbs();
172 typename CppInt1::limb_pointer pr = result.limbs();
173 bool swapped = false;
174 if(c < 0)
175 {
176 swap(pa, pb);
177 swapped = true;
178 }
179 else if(c == 0)
180 {
181 result = static_cast<limb_type>(0);
182 return;
183 }
184
185 unsigned i = 0;
186 // First where a and b overlap:
187 while(i < m)
188 {
189 borrow = static_cast<double_limb_type>(pa[i]) - static_cast<double_limb_type>(pb[i]) - borrow;
190 pr[i] = static_cast<limb_type>(borrow);
191 borrow = (borrow >> CppInt1::limb_bits) & 1u;
192 ++i;
193 }
194 // Now where only a has digits, only as long as we've borrowed:
195 while(borrow && (i < x))
196 {
197 borrow = static_cast<double_limb_type>(pa[i]) - borrow;
198 pr[i] = static_cast<limb_type>(borrow);
199 borrow = (borrow >> CppInt1::limb_bits) & 1u;
200 ++i;
201 }
202 // Any remaining digits are the same as those in pa:
203 if((x != i) && (pa != pr))
204 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
205 std::copy(pa + i, pa + x, stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i));
206 #else
207 std::copy(pa + i, pa + x, pr + i);
208 #endif
209 BOOST_ASSERT(0 == borrow);
210
211 //
212 // We may have lost digits, if so update limb usage count:
213 //
214 result.normalize();
215 result.sign(a.sign());
216 if(swapped)
217 result.negate();
218 }
219 //
220 // And again to subtract a single limb:
221 //
222 template <class CppInt1, class CppInt2>
223 inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const limb_type& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value)
224 {
225 // Subtract one limb.
226 // Nothing fancy, just let uintmax_t take the strain:
227 BOOST_STATIC_CONSTANT(double_limb_type, borrow = static_cast<double_limb_type>(CppInt1::max_limb_value) + 1);
228 result.resize(a.size(), a.size());
229 typename CppInt1::limb_pointer pr = result.limbs();
230 typename CppInt2::const_limb_pointer pa = a.limbs();
231 if(*pa >= b)
232 {
233 *pr = *pa - b;
234 if(&result != &a)
235 {
236 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
237 std::copy(pa + 1, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + 1, result.size() - 1));
238 #else
239 std::copy(pa + 1, pa + a.size(), pr + 1);
240 #endif
241 result.sign(a.sign());
242 }
243 else if((result.size() == 1) && (*pr == 0))
244 {
245 result.sign(false); // zero is unsigned.
246 }
247 }
248 else if(result.size() == 1)
249 {
250 *pr = b - *pa;
251 result.sign(!a.sign());
252 }
253 else
254 {
255 *pr = static_cast<limb_type>((borrow + *pa) - b);
256 unsigned i = 1;
257 while(!pa[i])
258 {
259 pr[i] = CppInt1::max_limb_value;
260 ++i;
261 }
262 pr[i] = pa[i] - 1;
263 if(&result != &a)
264 {
265 ++i;
266 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
267 std::copy(pa + i, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i));
268 #else
269 std::copy(pa + i, pa + a.size(), pr + i);
270 #endif
271 }
272 result.normalize();
273 result.sign(a.sign());
274 }
275 }
276
277 //
278 // Now the actual functions called by the front end, all of which forward to one of the above:
279 //
280 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>
281 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
282 eval_add(
283 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
284 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
285 {
286 eval_add(result, result, o);
287 }
288 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>
289 inline 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
290 eval_add(
291 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
292 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
293 const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
294 {
295 if(a.sign() != b.sign())
296 {
297 subtract_unsigned(result, a, b);
298 return;
299 }
300 add_unsigned(result, a, b);
301 }
302 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
303 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
304 eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
305 {
306 if(result.sign())
307 {
308 subtract_unsigned(result, result, o);
309 }
310 else
311 add_unsigned(result, result, o);
312 }
313 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>
314 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
315 eval_add(
316 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
317 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
318 const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
319 {
320 if(a.sign())
321 {
322 subtract_unsigned(result, a, o);
323 }
324 else
325 add_unsigned(result, a, o);
326 }
327 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
328 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
329 eval_add(
330 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
331 const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
332 {
333 if(o < 0)
334 eval_subtract(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
335 else if(o > 0)
336 eval_add(result, static_cast<limb_type>(o));
337 }
338 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>
339 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
340 eval_add(
341 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
342 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
343 const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
344 {
345 if(o < 0)
346 eval_subtract(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
347 else if(o > 0)
348 eval_add(result, a, static_cast<limb_type>(o));
349 else if(&result != &a)
350 result = a;
351 }
352 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
353 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
354 eval_subtract(
355 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
356 const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
357 {
358 if(result.sign())
359 {
360 add_unsigned(result, result, o);
361 }
362 else
363 subtract_unsigned(result, result, o);
364 }
365 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>
366 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
367 eval_subtract(
368 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
369 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
370 const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
371 {
372 if(a.sign())
373 {
374 add_unsigned(result, a, o);
375 }
376 else
377 {
378 subtract_unsigned(result, a, o);
379 }
380 }
381 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
382 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
383 eval_subtract(
384 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
385 const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
386 {
387 if(o)
388 {
389 if(o < 0)
390 eval_add(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
391 else
392 eval_subtract(result, static_cast<limb_type>(o));
393 }
394 }
395 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>
396 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
397 eval_subtract(
398 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
399 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
400 const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
401 {
402 if(o)
403 {
404 if(o < 0)
405 eval_add(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o)));
406 else
407 eval_subtract(result, a, static_cast<limb_type>(o));
408 }
409 else if(&result != &a)
410 result = a;
411 }
412
413 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
414 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
415 eval_increment(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
416 {
417 static const limb_type one = 1;
418 if(!result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
419 ++result.limbs()[0];
420 else if(result.sign() && result.limbs()[0])
421 --result.limbs()[0];
422 else
423 eval_add(result, one);
424 }
425 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
426 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
427 eval_decrement(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
428 {
429 static const limb_type one = 1;
430 if(!result.sign() && result.limbs()[0])
431 --result.limbs()[0];
432 else if(result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value))
433 ++result.limbs()[0];
434 else
435 eval_subtract(result, one);
436 }
437 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>
438 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
439 eval_subtract(
440 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
441 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
442 {
443 eval_subtract(result, result, o);
444 }
445 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>
446 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
447 eval_subtract(
448 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
449 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
450 const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
451 {
452 if(a.sign() != b.sign())
453 {
454 add_unsigned(result, a, b);
455 return;
456 }
457 subtract_unsigned(result, a, b);
458 }
459
460 //
461 // Simple addition and subtraction routine for trivial cpp_int's come last:
462 //
463 // One of the arguments is signed:
464 //
465 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
466 inline typename enable_if_c<
467 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
468 && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
469 && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
470 >::type
471 eval_add(
472 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
473 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
474 {
475 if(result.sign() != o.sign())
476 {
477 if(*o.limbs() > *result.limbs())
478 {
479 *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
480 result.negate();
481 }
482 else
483 *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
484 }
485 else
486 *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
487 result.normalize();
488 }
489 // Simple version for two unsigned arguments:
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<
492 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
493 && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
494 && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
495 && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
496 >::type
497 eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
498 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
499 {
500 *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
501 result.normalize();
502 }
503
504 // signed subtraction:
505 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
506 inline typename enable_if_c<
507 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
508 && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
509 && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)
510 >::type
511 eval_subtract(
512 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
513 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
514 {
515 if(result.sign() != o.sign())
516 {
517 *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
518 }
519 else if(*result.limbs() < *o.limbs())
520 {
521 *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
522 result.negate();
523 }
524 else
525 *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
526 result.normalize();
527 }
528
529 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
530 BOOST_MP_FORCEINLINE typename enable_if_c<
531 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
532 && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
533 && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
534 && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
535 >::type
536 eval_subtract(
537 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
538 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
539 {
540 *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
541 result.normalize();
542 }
543
544 #ifdef _MSC_VER
545 #pragma warning(pop)
546 #endif
547
548 }}} // namespaces
549
550 #endif