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/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 6285)
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 
verify_new_size(unsigned new_size,unsigned min_size,const mpl::int_<checked> &)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 }
verify_new_size(unsigned,unsigned,const mpl::int_<unchecked> &)140 inline void verify_new_size(unsigned /*new_size*/, unsigned /*min_size*/, const mpl::int_<unchecked>&){}
141 
142 template <class U>
verify_limb_mask(bool b,U limb,U mask,const mpl::int_<checked> &)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>
verify_limb_mask(bool,U,U,const mpl::int_<unchecked> &)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 
data_type()196       BOOST_CONSTEXPR data_type() : first(0) {}
data_type(limb_type i)197       BOOST_CONSTEXPR data_type(limb_type i) : first(i) {}
data_type(signed_limb_type i)198       BOOST_CONSTEXPR data_type(signed_limb_type i) : first(i < 0 ? static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i) {}
199 #ifdef BOOST_LITTLE_ENDIAN
data_type(double_limb_type i)200       BOOST_CONSTEXPR data_type(double_limb_type i) : double_first(i) {}
data_type(signed_double_limb_type i)201       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) {}
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    //
cpp_int_baseboost::multiprecision::backends::cpp_int_base213    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) { }
cpp_int_baseboost::multiprecision::backends::cpp_int_base215    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)
cpp_int_baseboost::multiprecision::backends::cpp_int_base218    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) { }
cpp_int_baseboost::multiprecision::backends::cpp_int_base220    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>(boost::multiprecision::detail::unsigned_abs(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    //
allocatorboost::multiprecision::backends::cpp_int_base227    BOOST_MP_FORCEINLINE allocator_type& allocator() BOOST_NOEXCEPT { return *this; }
allocatorboost::multiprecision::backends::cpp_int_base228    BOOST_MP_FORCEINLINE const allocator_type& allocator()const BOOST_NOEXCEPT { return *this; }
sizeboost::multiprecision::backends::cpp_int_base229    BOOST_MP_FORCEINLINE unsigned size()const  BOOST_NOEXCEPT { return m_limbs; }
limbsboost::multiprecision::backends::cpp_int_base230    BOOST_MP_FORCEINLINE limb_pointer limbs()  BOOST_NOEXCEPT { return m_internal ? m_data.la : m_data.ld.data; }
limbsboost::multiprecision::backends::cpp_int_base231    BOOST_MP_FORCEINLINE const_limb_pointer limbs()const  BOOST_NOEXCEPT { return m_internal ? m_data.la : m_data.ld.data; }
capacityboost::multiprecision::backends::cpp_int_base232    BOOST_MP_FORCEINLINE unsigned capacity()const  BOOST_NOEXCEPT { return m_internal ? internal_limb_count : m_data.ld.capacity; }
signboost::multiprecision::backends::cpp_int_base233    BOOST_MP_FORCEINLINE bool sign()const  BOOST_NOEXCEPT { return m_sign; }
signboost::multiprecision::backends::cpp_int_base234    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    }
resizeboost::multiprecision::backends::cpp_int_base244    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          std::memcpy(pl, limbs(), size() * sizeof(limbs()[0]));
259          if(!m_internal)
260             allocator().deallocate(limbs(), capacity());
261          else
262             m_internal = false;
263          m_limbs = new_size;
264          m_data.ld.capacity = cap;
265          m_data.ld.data = pl;
266       }
267       else
268       {
269          m_limbs = new_size;
270       }
271    }
normalizeboost::multiprecision::backends::cpp_int_base272    BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT
273    {
274       limb_pointer p = limbs();
275       while((m_limbs-1) && !p[m_limbs - 1])--m_limbs;
276    }
cpp_int_baseboost::multiprecision::backends::cpp_int_base277    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_data(), m_limbs(1), m_sign(false), m_internal(true) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base278    BOOST_MP_FORCEINLINE cpp_int_base(const cpp_int_base& o) : allocator_type(o), m_limbs(0), m_internal(true)
279    {
280       resize(o.size(), o.size());
281       std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
282       m_sign = o.m_sign;
283    }
284 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
cpp_int_baseboost::multiprecision::backends::cpp_int_base285    cpp_int_base(cpp_int_base&& o)
286       : allocator_type(static_cast<allocator_type&&>(o)), m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal)
287    {
288       if(m_internal)
289       {
290          std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
291       }
292       else
293       {
294          m_data.ld = o.m_data.ld;
295          o.m_limbs = 0;
296          o.m_internal = true;
297       }
298    }
operator =boost::multiprecision::backends::cpp_int_base299    cpp_int_base& operator = (cpp_int_base&& o) BOOST_NOEXCEPT
300    {
301       if(!m_internal)
302          allocator().deallocate(m_data.ld.data, m_data.ld.capacity);
303       *static_cast<allocator_type*>(this) = static_cast<allocator_type&&>(o);
304       m_limbs = o.m_limbs;
305       m_sign = o.m_sign;
306       m_internal = o.m_internal;
307       if(m_internal)
308       {
309          std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
310       }
311       else
312       {
313          m_data.ld = o.m_data.ld;
314          o.m_limbs = 0;
315          o.m_internal = true;
316       }
317       return *this;
318    }
319 #endif
~cpp_int_baseboost::multiprecision::backends::cpp_int_base320    BOOST_MP_FORCEINLINE ~cpp_int_base() BOOST_NOEXCEPT
321    {
322       if(!m_internal)
323          allocator().deallocate(limbs(), capacity());
324    }
assignboost::multiprecision::backends::cpp_int_base325    void assign(const cpp_int_base& o)
326    {
327       if(this != &o)
328       {
329          static_cast<allocator_type&>(*this) = static_cast<const allocator_type&>(o);
330          m_limbs = 0;
331          resize(o.size(), o.size());
332          std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
333          m_sign = o.m_sign;
334       }
335    }
negateboost::multiprecision::backends::cpp_int_base336    BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT
337    {
338       m_sign = !m_sign;
339       // Check for zero value:
340       if(m_sign && (m_limbs == 1))
341       {
342          if(limbs()[0] == 0)
343             m_sign = false;
344       }
345    }
isnegboost::multiprecision::backends::cpp_int_base346    BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT
347    {
348       return m_sign;
349    }
do_swapboost::multiprecision::backends::cpp_int_base350    BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
351    {
352       std::swap(m_data, o.m_data);
353       std::swap(m_sign, o.m_sign);
354       std::swap(m_internal, o.m_internal);
355       std::swap(m_limbs, o.m_limbs);
356    }
357 protected:
358    template <class A>
check_in_rangeboost::multiprecision::backends::cpp_int_base359    void check_in_range(const A&) BOOST_NOEXCEPT {}
360 };
361 
362 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
363 
364 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
365 const unsigned cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::limb_bits;
366 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
367 const limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::max_limb_value;
368 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
369 const limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::sign_bit_mask;
370 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
371 const unsigned cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::internal_limb_count;
372 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
373 const bool cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::variable;
374 
375 #endif
376 
377 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
378 struct cpp_int_base<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator, false> : private Allocator::template rebind<limb_type>::other
379 {
380    //
381    // There is currently no support for unsigned arbitrary precision arithmetic, largely
382    // because it's not clear what subtraction should do:
383    //
384    BOOST_STATIC_ASSERT_MSG(((sizeof(Allocator) == 0) && !is_void<Allocator>::value), "There is curently no support for unsigned arbitrary precision integers.");
385 };
386 //
387 // Fixed precision (i.e. no allocator), signed-magnitude type with limb-usage count:
388 //
389 template <unsigned MinBits, cpp_int_check_type Checked>
390 struct cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>
391 {
392    typedef limb_type*                      limb_pointer;
393    typedef const limb_type*                const_limb_pointer;
394    typedef mpl::int_<Checked>              checked_type;
395 
396    //
397    // Interface invariants:
398    //
399    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?");
400 
401 public:
402    BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
403    BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
404    BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1));
405    BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0));
406    BOOST_STATIC_CONSTANT(bool, variable = false);
407    BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = (MinBits % limb_bits) ? (limb_type(1) << (MinBits % limb_bits)) -1 : (~limb_type(0)));
408    BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs");
409 
410 private:
411    union data_type{
412       limb_type          m_data[internal_limb_count];
413       limb_type          m_first_limb;
414       double_limb_type   m_double_first_limb;
415 
data_type()416       BOOST_CONSTEXPR data_type() : m_first_limb(0) {}
data_type(limb_type i)417       BOOST_CONSTEXPR data_type(limb_type i) : m_first_limb(i) {}
data_type(double_limb_type i)418       BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i) {}
419 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
420       template <limb_type...VALUES>
data_type(literals::detail::value_pack<VALUES...>)421       BOOST_CONSTEXPR data_type(literals::detail::value_pack<VALUES...>) : m_data{ VALUES... } {}
422 #endif
423    } m_wrapper;
424    boost::uint16_t    m_limbs;
425    bool               m_sign;
426 
427 public:
428    //
429    // Direct construction:
430    //
cpp_int_baseboost::multiprecision::backends::cpp_int_base431    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT
432       : m_wrapper(i), m_limbs(1), m_sign(false) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base433    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT
434       : 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) {}
435 #if defined(BOOST_LITTLE_ENDIAN)
cpp_int_baseboost::multiprecision::backends::cpp_int_base436    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT
437       : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base438    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT
439       : m_wrapper(double_limb_type(i < 0 ? static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i)),
440         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)),
441         m_sign(i < 0) {}
442 #endif
443 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
444       template <limb_type...VALUES>
cpp_int_baseboost::multiprecision::backends::cpp_int_base445       BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<VALUES...> i)
446          : m_wrapper(i), m_limbs(sizeof...(VALUES)), m_sign(false) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base447       BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<> i)
448          : m_wrapper(i), m_limbs(1), m_sign(false) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base449       BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& a, const literals::detail::negate_tag&)
450          : m_wrapper(a.m_wrapper), m_limbs(a.m_limbs), m_sign((a.m_limbs == 1) && (*a.limbs() == 0) ? false : !a.m_sign) {}
451 #endif
452    //
453    // Helper functions for getting at our internal data, and manipulating storage:
454    //
sizeboost::multiprecision::backends::cpp_int_base455    BOOST_MP_FORCEINLINE unsigned size()const BOOST_NOEXCEPT { return m_limbs; }
limbsboost::multiprecision::backends::cpp_int_base456    BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return m_wrapper.m_data; }
limbsboost::multiprecision::backends::cpp_int_base457    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return m_wrapper.m_data; }
signboost::multiprecision::backends::cpp_int_base458    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign()const BOOST_NOEXCEPT { return m_sign; }
signboost::multiprecision::backends::cpp_int_base459    BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT
460    {
461       m_sign = b;
462       // Check for zero value:
463       if(m_sign && (m_limbs == 1))
464       {
465          if(limbs()[0] == 0)
466             m_sign = false;
467       }
468    }
resizeboost::multiprecision::backends::cpp_int_base469    BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
470    {
471       m_limbs = static_cast<boost::uint16_t>((std::min)(new_size, internal_limb_count));
472       detail::verify_new_size(m_limbs, min_size, checked_type());
473    }
normalizeboost::multiprecision::backends::cpp_int_base474    BOOST_MP_FORCEINLINE void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
475    {
476       limb_pointer p = limbs();
477       detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count-1], upper_limb_mask, checked_type());
478       p[internal_limb_count-1] &= upper_limb_mask;
479       while((m_limbs-1) && !p[m_limbs - 1])--m_limbs;
480       if((m_limbs == 1) && (!*p)) m_sign = false; // zero is always unsigned
481    }
482 
cpp_int_baseboost::multiprecision::backends::cpp_int_base483    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base()BOOST_NOEXCEPT : m_wrapper(limb_type(0u)), m_limbs(1), m_sign(false) {}
484    // Not defaulted, it breaks constexpr support in the Intel compiler for some reason:
cpp_int_baseboost::multiprecision::backends::cpp_int_base485    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o)BOOST_NOEXCEPT
486       : m_wrapper(o.m_wrapper), m_limbs(o.m_limbs), m_sign(o.m_sign) {}
487    // Defaulted functions:
488    //~cpp_int_base() BOOST_NOEXCEPT {}
489 
assignboost::multiprecision::backends::cpp_int_base490    void assign(const cpp_int_base& o) BOOST_NOEXCEPT
491    {
492       if(this != &o)
493       {
494          m_limbs = o.m_limbs;
495          std::memcpy(limbs(), o.limbs(), o.size() * sizeof(o.limbs()[0]));
496          m_sign = o.m_sign;
497       }
498    }
negateboost::multiprecision::backends::cpp_int_base499    BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT
500    {
501       m_sign = !m_sign;
502       // Check for zero value:
503       if(m_sign && (m_limbs == 1))
504       {
505          if(limbs()[0] == 0)
506             m_sign = false;
507       }
508    }
isnegboost::multiprecision::backends::cpp_int_base509    BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT
510    {
511       return m_sign;
512    }
do_swapboost::multiprecision::backends::cpp_int_base513    BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
514    {
515       for(unsigned i = 0; i < (std::max)(size(), o.size()); ++i)
516          std::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]);
517       std::swap(m_sign, o.m_sign);
518       std::swap(m_limbs, o.m_limbs);
519    }
520 protected:
521    template <class A>
check_in_rangeboost::multiprecision::backends::cpp_int_base522    void check_in_range(const A&) BOOST_NOEXCEPT {}
523 };
524 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
525 
526 template <unsigned MinBits, cpp_int_check_type Checked>
527 const unsigned cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::limb_bits;
528 template <unsigned MinBits, cpp_int_check_type Checked>
529 const limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::max_limb_value;
530 template <unsigned MinBits, cpp_int_check_type Checked>
531 const limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::sign_bit_mask;
532 template <unsigned MinBits, cpp_int_check_type Checked>
533 const unsigned cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::internal_limb_count;
534 template <unsigned MinBits, cpp_int_check_type Checked>
535 const bool cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::variable;
536 
537 #endif
538 //
539 // Fixed precision (i.e. no allocator), unsigned type with limb-usage count:
540 //
541 template <unsigned MinBits, cpp_int_check_type Checked>
542 struct cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>
543 {
544    typedef limb_type*                      limb_pointer;
545    typedef const limb_type*                const_limb_pointer;
546    typedef mpl::int_<Checked>              checked_type;
547 
548    //
549    // Interface invariants:
550    //
551    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?");
552 
553 public:
554    BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
555    BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
556    BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1));
557    BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0));
558    BOOST_STATIC_CONSTANT(bool, variable = false);
559    BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = (MinBits % limb_bits) ? (limb_type(1) << (MinBits % limb_bits)) -1 : (~limb_type(0)));
560    BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs");
561 
562 private:
563    union data_type{
564       limb_type          m_data[internal_limb_count];
565       limb_type          m_first_limb;
566       double_limb_type   m_double_first_limb;
567 
data_type()568       BOOST_CONSTEXPR data_type() : m_first_limb(0) {}
data_type(limb_type i)569       BOOST_CONSTEXPR data_type(limb_type i) : m_first_limb(i) {}
data_type(double_limb_type i)570       BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i) {}
571 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
572       template <limb_type...VALUES>
data_type(literals::detail::value_pack<VALUES...>)573       BOOST_CONSTEXPR data_type(literals::detail::value_pack<VALUES...>) : m_data{ VALUES... } {}
574 #endif
575    } m_wrapper;
576    limb_type          m_limbs;
577 
578 public:
579    //
580    // Direct construction:
581    //
cpp_int_baseboost::multiprecision::backends::cpp_int_base582    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT
583       : m_wrapper(i), m_limbs(1) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base584    BOOST_MP_FORCEINLINE cpp_int_base(signed_limb_type i)BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
585       : 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(); }
586 #ifdef BOOST_LITTLE_ENDIAN
cpp_int_baseboost::multiprecision::backends::cpp_int_base587    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT
588       : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base589    BOOST_MP_FORCEINLINE cpp_int_base(signed_double_limb_type i)BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
590       : m_wrapper(double_limb_type(i < 0 ? static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i)),
591       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))
592    {
593       if (i < 0) negate();
594    }
595 #endif
596 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
597       template <limb_type...VALUES>
cpp_int_baseboost::multiprecision::backends::cpp_int_base598       BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<VALUES...> i)
599          : m_wrapper(i), m_limbs(sizeof...(VALUES)) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base600       BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>)
601          : m_wrapper(static_cast<limb_type>(0u)), m_limbs(1) {}
602 #endif
603    //
604    // Helper functions for getting at our internal data, and manipulating storage:
605    //
sizeboost::multiprecision::backends::cpp_int_base606    BOOST_MP_FORCEINLINE unsigned size()const BOOST_NOEXCEPT { return m_limbs; }
limbsboost::multiprecision::backends::cpp_int_base607    BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return m_wrapper.m_data; }
limbsboost::multiprecision::backends::cpp_int_base608    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return m_wrapper.m_data; }
signboost::multiprecision::backends::cpp_int_base609    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign()const BOOST_NOEXCEPT { return false; }
signboost::multiprecision::backends::cpp_int_base610    BOOST_MP_FORCEINLINE void sign(bool b) BOOST_MP_NOEXCEPT_IF((Checked == unchecked)) {  if(b) negate(); }
resizeboost::multiprecision::backends::cpp_int_base611    BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
612    {
613       m_limbs = (std::min)(new_size, internal_limb_count);
614       detail::verify_new_size(m_limbs, min_size, checked_type());
615    }
normalizeboost::multiprecision::backends::cpp_int_base616    BOOST_MP_FORCEINLINE void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
617    {
618       limb_pointer p = limbs();
619       detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count-1], upper_limb_mask, checked_type());
620       p[internal_limb_count-1] &= upper_limb_mask;
621       while((m_limbs-1) && !p[m_limbs - 1])--m_limbs;
622    }
623 
cpp_int_baseboost::multiprecision::backends::cpp_int_base624    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT
625       : m_wrapper(limb_type(0u)), m_limbs(1) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base626    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
627       : m_wrapper(o.m_wrapper), m_limbs(o.m_limbs) {}
628    // Defaulted functions:
629    //~cpp_int_base() BOOST_NOEXCEPT {}
630 
assignboost::multiprecision::backends::cpp_int_base631    BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT
632    {
633       if(this != &o)
634       {
635          m_limbs = o.m_limbs;
636          std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
637       }
638    }
639 private:
check_negateboost::multiprecision::backends::cpp_int_base640    void check_negate(const mpl::int_<checked>&)
641    {
642       BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned number."));
643    }
check_negateboost::multiprecision::backends::cpp_int_base644    void check_negate(const mpl::int_<unchecked>&){}
645 public:
negateboost::multiprecision::backends::cpp_int_base646    void negate() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
647    {
648       // Not so much a negate as a complement - this gets called when subtraction
649       // would result in a "negative" number:
650       unsigned i;
651       if((m_limbs == 1) && (m_wrapper.m_data[0] == 0))
652          return; // negating zero is always zero, and always OK.
653       check_negate(checked_type());
654       for(i = m_limbs; i < internal_limb_count; ++i)
655          m_wrapper.m_data[i] = 0;
656       m_limbs = internal_limb_count;
657       for(i = 0; i < internal_limb_count; ++i)
658          m_wrapper.m_data[i] = ~m_wrapper.m_data[i];
659       normalize();
660       eval_increment(static_cast<cpp_int_backend<MinBits, MinBits, unsigned_magnitude, Checked, void>& >(*this));
661    }
isnegboost::multiprecision::backends::cpp_int_base662    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool isneg()const BOOST_NOEXCEPT
663    {
664       return false;
665    }
do_swapboost::multiprecision::backends::cpp_int_base666    BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
667    {
668       for(unsigned i = 0; i < (std::max)(size(), o.size()); ++i)
669          std::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]);
670       std::swap(m_limbs, o.m_limbs);
671    }
672 protected:
673    template <class A>
check_in_rangeboost::multiprecision::backends::cpp_int_base674    void check_in_range(const A&) BOOST_NOEXCEPT {}
675 };
676 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
677 
678 template <unsigned MinBits, cpp_int_check_type Checked>
679 const unsigned cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::limb_bits;
680 template <unsigned MinBits, cpp_int_check_type Checked>
681 const limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::max_limb_value;
682 template <unsigned MinBits, cpp_int_check_type Checked>
683 const limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::sign_bit_mask;
684 template <unsigned MinBits, cpp_int_check_type Checked>
685 const unsigned cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::internal_limb_count;
686 template <unsigned MinBits, cpp_int_check_type Checked>
687 const bool cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::variable;
688 
689 #endif
690 //
691 // Traits classes to figure out a native type with N bits, these vary from boost::uint_t<N> only
692 // because some platforms have native integer types longer than boost::long_long_type, "really boost::long_long_type" anyone??
693 //
694 template <unsigned N, bool s>
695 struct trivial_limb_type_imp
696 {
697    typedef double_limb_type type;
698 };
699 
700 template <unsigned N>
701 struct trivial_limb_type_imp<N, true>
702 {
703    typedef typename boost::uint_t<N>::least type;
704 };
705 
706 template <unsigned N>
707 struct trivial_limb_type : public trivial_limb_type_imp<N, N <= sizeof(boost::long_long_type) * CHAR_BIT> {};
708 //
709 // Backend for fixed precision signed-magnitude type which will fit entirely inside a "double_limb_type":
710 //
711 template <unsigned MinBits, cpp_int_check_type Checked>
712 struct cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, true>
713 {
714    typedef typename trivial_limb_type<MinBits>::type  local_limb_type;
715    typedef local_limb_type*                           limb_pointer;
716    typedef const local_limb_type*                     const_limb_pointer;
717    typedef mpl::int_<Checked>                         checked_type;
718 protected:
719    BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT);
720    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)));
721 private:
722    local_limb_type    m_data;
723    bool               m_sign;
724 
725    //
726    // Interface invariants:
727    //
728    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?");
729 protected:
730    template <class T>
731    typename boost::disable_if_c<!boost::is_integral<T>::value || (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= (int)MinBits))>::type
check_in_rangeboost::multiprecision::backends::cpp_int_base732       check_in_range(T val, const mpl::int_<checked>&)
733    {
734       typedef typename common_type<typename make_unsigned<T>::type, local_limb_type>::type common_type;
735 
736       if(static_cast<common_type>(boost::multiprecision::detail::unsigned_abs(val)) > static_cast<common_type>(limb_mask))
737          BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
738    }
739    template <class T>
740    typename boost::disable_if_c<boost::is_integral<T>::value || (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= (int)MinBits))>::type
check_in_rangeboost::multiprecision::backends::cpp_int_base741       check_in_range(T val, const mpl::int_<checked>&)
742    {
743          using std::abs;
744          typedef typename common_type<T, local_limb_type>::type common_type;
745 
746          if (static_cast<common_type>(abs(val)) > static_cast<common_type>(limb_mask))
747             BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
748    }
749    template <class T, int C>
check_in_rangeboost::multiprecision::backends::cpp_int_base750    void check_in_range(T, const mpl::int_<C>&) BOOST_NOEXCEPT {}
751 
752    template <class T>
check_in_rangeboost::multiprecision::backends::cpp_int_base753    void check_in_range(T val) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<T>(), checked_type())))
754    {
755       check_in_range(val, checked_type());
756    }
757 
758 public:
759    //
760    // Direct construction:
761    //
762    template <class SI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base763    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>())))
764       : 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) {}
765    template <class SI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base766    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>())))
767       : 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)
768    { check_in_range(i); }
769    template <class UI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base770    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
771       : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) {}
772    template <class UI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base773    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>())))
774       : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) { check_in_range(i); }
775    template <class F>
cpp_int_baseboost::multiprecision::backends::cpp_int_base776    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
777       : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask), m_sign(i < 0) {}
778    template <class F>
cpp_int_baseboost::multiprecision::backends::cpp_int_base779    BOOST_MP_FORCEINLINE cpp_int_base(F i, typename boost::enable_if_c<is_floating_point<F>::value && (Checked == checked)>::type const* = 0)
780       : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask), m_sign(i < 0) { check_in_range(i); }
781 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
cpp_int_baseboost::multiprecision::backends::cpp_int_base782       BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>) BOOST_NOEXCEPT
783          : m_data(static_cast<local_limb_type>(0u)), m_sign(false) {}
784       template <limb_type a>
cpp_int_baseboost::multiprecision::backends::cpp_int_base785       BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a>)BOOST_NOEXCEPT
786          : m_data(static_cast<local_limb_type>(a)), m_sign(false) {}
787       template <limb_type a, limb_type b>
cpp_int_baseboost::multiprecision::backends::cpp_int_base788       BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a, b>)BOOST_NOEXCEPT
789          : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)), m_sign(false) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base790       BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& a, const literals::detail::negate_tag&)BOOST_NOEXCEPT
791          : m_data(a.m_data), m_sign(a.m_data ? !a.m_sign : false) {}
792 #endif
793    //
794    // Helper functions for getting at our internal data, and manipulating storage:
795    //
sizeboost::multiprecision::backends::cpp_int_base796    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned size()const BOOST_NOEXCEPT { return 1; }
limbsboost::multiprecision::backends::cpp_int_base797    BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return &m_data; }
limbsboost::multiprecision::backends::cpp_int_base798    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return &m_data; }
signboost::multiprecision::backends::cpp_int_base799    BOOST_MP_FORCEINLINE bool sign()const BOOST_NOEXCEPT { return m_sign; }
signboost::multiprecision::backends::cpp_int_base800    BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT
801    {
802       m_sign = b;
803       // Check for zero value:
804       if(m_sign && !m_data)
805       {
806          m_sign = false;
807       }
808    }
resizeboost::multiprecision::backends::cpp_int_base809    BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size)
810    {
811       detail::verify_new_size(2, min_size, checked_type());
812    }
normalizeboost::multiprecision::backends::cpp_int_base813    BOOST_MP_FORCEINLINE void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
814    {
815       if(!m_data)
816          m_sign = false; // zero is always unsigned
817       detail::verify_limb_mask(true, m_data, limb_mask, checked_type());
818       m_data &= limb_mask;
819    }
820 
cpp_int_baseboost::multiprecision::backends::cpp_int_base821    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_data(0), m_sign(false) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base822    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
823       : m_data(o.m_data), m_sign(o.m_sign) {}
824    //~cpp_int_base() BOOST_NOEXCEPT {}
assignboost::multiprecision::backends::cpp_int_base825    BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT
826    {
827       m_data = o.m_data;
828       m_sign = o.m_sign;
829    }
negateboost::multiprecision::backends::cpp_int_base830    BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT
831    {
832       m_sign = !m_sign;
833       // Check for zero value:
834       if(m_data == 0)
835       {
836          m_sign = false;
837       }
838    }
isnegboost::multiprecision::backends::cpp_int_base839    BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT
840    {
841       return m_sign;
842    }
do_swapboost::multiprecision::backends::cpp_int_base843    BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
844    {
845       std::swap(m_sign, o.m_sign);
846       std::swap(m_data, o.m_data);
847    }
848 };
849 //
850 // Backend for unsigned fixed precision (i.e. no allocator) type which will fit entirely inside a "double_limb_type":
851 //
852 template <unsigned MinBits, cpp_int_check_type Checked>
853 struct cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, true>
854 {
855    typedef typename trivial_limb_type<MinBits>::type  local_limb_type;
856    typedef local_limb_type*                           limb_pointer;
857    typedef const local_limb_type*                     const_limb_pointer;
858 private:
859    BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT);
860    BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = limb_bits != MinBits ?
861       static_cast<local_limb_type>(static_cast<local_limb_type>(~local_limb_type(0)) >> (limb_bits - MinBits))
862       : static_cast<local_limb_type>(~local_limb_type(0)));
863 
864    local_limb_type    m_data;
865 
866    typedef mpl::int_<Checked>                          checked_type;
867 
868    //
869    // Interface invariants:
870    //
871    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?");
872 protected:
873    template <class T>
874    typename boost::disable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= (int)MinBits)>::type
check_in_rangeboost::multiprecision::backends::cpp_int_base875       check_in_range(T val, const mpl::int_<checked>&, const boost::false_type&)
876    {
877       typedef typename common_type<T, local_limb_type>::type common_type;
878 
879       if(static_cast<common_type>(val) > limb_mask)
880          BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
881    }
882    template <class T>
check_in_rangeboost::multiprecision::backends::cpp_int_base883    void check_in_range(T val, const mpl::int_<checked>&, const boost::true_type&)
884    {
885       typedef typename common_type<T, local_limb_type>::type common_type;
886 
887       if(static_cast<common_type>(val) > limb_mask)
888          BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
889       if(val < 0)
890          BOOST_THROW_EXCEPTION(std::range_error("The argument to an unsigned cpp_int constructor was negative."));
891    }
892    template <class T, int C, bool B>
check_in_rangeboost::multiprecision::backends::cpp_int_base893    BOOST_MP_FORCEINLINE void check_in_range(T, const mpl::int_<C>&, const boost::integral_constant<bool, B>&) BOOST_NOEXCEPT {}
894 
895    template <class T>
check_in_rangeboost::multiprecision::backends::cpp_int_base896    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>())))
897    {
898       check_in_range(val, checked_type(), is_signed<T>());
899    }
900 
901 public:
902    //
903    // Direct construction:
904    //
905    template <class SI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base906    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
907       : m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i)) & limb_mask : static_cast<local_limb_type>(i) & limb_mask) {}
908    template <class SI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base909    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>())))
910       : m_data(i < 0 ? 1 + ~static_cast<local_limb_type>(-i) : static_cast<local_limb_type>(i)) { check_in_range(i); }
911    template <class UI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base912    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
913       : m_data(static_cast<local_limb_type>(i) & limb_mask) {}
914    template <class UI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base915    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>())))
916       : m_data(static_cast<local_limb_type>(i)) { check_in_range(i); }
917    template <class F>
cpp_int_baseboost::multiprecision::backends::cpp_int_base918    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))
919       : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask)
920    {
921       check_in_range(i);
922       if(i < 0)
923          negate();
924    }
925 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
cpp_int_baseboost::multiprecision::backends::cpp_int_base926       BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>) BOOST_NOEXCEPT
927          : m_data(static_cast<local_limb_type>(0u)) {}
928       template <limb_type a>
cpp_int_baseboost::multiprecision::backends::cpp_int_base929       BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a>) BOOST_NOEXCEPT
930          : m_data(static_cast<local_limb_type>(a)) {}
931       template <limb_type a, limb_type b>
cpp_int_baseboost::multiprecision::backends::cpp_int_base932       BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a, b>) BOOST_NOEXCEPT
933          : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)) {}
934 #endif
935    //
936    // Helper functions for getting at our internal data, and manipulating storage:
937    //
sizeboost::multiprecision::backends::cpp_int_base938    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned size()const BOOST_NOEXCEPT { return 1; }
limbsboost::multiprecision::backends::cpp_int_base939    BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return &m_data; }
limbsboost::multiprecision::backends::cpp_int_base940    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return &m_data; }
signboost::multiprecision::backends::cpp_int_base941    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign()const BOOST_NOEXCEPT { return false; }
signboost::multiprecision::backends::cpp_int_base942    BOOST_MP_FORCEINLINE void sign(bool b) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
943    {
944       if(b)
945          negate();
946    }
resizeboost::multiprecision::backends::cpp_int_base947    BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size)
948    {
949       detail::verify_new_size(2, min_size, checked_type());
950    }
normalizeboost::multiprecision::backends::cpp_int_base951    BOOST_MP_FORCEINLINE void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
952    {
953       detail::verify_limb_mask(true, m_data, limb_mask, checked_type());
954       m_data &= limb_mask;
955    }
956 
cpp_int_baseboost::multiprecision::backends::cpp_int_base957    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_data(0) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base958    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
959       : m_data(o.m_data) {}
960    //~cpp_int_base() BOOST_NOEXCEPT {}
assignboost::multiprecision::backends::cpp_int_base961    BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT
962    {
963       m_data = o.m_data;
964    }
negateboost::multiprecision::backends::cpp_int_base965    BOOST_MP_FORCEINLINE void negate() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
966    {
967       if(Checked == checked)
968       {
969          BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned type."));
970       }
971       m_data = ~m_data;
972       ++m_data;
973    }
isnegboost::multiprecision::backends::cpp_int_base974    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool isneg()const BOOST_NOEXCEPT
975    {
976       return false;
977    }
do_swapboost::multiprecision::backends::cpp_int_base978    BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
979    {
980       std::swap(m_data, o.m_data);
981    }
982 };
983 //
984 // Traits class, lets us know whether type T can be directly converted to the base type,
985 // used to enable/disable constructors etc:
986 //
987 template <class Arg, class Base>
988 struct is_allowed_cpp_int_base_conversion : public mpl::if_c<
989       is_same<Arg, limb_type>::value || is_same<Arg, signed_limb_type>::value
990 #ifdef BOOST_LITTLE_ENDIAN
991       || is_same<Arg, double_limb_type>::value || is_same<Arg, signed_double_limb_type>::value
992 #endif
993 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
994       || literals::detail::is_value_pack<Arg>::value
995 #endif
996       || (is_trivial_cpp_int<Base>::value && is_arithmetic<Arg>::value),
997       mpl::true_,
998       mpl::false_
999    >::type
1000 {};
1001 //
1002 // Now the actual backend, normalising parameters passed to the base class:
1003 //
1004 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
1005 struct cpp_int_backend
1006    : public cpp_int_base<
1007                min_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
1008                max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
1009                SignType,
1010                Checked,
1011                Allocator,
1012                is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value>
1013 {
1014    typedef cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>    self_type;
1015    typedef cpp_int_base<
1016                min_precision<self_type>::value,
1017                max_precision<self_type>::value,
1018                SignType,
1019                Checked,
1020                Allocator,
1021                is_trivial_cpp_int<self_type>::value>                 base_type;
1022    typedef mpl::bool_<is_trivial_cpp_int<self_type>::value>          trivial_tag;
1023 public:
1024    typedef typename mpl::if_<
1025       trivial_tag,
1026       mpl::list<
1027       signed char, short, int, long,
1028       boost::long_long_type, signed_double_limb_type>,
1029       mpl::list<signed_limb_type, signed_double_limb_type>
1030    >::type                                                           signed_types;
1031    typedef typename mpl::if_<
1032       trivial_tag,
1033       mpl::list<unsigned char, unsigned short, unsigned,
1034       unsigned long, boost::ulong_long_type, double_limb_type>,
1035       mpl::list<limb_type, double_limb_type>
1036    >::type                                                           unsigned_types;
1037    typedef typename mpl::if_<
1038       trivial_tag,
1039       mpl::list<float, double, long double>,
1040       mpl::list<long double>
1041    >::type                                                           float_types;
1042    typedef mpl::int_<Checked>                                        checked_type;
1043 
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1044    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend() BOOST_NOEXCEPT{}
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1045    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) {}
1046 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1047    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(cpp_int_backend&& o) BOOST_NOEXCEPT
1048       : base_type(static_cast<base_type&&>(o)) {}
1049 #endif
1050    //
1051    // Direct construction from arithmetic type:
1052    //
1053    template <class Arg>
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1054    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>())))
1055       : base_type(i) {}
1056 
1057 private:
1058    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
do_assignboost::multiprecision::backends::cpp_int_backend1059    void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::true_ const&, mpl::true_ const &)
1060    {
1061       // Assigning trivial type to trivial type:
1062       this->check_in_range(*other.limbs());
1063       *this->limbs() = static_cast<typename self_type::local_limb_type>(*other.limbs());
1064       this->sign(other.sign());
1065       this->normalize();
1066    }
1067    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
do_assignboost::multiprecision::backends::cpp_int_backend1068    void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::true_ const&, mpl::false_ const &)
1069    {
1070       // non-trivial to trivial narrowing conversion:
1071       double_limb_type v = *other.limbs();
1072       if(other.size() > 1)
1073       {
1074          v |= static_cast<double_limb_type>(other.limbs()[1]) << bits_per_limb;
1075          if((Checked == checked) && (other.size() > 2))
1076          {
1077             BOOST_THROW_EXCEPTION(std::range_error("Assignment of a cpp_int that is out of range for the target type."));
1078          }
1079       }
1080       *this = v;
1081       this->sign(other.sign());
1082       this->normalize();
1083    }
1084    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
do_assignboost::multiprecision::backends::cpp_int_backend1085    void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::false_ const&, mpl::true_ const &)
1086    {
1087       // trivial to non-trivial, treat the trivial argument as if it were an unsigned arithmetic type, then set the sign afterwards:
1088        *this = static_cast<
1089             typename boost::multiprecision::detail::canonical<
1090                typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::local_limb_type,
1091                cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>
1092             >::type
1093          >(*other.limbs());
1094        this->sign(other.sign());
1095    }
1096    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
do_assignboost::multiprecision::backends::cpp_int_backend1097    void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::false_ const&, mpl::false_ const &)
1098    {
1099       // regular non-trivial to non-trivial assign:
1100       this->resize(other.size(), other.size());
1101       std::memcpy(this->limbs(), other.limbs(), (std::min)(other.size(), this->size()) * sizeof(this->limbs()[0]));
1102       this->sign(other.sign());
1103       this->normalize();
1104    }
1105 public:
1106    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1107    cpp_int_backend(
1108       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other,
1109       typename boost::enable_if_c<is_implicit_cpp_int_conversion<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>, self_type>::value>::type* = 0)
1110       : base_type()
1111    {
1112       do_assign(
1113          other,
1114          mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
1115          mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
1116    }
1117    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1118    explicit cpp_int_backend(
1119       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other,
1120       typename boost::disable_if_c<is_implicit_cpp_int_conversion<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>, self_type>::value>::type* = 0)
1121       : base_type()
1122    {
1123       do_assign(
1124          other,
1125          mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
1126          mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
1127    }
1128    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
operator =boost::multiprecision::backends::cpp_int_backend1129    cpp_int_backend& operator=(
1130       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other)
1131    {
1132       do_assign(
1133          other,
1134          mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
1135          mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
1136       return *this;
1137    }
1138 #ifdef BOOST_MP_USER_DEFINED_LITERALS
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1139    BOOST_CONSTEXPR cpp_int_backend(const cpp_int_backend& a, const literals::detail::negate_tag& tag)
1140       : base_type(static_cast<const base_type&>(a), tag){}
1141 #endif
1142 
operator =boost::multiprecision::backends::cpp_int_backend1143    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&>())))
1144    {
1145       this->assign(o);
1146       return *this;
1147    }
1148 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =boost::multiprecision::backends::cpp_int_backend1149    BOOST_MP_FORCEINLINE cpp_int_backend& operator = (cpp_int_backend&& o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<base_type&>() = std::declval<base_type>()))
1150    {
1151       *static_cast<base_type*>(this) = static_cast<base_type&&>(o);
1152       return *this;
1153    }
1154 #endif
1155 private:
1156    template <class A>
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1157    typename boost::enable_if<is_unsigned<A> >::type do_assign_arithmetic(A val, const mpl::true_&)
1158          BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().check_in_range(std::declval<A>())))
1159    {
1160       this->check_in_range(val);
1161       *this->limbs() = static_cast<typename self_type::local_limb_type>(val);
1162       this->normalize();
1163    }
1164    template <class A>
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1165    typename boost::disable_if_c<is_unsigned<A>::value || !is_integral<A>::value >::type do_assign_arithmetic(A val, const mpl::true_&)
1166          BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().check_in_range(std::declval<A>())) && noexcept(std::declval<cpp_int_backend>().sign(true)))
1167    {
1168       this->check_in_range(val);
1169       *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);
1170       this->sign(val < 0);
1171       this->normalize();
1172    }
1173    template <class A>
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1174    typename boost::enable_if_c< !is_integral<A>::value>::type do_assign_arithmetic(A val, const mpl::true_&)
1175    {
1176       this->check_in_range(val);
1177       *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);
1178       this->sign(val < 0);
1179       this->normalize();
1180    }
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1181    BOOST_MP_FORCEINLINE void do_assign_arithmetic(limb_type i, const mpl::false_&) BOOST_NOEXCEPT
1182    {
1183       this->resize(1, 1);
1184       *this->limbs() = i;
1185       this->sign(false);
1186    }
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1187    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)))
1188    {
1189       this->resize(1, 1);
1190       *this->limbs() = static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(i));
1191       this->sign(i < 0);
1192    }
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1193    void do_assign_arithmetic(double_limb_type i, const mpl::false_&) BOOST_NOEXCEPT
1194    {
1195       BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type));
1196       BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2);
1197       typename base_type::limb_pointer p = this->limbs();
1198       *p = static_cast<limb_type>(i);
1199       p[1] = static_cast<limb_type>(i >> base_type::limb_bits);
1200       this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1);
1201       this->sign(false);
1202    }
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1203    void do_assign_arithmetic(signed_double_limb_type i, const mpl::false_&) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().sign(true)))
1204    {
1205       BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type));
1206       BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2);
1207       bool s = false;
1208       double_limb_type ui;
1209       if(i < 0)
1210          s = true;
1211       ui = static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i));
1212       typename base_type::limb_pointer p = this->limbs();
1213       *p = static_cast<limb_type>(ui);
1214       p[1] = static_cast<limb_type>(ui >> base_type::limb_bits);
1215       this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1);
1216       this->sign(s);
1217    }
1218 
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1219    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       {
1229          do_assign_arithmetic(-a, mpl::false_());
1230          this->sign(true);
1231          return;
1232       }
1233 
1234       if (a == 0) {
1235          *this = static_cast<limb_type>(0u);
1236       }
1237 
1238       if (a == 1) {
1239          *this = static_cast<limb_type>(1u);
1240       }
1241 
1242       BOOST_ASSERT(!(boost::math::isinf)(a));
1243       BOOST_ASSERT(!(boost::math::isnan)(a));
1244 
1245       int e;
1246       long double f, term;
1247       *this = static_cast<limb_type>(0u);
1248 
1249       f = frexp(a, &e);
1250 
1251       static const limb_type shift = std::numeric_limits<limb_type>::digits;
1252 
1253       while(f)
1254       {
1255          // extract int sized bits from f:
1256          f = ldexp(f, shift);
1257          term = floor(f);
1258          e -= shift;
1259          eval_left_shift(*this, shift);
1260          if(term > 0)
1261             eval_add(*this, static_cast<limb_type>(term));
1262          else
1263             eval_subtract(*this, static_cast<limb_type>(-term));
1264          f -= term;
1265       }
1266       if(e > 0)
1267          eval_left_shift(*this, e);
1268       else if(e < 0)
1269          eval_right_shift(*this, -e);
1270    }
1271 public:
1272    template <class Arithmetic>
operator =boost::multiprecision::backends::cpp_int_backend1273    BOOST_MP_FORCEINLINE cpp_int_backend& operator = (Arithmetic val) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().do_assign_arithmetic(std::declval<Arithmetic>(), trivial_tag())))
1274    {
1275       do_assign_arithmetic(val, trivial_tag());
1276       return *this;
1277    }
1278 private:
do_assign_stringboost::multiprecision::backends::cpp_int_backend1279    void do_assign_string(const char* s, const mpl::true_&)
1280    {
1281       std::size_t n = s ? std::strlen(s) : 0;
1282       *this = 0;
1283       unsigned radix = 10;
1284       bool isneg = false;
1285       if(n && (*s == '-'))
1286       {
1287          --n;
1288          ++s;
1289          isneg = true;
1290       }
1291       if(n && (*s == '0'))
1292       {
1293          if((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
1294          {
1295             radix = 16;
1296             s +=2;
1297             n -= 2;
1298          }
1299          else
1300          {
1301             radix = 8;
1302             n -= 1;
1303          }
1304       }
1305       if(n)
1306       {
1307          unsigned val;
1308          while(*s)
1309          {
1310             if(*s >= '0' && *s <= '9')
1311                val = *s - '0';
1312             else if(*s >= 'a' && *s <= 'f')
1313                val = 10 + *s - 'a';
1314             else if(*s >= 'A' && *s <= 'F')
1315                val = 10 + *s - 'A';
1316             else
1317                val = radix + 1;
1318             if(val >= radix)
1319             {
1320                BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string."));
1321             }
1322             *this->limbs() = detail::checked_multiply(*this->limbs(), static_cast<typename base_type::local_limb_type>(radix), checked_type());
1323             *this->limbs() = detail::checked_add(*this->limbs(), static_cast<typename base_type::local_limb_type>(val), checked_type());
1324             ++s;
1325          }
1326       }
1327       if(isneg)
1328          this->negate();
1329    }
do_assign_stringboost::multiprecision::backends::cpp_int_backend1330    void do_assign_string(const char* s, const mpl::false_&)
1331    {
1332       using default_ops::eval_multiply;
1333       using default_ops::eval_add;
1334       std::size_t n = s ? std::strlen(s) : 0;
1335       *this = static_cast<limb_type>(0u);
1336       unsigned radix = 10;
1337       bool isneg = false;
1338       if(n && (*s == '-'))
1339       {
1340          --n;
1341          ++s;
1342          isneg = true;
1343       }
1344       if(n && (*s == '0'))
1345       {
1346          if((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
1347          {
1348             radix = 16;
1349             s +=2;
1350             n -= 2;
1351          }
1352          else
1353          {
1354             radix = 8;
1355             n -= 1;
1356          }
1357       }
1358       if(n)
1359       {
1360          if(radix == 8 || radix == 16)
1361          {
1362             unsigned shift = radix == 8 ? 3 : 4;
1363             unsigned block_count = base_type::limb_bits / shift;
1364             unsigned block_shift = shift * block_count;
1365             limb_type val, block;
1366             while(*s)
1367             {
1368                block = 0;
1369                for(unsigned i = 0; (i < block_count); ++i)
1370                {
1371                   if(*s >= '0' && *s <= '9')
1372                      val = *s - '0';
1373                   else if(*s >= 'a' && *s <= 'f')
1374                      val = 10 + *s - 'a';
1375                   else if(*s >= 'A' && *s <= 'F')
1376                      val = 10 + *s - 'A';
1377                   else
1378                      val = base_type::max_limb_value;
1379                   if(val >= radix)
1380                   {
1381                      BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string."));
1382                   }
1383                   block <<= shift;
1384                   block |= val;
1385                   if(!*++s)
1386                   {
1387                      // final shift is different:
1388                      block_shift = (i + 1) * shift;
1389                      break;
1390                   }
1391                }
1392                eval_left_shift(*this, block_shift);
1393                this->limbs()[0] |= block;
1394             }
1395          }
1396          else
1397          {
1398             // Base 10, we extract blocks of size 10^9 at a time, that way
1399             // the number of multiplications is kept to a minimum:
1400             limb_type block_mult = max_block_10;
1401             while(*s)
1402             {
1403                limb_type block = 0;
1404                for(unsigned i = 0; i < digits_per_block_10; ++i)
1405                {
1406                   limb_type val;
1407                   if(*s >= '0' && *s <= '9')
1408                      val = *s - '0';
1409                   else
1410                      BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected character encountered in input."));
1411                   block *= 10;
1412                   block += val;
1413                   if(!*++s)
1414                   {
1415                      block_mult = block_multiplier(i);
1416                      break;
1417                   }
1418                }
1419                eval_multiply(*this, block_mult);
1420                eval_add(*this, block);
1421             }
1422          }
1423       }
1424       if(isneg)
1425          this->negate();
1426    }
1427 public:
operator =boost::multiprecision::backends::cpp_int_backend1428    cpp_int_backend& operator = (const char* s)
1429    {
1430       do_assign_string(s, trivial_tag());
1431       return *this;
1432    }
swapboost::multiprecision::backends::cpp_int_backend1433    BOOST_MP_FORCEINLINE void swap(cpp_int_backend& o) BOOST_NOEXCEPT
1434    {
1435       this->do_swap(o);
1436    }
1437 private:
do_get_trivial_stringboost::multiprecision::backends::cpp_int_backend1438    std::string do_get_trivial_string(std::ios_base::fmtflags f, const mpl::false_&)const
1439    {
1440       typedef typename mpl::if_c<sizeof(typename base_type::local_limb_type) == 1, unsigned, typename base_type::local_limb_type>::type io_type;
1441       if(this->sign() && (((f & std::ios_base::hex) == std::ios_base::hex) || ((f & std::ios_base::oct) == std::ios_base::oct)))
1442          BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported."));
1443       std::stringstream ss;
1444       ss.flags(f & ~std::ios_base::showpos);
1445       ss << static_cast<io_type>(*this->limbs());
1446       std::string result;
1447       if(this->sign())
1448          result += '-';
1449       else if(f & std::ios_base::showpos)
1450          result += '+';
1451       result += ss.str();
1452       return result;
1453    }
do_get_trivial_stringboost::multiprecision::backends::cpp_int_backend1454    std::string do_get_trivial_string(std::ios_base::fmtflags f, const mpl::true_&)const
1455    {
1456       // Even though we have only one limb, we can't do IO on it :-(
1457       int base = 10;
1458       if((f & std::ios_base::oct) == std::ios_base::oct)
1459          base = 8;
1460       else if((f & std::ios_base::hex) == std::ios_base::hex)
1461          base = 16;
1462       std::string result;
1463 
1464       unsigned Bits = sizeof(typename base_type::local_limb_type) * CHAR_BIT;
1465 
1466       if(base == 8 || base == 16)
1467       {
1468          if(this->sign())
1469             BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported."));
1470          limb_type shift = base == 8 ? 3 : 4;
1471          limb_type mask = static_cast<limb_type>((1u << shift) - 1);
1472          typename base_type::local_limb_type v = *this->limbs();
1473          result.assign(Bits / shift + (Bits % shift ? 1 : 0), '0');
1474          std::string::difference_type pos = result.size() - 1;
1475          for(unsigned i = 0; i < Bits / shift; ++i)
1476          {
1477             char c = '0' + static_cast<char>(v & mask);
1478             if(c > '9')
1479                c += 'A' - '9' - 1;
1480             result[pos--] = c;
1481             v >>= shift;
1482          }
1483          if(Bits % shift)
1484          {
1485             mask = static_cast<limb_type>((1u << (Bits % shift)) - 1);
1486             char c = '0' + static_cast<char>(v & mask);
1487             if(c > '9')
1488                c += 'A' - '9';
1489             result[pos] = c;
1490          }
1491          //
1492          // Get rid of leading zeros:
1493          //
1494          std::string::size_type n = result.find_first_not_of('0');
1495          if(!result.empty() && (n == std::string::npos))
1496             n = result.size() - 1;
1497          result.erase(0, n);
1498          if(f & std::ios_base::showbase)
1499          {
1500             const char* pp = base == 8 ? "0" : "0x";
1501             result.insert(static_cast<std::string::size_type>(0), pp);
1502          }
1503       }
1504       else
1505       {
1506          result.assign(Bits / 3 + 1, '0');
1507          std::string::difference_type pos = result.size() - 1;
1508          typename base_type::local_limb_type v(*this->limbs());
1509          bool neg = false;
1510          if(this->sign())
1511          {
1512             neg = true;
1513          }
1514          while(v)
1515          {
1516             result[pos] = (v % 10) + '0';
1517             --pos;
1518             v /= 10;
1519          }
1520          std::string::size_type n = result.find_first_not_of('0');
1521          result.erase(0, n);
1522          if(result.empty())
1523             result = "0";
1524          if(neg)
1525             result.insert(static_cast<std::string::size_type>(0), 1, '-');
1526          else if(f & std::ios_base::showpos)
1527             result.insert(static_cast<std::string::size_type>(0), 1, '+');
1528       }
1529       return result;
1530    }
do_get_stringboost::multiprecision::backends::cpp_int_backend1531    std::string do_get_string(std::ios_base::fmtflags f, const mpl::true_&)const
1532    {
1533 #ifdef BOOST_MP_NO_DOUBLE_LIMB_TYPE_IO
1534       return do_get_trivial_string(f, mpl::bool_<is_same<typename base_type::local_limb_type, double_limb_type>::value>());
1535 #else
1536       return do_get_trivial_string(f, mpl::bool_<false>());
1537 #endif
1538    }
do_get_stringboost::multiprecision::backends::cpp_int_backend1539    std::string do_get_string(std::ios_base::fmtflags f, const mpl::false_&)const
1540    {
1541       using default_ops::eval_get_sign;
1542       int base = 10;
1543       if((f & std::ios_base::oct) == std::ios_base::oct)
1544          base = 8;
1545       else if((f & std::ios_base::hex) == std::ios_base::hex)
1546          base = 16;
1547       std::string result;
1548 
1549       unsigned Bits = this->size() * base_type::limb_bits;
1550 
1551       if(base == 8 || base == 16)
1552       {
1553          if(this->sign())
1554             BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported."));
1555          limb_type shift = base == 8 ? 3 : 4;
1556          limb_type mask = static_cast<limb_type>((1u << shift) - 1);
1557          cpp_int_backend t(*this);
1558          result.assign(Bits / shift + ((Bits % shift) ? 1 : 0), '0');
1559          std::string::difference_type pos = result.size() - 1;
1560          for(unsigned i = 0; i < Bits / shift; ++i)
1561          {
1562             char c = '0' + static_cast<char>(t.limbs()[0] & mask);
1563             if(c > '9')
1564                c += 'A' - '9' - 1;
1565             result[pos--] = c;
1566             eval_right_shift(t, shift);
1567          }
1568          if(Bits % shift)
1569          {
1570             mask = static_cast<limb_type>((1u << (Bits % shift)) - 1);
1571             char c = '0' + static_cast<char>(t.limbs()[0] & mask);
1572             if(c > '9')
1573                c += 'A' - '9';
1574             result[pos] = c;
1575          }
1576          //
1577          // Get rid of leading zeros:
1578          //
1579          std::string::size_type n = result.find_first_not_of('0');
1580          if(!result.empty() && (n == std::string::npos))
1581             n = result.size() - 1;
1582          result.erase(0, n);
1583          if(f & std::ios_base::showbase)
1584          {
1585             const char* pp = base == 8 ? "0" : "0x";
1586             result.insert(static_cast<std::string::size_type>(0), pp);
1587          }
1588       }
1589       else
1590       {
1591          result.assign(Bits / 3 + 1, '0');
1592          std::string::difference_type pos = result.size() - 1;
1593          cpp_int_backend t(*this);
1594          cpp_int_backend r;
1595          bool neg = false;
1596          if(t.sign())
1597          {
1598             t.negate();
1599             neg = true;
1600          }
1601          if(this->size() == 1)
1602          {
1603             result = boost::lexical_cast<std::string>(t.limbs()[0]);
1604          }
1605          else
1606          {
1607             cpp_int_backend block10;
1608             block10 = max_block_10;
1609             while(eval_get_sign(t) != 0)
1610             {
1611                cpp_int_backend t2;
1612                divide_unsigned_helper(&t2, t, block10, r);
1613                t = t2;
1614                limb_type v = r.limbs()[0];
1615                for(unsigned i = 0; i < digits_per_block_10; ++i)
1616                {
1617                   char c = '0' + v % 10;
1618                   v /= 10;
1619                   result[pos] = c;
1620                   if(pos-- == 0)
1621                      break;
1622                }
1623             }
1624          }
1625          std::string::size_type n = result.find_first_not_of('0');
1626          result.erase(0, n);
1627          if(result.empty())
1628             result = "0";
1629          if(neg)
1630             result.insert(static_cast<std::string::size_type>(0), 1, '-');
1631          else if(f & std::ios_base::showpos)
1632             result.insert(static_cast<std::string::size_type>(0), 1, '+');
1633       }
1634       return result;
1635    }
1636 public:
strboost::multiprecision::backends::cpp_int_backend1637    std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f)const
1638    {
1639       return do_get_string(f, trivial_tag());
1640    }
1641    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compare_impboost::multiprecision::backends::cpp_int_backend1642    int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::false_&, const mpl::false_&)const BOOST_NOEXCEPT
1643    {
1644       if(this->sign() != o.sign())
1645          return this->sign() ? -1 : 1;
1646 
1647       // Only do the compare if the same sign:
1648       int result = compare_unsigned(o);
1649 
1650       if(this->sign())
1651          result = -result;
1652       return result;
1653    }
1654    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compare_impboost::multiprecision::backends::cpp_int_backend1655    int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::true_&, const mpl::false_&)const
1656    {
1657       cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> t(*this);
1658       return t.compare(o);
1659    }
1660    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compare_impboost::multiprecision::backends::cpp_int_backend1661    int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::false_&, const mpl::true_&)const
1662    {
1663       cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> t(o);
1664       return compare(t);
1665    }
1666    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compare_impboost::multiprecision::backends::cpp_int_backend1667    int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::true_&, const mpl::true_&)const BOOST_NOEXCEPT
1668    {
1669       if(this->sign())
1670       {
1671          if(o.sign())
1672          {
1673             return *this->limbs() < *o.limbs() ? 1 : (*this->limbs() > *o.limbs() ? -1 : 0);
1674          }
1675          else
1676             return -1;
1677       }
1678       else
1679       {
1680          if(o.sign())
1681             return 1;
1682          return *this->limbs() < *o.limbs() ? -1 : (*this->limbs() > *o.limbs() ? 1 : 0);
1683       }
1684    }
1685    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compareboost::multiprecision::backends::cpp_int_backend1686    int compare(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o)const BOOST_NOEXCEPT
1687    {
1688       typedef mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value> t1;
1689       typedef mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value> t2;
1690       return compare_imp(o, t1(), t2());
1691    }
1692    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compare_unsignedboost::multiprecision::backends::cpp_int_backend1693    int compare_unsigned(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o)const BOOST_NOEXCEPT
1694    {
1695       if(this->size() != o.size())
1696       {
1697          return this->size() > o.size() ? 1 : -1;
1698       }
1699       typename base_type::const_limb_pointer pa = this->limbs();
1700       typename base_type::const_limb_pointer pb = o.limbs();
1701       for(int i = this->size() - 1; i >= 0; --i)
1702       {
1703          if(pa[i] != pb[i])
1704             return pa[i] > pb[i] ? 1 : -1;
1705       }
1706       return 0;
1707    }
1708    template <class Arithmetic>
compareboost::multiprecision::backends::cpp_int_backend1709    BOOST_MP_FORCEINLINE typename boost::enable_if<is_arithmetic<Arithmetic>, int>::type compare(Arithmetic i)const
1710    {
1711       // braindead version:
1712       cpp_int_backend t;
1713       t = i;
1714       return compare(t);
1715    }
1716 };
1717 
1718 } // namespace backends
1719 
1720 namespace default_ops{
1721 
1722 template <class Backend>
1723 struct double_precision_type;
1724 
1725 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
1726 struct double_precision_type<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
1727 {
1728    typedef typename mpl::if_c<
1729       backends::is_fixed_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
1730       backends::cpp_int_backend<
1731          (is_void<Allocator>::value ?
1732             2 * backends::max_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value
1733             : MinBits),
1734          2 * backends::max_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
1735          SignType,
1736          Checked,
1737          Allocator>,
1738       backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>
1739    >::type type;
1740 };
1741 
1742 
1743 }
1744 
1745 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked>
1746 struct expression_template_default<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, void> >
1747 {
1748    static const expression_template_option value = et_off;
1749 };
1750 
1751 using boost::multiprecision::backends::cpp_int_backend;
1752 
1753 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
1754 struct number_category<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > : public mpl::int_<number_kind_integer>{};
1755 
1756 typedef number<cpp_int_backend<> >                   cpp_int;
1757 typedef rational_adaptor<cpp_int_backend<> >         cpp_rational_backend;
1758 typedef number<cpp_rational_backend>                 cpp_rational;
1759 
1760 // Fixed precision unsigned types:
1761 typedef number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> >   uint128_t;
1762 typedef number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> >   uint256_t;
1763 typedef number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> >   uint512_t;
1764 typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> > uint1024_t;
1765 
1766 // Fixed precision signed types:
1767 typedef number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> >    int128_t;
1768 typedef number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> >    int256_t;
1769 typedef number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> >    int512_t;
1770 typedef number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> >  int1024_t;
1771 
1772 // Over again, but with checking enabled this time:
1773 typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> >               checked_cpp_int;
1774 typedef rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> >     checked_cpp_rational_backend;
1775 typedef number<checked_cpp_rational_backend>                                    checked_cpp_rational;
1776 // Fixed precision unsigned types:
1777 typedef number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> >   checked_uint128_t;
1778 typedef number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> >   checked_uint256_t;
1779 typedef number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> >   checked_uint512_t;
1780 typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> > checked_uint1024_t;
1781 
1782 // Fixed precision signed types:
1783 typedef number<cpp_int_backend<128, 128, signed_magnitude, checked, void> >    checked_int128_t;
1784 typedef number<cpp_int_backend<256, 256, signed_magnitude, checked, void> >    checked_int256_t;
1785 typedef number<cpp_int_backend<512, 512, signed_magnitude, checked, void> >    checked_int512_t;
1786 typedef number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> >  checked_int1024_t;
1787 
1788 #ifdef BOOST_NO_SFINAE_EXPR
1789 
1790 namespace detail{
1791 
1792 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>
1793 struct is_explicitly_convertible<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > : public mpl::true_ {};
1794 
1795 }
1796 #endif
1797 
1798 }} // namespaces
1799 
1800 //
1801 // Last of all we include the implementations of all the eval_* non member functions:
1802 //
1803 #include <boost/multiprecision/cpp_int/comparison.hpp>
1804 #include <boost/multiprecision/cpp_int/add.hpp>
1805 #include <boost/multiprecision/cpp_int/multiply.hpp>
1806 #include <boost/multiprecision/cpp_int/divide.hpp>
1807 #include <boost/multiprecision/cpp_int/bitwise.hpp>
1808 #include <boost/multiprecision/cpp_int/misc.hpp>
1809 #include <boost/multiprecision/cpp_int/limits.hpp>
1810 #ifdef BOOST_MP_USER_DEFINED_LITERALS
1811 #include <boost/multiprecision/cpp_int/literals.hpp>
1812 #endif
1813 #include <boost/multiprecision/cpp_int/serialize.hpp>
1814 
1815 #endif
1816