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>
add_unsigned(CppInt1 & result,const CppInt2 & a,const CppInt3 & b)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>
add_unsigned(CppInt1 & result,const CppInt2 & a,const limb_type & o)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>
subtract_unsigned(CppInt1 & result,const CppInt2 & a,const CppInt3 & b)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>
subtract_unsigned(CppInt1 & result,const CppInt2 & a,const limb_type & b)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
eval_add(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits2,MaxBits2,SignType2,Checked2,Allocator2> & o)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
eval_add(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits2,MaxBits2,SignType2,Checked2,Allocator2> & a,const cpp_int_backend<MinBits3,MaxBits3,SignType3,Checked3,Allocator3> & b)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
eval_add(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const limb_type & o)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
eval_add(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits2,MaxBits2,SignType2,Checked2,Allocator2> & a,const limb_type & o)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
eval_add(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const signed_limb_type & o)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
eval_add(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits2,MaxBits2,SignType2,Checked2,Allocator2> & a,const signed_limb_type & o)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
eval_subtract(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const limb_type & o)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
eval_subtract(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits2,MaxBits2,SignType2,Checked2,Allocator2> & a,const limb_type & o)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
eval_subtract(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const signed_limb_type & o)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
eval_subtract(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits2,MaxBits2,SignType2,Checked2,Allocator2> & a,const signed_limb_type & o)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
eval_increment(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result)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
eval_decrement(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result)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
eval_subtract(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits2,MaxBits2,SignType2,Checked2,Allocator2> & o)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
eval_subtract(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits2,MaxBits2,SignType2,Checked2,Allocator2> & a,const cpp_int_backend<MinBits3,MaxBits3,SignType3,Checked3,Allocator3> & b)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
eval_add(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & o)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
eval_add(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & o)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
eval_subtract(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & o)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
eval_subtract(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & o)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
551