Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/multiprecision/cpp_int/add.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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>(-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>(-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>(-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>(-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 |