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