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