• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 https://www.boost.org/LICENSE_1_0.txt
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/multiprecision/detail/rebind.hpp>
15 #include <boost/core/empty_value.hpp>
16 #include <boost/array.hpp>
17 #include <boost/type_traits/is_integral.hpp>
18 #include <boost/type_traits/is_floating_point.hpp>
19 #include <boost/multiprecision/cpp_int/cpp_int_config.hpp>
20 #include <boost/multiprecision/rational_adaptor.hpp>
21 #include <boost/multiprecision/traits/is_byte_container.hpp>
22 #include <boost/predef/other/endian.h>
23 #include <boost/integer/static_min_max.hpp>
24 #include <boost/type_traits/common_type.hpp>
25 #include <boost/type_traits/make_signed.hpp>
26 #include <boost/multiprecision/cpp_int/checked.hpp>
27 #include <boost/multiprecision/detail/constexpr.hpp>
28 #ifdef BOOST_MP_USER_DEFINED_LITERALS
29 #include <boost/multiprecision/cpp_int/value_pack.hpp>
30 #endif
31 
32 namespace boost {
33 namespace multiprecision {
34 namespace backends {
35 
36 using boost::enable_if;
37 
38 #ifdef BOOST_MSVC
39 #pragma warning(push)
40 #pragma warning(disable : 4307) // integral constant overflow (oveflow is in a branch not taken when it would overflow)
41 #pragma warning(disable : 4127) // conditional expression is constant
42 #pragma warning(disable : 4702) // Unreachable code (reachability depends on template params)
43 #endif
44 
45 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>
46 struct cpp_int_backend;
47 
48 } // namespace backends
49 
50 namespace detail {
51 
52 template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
53 struct is_byte_container<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > : public boost::false_type
54 {};
55 
56 } // namespace detail
57 
58 namespace backends {
59 
60 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, bool trivial = false>
61 struct cpp_int_base;
62 //
63 // Traits class determines the maximum and minimum precision values:
64 //
65 template <class T>
66 struct max_precision;
67 
68 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
69 struct max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
70 {
71    static const unsigned value = is_void<Allocator>::value ? static_unsigned_max<MinBits, MaxBits>::value
72                                                            : (((MaxBits >= MinBits) && MaxBits) ? MaxBits : UINT_MAX);
73 };
74 
75 template <class T>
76 struct min_precision;
77 
78 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
79 struct min_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
80 {
81    static const unsigned value = (is_void<Allocator>::value ? static_unsigned_max<MinBits, MaxBits>::value : MinBits);
82 };
83 //
84 // Traits class determines whether the number of bits precision requested could fit in a native type,
85 // we call this a "trivial" cpp_int:
86 //
87 template <class T>
88 struct is_trivial_cpp_int
89 {
90    static const bool value = false;
91 };
92 
93 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
94 struct is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
95 {
96    typedef cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> self;
97    static const bool                                                       value = is_void<Allocator>::value && (max_precision<self>::value <= (sizeof(double_limb_type) * CHAR_BIT) - (SignType == signed_packed ? 1 : 0));
98 };
99 
100 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
101 struct is_trivial_cpp_int<cpp_int_base<MinBits, MaxBits, SignType, Checked, Allocator, true> >
102 {
103    static const bool value = true;
104 };
105 
106 } // namespace backends
107 //
108 // Traits class to determine whether a cpp_int_backend is signed or not:
109 //
110 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
111 struct is_unsigned_number<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
112     : public mpl::bool_<(SignType == unsigned_magnitude) || (SignType == unsigned_packed)>
113 {};
114 
115 namespace backends {
116 //
117 // Traits class determines whether T should be implicitly convertible to U, or
118 // whether the constructor should be made explicit.  The latter happens if we
119 // are losing the sign, or have fewer digits precision in the target type:
120 //
121 template <class T, class U>
122 struct is_implicit_cpp_int_conversion;
123 
124 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>
125 struct is_implicit_cpp_int_conversion<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >
126 {
127    typedef cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>      t1;
128    typedef cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> t2;
129    static const bool                                                            value =
130        (is_signed_number<t2>::value || !is_signed_number<t1>::value) && (max_precision<t1>::value <= max_precision<t2>::value);
131 };
132 
133 //
134 // Traits class to determine whether operations on a cpp_int may throw:
135 //
136 template <class T>
137 struct is_non_throwing_cpp_int : public mpl::false_
138 {};
139 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType>
140 struct is_non_throwing_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, unchecked, void> > : public mpl::true_
141 {};
142 
143 //
144 // Traits class, determines whether the cpp_int is fixed precision or not:
145 //
146 template <class T>
147 struct is_fixed_precision;
148 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
149 struct is_fixed_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
150     : public mpl::bool_<max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value != UINT_MAX>
151 {};
152 
153 namespace detail {
154 
verify_new_size(unsigned new_size,unsigned min_size,const mpl::int_<checked> &)155 inline BOOST_MP_CXX14_CONSTEXPR void verify_new_size(unsigned new_size, unsigned min_size, const mpl::int_<checked>&)
156 {
157    if (new_size < min_size)
158       BOOST_THROW_EXCEPTION(std::overflow_error("Unable to allocate sufficient storage for the value of the result: value overflows the maximum allowable magnitude."));
159 }
verify_new_size(unsigned,unsigned,const mpl::int_<unchecked> &)160 inline BOOST_MP_CXX14_CONSTEXPR void verify_new_size(unsigned /*new_size*/, unsigned /*min_size*/, const mpl::int_<unchecked>&) {}
161 
162 template <class U>
verify_limb_mask(bool b,U limb,U mask,const mpl::int_<checked> &)163 inline BOOST_MP_CXX14_CONSTEXPR void verify_limb_mask(bool b, U limb, U mask, const mpl::int_<checked>&)
164 {
165    // When we mask out "limb" with "mask", do we loose bits?  If so it's an overflow error:
166    if (b && (limb & ~mask))
167       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."));
168 }
169 template <class U>
verify_limb_mask(bool,U,U,const mpl::int_<unchecked> &)170 inline BOOST_MP_CXX14_CONSTEXPR void verify_limb_mask(bool /*b*/, U /*limb*/, U /*mask*/, const mpl::int_<unchecked>&) {}
171 
172 } // namespace detail
173 
174 //
175 // Now define the various data layouts that are possible as partial specializations of the base class,
176 // starting with the default arbitrary precision signed integer type:
177 //
178 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
179 struct cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>
180     : private boost::empty_value<typename detail::rebind<limb_type, Allocator>::type>
181 {
182    typedef typename detail::rebind<limb_type, Allocator>::type allocator_type;
183 #ifdef BOOST_NO_CXX11_ALLOCATOR
184    typedef typename allocator_type::pointer       limb_pointer;
185    typedef typename allocator_type::const_pointer const_limb_pointer;
186 #else
187    typedef typename std::allocator_traits<allocator_type>::pointer       limb_pointer;
188    typedef typename std::allocator_traits<allocator_type>::const_pointer const_limb_pointer;
189 #endif
190    typedef mpl::int_<Checked> checked_type;
191 
192    //
193    // Interface invariants:
194    //
195    BOOST_STATIC_ASSERT(!is_void<Allocator>::value);
196 
197  private:
198    typedef boost::empty_value<allocator_type> base_type;
199 
200    struct limb_data
201    {
202       unsigned        capacity;
203       limb_pointer    data;
204    };
205 
206  public:
207    BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
208    BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
209    BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast<limb_type>(1u) << (limb_bits - 1));
210    BOOST_STATIC_CONSTANT(unsigned, internal_limb_count =
211                                        MinBits
212                                            ? (MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0))
213                                            : (sizeof(limb_data) / sizeof(limb_type)) > 1 ? (sizeof(limb_data) / sizeof(limb_type)) : 2);
214  private:
215    union data_type
216    {
217       limb_data        ld;
218       limb_type        la[internal_limb_count];
219       limb_type        first;
220       double_limb_type double_first;
221 
data_type()222       BOOST_CONSTEXPR data_type() BOOST_NOEXCEPT : first(0) {}
data_type(limb_type i)223       BOOST_CONSTEXPR data_type(limb_type i) BOOST_NOEXCEPT : first(i) {}
data_type(signed_limb_type i)224       BOOST_CONSTEXPR data_type(signed_limb_type i) BOOST_NOEXCEPT : first(i < 0 ? static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i) {}
225 #if BOOST_ENDIAN_LITTLE_BYTE
data_type(double_limb_type i)226       BOOST_CONSTEXPR data_type(double_limb_type i) BOOST_NOEXCEPT : double_first(i)
227       {}
data_type(signed_double_limb_type i)228       BOOST_CONSTEXPR data_type(signed_double_limb_type i) BOOST_NOEXCEPT : double_first(i < 0 ? static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i) {}
229 #endif
230 #if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !(defined(BOOST_MSVC) && (BOOST_MSVC < 1900))
data_type(limb_type * limbs,unsigned len)231       BOOST_CONSTEXPR data_type(limb_type* limbs, unsigned len) BOOST_NOEXCEPT : ld{ len, limbs }
232       {}
233 #else
data_type(limb_type * limbs,unsigned len)234       BOOST_CONSTEXPR data_type(limb_type* limbs, unsigned len) BOOST_NOEXCEPT
235       {
236          ld.capacity = len;
237          ld.data = limbs;
238       }
239 #endif
240    };
241 
242    data_type m_data;
243    unsigned  m_limbs;
244    bool      m_sign, m_internal, m_alias;
245 
246  public:
247    //
248    // Direct construction:
249    //
cpp_int_baseboost::multiprecision::backends::cpp_int_base250    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i) BOOST_NOEXCEPT
251        : m_data(i),
252          m_limbs(1),
253          m_sign(false),
254          m_internal(true),
255          m_alias(false) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base256    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_limb_type i) BOOST_NOEXCEPT
257        : m_data(i),
258          m_limbs(1),
259          m_sign(i < 0),
260          m_internal(true),
261          m_alias(false) {}
262 #if BOOST_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
cpp_int_baseboost::multiprecision::backends::cpp_int_base263    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i) BOOST_NOEXCEPT
264        : m_data(i),
265          m_limbs(i > max_limb_value ? 2 : 1),
266          m_sign(false),
267          m_internal(true),
268          m_alias(false)
269    {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base270    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i) BOOST_NOEXCEPT
271        : m_data(i),
272          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)),
273          m_sign(i < 0),
274          m_internal(true),
275          m_alias(false) {}
276 #endif
277    //
278    // Aliasing constructor aliases data:
279    //
280    struct scoped_shared_storage : private boost::empty_value<allocator_type>
281    {
282     private:
283       limb_type*      data;
284       unsigned        capacity;
285       unsigned        allocated;
286       bool            is_alias;
allocatorboost::multiprecision::backends::cpp_int_base::scoped_shared_storage287       allocator_type& allocator() BOOST_NOEXCEPT { return boost::empty_value<allocator_type>::get(); }
288 
289     public:
scoped_shared_storageboost::multiprecision::backends::cpp_int_base::scoped_shared_storage290       scoped_shared_storage(const allocator_type& a, unsigned len)
291           : boost::empty_value<allocator_type>(boost::empty_init_t(), a), capacity(len), allocated(0), is_alias(false)
292       {
293          data = allocator().allocate(len);
294       }
scoped_shared_storageboost::multiprecision::backends::cpp_int_base::scoped_shared_storage295       scoped_shared_storage(limb_type* limbs, unsigned n) : data(limbs), capacity(n), allocated(0), is_alias(true) {}
~scoped_shared_storageboost::multiprecision::backends::cpp_int_base::scoped_shared_storage296       ~scoped_shared_storage()
297       {
298          if(!is_alias)
299             allocator().deallocate(data, capacity);
300       }
allocateboost::multiprecision::backends::cpp_int_base::scoped_shared_storage301       limb_type* allocate(unsigned n) BOOST_NOEXCEPT
302       {
303          limb_type* result = data + allocated;
304          allocated += n;
305          BOOST_ASSERT(allocated <= capacity);
306          return result;
307       }
deallocateboost::multiprecision::backends::cpp_int_base::scoped_shared_storage308       void deallocate(unsigned n)
309       {
310          BOOST_ASSERT(n <= allocated);
311          allocated -= n;
312       }
313    };
cpp_int_baseboost::multiprecision::backends::cpp_int_base314    explicit BOOST_CONSTEXPR cpp_int_base(limb_type* data, unsigned offset, unsigned len) BOOST_NOEXCEPT
315        : m_data(data + offset, len),
316          m_limbs(len),
317          m_sign(false),
318          m_internal(false),
319          m_alias(true) {}
320    // This next constructor is for constructing const objects from const limb_type*'s only.
321    // Unfortunately we appear to have no way to assert that within the language, and the const_cast
322    // is a side effect of that :(
cpp_int_baseboost::multiprecision::backends::cpp_int_base323    explicit BOOST_CONSTEXPR cpp_int_base(const limb_type* data, unsigned offset, unsigned len) BOOST_NOEXCEPT
324        : m_data(const_cast<limb_type*>(data) + offset, len),
325          m_limbs(len),
326          m_sign(false),
327          m_internal(false),
328          m_alias(true) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base329    explicit BOOST_CONSTEXPR cpp_int_base(scoped_shared_storage& data, unsigned len) BOOST_NOEXCEPT
330        : m_data(data.allocate(len), len),
331          m_limbs(len),
332          m_sign(false),
333          m_internal(false),
334          m_alias(true) {}
335    //
336    // Helper functions for getting at our internal data, and manipulating storage:
337    //
allocatorboost::multiprecision::backends::cpp_int_base338    BOOST_MP_FORCEINLINE allocator_type&       allocator() BOOST_NOEXCEPT { return base_type::get(); }
allocatorboost::multiprecision::backends::cpp_int_base339    BOOST_MP_FORCEINLINE const allocator_type& allocator() const BOOST_NOEXCEPT { return base_type::get(); }
sizeboost::multiprecision::backends::cpp_int_base340    BOOST_MP_FORCEINLINE unsigned              size() const BOOST_NOEXCEPT { return m_limbs; }
limbsboost::multiprecision::backends::cpp_int_base341    BOOST_MP_FORCEINLINE limb_pointer          limbs() BOOST_NOEXCEPT { return m_internal ? m_data.la : m_data.ld.data; }
limbsboost::multiprecision::backends::cpp_int_base342    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_base343    BOOST_MP_FORCEINLINE unsigned              capacity() const BOOST_NOEXCEPT { return m_internal ? internal_limb_count : m_data.ld.capacity; }
signboost::multiprecision::backends::cpp_int_base344    BOOST_MP_FORCEINLINE bool                  sign() const BOOST_NOEXCEPT { return m_sign; }
signboost::multiprecision::backends::cpp_int_base345    void                                       sign(bool b) BOOST_NOEXCEPT
346    {
347       m_sign = b;
348       // Check for zero value:
349       if (m_sign && (m_limbs == 1))
350       {
351          if (limbs()[0] == 0)
352             m_sign = false;
353       }
354    }
resizeboost::multiprecision::backends::cpp_int_base355    void resize(unsigned new_size, unsigned min_size)
356    {
357       static const unsigned max_limbs = MaxBits / (CHAR_BIT * sizeof(limb_type)) + ((MaxBits % (CHAR_BIT * sizeof(limb_type))) ? 1 : 0);
358       // We never resize beyond MaxSize:
359       if (new_size > max_limbs)
360          new_size = max_limbs;
361       detail::verify_new_size(new_size, min_size, checked_type());
362       // See if we have enough capacity already:
363       unsigned cap = capacity();
364       if (new_size > cap)
365       {
366          // We must not be an alias, memory allocation here defeats the whole point of aliasing:
367          BOOST_ASSERT(!m_alias);
368          // Allocate a new buffer and copy everything over:
369          cap             = (std::min)((std::max)(cap * 4, new_size), max_limbs);
370          limb_pointer pl = allocator().allocate(cap);
371          std::memcpy(pl, limbs(), size() * sizeof(limbs()[0]));
372          if (!m_internal && !m_alias)
373             allocator().deallocate(limbs(), capacity());
374          else
375             m_internal = false;
376          m_limbs            = new_size;
377          m_data.ld.capacity = cap;
378          m_data.ld.data     = pl;
379       }
380       else
381       {
382          m_limbs = new_size;
383       }
384    }
normalizeboost::multiprecision::backends::cpp_int_base385    BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT
386    {
387       limb_pointer p = limbs();
388       while ((m_limbs - 1) && !p[m_limbs - 1])
389          --m_limbs;
390    }
cpp_int_baseboost::multiprecision::backends::cpp_int_base391    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_data(), m_limbs(1), m_sign(false), m_internal(true), m_alias(false){}
cpp_int_baseboost::multiprecision::backends::cpp_int_base392    BOOST_MP_FORCEINLINE                 cpp_int_base(const cpp_int_base& o) : base_type(o), m_limbs(o.m_alias ? o.m_limbs : 0), m_sign(o.m_sign), m_internal(o.m_alias ? false : true), m_alias(o.m_alias)
393    {
394       if (m_alias)
395       {
396          m_data.ld = o.m_data.ld;
397       }
398       else
399       {
400          resize(o.size(), o.size());
401          std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
402       }
403    }
404 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
cpp_int_baseboost::multiprecision::backends::cpp_int_base405    cpp_int_base(cpp_int_base&& o)
406        : base_type(static_cast<base_type&&>(o)), m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal), m_alias(o.m_alias)
407    {
408       if (m_internal)
409       {
410          std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
411       }
412       else
413       {
414          m_data.ld    = o.m_data.ld;
415          o.m_limbs    = 0;
416          o.m_internal = true;
417       }
418    }
operator =boost::multiprecision::backends::cpp_int_base419    cpp_int_base& operator=(cpp_int_base&& o) BOOST_NOEXCEPT
420    {
421       if (!m_internal && !m_alias)
422          allocator().deallocate(m_data.ld.data, m_data.ld.capacity);
423       *static_cast<base_type*>(this) = static_cast<base_type&&>(o);
424       m_limbs                        = o.m_limbs;
425       m_sign                         = o.m_sign;
426       m_internal                     = o.m_internal;
427       m_alias                        = o.m_alias;
428       if (m_internal)
429       {
430          std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
431       }
432       else
433       {
434          m_data.ld    = o.m_data.ld;
435          o.m_limbs    = 0;
436          o.m_internal = true;
437       }
438       return *this;
439    }
440 #endif
~cpp_int_baseboost::multiprecision::backends::cpp_int_base441    BOOST_MP_FORCEINLINE ~cpp_int_base() BOOST_NOEXCEPT
442    {
443       if (!m_internal && !m_alias)
444          allocator().deallocate(limbs(), capacity());
445    }
assignboost::multiprecision::backends::cpp_int_base446    void assign(const cpp_int_base& o)
447    {
448       if (this != &o)
449       {
450          static_cast<base_type&>(*this) = static_cast<const base_type&>(o);
451          m_limbs                        = 0;
452          resize(o.size(), o.size());
453          std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
454          m_sign = o.m_sign;
455       }
456    }
negateboost::multiprecision::backends::cpp_int_base457    BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT
458    {
459       m_sign = !m_sign;
460       // Check for zero value:
461       if (m_sign && (m_limbs == 1))
462       {
463          if (limbs()[0] == 0)
464             m_sign = false;
465       }
466    }
isnegboost::multiprecision::backends::cpp_int_base467    BOOST_MP_FORCEINLINE bool isneg() const BOOST_NOEXCEPT
468    {
469       return m_sign;
470    }
do_swapboost::multiprecision::backends::cpp_int_base471    BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
472    {
473       std::swap(m_data, o.m_data);
474       std::swap(m_sign, o.m_sign);
475       std::swap(m_internal, o.m_internal);
476       std::swap(m_limbs, o.m_limbs);
477    }
478 
479  protected:
480    template <class A>
check_in_rangeboost::multiprecision::backends::cpp_int_base481    void check_in_range(const A&) BOOST_NOEXCEPT {}
482 };
483 
484 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
485 
486 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
487 const unsigned cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::limb_bits;
488 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
489 const limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::max_limb_value;
490 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
491 const limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::sign_bit_mask;
492 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
493 const unsigned cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::internal_limb_count;
494 
495 #endif
496 
497 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
498 struct cpp_int_base<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator, false>
499     : private boost::empty_value<typename detail::rebind<limb_type, Allocator>::type>
500 {
501    //
502    // There is currently no support for unsigned arbitrary precision arithmetic, largely
503    // because it's not clear what subtraction should do:
504    //
505    BOOST_STATIC_ASSERT_MSG(((sizeof(Allocator) == 0) && !is_void<Allocator>::value), "There is curently no support for unsigned arbitrary precision integers.");
506 };
507 //
508 // Fixed precision (i.e. no allocator), signed-magnitude type with limb-usage count:
509 //
510 template <unsigned MinBits, cpp_int_check_type Checked>
511 struct cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>
512 {
513    typedef limb_type*         limb_pointer;
514    typedef const limb_type*   const_limb_pointer;
515    typedef mpl::int_<Checked> checked_type;
516 
517    struct scoped_shared_storage {};
518 
519    //
520    // Interface invariants:
521    //
522    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?");
523 
524  public:
525    BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
526    BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
527    BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast<limb_type>(1u) << (limb_bits - 1));
528    BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0));
529    BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = (MinBits % limb_bits) ? (limb_type(1) << (MinBits % limb_bits)) - 1 : (~limb_type(0)));
530    BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs");
531 
532  private:
533    union data_type
534    {
535       limb_type        m_data[internal_limb_count];
536       limb_type        m_first_limb;
537       double_limb_type m_double_first_limb;
538 
data_type()539       BOOST_CONSTEXPR data_type()
540 #if defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) || defined(BOOST_NO_CXX14_CONSTEXPR)
541           : m_first_limb(0)
542       {}
543 #else
544           : m_data{0}
545       {}
546 #endif
data_type(limb_type i)547       BOOST_CONSTEXPR data_type(limb_type i)
548 #if defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) || defined(BOOST_NO_CXX14_CONSTEXPR)
549           : m_first_limb(i)
550       {}
551 #else
552           : m_data{i}
553       {}
554 #endif
555 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
data_type(limb_type i,limb_type j)556       BOOST_CONSTEXPR data_type(limb_type i, limb_type j) : m_data{i, j}
557       {}
558 #endif
data_type(double_limb_type i)559       BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i)
560       {
561 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
562          if (BOOST_MP_IS_CONST_EVALUATED(m_double_first_limb))
563          {
564             data_type t(static_cast<limb_type>(i & max_limb_value), static_cast<limb_type>(i >> limb_bits));
565             *this = t;
566          }
567 #endif
568       }
569 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
570       template <limb_type... VALUES>
data_type(literals::detail::value_pack<VALUES...>)571       BOOST_CONSTEXPR data_type(literals::detail::value_pack<VALUES...>) : m_data{VALUES...}
572       {}
573 #endif
574    } m_wrapper;
575    boost::uint16_t m_limbs;
576    bool            m_sign;
577 
578  public:
579    //
580    // Direct construction:
581    //
cpp_int_baseboost::multiprecision::backends::cpp_int_base582    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i) BOOST_NOEXCEPT
583        : m_wrapper(i),
584          m_limbs(1),
585          m_sign(false) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base586    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_limb_type i) BOOST_NOEXCEPT
587        : m_wrapper(limb_type(i < 0 ? static_cast<limb_type>(-static_cast<signed_double_limb_type>(i)) : i)),
588          m_limbs(1),
589          m_sign(i < 0) {}
590 #if BOOST_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
cpp_int_baseboost::multiprecision::backends::cpp_int_base591    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i) BOOST_NOEXCEPT
592        : m_wrapper(i),
593          m_limbs(i > max_limb_value ? 2 : 1),
594          m_sign(false)
595    {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base596    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i) BOOST_NOEXCEPT
597        : m_wrapper(double_limb_type(i < 0 ? static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i)),
598          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)),
599          m_sign(i < 0) {}
600 #endif
601 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
602    template <limb_type... VALUES>
cpp_int_baseboost::multiprecision::backends::cpp_int_base603    BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<VALUES...> i)
604        : m_wrapper(i), m_limbs(sizeof...(VALUES)), m_sign(false)
605    {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base606    BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<> i)
607        : m_wrapper(i), m_limbs(1), m_sign(false) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base608    BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& a, const literals::detail::negate_tag&)
609        : m_wrapper(a.m_wrapper), m_limbs(a.m_limbs), m_sign((a.m_limbs == 1) && (*a.limbs() == 0) ? false : !a.m_sign) {}
610 #endif
611 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
612    //
613    // These are deprecated in C++20 unless we make them explicit:
614    //
615    constexpr cpp_int_base& operator=(const cpp_int_base&) = default;
616 #endif
617    //
618    // Helper functions for getting at our internal data, and manipulating storage:
619    //
sizeboost::multiprecision::backends::cpp_int_base620    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned              size() const BOOST_NOEXCEPT { return m_limbs; }
limbsboost::multiprecision::backends::cpp_int_base621    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR limb_pointer limbs() BOOST_NOEXCEPT { return m_wrapper.m_data; }
limbsboost::multiprecision::backends::cpp_int_base622    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer    limbs() const BOOST_NOEXCEPT { return m_wrapper.m_data; }
signboost::multiprecision::backends::cpp_int_base623    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool                  sign() const BOOST_NOEXCEPT { return m_sign; }
signboost::multiprecision::backends::cpp_int_base624    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void         sign(bool b) BOOST_NOEXCEPT
625    {
626       m_sign = b;
627       // Check for zero value:
628       if (m_sign && (m_limbs == 1))
629       {
630          if (limbs()[0] == 0)
631             m_sign = false;
632       }
633    }
resizeboost::multiprecision::backends::cpp_int_base634    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void resize(unsigned new_size, unsigned min_size) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
635    {
636       m_limbs = static_cast<boost::uint16_t>((std::min)(new_size, internal_limb_count));
637       detail::verify_new_size(m_limbs, min_size, checked_type());
638    }
normalizeboost::multiprecision::backends::cpp_int_base639    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
640    {
641       limb_pointer p = limbs();
642       detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count - 1], upper_limb_mask, checked_type());
643       p[internal_limb_count - 1] &= upper_limb_mask;
644       while ((m_limbs - 1) && !p[m_limbs - 1])
645          --m_limbs;
646       if ((m_limbs == 1) && (!*p))
647          m_sign = false; // zero is always unsigned
648    }
649 
cpp_int_baseboost::multiprecision::backends::cpp_int_base650    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_wrapper(limb_type(0u)), m_limbs(1), m_sign(false) {}
651    // Not defaulted, it breaks constexpr support in the Intel compiler for some reason:
cpp_int_baseboost::multiprecision::backends::cpp_int_base652    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
653        : m_wrapper(o.m_wrapper),
654          m_limbs(o.m_limbs),
655          m_sign(o.m_sign) {}
656    // Defaulted functions:
657    //~cpp_int_base() BOOST_NOEXCEPT {}
658 
assignboost::multiprecision::backends::cpp_int_base659    void BOOST_MP_CXX14_CONSTEXPR assign(const cpp_int_base& o) BOOST_NOEXCEPT
660    {
661       if (this != &o)
662       {
663          m_limbs = o.m_limbs;
664 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
665          if (BOOST_MP_IS_CONST_EVALUATED(m_limbs))
666          {
667             for (unsigned i = 0; i < m_limbs; ++i)
668                limbs()[i] = o.limbs()[i];
669          }
670          else
671 #endif
672             std::memcpy(limbs(), o.limbs(), o.size() * sizeof(o.limbs()[0]));
673          m_sign = o.m_sign;
674       }
675    }
negateboost::multiprecision::backends::cpp_int_base676    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void negate() BOOST_NOEXCEPT
677    {
678       m_sign = !m_sign;
679       // Check for zero value:
680       if (m_sign && (m_limbs == 1))
681       {
682          if (limbs()[0] == 0)
683             m_sign = false;
684       }
685    }
isnegboost::multiprecision::backends::cpp_int_base686    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool isneg() const BOOST_NOEXCEPT
687    {
688       return m_sign;
689    }
do_swapboost::multiprecision::backends::cpp_int_base690    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
691    {
692       for (unsigned i = 0; i < (std::max)(size(), o.size()); ++i)
693          std_constexpr::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]);
694       std_constexpr::swap(m_sign, o.m_sign);
695       std_constexpr::swap(m_limbs, o.m_limbs);
696    }
697 
698  protected:
699    template <class A>
check_in_rangeboost::multiprecision::backends::cpp_int_base700    BOOST_MP_CXX14_CONSTEXPR void check_in_range(const A&) BOOST_NOEXCEPT {}
701 };
702 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
703 
704 template <unsigned MinBits, cpp_int_check_type Checked>
705 const unsigned cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::limb_bits;
706 template <unsigned MinBits, cpp_int_check_type Checked>
707 const limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::max_limb_value;
708 template <unsigned MinBits, cpp_int_check_type Checked>
709 const limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::sign_bit_mask;
710 template <unsigned MinBits, cpp_int_check_type Checked>
711 const unsigned cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::internal_limb_count;
712 
713 #endif
714 //
715 // Fixed precision (i.e. no allocator), unsigned type with limb-usage count:
716 //
717 template <unsigned MinBits, cpp_int_check_type Checked>
718 struct cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>
719 {
720    typedef limb_type*         limb_pointer;
721    typedef const limb_type*   const_limb_pointer;
722    typedef mpl::int_<Checked> checked_type;
723 
724    struct scoped_shared_storage {};
725    //
726    // Interface invariants:
727    //
728    BOOST_STATIC_ASSERT_MSG(MinBits > sizeof(double_limb_type) * CHAR_BIT, "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?");
729 
730  public:
731    BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
732    BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
733    BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast<limb_type>(1u) << (limb_bits - 1));
734    BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0));
735    BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = (MinBits % limb_bits) ? (limb_type(1) << (MinBits % limb_bits)) - 1 : (~limb_type(0)));
736    BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs");
737 
738  private:
739    union data_type
740    {
741       limb_type        m_data[internal_limb_count];
742       limb_type        m_first_limb;
743       double_limb_type m_double_first_limb;
744 
data_type()745       BOOST_CONSTEXPR data_type()
746 #if defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) || defined(BOOST_NO_CXX14_CONSTEXPR)
747           : m_first_limb(0)
748       {}
749 #else
750           : m_data{0}
751       {}
752 #endif
data_type(limb_type i)753       BOOST_CONSTEXPR data_type(limb_type i)
754 #if defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) || defined(BOOST_NO_CXX14_CONSTEXPR)
755           : m_first_limb(i)
756       {}
757 #else
758           : m_data{i}
759       {}
760 #endif
761 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
data_type(limb_type i,limb_type j)762       BOOST_CONSTEXPR data_type(limb_type i, limb_type j) : m_data{i, j}
763       {}
764 #endif
data_type(double_limb_type i)765       BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i)
766       {
767 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
768          if (BOOST_MP_IS_CONST_EVALUATED(m_double_first_limb))
769          {
770             data_type t(static_cast<limb_type>(i & max_limb_value), static_cast<limb_type>(i >> limb_bits));
771             *this = t;
772          }
773 #endif
774       }
775 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
776       template <limb_type... VALUES>
data_type(literals::detail::value_pack<VALUES...>)777       BOOST_CONSTEXPR data_type(literals::detail::value_pack<VALUES...>) : m_data{VALUES...}
778       {}
779 #endif
780    } m_wrapper;
781    limb_type m_limbs;
782 
783  public:
784    //
785    // Direct construction:
786    //
cpp_int_baseboost::multiprecision::backends::cpp_int_base787    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i) BOOST_NOEXCEPT
788        : m_wrapper(i),
789          m_limbs(1) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base790    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(signed_limb_type i) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
791        : m_wrapper(limb_type(i < 0 ? static_cast<limb_type>(-static_cast<signed_double_limb_type>(i)) : i)), m_limbs(1)
792    {
793       if (i < 0)
794          negate();
795    }
796 #if BOOST_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
cpp_int_baseboost::multiprecision::backends::cpp_int_base797    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i) BOOST_NOEXCEPT
798        : m_wrapper(i),
799          m_limbs(i > max_limb_value ? 2 : 1)
800    {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base801    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(signed_double_limb_type i) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
802        : m_wrapper(double_limb_type(i < 0 ? static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i)) : i)),
803          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))
804    {
805       if (i < 0)
806          negate();
807    }
808 #endif
809 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
810    template <limb_type... VALUES>
cpp_int_baseboost::multiprecision::backends::cpp_int_base811    BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<VALUES...> i)
812        : m_wrapper(i), m_limbs(sizeof...(VALUES))
813    {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base814    BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>)
815        : m_wrapper(static_cast<limb_type>(0u)), m_limbs(1) {}
816 #endif
817    //
818    // Helper functions for getting at our internal data, and manipulating storage:
819    //
sizeboost::multiprecision::backends::cpp_int_base820    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned              size() const BOOST_NOEXCEPT { return m_limbs; }
limbsboost::multiprecision::backends::cpp_int_base821    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR limb_pointer limbs() BOOST_NOEXCEPT { return m_wrapper.m_data; }
limbsboost::multiprecision::backends::cpp_int_base822    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer    limbs() const BOOST_NOEXCEPT { return m_wrapper.m_data; }
signboost::multiprecision::backends::cpp_int_base823    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool                  sign() const BOOST_NOEXCEPT { return false; }
signboost::multiprecision::backends::cpp_int_base824    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void         sign(bool b) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
825    {
826       if (b)
827          negate();
828    }
resizeboost::multiprecision::backends::cpp_int_base829    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void resize(unsigned new_size, unsigned min_size) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
830    {
831       m_limbs = (std::min)(new_size, internal_limb_count);
832       detail::verify_new_size(m_limbs, min_size, checked_type());
833    }
normalizeboost::multiprecision::backends::cpp_int_base834    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
835    {
836       limb_pointer p = limbs();
837       detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count - 1], upper_limb_mask, checked_type());
838       p[internal_limb_count - 1] &= upper_limb_mask;
839       while ((m_limbs - 1) && !p[m_limbs - 1])
840          --m_limbs;
841    }
842 
cpp_int_baseboost::multiprecision::backends::cpp_int_base843    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT
844        : m_wrapper(limb_type(0u)),
845          m_limbs(1) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base846    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
847        : m_wrapper(o.m_wrapper),
848          m_limbs(o.m_limbs) {}
849    // Defaulted functions:
850    //~cpp_int_base() BOOST_NOEXCEPT {}
851 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
852    //
853    // These are deprecated in C++20 unless we make them explicit:
854    //
855    constexpr cpp_int_base& operator=(const cpp_int_base&) = default;
856 #endif
857 
assignboost::multiprecision::backends::cpp_int_base858    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void assign(const cpp_int_base& o) BOOST_NOEXCEPT
859    {
860       if (this != &o)
861       {
862          m_limbs = o.m_limbs;
863 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
864          if (BOOST_MP_IS_CONST_EVALUATED(m_limbs))
865          {
866             for (unsigned i = 0; i < m_limbs; ++i)
867                limbs()[i] = o.limbs()[i];
868          }
869          else
870 #endif
871             std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
872       }
873    }
874 
875  private:
check_negateboost::multiprecision::backends::cpp_int_base876    void check_negate(const mpl::int_<checked>&)
877    {
878       BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned number."));
879    }
check_negateboost::multiprecision::backends::cpp_int_base880    BOOST_MP_CXX14_CONSTEXPR void check_negate(const mpl::int_<unchecked>&) {}
881 
882  public:
negateboost::multiprecision::backends::cpp_int_base883    BOOST_MP_CXX14_CONSTEXPR void negate() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
884    {
885       // Not so much a negate as a complement - this gets called when subtraction
886       // would result in a "negative" number:
887       if ((m_limbs == 1) && (m_wrapper.m_data[0] == 0))
888          return; // negating zero is always zero, and always OK.
889       check_negate(checked_type());
890       unsigned i = m_limbs;
891       for (; i < internal_limb_count; ++i)
892          m_wrapper.m_data[i] = 0;
893       m_limbs = internal_limb_count;
894       for (i = 0; i < internal_limb_count; ++i)
895          m_wrapper.m_data[i] = ~m_wrapper.m_data[i];
896       normalize();
897       eval_increment(static_cast<cpp_int_backend<MinBits, MinBits, unsigned_magnitude, Checked, void>&>(*this));
898    }
isnegboost::multiprecision::backends::cpp_int_base899    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool isneg() const BOOST_NOEXCEPT
900    {
901       return false;
902    }
do_swapboost::multiprecision::backends::cpp_int_base903    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
904    {
905       for (unsigned i = 0; i < (std::max)(size(), o.size()); ++i)
906          std_constexpr::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]);
907       std_constexpr::swap(m_limbs, o.m_limbs);
908    }
909 
910  protected:
911    template <class A>
check_in_rangeboost::multiprecision::backends::cpp_int_base912    BOOST_MP_CXX14_CONSTEXPR void check_in_range(const A&) BOOST_NOEXCEPT {}
913 };
914 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
915 
916 template <unsigned MinBits, cpp_int_check_type Checked>
917 const unsigned cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::limb_bits;
918 template <unsigned MinBits, cpp_int_check_type Checked>
919 const limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::max_limb_value;
920 template <unsigned MinBits, cpp_int_check_type Checked>
921 const limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::sign_bit_mask;
922 template <unsigned MinBits, cpp_int_check_type Checked>
923 const unsigned cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::internal_limb_count;
924 
925 #endif
926 //
927 // Traits classes to figure out a native type with N bits, these vary from boost::uint_t<N> only
928 // because some platforms have native integer types longer than boost::long_long_type, "really boost::long_long_type" anyone??
929 //
930 template <unsigned N, bool s>
931 struct trivial_limb_type_imp
932 {
933    typedef double_limb_type type;
934 };
935 
936 template <unsigned N>
937 struct trivial_limb_type_imp<N, true>
938 {
939    typedef typename boost::uint_t<N>::least type;
940 };
941 
942 template <unsigned N>
943 struct trivial_limb_type : public trivial_limb_type_imp<N, N <= sizeof(boost::long_long_type) * CHAR_BIT>
944 {};
945 //
946 // Backend for fixed precision signed-magnitude type which will fit entirely inside a "double_limb_type":
947 //
948 template <unsigned MinBits, cpp_int_check_type Checked>
949 struct cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, true>
950 {
951    typedef typename trivial_limb_type<MinBits>::type local_limb_type;
952    typedef local_limb_type*                          limb_pointer;
953    typedef const local_limb_type*                    const_limb_pointer;
954    typedef mpl::int_<Checked>                        checked_type;
955 
956    struct scoped_shared_storage {};
957 protected:
958    BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT);
959    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)));
960 
961  private:
962    local_limb_type m_data;
963    bool            m_sign;
964 
965    //
966    // Interface invariants:
967    //
968    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?");
969 
970  protected:
971    template <class T>
972    BOOST_MP_CXX14_CONSTEXPR 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_base973    check_in_range(T val, const mpl::int_<checked>&)
974    {
975       typedef typename common_type<typename make_unsigned<T>::type, local_limb_type>::type common_type;
976 
977       if (static_cast<common_type>(boost::multiprecision::detail::unsigned_abs(val)) > static_cast<common_type>(limb_mask))
978          BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
979    }
980    template <class T>
981    BOOST_MP_CXX14_CONSTEXPR 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_base982    check_in_range(T val, const mpl::int_<checked>&)
983    {
984       using std::abs;
985       typedef typename common_type<T, local_limb_type>::type common_type;
986 
987       if (static_cast<common_type>(abs(val)) > static_cast<common_type>(limb_mask))
988          BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
989    }
990    template <class T, int C>
check_in_rangeboost::multiprecision::backends::cpp_int_base991    BOOST_MP_CXX14_CONSTEXPR void check_in_range(T, const mpl::int_<C>&) BOOST_NOEXCEPT {}
992 
993    template <class T>
check_in_rangeboost::multiprecision::backends::cpp_int_base994    BOOST_MP_CXX14_CONSTEXPR void check_in_range(T val) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<T>(), checked_type())))
995    {
996       check_in_range(val, checked_type());
997    }
998 
999  public:
1000    //
1001    // Direct construction:
1002    //
1003    template <class SI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1004    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>())))
1005        : 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) {}
1006    template <class SI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1007    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR 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>())))
1008        : 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)
1009    {
1010       check_in_range(i);
1011    }
1012    template <class UI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1013    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
1014        : m_data(static_cast<local_limb_type>(i) & limb_mask),
1015          m_sign(false) {}
1016    template <class UI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1017    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR 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>())))
1018        : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) { check_in_range(i); }
1019    template <class F>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1020    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
1021        : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask),
1022          m_sign(i < 0) {}
1023    template <class F>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1024    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(F i, typename boost::enable_if_c<is_floating_point<F>::value && (Checked == checked)>::type const* = 0)
1025        : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask), m_sign(i < 0) { check_in_range(i); }
1026 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
cpp_int_baseboost::multiprecision::backends::cpp_int_base1027    BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>) BOOST_NOEXCEPT
1028        : m_data(static_cast<local_limb_type>(0u)),
1029          m_sign(false)
1030    {}
1031    template <limb_type a>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1032    BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a>) BOOST_NOEXCEPT
1033        : m_data(static_cast<local_limb_type>(a)),
1034          m_sign(false) {}
1035    template <limb_type a, limb_type b>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1036    BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a, b>) BOOST_NOEXCEPT
1037        : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)),
1038          m_sign(false) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base1039    BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& a, const literals::detail::negate_tag&) BOOST_NOEXCEPT
1040        : m_data(a.m_data),
1041          m_sign(a.m_data ? !a.m_sign : false) {}
1042 #endif
1043 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
1044    //
1045    // These are deprecated in C++20 unless we make them explicit:
1046    //
1047    constexpr cpp_int_base& operator=(const cpp_int_base&) = default;
1048 #endif
1049    //
1050    // Helper functions for getting at our internal data, and manipulating storage:
1051    //
sizeboost::multiprecision::backends::cpp_int_base1052    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned              size() const BOOST_NOEXCEPT { return 1; }
limbsboost::multiprecision::backends::cpp_int_base1053    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR limb_pointer limbs() BOOST_NOEXCEPT { return &m_data; }
limbsboost::multiprecision::backends::cpp_int_base1054    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer    limbs() const BOOST_NOEXCEPT { return &m_data; }
signboost::multiprecision::backends::cpp_int_base1055    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool         sign() const BOOST_NOEXCEPT { return m_sign; }
signboost::multiprecision::backends::cpp_int_base1056    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void         sign(bool b) BOOST_NOEXCEPT
1057    {
1058       m_sign = b;
1059       // Check for zero value:
1060       if (m_sign && !m_data)
1061       {
1062          m_sign = false;
1063       }
1064    }
resizeboost::multiprecision::backends::cpp_int_base1065    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void resize(unsigned /* new_size */, unsigned min_size)
1066    {
1067       detail::verify_new_size(2, min_size, checked_type());
1068    }
normalizeboost::multiprecision::backends::cpp_int_base1069    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
1070    {
1071       if (!m_data)
1072          m_sign = false; // zero is always unsigned
1073       detail::verify_limb_mask(true, m_data, limb_mask, checked_type());
1074       m_data &= limb_mask;
1075    }
1076 
cpp_int_baseboost::multiprecision::backends::cpp_int_base1077    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_data(0), m_sign(false) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base1078    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
1079        : m_data(o.m_data),
1080          m_sign(o.m_sign) {}
1081    //~cpp_int_base() BOOST_NOEXCEPT {}
assignboost::multiprecision::backends::cpp_int_base1082    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void assign(const cpp_int_base& o) BOOST_NOEXCEPT
1083    {
1084       m_data = o.m_data;
1085       m_sign = o.m_sign;
1086    }
negateboost::multiprecision::backends::cpp_int_base1087    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void negate() BOOST_NOEXCEPT
1088    {
1089       m_sign = !m_sign;
1090       // Check for zero value:
1091       if (m_data == 0)
1092       {
1093          m_sign = false;
1094       }
1095    }
isnegboost::multiprecision::backends::cpp_int_base1096    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool isneg() const BOOST_NOEXCEPT
1097    {
1098       return m_sign;
1099    }
do_swapboost::multiprecision::backends::cpp_int_base1100    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
1101    {
1102       std_constexpr::swap(m_sign, o.m_sign);
1103       std_constexpr::swap(m_data, o.m_data);
1104    }
1105 };
1106 //
1107 // Backend for unsigned fixed precision (i.e. no allocator) type which will fit entirely inside a "double_limb_type":
1108 //
1109 template <unsigned MinBits, cpp_int_check_type Checked>
1110 struct cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, true>
1111 {
1112    typedef typename trivial_limb_type<MinBits>::type local_limb_type;
1113    typedef local_limb_type*                          limb_pointer;
1114    typedef const local_limb_type*                    const_limb_pointer;
1115 
1116    struct scoped_shared_storage {};
1117 private:
1118    BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT);
1119    BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = limb_bits != MinBits ? static_cast<local_limb_type>(static_cast<local_limb_type>(~local_limb_type(0)) >> (limb_bits - MinBits))
1120                                                                            : static_cast<local_limb_type>(~local_limb_type(0)));
1121 
1122    local_limb_type m_data;
1123 
1124    typedef mpl::int_<Checked> checked_type;
1125 
1126    //
1127    // Interface invariants:
1128    //
1129    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?");
1130 
1131  protected:
1132    template <class T>
1133    BOOST_MP_CXX14_CONSTEXPR 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_base1134    check_in_range(T val, const mpl::int_<checked>&, const boost::false_type&)
1135    {
1136       typedef typename common_type<T, local_limb_type>::type common_type;
1137 
1138       if (static_cast<common_type>(val) > limb_mask)
1139          BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
1140    }
1141    template <class T>
check_in_rangeboost::multiprecision::backends::cpp_int_base1142    BOOST_MP_CXX14_CONSTEXPR void check_in_range(T val, const mpl::int_<checked>&, const boost::true_type&)
1143    {
1144       typedef typename common_type<T, local_limb_type>::type common_type;
1145 
1146       if (static_cast<common_type>(val) > limb_mask)
1147          BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
1148       if (val < 0)
1149          BOOST_THROW_EXCEPTION(std::range_error("The argument to an unsigned cpp_int constructor was negative."));
1150    }
1151    template <class T, int C, bool B>
check_in_rangeboost::multiprecision::backends::cpp_int_base1152    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void check_in_range(T, const mpl::int_<C>&, const boost::integral_constant<bool, B>&) BOOST_NOEXCEPT {}
1153 
1154    template <class T>
check_in_rangeboost::multiprecision::backends::cpp_int_base1155    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR 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>())))
1156    {
1157       check_in_range(val, checked_type(), is_signed<T>());
1158    }
1159 
1160  public:
1161    //
1162    // Direct construction:
1163    //
1164 #ifdef __MSVC_RUNTIME_CHECKS
1165    template <class SI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1166    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
1167        : m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i & limb_mask)) & limb_mask : static_cast<local_limb_type>(i & limb_mask))
1168    {}
1169    template <class SI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1170    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR 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>())))
1171        : 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); }
1172    template <class UI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1173    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
1174        : m_data(static_cast<local_limb_type>(i& limb_mask)) {}
1175    template <class UI>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1176    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR 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>())))
1177        : m_data(static_cast<local_limb_type>(i & limb_mask)) { check_in_range(i); }
1178 #else
1179    template <class SI>
1180    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
1181        : m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i)) & limb_mask : static_cast<local_limb_type>(i) & limb_mask)
1182    {}
1183    template <class SI>
1184    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR 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>())))
1185        : m_data(i < 0 ? 1 + ~static_cast<local_limb_type>(-i) : static_cast<local_limb_type>(i)) { check_in_range(i); }
1186    template <class UI>
1187    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
1188        : m_data(static_cast<local_limb_type>(i) & limb_mask) {}
1189    template <class UI>
1190    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR 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>())))
1191        : m_data(static_cast<local_limb_type>(i)) { check_in_range(i); }
1192 #endif
1193    template <class F>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1194    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_base(F i, typename boost::enable_if<is_floating_point<F> >::type const* = 0) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
1195        : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask)
1196    {
1197       check_in_range(i);
1198       if (i < 0)
1199          negate();
1200    }
1201 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
cpp_int_baseboost::multiprecision::backends::cpp_int_base1202    BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>) BOOST_NOEXCEPT
1203        : m_data(static_cast<local_limb_type>(0u))
1204    {}
1205    template <limb_type a>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1206    BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a>) BOOST_NOEXCEPT
1207        : m_data(static_cast<local_limb_type>(a)) {}
1208    template <limb_type a, limb_type b>
cpp_int_baseboost::multiprecision::backends::cpp_int_base1209    BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a, b>) BOOST_NOEXCEPT
1210        : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)) {}
1211 #endif
1212 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
1213    //
1214    // These are deprecated in C++20 unless we make them explicit:
1215    //
1216    constexpr cpp_int_base& operator=(const cpp_int_base&) = default;
1217 #endif
1218    //
1219    // Helper functions for getting at our internal data, and manipulating storage:
1220    //
sizeboost::multiprecision::backends::cpp_int_base1221    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned              size() const BOOST_NOEXCEPT { return 1; }
limbsboost::multiprecision::backends::cpp_int_base1222    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR limb_pointer limbs() BOOST_NOEXCEPT { return &m_data; }
limbsboost::multiprecision::backends::cpp_int_base1223    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer    limbs() const BOOST_NOEXCEPT { return &m_data; }
signboost::multiprecision::backends::cpp_int_base1224    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool                  sign() const BOOST_NOEXCEPT { return false; }
signboost::multiprecision::backends::cpp_int_base1225    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void         sign(bool b) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
1226    {
1227       if (b)
1228          negate();
1229    }
resizeboost::multiprecision::backends::cpp_int_base1230    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void resize(unsigned, unsigned min_size)
1231    {
1232       detail::verify_new_size(2, min_size, checked_type());
1233    }
normalizeboost::multiprecision::backends::cpp_int_base1234    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void normalize() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
1235    {
1236       detail::verify_limb_mask(true, m_data, limb_mask, checked_type());
1237       m_data &= limb_mask;
1238    }
1239 
cpp_int_baseboost::multiprecision::backends::cpp_int_base1240    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_data(0) {}
cpp_int_baseboost::multiprecision::backends::cpp_int_base1241    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
1242        : m_data(o.m_data) {}
1243    //~cpp_int_base() BOOST_NOEXCEPT {}
assignboost::multiprecision::backends::cpp_int_base1244    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void assign(const cpp_int_base& o) BOOST_NOEXCEPT
1245    {
1246       m_data = o.m_data;
1247    }
negateboost::multiprecision::backends::cpp_int_base1248    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void negate() BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
1249    {
1250       if (Checked == checked)
1251       {
1252          BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned type."));
1253       }
1254       m_data = ~m_data;
1255       ++m_data;
1256    }
isnegboost::multiprecision::backends::cpp_int_base1257    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool isneg() const BOOST_NOEXCEPT
1258    {
1259       return false;
1260    }
do_swapboost::multiprecision::backends::cpp_int_base1261    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
1262    {
1263       std_constexpr::swap(m_data, o.m_data);
1264    }
1265 };
1266 //
1267 // Traits class, lets us know whether type T can be directly converted to the base type,
1268 // used to enable/disable constructors etc:
1269 //
1270 template <class Arg, class Base>
1271 struct is_allowed_cpp_int_base_conversion : public mpl::if_c<
1272                                                 is_same<Arg, limb_type>::value || is_same<Arg, signed_limb_type>::value
1273 #if BOOST_ENDIAN_LITTLE_BYTE && !defined(BOOST_MP_TEST_NO_LE)
1274                                                     || is_same<Arg, double_limb_type>::value || is_same<Arg, signed_double_limb_type>::value
1275 #endif
1276 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
1277                                                     || literals::detail::is_value_pack<Arg>::value
1278 #endif
1279                                                     || (is_trivial_cpp_int<Base>::value && is_arithmetic<Arg>::value),
1280                                                 mpl::true_,
1281                                                 mpl::false_>::type
1282 {};
1283 //
1284 // Now the actual backend, normalising parameters passed to the base class:
1285 //
1286 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
1287 struct cpp_int_backend
1288     : public cpp_int_base<
1289           min_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
1290           max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
1291           SignType,
1292           Checked,
1293           Allocator,
1294           is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value>
1295 {
1296    typedef cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> self_type;
1297    typedef cpp_int_base<
1298        min_precision<self_type>::value,
1299        max_precision<self_type>::value,
1300        SignType,
1301        Checked,
1302        Allocator,
1303        is_trivial_cpp_int<self_type>::value>
1304        base_type;
1305    typedef mpl::bool_<is_trivial_cpp_int<self_type>::value> trivial_tag;
1306 
1307  public:
1308    typedef typename mpl::if_<
1309        trivial_tag,
1310        mpl::list<
1311            signed char, short, int, long,
1312            boost::long_long_type, signed_double_limb_type>,
1313        mpl::list<signed_limb_type, signed_double_limb_type> >::type signed_types;
1314    typedef typename mpl::if_<
1315        trivial_tag,
1316        mpl::list<unsigned char, unsigned short, unsigned,
1317                  unsigned long, boost::ulong_long_type, double_limb_type>,
1318        mpl::list<limb_type, double_limb_type> >::type unsigned_types;
1319    typedef typename mpl::if_<
1320        trivial_tag,
1321        mpl::list<float, double, long double>,
1322        mpl::list<long double> >::type float_types;
1323    typedef mpl::int_<Checked>         checked_type;
1324 
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1325    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend() BOOST_NOEXCEPT {}
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1326    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) {}
1327 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1328    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(cpp_int_backend&& o) BOOST_NOEXCEPT
1329        : base_type(static_cast<base_type&&>(o))
1330    {}
1331 #endif
1332    //
1333    // Direct construction from arithmetic type:
1334    //
1335    template <class Arg>
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1336    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>())))
1337        : base_type(i) {}
1338    //
1339    // Aliasing constructor: the result will alias the memory referenced, unless
1340    // we have fixed precision and storage, in which case we copy the memory:
1341    //
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1342    explicit BOOST_CONSTEXPR cpp_int_backend(limb_type* data, unsigned offset, unsigned len) BOOST_NOEXCEPT
1343        : base_type(data, offset, len) {}
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1344    explicit cpp_int_backend(const limb_type* data, unsigned offset, unsigned len) BOOST_NOEXCEPT
1345        : base_type(data, offset, len) { this->normalize(); }
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1346    explicit BOOST_CONSTEXPR cpp_int_backend(typename base_type::scoped_shared_storage& data, unsigned len) BOOST_NOEXCEPT
1347        : base_type(data, len) {}
1348 
1349  private:
1350    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
do_assignboost::multiprecision::backends::cpp_int_backend1351    BOOST_MP_CXX14_CONSTEXPR void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::true_ const&, mpl::true_ const&)
1352    {
1353       // Assigning trivial type to trivial type:
1354       this->check_in_range(*other.limbs());
1355       *this->limbs() = static_cast<typename self_type::local_limb_type>(*other.limbs());
1356       this->sign(other.sign());
1357       this->normalize();
1358    }
1359    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
do_assignboost::multiprecision::backends::cpp_int_backend1360    BOOST_MP_CXX14_CONSTEXPR void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::true_ const&, mpl::false_ const&)
1361    {
1362       // non-trivial to trivial narrowing conversion:
1363       double_limb_type v = *other.limbs();
1364       if (other.size() > 1)
1365       {
1366          v |= static_cast<double_limb_type>(other.limbs()[1]) << bits_per_limb;
1367          if ((Checked == checked) && (other.size() > 2))
1368          {
1369             BOOST_THROW_EXCEPTION(std::range_error("Assignment of a cpp_int that is out of range for the target type."));
1370          }
1371       }
1372       *this = v;
1373       this->sign(other.sign());
1374       this->normalize();
1375    }
1376    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
do_assignboost::multiprecision::backends::cpp_int_backend1377    BOOST_MP_CXX14_CONSTEXPR void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::false_ const&, mpl::true_ const&)
1378    {
1379       // trivial to non-trivial, treat the trivial argument as if it were an unsigned arithmetic type, then set the sign afterwards:
1380       *this = static_cast<
1381           typename boost::multiprecision::detail::canonical<
1382               typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::local_limb_type,
1383               cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::type>(*other.limbs());
1384       this->sign(other.sign());
1385    }
1386    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
do_assignboost::multiprecision::backends::cpp_int_backend1387    BOOST_MP_CXX14_CONSTEXPR void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::false_ const&, mpl::false_ const&)
1388    {
1389       // regular non-trivial to non-trivial assign:
1390       this->resize(other.size(), other.size());
1391 
1392       unsigned count = (std::min)(other.size(), this->size());
1393       for (unsigned i = 0; i < count; ++i)
1394          this->limbs()[i] = other.limbs()[i];
1395       //std::memcpy(this->limbs(), other.limbs(), (std::min)(other.size(), this->size()) * sizeof(this->limbs()[0]));
1396 
1397       this->sign(other.sign());
1398       this->normalize();
1399    }
1400 
1401  public:
1402    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1403    BOOST_MP_CXX14_CONSTEXPR cpp_int_backend(
1404        const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other,
1405        typename boost::enable_if_c<is_implicit_cpp_int_conversion<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>, self_type>::value>::type* = 0)
1406        : base_type()
1407    {
1408       do_assign(
1409           other,
1410           mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
1411           mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
1412    }
1413    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1414    explicit BOOST_MP_CXX14_CONSTEXPR cpp_int_backend(
1415        const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other,
1416        typename boost::disable_if_c<is_implicit_cpp_int_conversion<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>, self_type>::value>::type* = 0)
1417        : base_type()
1418    {
1419       do_assign(
1420           other,
1421           mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
1422           mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
1423    }
1424    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
operator =boost::multiprecision::backends::cpp_int_backend1425    BOOST_MP_CXX14_CONSTEXPR cpp_int_backend& operator=(
1426        const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other)
1427    {
1428       do_assign(
1429           other,
1430           mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
1431           mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
1432       return *this;
1433    }
1434 #ifdef BOOST_MP_USER_DEFINED_LITERALS
cpp_int_backendboost::multiprecision::backends::cpp_int_backend1435    BOOST_CONSTEXPR cpp_int_backend(const cpp_int_backend& a, const literals::detail::negate_tag& tag)
1436        : base_type(static_cast<const base_type&>(a), tag)
1437    {}
1438 #endif
1439 
operator =boost::multiprecision::backends::cpp_int_backend1440    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR 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&>())))
1441    {
1442       this->assign(o);
1443       return *this;
1444    }
1445 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =boost::multiprecision::backends::cpp_int_backend1446    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR cpp_int_backend& operator=(cpp_int_backend&& o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<base_type&>() = std::declval<base_type>()))
1447    {
1448       *static_cast<base_type*>(this) = static_cast<base_type&&>(o);
1449       return *this;
1450    }
1451 #endif
1452  private:
1453    template <class A>
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1454    BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if<is_unsigned<A> >::type do_assign_arithmetic(A val, const mpl::true_&)
1455        BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().check_in_range(std::declval<A>())))
1456    {
1457       this->check_in_range(val);
1458       *this->limbs() = static_cast<typename self_type::local_limb_type>(val);
1459       this->sign(false);
1460       this->normalize();
1461    }
1462    template <class A>
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1463    BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<is_unsigned<A>::value || !is_integral<A>::value>::type do_assign_arithmetic(A val, const mpl::true_&)
1464        BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().check_in_range(std::declval<A>())) && noexcept(std::declval<cpp_int_backend>().sign(true)))
1465    {
1466       this->check_in_range(val);
1467       *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);
1468       this->sign(val < 0);
1469       this->normalize();
1470    }
1471    template <class A>
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1472    BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<!is_integral<A>::value>::type do_assign_arithmetic(A val, const mpl::true_&)
1473    {
1474       this->check_in_range(val);
1475       *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);
1476       this->sign(val < 0);
1477       this->normalize();
1478    }
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1479    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void do_assign_arithmetic(limb_type i, const mpl::false_&) BOOST_NOEXCEPT
1480    {
1481       this->resize(1, 1);
1482       *this->limbs() = i;
1483       this->sign(false);
1484    }
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1485    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void do_assign_arithmetic(signed_limb_type i, const mpl::false_&) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().sign(true)))
1486    {
1487       this->resize(1, 1);
1488       *this->limbs() = static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(i));
1489       this->sign(i < 0);
1490    }
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1491    BOOST_MP_CXX14_CONSTEXPR void do_assign_arithmetic(double_limb_type i, const mpl::false_&) BOOST_NOEXCEPT
1492    {
1493       BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type));
1494       BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2);
1495       typename base_type::limb_pointer p = this->limbs();
1496 #ifdef __MSVC_RUNTIME_CHECKS
1497       *p = static_cast<limb_type>(i & ~static_cast<limb_type>(0));
1498 #else
1499       *p                        = static_cast<limb_type>(i);
1500 #endif
1501       p[1] = static_cast<limb_type>(i >> base_type::limb_bits);
1502       this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1);
1503       this->sign(false);
1504    }
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1505    BOOST_MP_CXX14_CONSTEXPR void do_assign_arithmetic(signed_double_limb_type i, const mpl::false_&) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_backend>().sign(true)))
1506    {
1507       BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type));
1508       BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2);
1509       bool s = false;
1510       if (i < 0)
1511          s = true;
1512       double_limb_type                 ui = static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i));
1513       typename base_type::limb_pointer p  = this->limbs();
1514 #ifdef __MSVC_RUNTIME_CHECKS
1515       *p = static_cast<limb_type>(ui & ~static_cast<limb_type>(0));
1516 #else
1517       *p                        = static_cast<limb_type>(ui);
1518 #endif
1519       p[1] = static_cast<limb_type>(ui >> base_type::limb_bits);
1520       this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1);
1521       this->sign(s);
1522    }
1523 
do_assign_arithmeticboost::multiprecision::backends::cpp_int_backend1524    BOOST_MP_CXX14_CONSTEXPR void do_assign_arithmetic(long double a, const mpl::false_&)
1525    {
1526       using default_ops::eval_add;
1527       using default_ops::eval_subtract;
1528       using std::floor;
1529       using std::frexp;
1530       using std::ldexp;
1531 
1532       if (a < 0)
1533       {
1534          do_assign_arithmetic(-a, mpl::false_());
1535          this->sign(true);
1536          return;
1537       }
1538 
1539       if (a == 0)
1540       {
1541          *this = static_cast<limb_type>(0u);
1542       }
1543 
1544       if (a == 1)
1545       {
1546          *this = static_cast<limb_type>(1u);
1547       }
1548 
1549       if ((boost::math::isinf)(a) || (boost::math::isnan)(a))
1550       {
1551          BOOST_THROW_EXCEPTION(std::runtime_error("Cannot convert a non-finite number to an integer."));
1552       }
1553 
1554       int         e = 0;
1555       long double f(0), term(0);
1556       *this = static_cast<limb_type>(0u);
1557 
1558       f = frexp(a, &e);
1559 
1560 #ifdef BOOST_NO_CXX11_CONSTEXPR
1561       static const limb_type shift = std::numeric_limits<limb_type>::digits;
1562 #else
1563       constexpr limb_type shift = std::numeric_limits<limb_type>::digits;
1564 #endif
1565 
1566       while (f)
1567       {
1568          // extract int sized bits from f:
1569          f    = ldexp(f, shift);
1570          term = floor(f);
1571          e -= shift;
1572          eval_left_shift(*this, shift);
1573          if (term > 0)
1574             eval_add(*this, static_cast<limb_type>(term));
1575          else
1576             eval_subtract(*this, static_cast<limb_type>(-term));
1577          f -= term;
1578       }
1579       if (e > 0)
1580          eval_left_shift(*this, e);
1581       else if (e < 0)
1582          eval_right_shift(*this, -e);
1583    }
1584 
1585  public:
1586    template <class Arithmetic>
operator =boost::multiprecision::backends::cpp_int_backend1587    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR 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())))
1588    {
1589       do_assign_arithmetic(val, trivial_tag());
1590       return *this;
1591    }
1592 
1593  private:
do_assign_stringboost::multiprecision::backends::cpp_int_backend1594    void do_assign_string(const char* s, const mpl::true_&)
1595    {
1596       std::size_t n  = s ? std::strlen(s) : 0;
1597       *this          = 0;
1598       unsigned radix = 10;
1599       bool     isneg = false;
1600       if (n && (*s == '-'))
1601       {
1602          --n;
1603          ++s;
1604          isneg = true;
1605       }
1606       if (n && (*s == '0'))
1607       {
1608          if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
1609          {
1610             radix = 16;
1611             s += 2;
1612             n -= 2;
1613          }
1614          else
1615          {
1616             radix = 8;
1617             n -= 1;
1618          }
1619       }
1620       if (n)
1621       {
1622          unsigned val;
1623          while (*s)
1624          {
1625             if (*s >= '0' && *s <= '9')
1626                val = *s - '0';
1627             else if (*s >= 'a' && *s <= 'f')
1628                val = 10 + *s - 'a';
1629             else if (*s >= 'A' && *s <= 'F')
1630                val = 10 + *s - 'A';
1631             else
1632                val = radix + 1;
1633             if (val >= radix)
1634             {
1635                BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string."));
1636             }
1637             *this->limbs() = detail::checked_multiply(*this->limbs(), static_cast<typename base_type::local_limb_type>(radix), checked_type());
1638             *this->limbs() = detail::checked_add(*this->limbs(), static_cast<typename base_type::local_limb_type>(val), checked_type());
1639             ++s;
1640          }
1641       }
1642       if (isneg)
1643          this->negate();
1644    }
do_assign_stringboost::multiprecision::backends::cpp_int_backend1645    void do_assign_string(const char* s, const mpl::false_&)
1646    {
1647       using default_ops::eval_add;
1648       using default_ops::eval_multiply;
1649       std::size_t n  = s ? std::strlen(s) : 0;
1650       *this          = static_cast<limb_type>(0u);
1651       unsigned radix = 10;
1652       bool     isneg = false;
1653       if (n && (*s == '-'))
1654       {
1655          --n;
1656          ++s;
1657          isneg = true;
1658       }
1659       if (n && (*s == '0'))
1660       {
1661          if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
1662          {
1663             radix = 16;
1664             s += 2;
1665             n -= 2;
1666          }
1667          else
1668          {
1669             radix = 8;
1670             n -= 1;
1671          }
1672       }
1673       //
1674       // Exception guarantee: create the result in stack variable "result"
1675       // then do a swap at the end.  In the event of a throw, *this will
1676       // be left unchanged.
1677       //
1678       cpp_int_backend result;
1679       if (n)
1680       {
1681          if (radix == 16)
1682          {
1683             while (*s == '0')
1684                ++s;
1685             std::size_t bitcount = 4 * std::strlen(s);
1686             limb_type   val;
1687             std::size_t limb, shift;
1688             if (bitcount > 4)
1689                bitcount -= 4;
1690             else
1691                bitcount = 0;
1692             std::size_t newsize = bitcount / (sizeof(limb_type) * CHAR_BIT) + 1;
1693             result.resize(static_cast<unsigned>(newsize), static_cast<unsigned>(newsize)); // will throw if this is a checked integer that cannot be resized
1694             std::memset(result.limbs(), 0, result.size() * sizeof(limb_type));
1695             while (*s)
1696             {
1697                if (*s >= '0' && *s <= '9')
1698                   val = *s - '0';
1699                else if (*s >= 'a' && *s <= 'f')
1700                   val = 10 + *s - 'a';
1701                else if (*s >= 'A' && *s <= 'F')
1702                   val = 10 + *s - 'A';
1703                else
1704                {
1705                   BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string."));
1706                }
1707                limb  = bitcount / (sizeof(limb_type) * CHAR_BIT);
1708                shift = bitcount % (sizeof(limb_type) * CHAR_BIT);
1709                val <<= shift;
1710                if (result.size() > limb)
1711                {
1712                   result.limbs()[limb] |= val;
1713                }
1714                ++s;
1715                bitcount -= 4;
1716             }
1717             result.normalize();
1718          }
1719          else if (radix == 8)
1720          {
1721             while (*s == '0')
1722                ++s;
1723             std::size_t bitcount = 3 * std::strlen(s);
1724             limb_type   val;
1725             std::size_t limb, shift;
1726             if (bitcount > 3)
1727                bitcount -= 3;
1728             else
1729                bitcount = 0;
1730             std::size_t newsize = bitcount / (sizeof(limb_type) * CHAR_BIT) + 1;
1731             result.resize(static_cast<unsigned>(newsize), static_cast<unsigned>(newsize)); // will throw if this is a checked integer that cannot be resized
1732             std::memset(result.limbs(), 0, result.size() * sizeof(limb_type));
1733             while (*s)
1734             {
1735                if (*s >= '0' && *s <= '7')
1736                   val = *s - '0';
1737                else
1738                {
1739                   BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string."));
1740                }
1741                limb  = bitcount / (sizeof(limb_type) * CHAR_BIT);
1742                shift = bitcount % (sizeof(limb_type) * CHAR_BIT);
1743                if (result.size() > limb)
1744                {
1745                   result.limbs()[limb] |= (val << shift);
1746                   if (shift > sizeof(limb_type) * CHAR_BIT - 3)
1747                   {
1748                      // Deal with the bits in val that overflow into the next limb:
1749                      val >>= (sizeof(limb_type) * CHAR_BIT - shift);
1750                      if (val)
1751                      {
1752                         // If this is the most-significant-limb, we may need to allocate an extra one for the overflow:
1753                         if (limb + 1 == newsize)
1754                            result.resize(static_cast<unsigned>(newsize + 1), static_cast<unsigned>(newsize + 1));
1755                         if (result.size() > limb + 1)
1756                         {
1757                            result.limbs()[limb + 1] |= val;
1758                         }
1759                      }
1760                   }
1761                }
1762                ++s;
1763                bitcount -= 3;
1764             }
1765             result.normalize();
1766          }
1767          else
1768          {
1769             // Base 10, we extract blocks of size 10^9 at a time, that way
1770             // the number of multiplications is kept to a minimum:
1771             limb_type block_mult = max_block_10;
1772             while (*s)
1773             {
1774                limb_type block = 0;
1775                for (unsigned i = 0; i < digits_per_block_10; ++i)
1776                {
1777                   limb_type val;
1778                   if (*s >= '0' && *s <= '9')
1779                      val = *s - '0';
1780                   else
1781                      BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected character encountered in input."));
1782                   block *= 10;
1783                   block += val;
1784                   if (!*++s)
1785                   {
1786                      block_mult = block_multiplier(i);
1787                      break;
1788                   }
1789                }
1790                eval_multiply(result, block_mult);
1791                eval_add(result, block);
1792             }
1793          }
1794       }
1795       if (isneg)
1796          result.negate();
1797       result.swap(*this);
1798    }
1799 
1800  public:
operator =boost::multiprecision::backends::cpp_int_backend1801    cpp_int_backend& operator=(const char* s)
1802    {
1803       do_assign_string(s, trivial_tag());
1804       return *this;
1805    }
swapboost::multiprecision::backends::cpp_int_backend1806    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(cpp_int_backend& o) BOOST_NOEXCEPT
1807    {
1808       this->do_swap(o);
1809    }
1810 
1811  private:
do_get_trivial_stringboost::multiprecision::backends::cpp_int_backend1812    std::string do_get_trivial_string(std::ios_base::fmtflags f, const mpl::false_&) const
1813    {
1814       typedef typename mpl::if_c<sizeof(typename base_type::local_limb_type) == 1, unsigned, typename base_type::local_limb_type>::type io_type;
1815       if (this->sign() && (((f & std::ios_base::hex) == std::ios_base::hex) || ((f & std::ios_base::oct) == std::ios_base::oct)))
1816          BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported."));
1817       std::stringstream ss;
1818       ss.flags(f & ~std::ios_base::showpos);
1819       ss << static_cast<io_type>(*this->limbs());
1820       std::string result;
1821       if (this->sign())
1822          result += '-';
1823       else if (f & std::ios_base::showpos)
1824          result += '+';
1825       result += ss.str();
1826       return result;
1827    }
do_get_trivial_stringboost::multiprecision::backends::cpp_int_backend1828    std::string do_get_trivial_string(std::ios_base::fmtflags f, const mpl::true_&) const
1829    {
1830       // Even though we have only one limb, we can't do IO on it :-(
1831       int base = 10;
1832       if ((f & std::ios_base::oct) == std::ios_base::oct)
1833          base = 8;
1834       else if ((f & std::ios_base::hex) == std::ios_base::hex)
1835          base = 16;
1836       std::string result;
1837 
1838       unsigned Bits = sizeof(typename base_type::local_limb_type) * CHAR_BIT;
1839 
1840       if (base == 8 || base == 16)
1841       {
1842          if (this->sign())
1843             BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported."));
1844          limb_type                           shift = base == 8 ? 3 : 4;
1845          limb_type                           mask  = static_cast<limb_type>((1u << shift) - 1);
1846          typename base_type::local_limb_type v     = *this->limbs();
1847          result.assign(Bits / shift + (Bits % shift ? 1 : 0), '0');
1848          std::string::difference_type pos      = result.size() - 1;
1849          char                         letter_a = f & std::ios_base::uppercase ? 'A' : 'a';
1850          for (unsigned i = 0; i < Bits / shift; ++i)
1851          {
1852             char c = '0' + static_cast<char>(v & mask);
1853             if (c > '9')
1854                c += letter_a - '9' - 1;
1855             result[pos--] = c;
1856             v >>= shift;
1857          }
1858          if (Bits % shift)
1859          {
1860             mask   = static_cast<limb_type>((1u << (Bits % shift)) - 1);
1861             char c = '0' + static_cast<char>(v & mask);
1862             if (c > '9')
1863                c += letter_a - '9';
1864             result[pos] = c;
1865          }
1866          //
1867          // Get rid of leading zeros:
1868          //
1869          std::string::size_type n = result.find_first_not_of('0');
1870          if (!result.empty() && (n == std::string::npos))
1871             n = result.size() - 1;
1872          result.erase(0, n);
1873          if (f & std::ios_base::showbase)
1874          {
1875             const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x";
1876             result.insert(static_cast<std::string::size_type>(0), pp);
1877          }
1878       }
1879       else
1880       {
1881          result.assign(Bits / 3 + 1, '0');
1882          std::string::difference_type        pos = result.size() - 1;
1883          typename base_type::local_limb_type v(*this->limbs());
1884          bool                                neg = false;
1885          if (this->sign())
1886          {
1887             neg = true;
1888          }
1889          while (v)
1890          {
1891             result[pos] = (v % 10) + '0';
1892             --pos;
1893             v /= 10;
1894          }
1895          std::string::size_type n = result.find_first_not_of('0');
1896          result.erase(0, n);
1897          if (result.empty())
1898             result = "0";
1899          if (neg)
1900             result.insert(static_cast<std::string::size_type>(0), 1, '-');
1901          else if (f & std::ios_base::showpos)
1902             result.insert(static_cast<std::string::size_type>(0), 1, '+');
1903       }
1904       return result;
1905    }
do_get_stringboost::multiprecision::backends::cpp_int_backend1906    std::string do_get_string(std::ios_base::fmtflags f, const mpl::true_&) const
1907    {
1908 #ifdef BOOST_MP_NO_DOUBLE_LIMB_TYPE_IO
1909       return do_get_trivial_string(f, mpl::bool_<is_same<typename base_type::local_limb_type, double_limb_type>::value>());
1910 #else
1911       return do_get_trivial_string(f, mpl::bool_<false>());
1912 #endif
1913    }
do_get_stringboost::multiprecision::backends::cpp_int_backend1914    std::string do_get_string(std::ios_base::fmtflags f, const mpl::false_&) const
1915    {
1916       using default_ops::eval_get_sign;
1917       int base = 10;
1918       if ((f & std::ios_base::oct) == std::ios_base::oct)
1919          base = 8;
1920       else if ((f & std::ios_base::hex) == std::ios_base::hex)
1921          base = 16;
1922       std::string result;
1923 
1924       unsigned Bits = this->size() * base_type::limb_bits;
1925 
1926       if (base == 8 || base == 16)
1927       {
1928          if (this->sign())
1929             BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported."));
1930          limb_type       shift = base == 8 ? 3 : 4;
1931          limb_type       mask  = static_cast<limb_type>((1u << shift) - 1);
1932          cpp_int_backend t(*this);
1933          result.assign(Bits / shift + ((Bits % shift) ? 1 : 0), '0');
1934          std::string::difference_type pos      = result.size() - 1;
1935          char                         letter_a = f & std::ios_base::uppercase ? 'A' : 'a';
1936          for (unsigned i = 0; i < Bits / shift; ++i)
1937          {
1938             char c = '0' + static_cast<char>(t.limbs()[0] & mask);
1939             if (c > '9')
1940                c += letter_a - '9' - 1;
1941             result[pos--] = c;
1942             eval_right_shift(t, shift);
1943          }
1944          if (Bits % shift)
1945          {
1946             mask   = static_cast<limb_type>((1u << (Bits % shift)) - 1);
1947             char c = '0' + static_cast<char>(t.limbs()[0] & mask);
1948             if (c > '9')
1949                c += letter_a - '9';
1950             result[pos] = c;
1951          }
1952          //
1953          // Get rid of leading zeros:
1954          //
1955          std::string::size_type n = result.find_first_not_of('0');
1956          if (!result.empty() && (n == std::string::npos))
1957             n = result.size() - 1;
1958          result.erase(0, n);
1959          if (f & std::ios_base::showbase)
1960          {
1961             const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x";
1962             result.insert(static_cast<std::string::size_type>(0), pp);
1963          }
1964       }
1965       else
1966       {
1967          result.assign(Bits / 3 + 1, '0');
1968          std::string::difference_type pos = result.size() - 1;
1969          cpp_int_backend              t(*this);
1970          cpp_int_backend              r;
1971          bool                         neg = false;
1972          if (t.sign())
1973          {
1974             t.negate();
1975             neg = true;
1976          }
1977          if (this->size() == 1)
1978          {
1979             result = boost::lexical_cast<std::string>(t.limbs()[0]);
1980          }
1981          else
1982          {
1983             cpp_int_backend block10;
1984             block10 = max_block_10;
1985             while (eval_get_sign(t) != 0)
1986             {
1987                cpp_int_backend t2;
1988                divide_unsigned_helper(&t2, t, block10, r);
1989                t           = t2;
1990                limb_type v = r.limbs()[0];
1991                for (unsigned i = 0; i < digits_per_block_10; ++i)
1992                {
1993                   char c = '0' + v % 10;
1994                   v /= 10;
1995                   result[pos] = c;
1996                   if (pos-- == 0)
1997                      break;
1998                }
1999             }
2000          }
2001          std::string::size_type n = result.find_first_not_of('0');
2002          result.erase(0, n);
2003          if (result.empty())
2004             result = "0";
2005          if (neg)
2006             result.insert(static_cast<std::string::size_type>(0), 1, '-');
2007          else if (f & std::ios_base::showpos)
2008             result.insert(static_cast<std::string::size_type>(0), 1, '+');
2009       }
2010       return result;
2011    }
2012 
2013  public:
strboost::multiprecision::backends::cpp_int_backend2014    std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f) const
2015    {
2016       return do_get_string(f, trivial_tag());
2017    }
2018 
2019  private:
2020    template <class Container>
construct_from_containerboost::multiprecision::backends::cpp_int_backend2021    void construct_from_container(const Container& c, const mpl::false_&)
2022    {
2023       //
2024       // We assume that c is a sequence of (unsigned) bytes with the most significant byte first:
2025       //
2026       unsigned newsize = static_cast<unsigned>(c.size() / sizeof(limb_type));
2027       if (c.size() % sizeof(limb_type))
2028       {
2029          ++newsize;
2030       }
2031       if (newsize)
2032       {
2033          this->resize(newsize, newsize); // May throw
2034          std::memset(this->limbs(), 0, this->size());
2035          typename Container::const_iterator i(c.begin()), j(c.end());
2036          unsigned                           byte_location = static_cast<unsigned>(c.size() - 1);
2037          while (i != j)
2038          {
2039             unsigned limb  = byte_location / sizeof(limb_type);
2040             unsigned shift = (byte_location % sizeof(limb_type)) * CHAR_BIT;
2041             if (this->size() > limb)
2042                this->limbs()[limb] |= static_cast<limb_type>(static_cast<unsigned char>(*i)) << shift;
2043             ++i;
2044             --byte_location;
2045          }
2046       }
2047    }
2048    template <class Container>
construct_from_containerboost::multiprecision::backends::cpp_int_backend2049    BOOST_MP_CXX14_CONSTEXPR void construct_from_container(const Container& c, const mpl::true_&)
2050    {
2051       //
2052       // We assume that c is a sequence of (unsigned) bytes with the most significant byte first:
2053       //
2054       typedef typename base_type::local_limb_type local_limb_type;
2055       *this->limbs() = 0;
2056       if (c.size())
2057       {
2058          typename Container::const_iterator i(c.begin()), j(c.end());
2059          unsigned                           byte_location = static_cast<unsigned>(c.size() - 1);
2060          while (i != j)
2061          {
2062             unsigned limb  = byte_location / sizeof(local_limb_type);
2063             unsigned shift = (byte_location % sizeof(local_limb_type)) * CHAR_BIT;
2064             if (limb == 0)
2065                this->limbs()[0] |= static_cast<limb_type>(static_cast<unsigned char>(*i)) << shift;
2066             ++i;
2067             --byte_location;
2068          }
2069       }
2070    }
2071 
2072  public:
2073    template <class Container>
cpp_int_backendboost::multiprecision::backends::cpp_int_backend2074    BOOST_MP_CXX14_CONSTEXPR cpp_int_backend(const Container& c, typename boost::enable_if_c<boost::multiprecision::detail::is_byte_container<Container>::value>::type const* = 0)
2075    {
2076       //
2077       // We assume that c is a sequence of (unsigned) bytes with the most significant byte first:
2078       //
2079       construct_from_container(c, trivial_tag());
2080    }
2081    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compare_impboost::multiprecision::backends::cpp_int_backend2082    BOOST_MP_CXX14_CONSTEXPR int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::false_&, const mpl::false_&) const BOOST_NOEXCEPT
2083    {
2084       if (this->sign() != o.sign())
2085          return this->sign() ? -1 : 1;
2086 
2087       // Only do the compare if the same sign:
2088       int result = compare_unsigned(o);
2089 
2090       if (this->sign())
2091          result = -result;
2092       return result;
2093    }
2094    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compare_impboost::multiprecision::backends::cpp_int_backend2095    BOOST_MP_CXX14_CONSTEXPR int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::true_&, const mpl::false_&) const
2096    {
2097       cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> t(*this);
2098       return t.compare(o);
2099    }
2100    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compare_impboost::multiprecision::backends::cpp_int_backend2101    BOOST_MP_CXX14_CONSTEXPR int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::false_&, const mpl::true_&) const
2102    {
2103       cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> t(o);
2104       return compare(t);
2105    }
2106    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compare_impboost::multiprecision::backends::cpp_int_backend2107    BOOST_MP_CXX14_CONSTEXPR int compare_imp(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::true_&, const mpl::true_&) const BOOST_NOEXCEPT
2108    {
2109       if (this->sign())
2110       {
2111          if (o.sign())
2112          {
2113             return *this->limbs() < *o.limbs() ? 1 : (*this->limbs() > *o.limbs() ? -1 : 0);
2114          }
2115          else
2116             return -1;
2117       }
2118       else
2119       {
2120          if (o.sign())
2121             return 1;
2122          return *this->limbs() < *o.limbs() ? -1 : (*this->limbs() > *o.limbs() ? 1 : 0);
2123       }
2124    }
2125    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compareboost::multiprecision::backends::cpp_int_backend2126    BOOST_MP_CXX14_CONSTEXPR int compare(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) const BOOST_NOEXCEPT
2127    {
2128       typedef mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value>      t1;
2129       typedef mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value> t2;
2130       return compare_imp(o, t1(), t2());
2131    }
2132    template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
compare_unsignedboost::multiprecision::backends::cpp_int_backend2133    BOOST_MP_CXX14_CONSTEXPR int compare_unsigned(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) const BOOST_NOEXCEPT
2134    {
2135       if (this->size() != o.size())
2136       {
2137          return this->size() > o.size() ? 1 : -1;
2138       }
2139       typename base_type::const_limb_pointer pa = this->limbs();
2140       typename base_type::const_limb_pointer pb = o.limbs();
2141       for (int i = this->size() - 1; i >= 0; --i)
2142       {
2143          if (pa[i] != pb[i])
2144             return pa[i] > pb[i] ? 1 : -1;
2145       }
2146       return 0;
2147    }
2148    template <class Arithmetic>
compareboost::multiprecision::backends::cpp_int_backend2149    BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if<is_arithmetic<Arithmetic>, int>::type compare(Arithmetic i) const
2150    {
2151       // braindead version:
2152       cpp_int_backend t;
2153       t = i;
2154       return compare(t);
2155    }
2156 };
2157 
2158 } // namespace backends
2159 
2160 namespace default_ops {
2161 
2162 template <class Backend>
2163 struct double_precision_type;
2164 
2165 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
2166 struct double_precision_type<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >
2167 {
2168    typedef typename mpl::if_c<
2169        backends::is_fixed_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
2170        backends::cpp_int_backend<
2171            (is_void<Allocator>::value ? 2 * backends::max_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value
2172                                       : MinBits),
2173            2 * backends::max_precision<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
2174            SignType,
2175            Checked,
2176            Allocator>,
2177        backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::type type;
2178 };
2179 
2180 } // namespace default_ops
2181 
2182 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked>
2183 struct expression_template_default<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, void> >
2184 {
2185    static const expression_template_option value = et_off;
2186 };
2187 
2188 using boost::multiprecision::backends::cpp_int_backend;
2189 
2190 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
2191 struct number_category<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> > : public mpl::int_<number_kind_integer>
2192 {};
2193 
2194 typedef number<cpp_int_backend<> >           cpp_int;
2195 typedef rational_adaptor<cpp_int_backend<> > cpp_rational_backend;
2196 typedef number<cpp_rational_backend>         cpp_rational;
2197 
2198 // Fixed precision unsigned types:
2199 typedef number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> >   uint128_t;
2200 typedef number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> >   uint256_t;
2201 typedef number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> >   uint512_t;
2202 typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> > uint1024_t;
2203 
2204 // Fixed precision signed types:
2205 typedef number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> >   int128_t;
2206 typedef number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> >   int256_t;
2207 typedef number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> >   int512_t;
2208 typedef number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> > int1024_t;
2209 
2210 // Over again, but with checking enabled this time:
2211 typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> >           checked_cpp_int;
2212 typedef rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_rational_backend;
2213 typedef number<checked_cpp_rational_backend>                                checked_cpp_rational;
2214 // Fixed precision unsigned types:
2215 typedef number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> >   checked_uint128_t;
2216 typedef number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> >   checked_uint256_t;
2217 typedef number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> >   checked_uint512_t;
2218 typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> > checked_uint1024_t;
2219 
2220 // Fixed precision signed types:
2221 typedef number<cpp_int_backend<128, 128, signed_magnitude, checked, void> >   checked_int128_t;
2222 typedef number<cpp_int_backend<256, 256, signed_magnitude, checked, void> >   checked_int256_t;
2223 typedef number<cpp_int_backend<512, 512, signed_magnitude, checked, void> >   checked_int512_t;
2224 typedef number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> > checked_int1024_t;
2225 
2226 #ifdef BOOST_NO_SFINAE_EXPR
2227 
2228 namespace detail {
2229 
2230 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>
2231 struct is_explicitly_convertible<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > : public mpl::true_
2232 {};
2233 
2234 } // namespace detail
2235 #endif
2236 
2237 #ifdef _MSC_VER
2238 #pragma warning(pop)
2239 #endif
2240 
2241 }} // namespace boost::multiprecision
2242 
2243 //
2244 // Last of all we include the implementations of all the eval_* non member functions:
2245 //
2246 #include <boost/multiprecision/cpp_int/comparison.hpp>
2247 #include <boost/multiprecision/cpp_int/add.hpp>
2248 #include <boost/multiprecision/cpp_int/multiply.hpp>
2249 #include <boost/multiprecision/cpp_int/divide.hpp>
2250 #include <boost/multiprecision/cpp_int/bitwise.hpp>
2251 #include <boost/multiprecision/cpp_int/misc.hpp>
2252 #include <boost/multiprecision/cpp_int/limits.hpp>
2253 #ifdef BOOST_MP_USER_DEFINED_LITERALS
2254 #include <boost/multiprecision/cpp_int/literals.hpp>
2255 #endif
2256 #include <boost/multiprecision/cpp_int/serialize.hpp>
2257 #include <boost/multiprecision/cpp_int/import_export.hpp>
2258 
2259 #endif
2260