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