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