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

source code of boost/boost/multiprecision/cpp_int.hpp