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