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