Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/multiprecision/cpp_int.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 #ifndef BOOST_MP_CPP_INT_HPP | |
7 #define BOOST_MP_CPP_INT_HPP | |
8 | |
9 #include <iostream> | |
10 #include <iomanip> | |
11 #include <boost/cstdint.hpp> | |
12 #include <boost/multiprecision/number.hpp> | |
13 #include <boost/multiprecision/detail/integer_ops.hpp> | |
14 #include <boost/array.hpp> | |
15 #include <boost/type_traits/is_integral.hpp> | |
16 #include <boost/type_traits/is_floating_point.hpp> | |
17 #include <boost/multiprecision/cpp_int/cpp_int_config.hpp> | |
18 #include <boost/multiprecision/rational_adaptor.hpp> | |
19 #include <boost/detail/endian.hpp> | |
20 #include <boost/integer/static_min_max.hpp> | |
21 #include <boost/type_traits/common_type.hpp> | |
22 #include <boost/type_traits/make_signed.hpp> | |
23 #include <boost/multiprecision/cpp_int/checked.hpp> | |
24 #ifdef BOOST_MP_USER_DEFINED_LITERALS | |
25 #include <boost/multiprecision/cpp_int/value_pack.hpp> | |
26 #endif | |
27 | |
28 namespace boost{ | |
29 namespace multiprecision{ | |
30 namespace backends{ | |
31 | |
32 using boost::enable_if; | |
33 | |
34 | |
35 #ifdef BOOST_MSVC | |
36 // warning C4127: conditional expression is constant | |
37 #pragma warning(push) | |
38 #pragma warning(disable:4127 4351 4293 4996 4307 4702) | |
39 #endif | |
40 | |
41 template <unsigned MinBits = 0, unsigned MaxBits = 0, cpp_integer_type SignType = signed_magnitude, cpp_int_check_type Checked = unchecked, class Allocator = typename mpl::if_c<MinBits && (MinBits == MaxBits), void, std::allocator<limb_type> >::type > | |
42 struct cpp_int_backend; | |
43 | |
44 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, bool trivial = false> | |
45 struct cpp_int_base; | |
46 // | |
47 // Traits class determines the maximum and minimum precision values: | |
48 // | |
49 template <class T> struct max_precision; | |
50 | |
51 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator> | |
52 struct max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > | |
53 { | |
54 static const unsigned value = is_void<Allocator>::value ? | |
55 static_unsigned_max<MinBits, MaxBits>::value | |
56 : (((MaxBits >= MinBits) && MaxBits) ? MaxBits : UINT_MAX); | |
57 }; | |
58 | |
59 template <class T> struct min_precision; | |
60 | |
61 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator> | |
62 struct min_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > | |
63 { | |
64 static const unsigned value = (is_void<Allocator>::value ? static_unsigned_max<MinBits, MaxBits>::value : MinBits); | |
65 }; | |
66 // | |
67 // Traits class determines whether the number of bits precision requested could fit in a native type, | |
68 // we call this a "trivial" cpp_int: | |
69 // | |
70 template <class T> | |
71 struct is_trivial_cpp_int | |
72 { | |
73 static const bool value = false; | |
74 }; | |
75 | |
76 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator> | |
77 struct is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > | |
78 { | |
79 typedef cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> self; | |
80 static const bool value = is_void<Allocator>::value && (max_precision<self>::value <= (sizeof(double_limb_type) * CHAR_BIT) - (SignType == signed_packed ? 1 : 0)); | |
81 }; | |
82 | |
83 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator> | |
84 struct is_trivial_cpp_int<cpp_int_base<MinBits, MaxBits, SignType, Checked, Allocator, true> > | |
85 { | |
86 static const bool value = true; | |
87 }; | |
88 | |
89 } // namespace backends | |
90 // | |
91 // Traits class to determine whether a cpp_int_backend is signed or not: | |
92 // | |
93 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator> | |
94 struct is_unsigned_number<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > | |
95 : public mpl::bool_<(SignType == unsigned_magnitude) || (SignType == unsigned_packed)>{}; | |
96 | |
97 namespace backends{ | |
98 // | |
99 // Traits class determines whether T should be implicitly convertible to U, or | |
100 // whether the constructor should be made explicit. The latter happens if we | |
101 // are losing the sign, or have fewer digits precision in the target type: | |
102 // | |
103 template <class T, class U> | |
104 struct is_implicit_cpp_int_conversion; | |
105 | |
106 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
107 struct is_implicit_cpp_int_conversion<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > | |
108 { | |
109 typedef cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> t1; | |
110 typedef cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> t2; | |
111 static const bool value = | |
112 (is_signed_number<t2>::value || !is_signed_number<t1>::value) | |
113 && (max_precision<t1>::value <= max_precision<t2>::value); | |
114 }; | |
115 | |
116 // | |
117 // Traits class to determine whether operations on a cpp_int may throw: | |
118 // | |
119 template <class T> | |
120 struct is_non_throwing_cpp_int : public mpl::false_{}; | |
121 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType> | |
122 struct is_non_throwing_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, unchecked, void> > : public mpl::true_ {}; | |
123 | |
124 // | |
125 // Traits class, determines whether the cpp_int is fixed precision or not: | |
126 // | |
127 template <class T> | |
128 struct is_fixed_precision; | |
129 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator> | |
130 struct is_fixed_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > | |
131 : public mpl::bool_<max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value != UINT_MAX> {}; | |
132 | |
133 namespace detail{ | |
134 | |
135 inline void verify_new_size(unsigned new_size, unsigned min_size, const mpl::int_<checked>&) | |
136 { | |
137 if(new_size < min_size) | |
138 BOOST_THROW_EXCEPTION(std::overflow_error("Unable to allocate sufficient storage for the value of the result: value overflows the maximum allowable magnitude.")); | |
139 } | |
140 inline void verify_new_size(unsigned /*new_size*/, unsigned /*min_size*/, const mpl::int_<unchecked>&){} | |
141 | |
142 template <class U> | |
143 inline void verify_limb_mask(bool b, U limb, U mask, const mpl::int_<checked>&) | |
144 { | |
145 // When we mask out "limb" with "mask", do we loose bits? If so it's an overflow error: | |
146 if(b && (limb & ~mask)) | |
147 BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in cpp_int arithmetic: there is insufficient precision in the target type to hold all of the bits of the result.")); | |
148 } | |
149 template <class U> | |
150 inline void verify_limb_mask(bool /*b*/, U /*limb*/, U /*mask*/, const mpl::int_<unchecked>&){} | |
151 | |
152 } | |
153 | |
154 // | |
155 // Now define the various data layouts that are possible as partial specializations of the base class, | |
156 // starting with the default arbitrary precision signed integer type: | |
157 // | |
158 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator> | |
159 struct cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false> : private Allocator::template rebind<limb_type>::other | |
160 { | |
161 typedef typename Allocator::template rebind<limb_type>::other allocator_type; | |
162 typedef typename allocator_type::pointer limb_pointer; | |
163 typedef typename allocator_type::const_pointer const_limb_pointer; | |
164 typedef mpl::int_<Checked> checked_type; | |
165 | |
166 // | |
167 // Interface invariants: | |
168 // | |
169 BOOST_STATIC_ASSERT(!is_void<Allocator>::value); | |
170 | |
171 private: | |
172 struct limb_data | |
173 { | |
174 unsigned capacity; | |
175 limb_pointer data; | |
176 }; | |
177 | |
178 public: | |
179 BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT); | |
180 BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u)); | |
181 BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1)); | |
182 BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = | |
183 MinBits | |
184 ? MinBits / limb_bits + (MinBits % limb_bits ? 1 : 0) | |
185 : sizeof(limb_data) / sizeof(limb_type)); | |
186 BOOST_STATIC_CONSTANT(bool, variable = true); | |
187 | |
188 private: | |
189 union data_type | |
190 { | |
191 limb_data ld; | |
192 limb_type la[internal_limb_count]; | |
193 limb_type first; | |
194 double_limb_type double_first; | |
195 | |
196 BOOST_CONSTEXPR data_type() : first(0) {} | |
197 BOOST_CONSTEXPR data_type(limb_type i) : first(i) {} | |
198 BOOST_CONSTEXPR data_type(signed_limb_type i) : first(i < 0 ? -i : i) {} | |
199 #ifdef BOOST_LITTLE_ENDIAN | |
200 BOOST_CONSTEXPR data_type(double_limb_type i) : double_first(i) {} | |
201 BOOST_CONSTEXPR data_type(signed_double_limb_type i) : double_first(i < 0 ? -i : i) {} | |
202 #endif | |
203 }; | |
204 | |
205 data_type m_data; | |
206 unsigned m_limbs; | |
207 bool m_sign, m_internal; | |
208 | |
209 public: | |
210 // | |
211 // Direct construction: | |
212 // | |
213 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT | |
214 : m_data(i), m_limbs(1), m_sign(false), m_internal(true) { } | |
215 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT | |
216 : m_data(i), m_limbs(1), m_sign(i < 0), m_internal(true) { } | |
217 #if defined(BOOST_LITTLE_ENDIAN) | |
218 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT | |
219 : m_data(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false), m_internal(true) { } | |
220 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT | |
221 : m_data(i), m_limbs(i < 0 ? (static_cast<double_limb_type>(-i) > static_cast<double_limb_type>(max_limb_value) ? 2 : 1) : (i > max_limb_value ? 2 : 1)), | |
222 m_sign(i < 0), m_internal(true) { } | |
223 #endif | |
224 // | |
225 // Helper functions for getting at our internal data, and manipulating storage: | |
226 // | |
227 BOOST_MP_FORCEINLINE allocator_type& allocator() BOOST_NOEXCEPT { return *this; } | |
228 BOOST_MP_FORCEINLINE const allocator_type& allocator()const BOOST_NOEXCEPT { return *this; } | |
229 BOOST_MP_FORCEINLINE unsigned size()const BOOST_NOEXCEPT { return m_limbs; } | |
230 BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return m_internal ? m_data.la : m_data.ld.data; } | |
231 BOOST_MP_FORCEINLINE const_limb_pointer limbs()const BOOST_NOEXCEPT { return m_internal ? m_data.la : m_data.ld.data; } | |
232 BOOST_MP_FORCEINLINE unsigned capacity()const BOOST_NOEXCEPT { return m_internal ? internal_limb_count : m_data.ld.capacity; } | |
233 BOOST_MP_FORCEINLINE bool sign()const BOOST_NOEXCEPT { return m_sign; } | |
234 void sign(bool b) BOOST_NOEXCEPT | |
235 { | |
236 m_sign = b; | |
237 // Check for zero value: | |
238 if(m_sign && (m_limbs == 1)) | |
239 { | |
240 if(limbs()[0] == 0) | |
241 m_sign = false; | |
242 } | |
243 } | |
244 void resize(unsigned new_size, unsigned min_size) | |
245 { | |
246 static const unsigned max_limbs = MaxBits / (CHAR_BIT * sizeof(limb_type)) + (MaxBits % (CHAR_BIT * sizeof(limb_type)) ? 1 : 0); | |
247 // We never resize beyond MaxSize: | |
248 if(new_size > max_limbs) | |
249 new_size = max_limbs; | |
250 detail::verify_new_size(new_size, min_size, checked_type()); | |
251 // See if we have enough capacity already: | |
252 unsigned cap = capacity(); | |
253 if(new_size > cap) | |
254 { | |
255 // Allocate a new buffer and copy everything over: | |
256 cap = (std::min)((std::max)(cap * 4, new_size), max_limbs); | |
257 limb_pointer pl = allocator().allocate(cap); | |
258 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | |
259 std::copy(limbs(), limbs() + size(), stdext::checked_array_iterator<limb_pointer>(pl, cap)); | |
260 #else | |
261 std::copy(limbs(), limbs() + size(), pl); | |
262 #endif | |
263 if(!m_internal) | |
264 allocator().deallocate(limbs(), capacity()); | |
265 else | |
266 m_internal = false; | |
267 m_limbs = new_size; | |
268 m_data.ld.capacity = cap; | |
269 m_data.ld.data = pl; | |
270 } | |
271 else | |
272 { | |
273 m_limbs = new_size; | |
274 } | |
275 } | |
276 BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT | |
277 { | |
278 limb_pointer p = limbs(); | |
279 while((m_limbs-1) && !p[m_limbs - 1])--m_limbs; | |
280 } | |
281 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_data(), m_limbs(1), m_sign(false), m_internal(true) {} | |
282 BOOST_MP_FORCEINLINE cpp_int_base(const cpp_int_base& o) : allocator_type(o), m_limbs(0), m_internal(true) | |
283 { | |
284 resize(o.size(), o.size()); | |
285 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | |
286 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size())); | |
287 #else | |
288 std::copy(o.limbs(), o.limbs() + o.size(), limbs()); | |
289 #endif | |
290 m_sign = o.m_sign; | |
291 } | |
292 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
293 cpp_int_base(cpp_int_base&& o) | |
294 : allocator_type(static_cast<Allocator&&>(o)), m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal) | |
295 { | |
296 if(m_internal) | |
297 { | |
298 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | |
299 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size())); | |
300 #else | |
301 std::copy(o.limbs(), o.limbs() + o.size(), limbs()); | |
302 #endif | |
303 } | |
304 else | |
305 { | |
306 m_data.ld = o.m_data.ld; | |
307 o.m_limbs = 0; | |
308 o.m_internal = true; | |
309 } | |
310 } | |
311 cpp_int_base& operator = (cpp_int_base&& o) BOOST_NOEXCEPT | |
312 { | |
313 if(!m_internal) | |
314 allocator().deallocate(m_data.ld.data, m_data.ld.capacity); | |
315 *static_cast<Allocator*>(this) = static_cast<Allocator&&>(o); | |
316 m_limbs = o.m_limbs; | |
317 m_sign = o.m_sign; | |
318 m_internal = o.m_internal; | |
319 if(m_internal) | |
320 { | |
321 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | |
322 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size())); | |
323 #else | |
324 std::copy(o.limbs(), o.limbs() + o.size(), limbs()); | |
325 #endif | |
326 } | |
327 else | |
328 { | |
329 m_data.ld = o.m_data.ld; | |
330 o.m_limbs = 0; | |
331 o.m_internal = true; | |
332 } | |
333 return *this; | |
334 } | |
335 #endif | |
336 BOOST_MP_FORCEINLINE ~cpp_int_base() BOOST_NOEXCEPT | |
337 { | |
338 if(!m_internal) | |
339 allocator().deallocate(limbs(), capacity()); | |
340 } | |
341 void assign(const cpp_int_base& o) | |
342 { | |
343 if(this != &o) | |
344 { | |
345 static_cast<allocator_type&>(*this) = static_cast<const allocator_type&>(o); | |
346 m_limbs = 0; | |
347 resize(o.size(), o.size()); | |
348 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | |
349 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size())); | |
350 #else | |
351 std::copy(o.limbs(), o.limbs() + o.size(), limbs()); | |
352 #endif | |
353 m_sign = o.m_sign; | |
354 } | |
355 } | |
356 BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT | |
357 { | |
358 m_sign = !m_sign; | |
359 // Check for zero value: | |
360 if(m_sign && (m_limbs == 1)) | |
361 { | |
362 if(limbs()[0] == 0) | |
363 m_sign = false; | |
364 } | |
365 } | |
366 BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT | |
367 { | |
368 return m_sign; | |
369 } | |
370 BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT | |
371 { | |
372 std::swap(m_data, o.m_data); | |
373 std::swap(m_sign, o.m_sign); | |
374 std::swap(m_internal, o.m_internal); | |
375 std::swap(m_limbs, o.m_limbs); | |
376 } | |
377 }; | |
378 | |
379 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | |
380 | |
381 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator> | |
382 const unsigned cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::limb_bits; | |
383 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator> | |
384 const limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::max_limb_value; | |
385 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator> | |
386 const limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::sign_bit_mask; | |
387 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator> | |
388 const unsigned cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::internal_limb_count; | |
389 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator> | |
390 const bool cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::variable; | |
391 | |
392 #endif | |
393 | |
394 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator> | |
395 struct cpp_int_base<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator, false> : private Allocator::template rebind<limb_type>::other | |
396 { | |
397 // | |
398 // There is currently no support for unsigned arbitrary precision arithmetic, largely | |
399 // because it's not clear what subtraction should do: | |
400 // | |
401 BOOST_STATIC_ASSERT_MSG(((sizeof(Allocator) == 0) && !is_void<Allocator>::value), "There is curently no support for unsigned arbitrary precision integers."); | |
402 }; | |
403 // | |
404 // Fixed precision (i.e. no allocator), signed-magnitude type with limb-usage count: | |
405 // | |
406 template <unsigned MinBits, cpp_int_check_type Checked> | |
407 struct cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false> | |
408 { | |
409 typedef limb_type* limb_pointer; | |
410 typedef const limb_type* const_limb_pointer; | |
411 typedef mpl::int_<Checked> checked_type; | |
412 | |
413 // | |
414 // Interface invariants: | |
415 // | |
416 BOOST_STATIC_ASSERT_MSG(MinBits > sizeof(double_limb_type) * CHAR_BIT, "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); | |
417 | |
418 public: | |
419 BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT); | |
420 BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u)); | |
421 BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1)); | |
422 BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + (MinBits % limb_bits ? 1 : 0)); | |
423 BOOST_STATIC_CONSTANT(bool, variable = false); | |
424 BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = MinBits % limb_bits ? (limb_type(1) << (MinBits % limb_bits)) -1 : (~limb_type(0))); | |
425 BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs"); | |
426 | |
427 private: | |
428 union data_type{ | |
429 limb_type m_data[internal_limb_count]; | |
430 limb_type m_first_limb; | |
431 double_limb_type m_double_first_limb; | |
432 | |
433 BOOST_CONSTEXPR data_type() : m_first_limb(0) {} | |
434 BOOST_CONSTEXPR data_type(limb_type i) : m_first_limb(i) {} | |
435 BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i) {} | |
436 #if defined(BOOST_MP_USER_DEFINED_LITERALS) | |
437 template <limb_type...VALUES> | |
438 BOOST_CONSTEXPR data_type(literals::detail::value_pack<VALUES...>) : m_data{ VALUES... } {} | |
439 #endif | |
440 } m_wrapper; | |
441 boost::uint16_t m_limbs; | |
442 bool m_sign; | |
443 | |
444 public: | |
445 // | |
446 // Direct construction: | |
447 // | |
448 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT | |
449 : m_wrapper(i), m_limbs(1), m_sign(false) {} | |
450 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT | |
451 : m_wrapper(limb_type(i < 0 ? -i : i)), m_limbs(1), m_sign(i < 0) {} | |
452 #if defined(BOOST_LITTLE_ENDIAN) | |
453 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT | |
454 : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false) {} | |
455 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT | |
456 : m_wrapper(double_limb_type(i < 0 ? -i : i)), | |
457 m_limbs(i < 0 ? (static_cast<double_limb_type>(-i) > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)), | |
458 m_sign(i < 0) {} | |
459 #endif | |
460 #if defined(BOOST_MP_USER_DEFINED_LITERALS) | |
461 template <limb_type...VALUES> | |
462 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<VALUES...> i) | |
463 : m_wrapper(i), m_limbs(sizeof...(VALUES)), m_sign(false) {} | |
464 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<> i) | |
465 : m_wrapper(i), m_limbs(1), m_sign(false) {} | |
466 BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& a, const literals::detail::negate_tag&) | |
467 : m_wrapper(a.m_wrapper), m_limbs(a.m_limbs), m_sign((a.m_limbs == 1) && (*a.limbs() == 0) ? false : !a.m_sign) {} | |
468 #endif | |
469 // | |
470 // Helper functions for getting at our internal data, and manipulating storage: | |
471 // | |
472 BOOST_MP_FORCEINLINE unsigned size()const BOOST_NOEXCEPT { return m_limbs; } | |
473 BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return m_wrapper.m_data; } | |
474 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return m_wrapper.m_data; } | |
475 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign()const BOOST_NOEXCEPT { return m_sign; } | |
476 BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT | |
477 { | |
478 m_sign = b; | |
479 // Check for zero value: | |
480 if(m_sign && (m_limbs == 1)) | |
481 { | |
482 if(limbs()[0] == 0) | |
483 m_sign = false; | |
484 } | |
485 } | |
486 BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
487 { | |
488 m_limbs = static_cast<boost::uint16_t>((std::min)(new_size, internal_limb_count)); | |
489 detail::verify_new_size(m_limbs, min_size, checked_type()); | |
490 } | |
491 BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
492 { | |
493 limb_pointer p = limbs(); | |
494 detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count-1], upper_limb_mask, checked_type()); | |
495 p[internal_limb_count-1] &= upper_limb_mask; | |
496 while((m_limbs-1) && !p[m_limbs - 1])--m_limbs; | |
497 if((m_limbs == 1) && (!*p)) m_sign = false; // zero is always unsigned | |
498 } | |
499 | |
500 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() : m_wrapper(limb_type(0u)), m_limbs(1), m_sign(false) {} | |
501 // Defaulted functions: | |
502 //BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& i)BOOST_NOEXCEPT; | |
503 //~cpp_int_base() BOOST_NOEXCEPT {} | |
504 | |
505 void assign(const cpp_int_base& o) BOOST_NOEXCEPT | |
506 { | |
507 if(this != &o) | |
508 { | |
509 resize(o.size(), o.size()); | |
510 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | |
511 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size())); | |
512 #else | |
513 std::copy(o.limbs(), o.limbs() + o.size(), limbs()); | |
514 #endif | |
515 m_sign = o.m_sign; | |
516 } | |
517 } | |
518 BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT | |
519 { | |
520 m_sign = !m_sign; | |
521 // Check for zero value: | |
522 if(m_sign && (m_limbs == 1)) | |
523 { | |
524 if(limbs()[0] == 0) | |
525 m_sign = false; | |
526 } | |
527 } | |
528 BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT | |
529 { | |
530 return m_sign; | |
531 } | |
532 BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT | |
533 { | |
534 for(unsigned i = 0; i < (std::max)(size(), o.size()); ++i) | |
535 std::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]); | |
536 std::swap(m_sign, o.m_sign); | |
537 std::swap(m_limbs, o.m_limbs); | |
538 } | |
539 }; | |
540 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | |
541 | |
542 template <unsigned MinBits, cpp_int_check_type Checked> | |
543 const unsigned cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::limb_bits; | |
544 template <unsigned MinBits, cpp_int_check_type Checked> | |
545 const limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::max_limb_value; | |
546 template <unsigned MinBits, cpp_int_check_type Checked> | |
547 const limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::sign_bit_mask; | |
548 template <unsigned MinBits, cpp_int_check_type Checked> | |
549 const unsigned cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::internal_limb_count; | |
550 template <unsigned MinBits, cpp_int_check_type Checked> | |
551 const bool cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::variable; | |
552 | |
553 #endif | |
554 // | |
555 // Fixed precision (i.e. no allocator), unsigned type with limb-usage count: | |
556 // | |
557 template <unsigned MinBits, cpp_int_check_type Checked> | |
558 struct cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false> | |
559 { | |
560 typedef limb_type* limb_pointer; | |
561 typedef const limb_type* const_limb_pointer; | |
562 typedef mpl::int_<Checked> checked_type; | |
563 | |
564 // | |
565 // Interface invariants: | |
566 // | |
567 BOOST_STATIC_ASSERT_MSG(MinBits > sizeof(double_limb_type) * CHAR_BIT, "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); | |
568 | |
569 public: | |
570 BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT); | |
571 BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u)); | |
572 BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1)); | |
573 BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + (MinBits % limb_bits ? 1 : 0)); | |
574 BOOST_STATIC_CONSTANT(bool, variable = false); | |
575 BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = MinBits % limb_bits ? (limb_type(1) << (MinBits % limb_bits)) -1 : (~limb_type(0))); | |
576 BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs"); | |
577 | |
578 private: | |
579 union data_type{ | |
580 limb_type m_data[internal_limb_count]; | |
581 limb_type m_first_limb; | |
582 double_limb_type m_double_first_limb; | |
583 | |
584 BOOST_CONSTEXPR data_type() : m_first_limb(0) {} | |
585 BOOST_CONSTEXPR data_type(limb_type i) : m_first_limb(i) {} | |
586 BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i) {} | |
587 #if defined(BOOST_MP_USER_DEFINED_LITERALS) | |
588 template <limb_type...VALUES> | |
589 BOOST_CONSTEXPR data_type(literals::detail::value_pack<VALUES...>) : m_data{ VALUES... } {} | |
590 #endif | |
591 } m_wrapper; | |
592 limb_type m_limbs; | |
593 | |
594 public: | |
595 // | |
596 // Direct construction: | |
597 // | |
598 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT | |
599 : m_wrapper(i), m_limbs(1) {} | |
600 BOOST_MP_FORCEINLINE cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
601 : m_wrapper(limb_type(i < 0 ? -i : i)), m_limbs(1) { if(i < 0) negate(); } | |
602 #ifdef BOOST_LITTLE_ENDIAN | |
603 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT | |
604 : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1) {} | |
605 BOOST_MP_FORCEINLINE cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
606 : m_wrapper(double_limb_type(i < 0 ? -i : i)), m_limbs(i < 0 ? (-i > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)) { if(i < 0) negate(); } | |
607 #endif | |
608 #if defined(BOOST_MP_USER_DEFINED_LITERALS) | |
609 template <limb_type...VALUES> | |
610 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<VALUES...> i) | |
611 : m_wrapper(i), m_limbs(sizeof...(VALUES)) {} | |
612 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>) | |
613 : m_wrapper(static_cast<limb_type>(0u)), m_limbs(1) {} | |
614 #endif | |
615 // | |
616 // Helper functions for getting at our internal data, and manipulating storage: | |
617 // | |
618 BOOST_MP_FORCEINLINE unsigned size()const BOOST_NOEXCEPT { return m_limbs; } | |
619 BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return m_wrapper.m_data; } | |
620 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return m_wrapper.m_data; } | |
621 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign()const BOOST_NOEXCEPT { return false; } | |
622 BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT_IF((Checked == unchecked)) { if(b) negate(); } | |
623 BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
624 { | |
625 m_limbs = (std::min)(new_size, internal_limb_count); | |
626 detail::verify_new_size(m_limbs, min_size, checked_type()); | |
627 } | |
628 BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
629 { | |
630 limb_pointer p = limbs(); | |
631 detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count-1], upper_limb_mask, checked_type()); | |
632 p[internal_limb_count-1] &= upper_limb_mask; | |
633 while((m_limbs-1) && !p[m_limbs - 1])--m_limbs; | |
634 } | |
635 | |
636 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT | |
637 : m_wrapper(limb_type(0u)), m_limbs(1) {} | |
638 // Defaulted functions: | |
639 //BOOST_MP_FORCEINLINE cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT; | |
640 //~cpp_int_base() BOOST_NOEXCEPT {} | |
641 | |
642 BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT | |
643 { | |
644 if(this != &o) | |
645 { | |
646 resize(o.size(), o.size()); | |
647 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | |
648 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size())); | |
649 #else | |
650 std::copy(o.limbs(), o.limbs() + o.size(), limbs()); | |
651 #endif | |
652 } | |
653 } | |
654 private: | |
655 void check_negate(const mpl::int_<checked>&) | |
656 { | |
657 BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned number.")); | |
658 } | |
659 void check_negate(const mpl::int_<unchecked>&){} | |
660 public: | |
661 void negate() BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
662 { | |
663 // Not so much a negate as a complement - this gets called when subtraction | |
664 // would result in a "negative" number: | |
665 unsigned i; | |
666 if((m_limbs == 1) && (m_wrapper.m_data[0] == 0)) | |
667 return; // negating zero is always zero, and always OK. | |
668 check_negate(checked_type()); | |
669 for(i = m_limbs; i < internal_limb_count; ++i) | |
670 m_wrapper.m_data[i] = 0; | |
671 m_limbs = internal_limb_count; | |
672 for(i = 0; i < internal_limb_count; ++i) | |
673 m_wrapper.m_data[i] = ~m_wrapper.m_data[i]; | |
674 normalize(); | |
675 eval_increment(static_cast<cpp_int_backend<MinBits, MinBits, unsigned_magnitude, Checked, void>& >(*this)); | |
676 } | |
677 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool isneg()const BOOST_NOEXCEPT | |
678 { | |
679 return false; | |
680 } | |
681 BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT | |
682 { | |
683 for(unsigned i = 0; i < (std::max)(size(), o.size()); ++i) | |
684 std::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]); | |
685 std::swap(m_limbs, o.m_limbs); | |
686 } | |
687 }; | |
688 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | |
689 | |
690 template <unsigned MinBits, cpp_int_check_type Checked> | |
691 const unsigned cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::limb_bits; | |
692 template <unsigned MinBits, cpp_int_check_type Checked> | |
693 const limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::max_limb_value; | |
694 template <unsigned MinBits, cpp_int_check_type Checked> | |
695 const limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::sign_bit_mask; | |
696 template <unsigned MinBits, cpp_int_check_type Checked> | |
697 const unsigned cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::internal_limb_count; | |
698 template <unsigned MinBits, cpp_int_check_type Checked> | |
699 const bool cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::variable; | |
700 | |
701 #endif | |
702 // | |
703 // Traits classes to figure out a native type with N bits, these vary from boost::uint_t<N> only | |
704 // because some platforms have native integer types longer than long long, "really long long" anyone?? | |
705 // | |
706 template <unsigned N, bool s> | |
707 struct trivial_limb_type_imp | |
708 { | |
709 typedef double_limb_type type; | |
710 }; | |
711 | |
712 template <unsigned N> | |
713 struct trivial_limb_type_imp<N, true> | |
714 { | |
715 typedef typename boost::uint_t<N>::least type; | |
716 }; | |
717 | |
718 template <unsigned N> | |
719 struct trivial_limb_type : public trivial_limb_type_imp<N, N <= sizeof(long long) * CHAR_BIT> {}; | |
720 // | |
721 // Backend for fixed precision signed-magnitude type which will fit entirely inside a "double_limb_type": | |
722 // | |
723 template <unsigned MinBits, cpp_int_check_type Checked> | |
724 struct cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, true> | |
725 { | |
726 typedef typename trivial_limb_type<MinBits>::type local_limb_type; | |
727 typedef local_limb_type* limb_pointer; | |
728 typedef const local_limb_type* const_limb_pointer; | |
729 typedef mpl::int_<Checked> checked_type; | |
730 protected: | |
731 BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT); | |
732 BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = (MinBits < limb_bits) ? local_limb_type((local_limb_type(~local_limb_type(0))) >> (limb_bits - MinBits)) : local_limb_type(~local_limb_type(0))); | |
733 private: | |
734 local_limb_type m_data; | |
735 bool m_sign; | |
736 | |
737 // | |
738 // Interface invariants: | |
739 // | |
740 BOOST_STATIC_ASSERT_MSG(MinBits <= sizeof(double_limb_type) * CHAR_BIT, "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); | |
741 protected: | |
742 template <class T> | |
743 typename boost::disable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= (int)MinBits)>::type | |
744 check_in_range(T val, const mpl::int_<checked>&) | |
745 { | |
746 BOOST_MP_USING_ABS | |
747 typedef typename common_type<T, local_limb_type>::type common_type; | |
748 | |
749 if(static_cast<common_type>(abs(val)) > static_cast<common_type>(limb_mask)) | |
750 BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent.")); | |
751 } | |
752 template <class T, int C> | |
753 void check_in_range(T, const mpl::int_<C>&){} | |
754 | |
755 template <class T> | |
756 void check_in_range(T val) | |
757 { | |
758 check_in_range(val, checked_type()); | |
759 } | |
760 | |
761 public: | |
762 // | |
763 // Direct construction: | |
764 // | |
765 template <class SI> | |
766 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
767 : m_data(i < 0 ? static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(-i)) & limb_mask : static_cast<local_limb_type>(i) & limb_mask), m_sign(i < 0) {} | |
768 template <class SI> | |
769 BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
770 : m_data(i < 0 ? static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(-i) & limb_mask) : static_cast<local_limb_type>(i) & limb_mask), m_sign(i < 0) { check_in_range(i); } | |
771 template <class UI> | |
772 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
773 : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) {} | |
774 template <class UI> | |
775 BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == checked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
776 : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) { check_in_range(i); } | |
777 template <class F> | |
778 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(F i, typename boost::enable_if_c<is_floating_point<F>::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
779 : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask), m_sign(i < 0) {} | |
780 template <class F> | |
781 BOOST_MP_FORCEINLINE cpp_int_base(F i, typename boost::enable_if_c<is_floating_point<F>::value && (Checked == checked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
782 : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask), m_sign(i < 0) { check_in_range(i); } | |
783 #if defined(BOOST_MP_USER_DEFINED_LITERALS) | |
784 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>) | |
785 : m_data(static_cast<local_limb_type>(0u)), m_sign(false) {} | |
786 template <limb_type a> | |
787 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a>) | |
788 : m_data(static_cast<local_limb_type>(a)), m_sign(false) {} | |
789 template <limb_type a, limb_type b> | |
790 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a, b>) | |
791 : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)), m_sign(false) {} | |
792 BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& a, const literals::detail::negate_tag&) | |
793 : m_data(a.m_data), m_sign(a.m_data ? !a.m_sign : false) {} | |
794 #endif | |
795 // | |
796 // Helper functions for getting at our internal data, and manipulating storage: | |
797 // | |
798 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned size()const BOOST_NOEXCEPT { return 1; } | |
799 BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return &m_data; } | |
800 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return &m_data; } | |
801 BOOST_MP_FORCEINLINE bool sign()const BOOST_NOEXCEPT { return m_sign; } | |
802 BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT | |
803 { | |
804 m_sign = b; | |
805 // Check for zero value: | |
806 if(m_sign && !m_data) | |
807 { | |
808 m_sign = false; | |
809 } | |
810 } | |
811 BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) | |
812 { | |
813 detail::verify_new_size(2, min_size, checked_type()); | |
814 } | |
815 BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
816 { | |
817 if(!m_data) | |
818 m_sign = false; // zero is always unsigned | |
819 detail::verify_limb_mask(true, m_data, limb_mask, checked_type()); | |
820 m_data &= limb_mask; | |
821 } | |
822 | |
823 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() : m_data(0), m_sign(false) {} | |
824 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT | |
825 : m_data(o.m_data), m_sign(o.m_sign) {} | |
826 //~cpp_int_base() BOOST_NOEXCEPT {} | |
827 BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT | |
828 { | |
829 m_data = o.m_data; | |
830 m_sign = o.m_sign; | |
831 } | |
832 BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT | |
833 { | |
834 m_sign = !m_sign; | |
835 // Check for zero value: | |
836 if(m_data == 0) | |
837 { | |
838 m_sign = false; | |
839 } | |
840 } | |
841 BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT | |
842 { | |
843 return m_sign; | |
844 } | |
845 BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT | |
846 { | |
847 std::swap(m_sign, o.m_sign); | |
848 std::swap(m_data, o.m_data); | |
849 } | |
850 }; | |
851 // | |
852 // Backend for unsigned fixed precision (i.e. no allocator) type which will fit entirely inside a "double_limb_type": | |
853 // | |
854 template <unsigned MinBits, cpp_int_check_type Checked> | |
855 struct cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, true> | |
856 { | |
857 typedef typename trivial_limb_type<MinBits>::type local_limb_type; | |
858 typedef local_limb_type* limb_pointer; | |
859 typedef const local_limb_type* const_limb_pointer; | |
860 private: | |
861 BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT); | |
862 BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = limb_bits != MinBits ? | |
863 static_cast<local_limb_type>(static_cast<local_limb_type>(~local_limb_type(0)) >> (limb_bits - MinBits)) | |
864 : static_cast<local_limb_type>(~local_limb_type(0))); | |
865 | |
866 local_limb_type m_data; | |
867 | |
868 typedef mpl::int_<Checked> checked_type; | |
869 | |
870 // | |
871 // Interface invariants: | |
872 // | |
873 BOOST_STATIC_ASSERT_MSG(MinBits <= sizeof(double_limb_type) * CHAR_BIT, "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); | |
874 protected: | |
875 template <class T> | |
876 typename boost::disable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= (int)MinBits)>::type | |
877 check_in_range(T val, const mpl::int_<checked>&, const mpl::false_&) | |
878 { | |
879 typedef typename common_type<T, local_limb_type>::type common_type; | |
880 | |
881 if(static_cast<common_type>(val) > limb_mask) | |
882 BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent.")); | |
883 } | |
884 template <class T> | |
885 void check_in_range(T val, const mpl::int_<checked>&, const mpl::true_&) | |
886 { | |
887 typedef typename common_type<T, local_limb_type>::type common_type; | |
888 | |
889 if(static_cast<common_type>(val) > limb_mask) | |
890 BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent.")); | |
891 if(val < 0) | |
892 BOOST_THROW_EXCEPTION(std::range_error("The argument to an unsigned cpp_int constructor was negative.")); | |
893 } | |
894 template <class T, int C, bool B> | |
895 BOOST_MP_FORCEINLINE void check_in_range(T, const mpl::int_<C>&, const mpl::bool_<B>&){} | |
896 | |
897 template <class T> | |
898 BOOST_MP_FORCEINLINE void check_in_range(T val) | |
899 { | |
900 check_in_range(val, checked_type(), is_signed<T>()); | |
901 } | |
902 | |
903 public: | |
904 // | |
905 // Direct construction: | |
906 // | |
907 template <class SI> | |
908 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
909 : m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i)) & limb_mask : static_cast<local_limb_type>(i) & limb_mask) {} | |
910 template <class SI> | |
911 BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
912 : m_data(i < 0 ? 1 + ~static_cast<local_limb_type>(-i) : static_cast<local_limb_type>(i)) { check_in_range(i); } | |
913 template <class UI> | |
914 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
915 : m_data(static_cast<local_limb_type>(i) & limb_mask) {} | |
916 template <class UI> | |
917 BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
918 : m_data(static_cast<local_limb_type>(i)) { check_in_range(i); } | |
919 template <class F> | |
920 BOOST_MP_FORCEINLINE cpp_int_base(F i, typename boost::enable_if<is_floating_point<F> >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
921 : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask) | |
922 { | |
923 check_in_range(i); | |
924 if(i < 0) | |
925 negate(); | |
926 } | |
927 #if defined(BOOST_MP_USER_DEFINED_LITERALS) | |
928 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>) | |
929 : m_data(static_cast<local_limb_type>(0u)) {} | |
930 template <limb_type a> | |
931 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a>) | |
932 : m_data(static_cast<local_limb_type>(a)) {} | |
933 template <limb_type a, limb_type b> | |
934 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a, b>) | |
935 : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)) {} | |
936 #endif | |
937 // | |
938 // Helper functions for getting at our internal data, and manipulating storage: | |
939 // | |
940 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned size()const BOOST_NOEXCEPT { return 1; } | |
941 BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return &m_data; } | |
942 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return &m_data; } | |
943 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign()const BOOST_NOEXCEPT { return false; } | |
944 BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
945 { | |
946 if(b) | |
947 negate(); | |
948 } | |
949 BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) | |
950 { | |
951 detail::verify_new_size(2, min_size, checked_type()); | |
952 } | |
953 BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
954 { | |
955 detail::verify_limb_mask(true, m_data, limb_mask, checked_type()); | |
956 m_data &= limb_mask; | |
957 } | |
958 | |
959 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() : m_data(0) {} | |
960 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT | |
961 : m_data(o.m_data) {} | |
962 //~cpp_int_base() BOOST_NOEXCEPT {} | |
963 BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT | |
964 { | |
965 m_data = o.m_data; | |
966 } | |
967 BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
968 { | |
969 if(Checked == checked) | |
970 { | |
971 BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned type.")); | |
972 } | |
973 m_data = ~m_data; | |
974 ++m_data; | |
975 } | |
976 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool isneg()const BOOST_NOEXCEPT | |
977 { | |
978 return false; | |
979 } | |
980 BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT | |
981 { | |
982 std::swap(m_data, o.m_data); | |
983 } | |
984 }; | |
985 // | |
986 // Traits class, lets us know whether type T can be directly converted to the base type, | |
987 // used to enable/disable constructors etc: | |
988 // | |
989 template <class Arg, class Base> | |
990 struct is_allowed_cpp_int_base_conversion : public mpl::if_c< | |
991 is_same<Arg, limb_type>::value || is_same<Arg, signed_limb_type>::value | |
992 #ifdef BOOST_LITTLE_ENDIAN | |
993 || is_same<Arg, double_limb_type>::value || is_same<Arg, signed_double_limb_type>::value | |
994 #endif | |
995 #if defined(BOOST_MP_USER_DEFINED_LITERALS) | |
996 || literals::detail::is_value_pack<Arg>::value | |
997 #endif | |
998 || (is_trivial_cpp_int<Base>::value && is_arithmetic<Arg>::value), | |
999 mpl::true_, | |
1000 mpl::false_ | |
1001 >::type | |
1002 {}; | |
1003 // | |
1004 // Now the actual backend, normalising parameters passed to the base class: | |
1005 // | |
1006 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator> | |
1007 struct cpp_int_backend | |
1008 : public cpp_int_base< | |
1009 min_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, | |
1010 max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, | |
1011 SignType, | |
1012 Checked, | |
1013 Allocator, | |
1014 is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value> | |
1015 { | |
1016 typedef cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> self_type; | |
1017 typedef cpp_int_base< | |
1018 min_precision<self_type>::value, | |
1019 max_precision<self_type>::value, | |
1020 SignType, | |
1021 Checked, | |
1022 Allocator, | |
1023 is_trivial_cpp_int<self_type>::value> base_type; | |
1024 typedef mpl::bool_<is_trivial_cpp_int<self_type>::value> trivial_tag; | |
1025 public: | |
1026 typedef typename mpl::if_< | |
1027 trivial_tag, | |
1028 mpl::list< | |
1029 signed char, short, int, long, | |
1030 long long, signed_double_limb_type>, | |
1031 mpl::list<signed_limb_type, signed_double_limb_type> | |
1032 >::type signed_types; | |
1033 typedef typename mpl::if_< | |
1034 trivial_tag, | |
1035 mpl::list<unsigned char, unsigned short, unsigned, | |
1036 unsigned long long, double_limb_type>, | |
1037 mpl::list<limb_type, double_limb_type> | |
1038 >::type unsigned_types; | |
1039 typedef typename mpl::if_< | |
1040 trivial_tag, | |
1041 mpl::list<float, double, long double>, | |
1042 mpl::list<long double> | |
1043 >::type float_types; | |
1044 typedef mpl::int_<Checked> checked_type; | |
1045 | |
1046 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend() BOOST_NOEXCEPT{} | |
1047 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(const cpp_int_backend& o) BOOST_NOEXCEPT_IF(boost::is_void<Allocator>::value) : base_type(o) {} | |
1048 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
1049 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(cpp_int_backend&& o) BOOST_NOEXCEPT | |
1050 : base_type(static_cast<base_type&&>(o)) {} | |
1051 #endif | |
1052 // | |
1053 // Direct construction from arithmetic type: | |
1054 // | |
1055 template <class Arg> | |
1056 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(Arg i, typename boost::enable_if_c<is_allowed_cpp_int_base_conversion<Arg, base_type>::value >::type const* = 0)BOOST_NOEXCEPT_IF((Checked == unchecked) && boost::is_void<Allocator>::value) | |
1057 : base_type(i) {} | |
1058 | |
1059 private: | |
1060 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1061 void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::true_ const&, mpl::true_ const &) | |
1062 { | |
1063 // Assigning trivial type to trivial type: | |
1064 this->check_in_range(*other.limbs()); | |
1065 *this->limbs() = static_cast<typename self_type::local_limb_type>(*other.limbs()); | |
1066 this->sign(other.sign()); | |
1067 this->normalize(); | |
1068 } | |
1069 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1070 void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::true_ const&, mpl::false_ const &) | |
1071 { | |
1072 // non-trivial to trivial narrowing conversion: | |
1073 double_limb_type v = *other.limbs(); | |
1074 if(other.size() > 1) | |
1075 { | |
1076 v |= static_cast<double_limb_type>(other.limbs()[1]) << bits_per_limb; | |
1077 if((Checked == checked) && (other.size() > 2)) | |
1078 { | |
1079 BOOST_THROW_EXCEPTION(std::range_error("Assignment of a cpp_int that is out of range for the target type.")); | |
1080 } | |
1081 } | |
1082 *this = v; | |
1083 this->sign(other.sign()); | |
1084 this->normalize(); | |
1085 } | |
1086 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1087 void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::false_ const&, mpl::true_ const &) | |
1088 { | |
1089 // trivial to non-trivial, treat the trivial argument as if it were an unsigned arithmetic type, then set the sign afterwards: | |
1090 *this = static_cast< | |
1091 typename boost::multiprecision::detail::canonical< | |
1092 typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::local_limb_type, | |
1093 cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> | |
1094 >::type | |
1095 >(*other.limbs()); | |
1096 this->sign(other.sign()); | |
1097 } | |
1098 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1099 void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::false_ const&, mpl::false_ const &) | |
1100 { | |
1101 // regular non-trivial to non-trivial assign: | |
1102 this->resize(other.size(), other.size()); | |
1103 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) | |
1104 std::copy(other.limbs(), other.limbs() + (std::min)(other.size(), this->size()), stdext::checked_array_iterator<limb_pointer>(this->limbs(), this->size())); | |
1105 #else | |
1106 std::copy(other.limbs(), other.limbs() + (std::min)(other.size(), this->size()), this->limbs()); | |
1107 #endif | |
1108 this->sign(other.sign()); | |
1109 this->normalize(); | |
1110 } | |
1111 public: | |
1112 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1113 cpp_int_backend( | |
1114 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, | |
1115 typename boost::enable_if_c<is_implicit_cpp_int_conversion<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>, self_type>::value>::type* = 0) | |
1116 : base_type() | |
1117 { | |
1118 do_assign( | |
1119 other, | |
1120 mpl::bool_<is_trivial_cpp_int<self_type>::value>(), | |
1121 mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>()); | |
1122 } | |
1123 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1124 explicit cpp_int_backend( | |
1125 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, | |
1126 typename boost::disable_if_c<is_implicit_cpp_int_conversion<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>, self_type>::value>::type* = 0) | |
1127 : base_type() | |
1128 { | |
1129 do_assign( | |
1130 other, | |
1131 mpl::bool_<is_trivial_cpp_int<self_type>::value>(), | |
1132 mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>()); | |
1133 } | |
1134 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1135 cpp_int_backend& operator=( | |
1136 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other) | |
1137 { | |
1138 do_assign( | |
1139 other, | |
1140 mpl::bool_<is_trivial_cpp_int<self_type>::value>(), | |
1141 mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>()); | |
1142 return *this; | |
1143 } | |
1144 #ifdef BOOST_MP_USER_DEFINED_LITERALS | |
1145 BOOST_CONSTEXPR cpp_int_backend(const cpp_int_backend& a, const literals::detail::negate_tag& tag) | |
1146 : base_type(static_cast<const base_type&>(a), tag){} | |
1147 #endif | |
1148 | |
1149 BOOST_MP_FORCEINLINE cpp_int_backend& operator = (const cpp_int_backend& o) BOOST_NOEXCEPT_IF((Checked == unchecked) && boost::is_void<Allocator>::value) | |
1150 { | |
1151 this->assign(o); | |
1152 return *this; | |
1153 } | |
1154 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
1155 BOOST_MP_FORCEINLINE cpp_int_backend& operator = (cpp_int_backend&& o) BOOST_NOEXCEPT_IF(boost::is_void<Allocator>::value) | |
1156 { | |
1157 *static_cast<base_type*>(this) = static_cast<base_type&&>(o); | |
1158 return *this; | |
1159 } | |
1160 #endif | |
1161 private: | |
1162 template <class A> | |
1163 typename boost::enable_if<is_unsigned<A> >::type do_assign_arithmetic(A val, const mpl::true_&) | |
1164 { | |
1165 this->check_in_range(val); | |
1166 *this->limbs() = static_cast<typename self_type::local_limb_type>(val); | |
1167 this->normalize(); | |
1168 } | |
1169 template <class A> | |
1170 typename boost::disable_if<is_unsigned<A> >::type do_assign_arithmetic(A val, const mpl::true_&) | |
1171 { | |
1172 typedef typename make_signed<typename self_type::local_limb_type>::type signed_limb_type; | |
1173 this->check_in_range(val); | |
1174 *this->limbs() = (val < 0) ? static_cast<typename self_type::local_limb_type>(-static_cast<signed_limb_type>(val)) : static_cast<typename self_type::local_limb_type>(val); | |
1175 this->sign(val < 0); | |
1176 this->normalize(); | |
1177 } | |
1178 BOOST_MP_FORCEINLINE void do_assign_arithmetic(limb_type i, const mpl::false_&) BOOST_NOEXCEPT | |
1179 { | |
1180 this->resize(1, 1); | |
1181 *this->limbs() = i; | |
1182 this->sign(false); | |
1183 } | |
1184 BOOST_MP_FORCEINLINE void do_assign_arithmetic(signed_limb_type i, const mpl::false_&) BOOST_NOEXCEPT_IF((Checked == unchecked)) | |
1185 { | |
1186 this->resize(1, 1); | |
1187 *this->limbs() = static_cast<limb_type>(std::abs(i)); | |
1188 this->sign(i < 0); | |
1189 } | |
1190 void do_assign_arithmetic(double_limb_type i, const mpl::false_&) | |
1191 { | |
1192 BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type)); | |
1193 BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2); | |
1194 typename base_type::limb_pointer p = this->limbs(); | |
1195 *p = static_cast<limb_type>(i); | |
1196 p[1] = static_cast<limb_type>(i >> base_type::limb_bits); | |
1197 this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1); | |
1198 this->sign(false); | |
1199 } | |
1200 void do_assign_arithmetic(signed_double_limb_type i, const mpl::false_&) | |
1201 { | |
1202 BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type)); | |
1203 BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2); | |
1204 bool s = false; | |
1205 if(i < 0) | |
1206 { | |
1207 s = true; | |
1208 i = -i; | |
1209 } | |
1210 else | |
1211 this->sign(false); | |
1212 typename base_type::limb_pointer p = this->limbs(); | |
1213 *p = static_cast<limb_type>(i); | |
1214 p[1] = static_cast<limb_type>(i >> base_type::limb_bits); | |
1215 this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1); | |
1216 this->sign(s); | |
1217 } | |
1218 | |
1219 void do_assign_arithmetic(long double a, const mpl::false_&) | |
1220 { | |
1221 using default_ops::eval_add; | |
1222 using default_ops::eval_subtract; | |
1223 using std::frexp; | |
1224 using std::ldexp; | |
1225 using std::floor; | |
1226 | |
1227 if (a == 0) { | |
1228 *this = static_cast<limb_type>(0u); | |
1229 } | |
1230 | |
1231 if (a == 1) { | |
1232 *this = static_cast<limb_type>(1u); | |
1233 } | |
1234 | |
1235 BOOST_ASSERT(!(boost::math::isinf)(a)); | |
1236 BOOST_ASSERT(!(boost::math::isnan)(a)); | |
1237 | |
1238 int e; | |
1239 long double f, term; | |
1240 *this = static_cast<limb_type>(0u); | |
1241 | |
1242 f = frexp(a, &e); | |
1243 | |
1244 static const limb_type shift = std::numeric_limits<limb_type>::digits; | |
1245 | |
1246 while(f) | |
1247 { | |
1248 // extract int sized bits from f: | |
1249 f = ldexp(f, shift); | |
1250 term = floor(f); | |
1251 e -= shift; | |
1252 eval_left_shift(*this, shift); | |
1253 if(term > 0) | |
1254 eval_add(*this, static_cast<limb_type>(term)); | |
1255 else | |
1256 eval_subtract(*this, static_cast<limb_type>(-term)); | |
1257 f -= term; | |
1258 } | |
1259 if(e > 0) | |
1260 eval_left_shift(*this, e); | |
1261 else if(e < 0) | |
1262 eval_right_shift(*this, -e); | |
1263 } | |
1264 public: | |
1265 template <class Arithmetic> | |
1266 BOOST_MP_FORCEINLINE cpp_int_backend& operator = (Arithmetic val) | |
1267 { | |
1268 do_assign_arithmetic(val, trivial_tag()); | |
1269 return *this; | |
1270 } | |
1271 private: | |
1272 void do_assign_string(const char* s, const mpl::true_&) | |
1273 { | |
1274 std::size_t n = s ? std::strlen(s) : 0; | |
1275 *this->limbs() = 0; | |
1276 unsigned radix = 10; | |
1277 bool isneg = false; | |
1278 if(n && (*s == '-')) | |
1279 { | |
1280 --n; | |
1281 ++s; | |
1282 isneg = true; | |
1283 } | |
1284 if(n && (*s == '0')) | |
1285 { | |
1286 if((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) | |
1287 { | |
1288 radix = 16; | |
1289 s +=2; | |
1290 n -= 2; | |
1291 } | |
1292 else | |
1293 { | |
1294 radix = 8; | |
1295 n -= 1; | |
1296 } | |
1297 } | |
1298 if(n) | |
1299 { | |
1300 unsigned val; | |
1301 while(*s) | |
1302 { | |
1303 if(*s >= '0' && *s <= '9') | |
1304 val = *s - '0'; | |
1305 else if(*s >= 'a' && *s <= 'f') | |
1306 val = 10 + *s - 'a'; | |
1307 else if(*s >= 'A' && *s <= 'F') | |
1308 val = 10 + *s - 'A'; | |
1309 else | |
1310 val = radix + 1; | |
1311 if(val >= radix) | |
1312 { | |
1313 BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string.")); | |
1314 } | |
1315 *this->limbs() = detail::checked_multiply(*this->limbs(), static_cast<typename base_type::local_limb_type>(radix), checked_type()); | |
1316 *this->limbs() = detail::checked_add(*this->limbs(), static_cast<typename base_type::local_limb_type>(val), checked_type()); | |
1317 ++s; | |
1318 } | |
1319 } | |
1320 if(isneg) | |
1321 this->negate(); | |
1322 } | |
1323 void do_assign_string(const char* s, const mpl::false_&) | |
1324 { | |
1325 using default_ops::eval_multiply; | |
1326 using default_ops::eval_add; | |
1327 std::size_t n = s ? std::strlen(s) : 0; | |
1328 *this = static_cast<limb_type>(0u); | |
1329 unsigned radix = 10; | |
1330 bool isneg = false; | |
1331 if(n && (*s == '-')) | |
1332 { | |
1333 --n; | |
1334 ++s; | |
1335 isneg = true; | |
1336 } | |
1337 if(n && (*s == '0')) | |
1338 { | |
1339 if((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) | |
1340 { | |
1341 radix = 16; | |
1342 s +=2; | |
1343 n -= 2; | |
1344 } | |
1345 else | |
1346 { | |
1347 radix = 8; | |
1348 n -= 1; | |
1349 } | |
1350 } | |
1351 if(n) | |
1352 { | |
1353 if(radix == 8 || radix == 16) | |
1354 { | |
1355 unsigned shift = radix == 8 ? 3 : 4; | |
1356 unsigned block_count = base_type::limb_bits / shift; | |
1357 unsigned block_shift = shift * block_count; | |
1358 limb_type val, block; | |
1359 while(*s) | |
1360 { | |
1361 block = 0; | |
1362 for(unsigned i = 0; (i < block_count); ++i) | |
1363 { | |
1364 if(*s >= '0' && *s <= '9') | |
1365 val = *s - '0'; | |
1366 else if(*s >= 'a' && *s <= 'f') | |
1367 val = 10 + *s - 'a'; | |
1368 else if(*s >= 'A' && *s <= 'F') | |
1369 val = 10 + *s - 'A'; | |
1370 else | |
1371 val = base_type::max_limb_value; | |
1372 if(val >= radix) | |
1373 { | |
1374 BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string.")); | |
1375 } | |
1376 block <<= shift; | |
1377 block |= val; | |
1378 if(!*++s) | |
1379 { | |
1380 // final shift is different: | |
1381 block_shift = (i + 1) * shift; | |
1382 break; | |
1383 } | |
1384 } | |
1385 eval_left_shift(*this, block_shift); | |
1386 this->limbs()[0] |= block; | |
1387 } | |
1388 } | |
1389 else | |
1390 { | |
1391 // Base 10, we extract blocks of size 10^9 at a time, that way | |
1392 // the number of multiplications is kept to a minimum: | |
1393 limb_type block_mult = max_block_10; | |
1394 while(*s) | |
1395 { | |
1396 limb_type block = 0; | |
1397 for(unsigned i = 0; i < digits_per_block_10; ++i) | |
1398 { | |
1399 limb_type val; | |
1400 if(*s >= '0' && *s <= '9') | |
1401 val = *s - '0'; | |
1402 else | |
1403 BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected character encountered in input.")); | |
1404 block *= 10; | |
1405 block += val; | |
1406 if(!*++s) | |
1407 { | |
1408 block_mult = block_multiplier(i); | |
1409 break; | |
1410 } | |
1411 } | |
1412 eval_multiply(*this, block_mult); | |
1413 eval_add(*this, block); | |
1414 } | |
1415 } | |
1416 } | |
1417 if(isneg) | |
1418 this->negate(); | |
1419 } | |
1420 public: | |
1421 cpp_int_backend& operator = (const char* s) | |
1422 { | |
1423 do_assign_string(s, trivial_tag()); | |
1424 return *this; | |
1425 } | |
1426 BOOST_MP_FORCEINLINE void swap(cpp_int_backend& o) BOOST_NOEXCEPT | |
1427 { | |
1428 this->do_swap(o); | |
1429 } | |
1430 private: | |
1431 std::string do_get_trivial_string(std::ios_base::fmtflags f, const mpl::false_&)const | |
1432 { | |
1433 typedef typename mpl::if_c<sizeof(*this->limbs()) == 1, unsigned, typename base_type::local_limb_type>::type io_type; | |
1434 if(this->sign() && (((f & std::ios_base::hex) == std::ios_base::hex) || ((f & std::ios_base::oct) == std::ios_base::oct))) | |
1435 BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported.")); | |
1436 std::stringstream ss; | |
1437 ss.flags(f & ~std::ios_base::showpos); | |
1438 ss << static_cast<io_type>(*this->limbs()); | |
1439 std::string result; | |
1440 if(this->sign()) | |
1441 result += '-'; | |
1442 else if(f & std::ios_base::showpos) | |
1443 result += '+'; | |
1444 result += ss.str(); | |
1445 return result; | |
1446 } | |
1447 std::string do_get_trivial_string(std::ios_base::fmtflags f, const mpl::true_&)const | |
1448 { | |
1449 // Even though we have only one limb, we can't do IO on it :-( | |
1450 int base = 10; | |
1451 if((f & std::ios_base::oct) == std::ios_base::oct) | |
1452 base = 8; | |
1453 else if((f & std::ios_base::hex) == std::ios_base::hex) | |
1454 base = 16; | |
1455 std::string result; | |
1456 | |
1457 unsigned Bits = sizeof(typename base_type::local_limb_type) * CHAR_BIT; | |
1458 | |
1459 if(base == 8 || base == 16) | |
1460 { | |
1461 if(this->sign()) | |
1462 BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported.")); | |
1463 limb_type shift = base == 8 ? 3 : 4; | |
1464 limb_type mask = static_cast<limb_type>((1u << shift) - 1); | |
1465 typename base_type::local_limb_type v = *this->limbs(); | |
1466 result.assign(Bits / shift + (Bits % shift ? 1 : 0), '0'); | |
1467 std::string::difference_type pos = result.size() - 1; | |
1468 for(unsigned i = 0; i < Bits / shift; ++i) | |
1469 { | |
1470 char c = '0' + static_cast<char>(v & mask); | |
1471 if(c > '9') | |
1472 c += 'A' - '9' - 1; | |
1473 result[pos--] = c; | |
1474 v >>= shift; | |
1475 } | |
1476 if(Bits % shift) | |
1477 { | |
1478 mask = static_cast<limb_type>((1u << (Bits % shift)) - 1); | |
1479 char c = '0' + static_cast<char>(v & mask); | |
1480 if(c > '9') | |
1481 c += 'A' - '9'; | |
1482 result[pos] = c; | |
1483 } | |
1484 // | |
1485 // Get rid of leading zeros: | |
1486 // | |
1487 std::string::size_type n = result.find_first_not_of('0'); | |
1488 if(!result.empty() && (n == std::string::npos)) | |
1489 n = result.size() - 1; | |
1490 result.erase(0, n); | |
1491 if(f & std::ios_base::showbase) | |
1492 { | |
1493 const char* pp = base == 8 ? "0" : "0x"; | |
1494 result.insert(0, pp); | |
1495 } | |
1496 } | |
1497 else | |
1498 { | |
1499 result.assign(Bits / 3 + 1, '0'); | |
1500 std::string::difference_type pos = result.size() - 1; | |
1501 typename base_type::local_limb_type v(*this->limbs()); | |
1502 bool neg = false; | |
1503 if(this->sign()) | |
1504 { | |
1505 neg = true; | |
1506 } | |
1507 while(v) | |
1508 { | |
1509 result[pos] = (v % 10) + '0'; | |
1510 --pos; | |
1511 v /= 10; | |
1512 } | |
1513 std::string::size_type n = result.find_first_not_of('0'); | |
1514 result.erase(0, n); | |
1515 if(result.empty()) | |
1516 result = "0"; | |
1517 if(neg) | |
1518 result.insert(0, 1, '-'); | |
1519 else if(f & std::ios_base::showpos) | |
1520 result.insert(0, 1, '+'); | |
1521 } | |
1522 return result; | |
1523 } | |
1524 std::string do_get_string(std::ios_base::fmtflags f, const mpl::true_&)const | |
1525 { | |
1526 #ifdef BOOST_MP_NO_DOUBLE_LIMB_TYPE_IO | |
1527 return do_get_trivial_string(f, mpl::bool_<is_same<typename base_type::local_limb_type, double_limb_type>::value>()); | |
1528 #else | |
1529 return do_get_trivial_string(f, mpl::bool_<false>()); | |
1530 #endif | |
1531 } | |
1532 std::string do_get_string(std::ios_base::fmtflags f, const mpl::false_&)const | |
1533 { | |
1534 using default_ops::eval_get_sign; | |
1535 int base = 10; | |
1536 if((f & std::ios_base::oct) == std::ios_base::oct) | |
1537 base = 8; | |
1538 else if((f & std::ios_base::hex) == std::ios_base::hex) | |
1539 base = 16; | |
1540 std::string result; | |
1541 | |
1542 unsigned Bits = this->size() * base_type::limb_bits; | |
1543 | |
1544 if(base == 8 || base == 16) | |
1545 { | |
1546 if(this->sign()) | |
1547 BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported.")); | |
1548 limb_type shift = base == 8 ? 3 : 4; | |
1549 limb_type mask = static_cast<limb_type>((1u << shift) - 1); | |
1550 cpp_int_backend t(*this); | |
1551 result.assign(Bits / shift + (Bits % shift ? 1 : 0), '0'); | |
1552 std::string::difference_type pos = result.size() - 1; | |
1553 for(unsigned i = 0; i < Bits / shift; ++i) | |
1554 { | |
1555 char c = '0' + static_cast<char>(t.limbs()[0] & mask); | |
1556 if(c > '9') | |
1557 c += 'A' - '9' - 1; | |
1558 result[pos--] = c; | |
1559 eval_right_shift(t, shift); | |
1560 } | |
1561 if(Bits % shift) | |
1562 { | |
1563 mask = static_cast<limb_type>((1u << (Bits % shift)) - 1); | |
1564 char c = '0' + static_cast<char>(t.limbs()[0] & mask); | |
1565 if(c > '9') | |
1566 c += 'A' - '9'; | |
1567 result[pos] = c; | |
1568 } | |
1569 // | |
1570 // Get rid of leading zeros: | |
1571 // | |
1572 std::string::size_type n = result.find_first_not_of('0'); | |
1573 if(!result.empty() && (n == std::string::npos)) | |
1574 n = result.size() - 1; | |
1575 result.erase(0, n); | |
1576 if(f & std::ios_base::showbase) | |
1577 { | |
1578 const char* pp = base == 8 ? "0" : "0x"; | |
1579 result.insert(0, pp); | |
1580 } | |
1581 } | |
1582 else | |
1583 { | |
1584 result.assign(Bits / 3 + 1, '0'); | |
1585 std::string::difference_type pos = result.size() - 1; | |
1586 cpp_int_backend t(*this); | |
1587 cpp_int_backend r; | |
1588 bool neg = false; | |
1589 if(t.sign()) | |
1590 { | |
1591 t.negate(); | |
1592 neg = true; | |
1593 } | |
1594 if(this->size() == 1) | |
1595 { | |
1596 result = boost::lexical_cast<std::string>(t.limbs()[0]); | |
1597 } | |
1598 else | |
1599 { | |
1600 cpp_int_backend block10; | |
1601 block10 = max_block_10; | |
1602 while(eval_get_sign(t) != 0) | |
1603 { | |
1604 cpp_int_backend t2; | |
1605 divide_unsigned_helper(&t2, t, block10, r); | |
1606 t = t2; | |
1607 limb_type v = r.limbs()[0]; | |
1608 for(unsigned i = 0; i < digits_per_block_10; ++i) | |
1609 { | |
1610 char c = '0' + v % 10; | |
1611 v /= 10; | |
1612 result[pos] = c; | |
1613 if(pos-- == 0) | |
1614 break; | |
1615 } | |
1616 } | |
1617 } | |
1618 std::string::size_type n = result.find_first_not_of('0'); | |
1619 result.erase(0, n); | |
1620 if(result.empty()) | |
1621 result = "0"; | |
1622 if(neg) | |
1623 result.insert(0, 1, '-'); | |
1624 else if(f & std::ios_base::showpos) | |
1625 result.insert(0, 1, '+'); | |
1626 } | |
1627 return result; | |
1628 } | |
1629 public: | |
1630 std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f)const | |
1631 { | |
1632 return do_get_string(f, trivial_tag()); | |
1633 } | |
1634 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1635 int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::false_&, const mpl::false_&)const BOOST_NOEXCEPT | |
1636 { | |
1637 if(this->sign() != o.sign()) | |
1638 return this->sign() ? -1 : 1; | |
1639 | |
1640 // Only do the compare if the same sign: | |
1641 int result = compare_unsigned(o); | |
1642 | |
1643 if(this->sign()) | |
1644 result = -result; | |
1645 return result; | |
1646 } | |
1647 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1648 int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::true_&, const mpl::false_&)const | |
1649 { | |
1650 cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> t(*this); | |
1651 return t.compare(o); | |
1652 } | |
1653 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1654 int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::false_&, const mpl::true_&)const | |
1655 { | |
1656 cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> t(o); | |
1657 return compare(t); | |
1658 } | |
1659 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1660 int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::true_&, const mpl::true_&)const BOOST_NOEXCEPT | |
1661 { | |
1662 if(this->sign()) | |
1663 { | |
1664 if(o.sign()) | |
1665 { | |
1666 return *this->limbs() < *o.limbs() ? 1 : (*this->limbs() > *o.limbs() ? -1 : 0); | |
1667 } | |
1668 else | |
1669 return -1; | |
1670 } | |
1671 else | |
1672 { | |
1673 if(o.sign()) | |
1674 return 1; | |
1675 return *this->limbs() < *o.limbs() ? -1 : (*this->limbs() > *o.limbs() ? 1 : 0); | |
1676 } | |
1677 } | |
1678 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1679 int compare(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o)const BOOST_NOEXCEPT | |
1680 { | |
1681 typedef mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value> t1; | |
1682 typedef mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value> t2; | |
1683 return compare_imp(o, t1(), t2()); | |
1684 } | |
1685 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1686 int compare_unsigned(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o)const BOOST_NOEXCEPT | |
1687 { | |
1688 if(this->size() != o.size()) | |
1689 { | |
1690 return this->size() > o.size() ? 1 : -1; | |
1691 } | |
1692 typename base_type::const_limb_pointer pa = this->limbs(); | |
1693 typename base_type::const_limb_pointer pb = o.limbs(); | |
1694 for(int i = this->size() - 1; i >= 0; --i) | |
1695 { | |
1696 if(pa[i] != pb[i]) | |
1697 return pa[i] > pb[i] ? 1 : -1; | |
1698 } | |
1699 return 0; | |
1700 } | |
1701 template <class Arithmetic> | |
1702 BOOST_MP_FORCEINLINE typename boost::enable_if<is_arithmetic<Arithmetic>, int>::type compare(Arithmetic i)const | |
1703 { | |
1704 // braindead version: | |
1705 cpp_int_backend t; | |
1706 t = i; | |
1707 return compare(t); | |
1708 } | |
1709 }; | |
1710 | |
1711 } // namespace backends | |
1712 | |
1713 namespace default_ops{ | |
1714 | |
1715 template <class Backend> | |
1716 struct double_precision_type; | |
1717 | |
1718 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator> | |
1719 struct double_precision_type<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > | |
1720 { | |
1721 typedef typename mpl::if_c< | |
1722 backends::is_fixed_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, | |
1723 backends::cpp_int_backend< | |
1724 (is_void<Allocator>::value ? | |
1725 2 * backends::max_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value | |
1726 : MinBits), | |
1727 2 * backends::max_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, | |
1728 SignType, | |
1729 Checked, | |
1730 Allocator>, | |
1731 backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> | |
1732 >::type type; | |
1733 }; | |
1734 | |
1735 | |
1736 } | |
1737 | |
1738 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked> | |
1739 struct expression_template_default<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, void> > | |
1740 { | |
1741 static const expression_template_option value = et_off; | |
1742 }; | |
1743 | |
1744 using boost::multiprecision::backends::cpp_int_backend; | |
1745 | |
1746 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator> | |
1747 struct number_category<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > : public mpl::int_<number_kind_integer>{}; | |
1748 | |
1749 typedef number<cpp_int_backend<> > cpp_int; | |
1750 typedef rational_adaptor<cpp_int_backend<> > cpp_rational_backend; | |
1751 typedef number<cpp_rational_backend> cpp_rational; | |
1752 | |
1753 // Fixed precision unsigned types: | |
1754 typedef number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> > uint128_t; | |
1755 typedef number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> > uint256_t; | |
1756 typedef number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> > uint512_t; | |
1757 typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> > uint1024_t; | |
1758 | |
1759 // Fixed precision signed types: | |
1760 typedef number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> > int128_t; | |
1761 typedef number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> > int256_t; | |
1762 typedef number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> > int512_t; | |
1763 typedef number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> > int1024_t; | |
1764 | |
1765 // Over again, but with checking enabled this time: | |
1766 typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_int; | |
1767 typedef rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_rational_backend; | |
1768 typedef number<cpp_rational_backend> checked_cpp_rational; | |
1769 // Fixed precision unsigned types: | |
1770 typedef number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> > checked_uint128_t; | |
1771 typedef number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> > checked_uint256_t; | |
1772 typedef number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> > checked_uint512_t; | |
1773 typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> > checked_uint1024_t; | |
1774 | |
1775 // Fixed precision signed types: | |
1776 typedef number<cpp_int_backend<128, 128, signed_magnitude, checked, void> > checked_int128_t; | |
1777 typedef number<cpp_int_backend<256, 256, signed_magnitude, checked, void> > checked_int256_t; | |
1778 typedef number<cpp_int_backend<512, 512, signed_magnitude, checked, void> > checked_int512_t; | |
1779 typedef number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> > checked_int1024_t; | |
1780 | |
1781 #ifdef BOOST_NO_SFINAE_EXPR | |
1782 | |
1783 namespace detail{ | |
1784 | |
1785 template<unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | |
1786 struct is_explicitly_convertible<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > : public mpl::true_ {}; | |
1787 | |
1788 } | |
1789 #endif | |
1790 | |
1791 }} // namespaces | |
1792 | |
1793 // | |
1794 // Last of all we include the implementations of all the eval_* non member functions: | |
1795 // | |
1796 #include <boost/multiprecision/cpp_int/comparison.hpp> | |
1797 #include <boost/multiprecision/cpp_int/add.hpp> | |
1798 #include <boost/multiprecision/cpp_int/multiply.hpp> | |
1799 #include <boost/multiprecision/cpp_int/divide.hpp> | |
1800 #include <boost/multiprecision/cpp_int/bitwise.hpp> | |
1801 #include <boost/multiprecision/cpp_int/misc.hpp> | |
1802 #include <boost/multiprecision/cpp_int/limits.hpp> | |
1803 #ifdef BOOST_MP_USER_DEFINED_LITERALS | |
1804 #include <boost/multiprecision/cpp_int/literals.hpp> | |
1805 #endif | |
1806 #include <boost/multiprecision/cpp_int/serialize.hpp> | |
1807 | |
1808 #endif |