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