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