]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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(CppInt1::variable || (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(CppInt1::variable || (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 |