annotate DEPENDENCIES/generic/include/boost/multiprecision/cpp_int.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
rev   line source
Chris@16 1 ///////////////////////////////////////////////////////////////
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@16 198 BOOST_CONSTEXPR data_type(signed_limb_type i) : first(i < 0 ? -i : i) {}
Chris@16 199 #ifdef BOOST_LITTLE_ENDIAN
Chris@16 200 BOOST_CONSTEXPR data_type(double_limb_type i) : double_first(i) {}
Chris@16 201 BOOST_CONSTEXPR data_type(signed_double_limb_type i) : double_first(i < 0 ? -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@16 221 : m_data(i), m_limbs(i < 0 ? (static_cast<double_limb_type>(-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@16 258 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 259 std::copy(limbs(), limbs() + size(), stdext::checked_array_iterator<limb_pointer>(pl, cap));
Chris@16 260 #else
Chris@16 261 std::copy(limbs(), limbs() + size(), pl);
Chris@16 262 #endif
Chris@16 263 if(!m_internal)
Chris@16 264 allocator().deallocate(limbs(), capacity());
Chris@16 265 else
Chris@16 266 m_internal = false;
Chris@16 267 m_limbs = new_size;
Chris@16 268 m_data.ld.capacity = cap;
Chris@16 269 m_data.ld.data = pl;
Chris@16 270 }
Chris@16 271 else
Chris@16 272 {
Chris@16 273 m_limbs = new_size;
Chris@16 274 }
Chris@16 275 }
Chris@16 276 BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT
Chris@16 277 {
Chris@16 278 limb_pointer p = limbs();
Chris@16 279 while((m_limbs-1) && !p[m_limbs - 1])--m_limbs;
Chris@16 280 }
Chris@16 281 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_data(), m_limbs(1), m_sign(false), m_internal(true) {}
Chris@16 282 BOOST_MP_FORCEINLINE cpp_int_base(const cpp_int_base& o) : allocator_type(o), m_limbs(0), m_internal(true)
Chris@16 283 {
Chris@16 284 resize(o.size(), o.size());
Chris@16 285 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 286 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size()));
Chris@16 287 #else
Chris@16 288 std::copy(o.limbs(), o.limbs() + o.size(), limbs());
Chris@16 289 #endif
Chris@16 290 m_sign = o.m_sign;
Chris@16 291 }
Chris@16 292 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 293 cpp_int_base(cpp_int_base&& o)
Chris@16 294 : allocator_type(static_cast<Allocator&&>(o)), m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal)
Chris@16 295 {
Chris@16 296 if(m_internal)
Chris@16 297 {
Chris@16 298 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 299 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size()));
Chris@16 300 #else
Chris@16 301 std::copy(o.limbs(), o.limbs() + o.size(), limbs());
Chris@16 302 #endif
Chris@16 303 }
Chris@16 304 else
Chris@16 305 {
Chris@16 306 m_data.ld = o.m_data.ld;
Chris@16 307 o.m_limbs = 0;
Chris@16 308 o.m_internal = true;
Chris@16 309 }
Chris@16 310 }
Chris@16 311 cpp_int_base& operator = (cpp_int_base&& o) BOOST_NOEXCEPT
Chris@16 312 {
Chris@16 313 if(!m_internal)
Chris@16 314 allocator().deallocate(m_data.ld.data, m_data.ld.capacity);
Chris@16 315 *static_cast<Allocator*>(this) = static_cast<Allocator&&>(o);
Chris@16 316 m_limbs = o.m_limbs;
Chris@16 317 m_sign = o.m_sign;
Chris@16 318 m_internal = o.m_internal;
Chris@16 319 if(m_internal)
Chris@16 320 {
Chris@16 321 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 322 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size()));
Chris@16 323 #else
Chris@16 324 std::copy(o.limbs(), o.limbs() + o.size(), limbs());
Chris@16 325 #endif
Chris@16 326 }
Chris@16 327 else
Chris@16 328 {
Chris@16 329 m_data.ld = o.m_data.ld;
Chris@16 330 o.m_limbs = 0;
Chris@16 331 o.m_internal = true;
Chris@16 332 }
Chris@16 333 return *this;
Chris@16 334 }
Chris@16 335 #endif
Chris@16 336 BOOST_MP_FORCEINLINE ~cpp_int_base() BOOST_NOEXCEPT
Chris@16 337 {
Chris@16 338 if(!m_internal)
Chris@16 339 allocator().deallocate(limbs(), capacity());
Chris@16 340 }
Chris@16 341 void assign(const cpp_int_base& o)
Chris@16 342 {
Chris@16 343 if(this != &o)
Chris@16 344 {
Chris@16 345 static_cast<allocator_type&>(*this) = static_cast<const allocator_type&>(o);
Chris@16 346 m_limbs = 0;
Chris@16 347 resize(o.size(), o.size());
Chris@16 348 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 349 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size()));
Chris@16 350 #else
Chris@16 351 std::copy(o.limbs(), o.limbs() + o.size(), limbs());
Chris@16 352 #endif
Chris@16 353 m_sign = o.m_sign;
Chris@16 354 }
Chris@16 355 }
Chris@16 356 BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT
Chris@16 357 {
Chris@16 358 m_sign = !m_sign;
Chris@16 359 // Check for zero value:
Chris@16 360 if(m_sign && (m_limbs == 1))
Chris@16 361 {
Chris@16 362 if(limbs()[0] == 0)
Chris@16 363 m_sign = false;
Chris@16 364 }
Chris@16 365 }
Chris@16 366 BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT
Chris@16 367 {
Chris@16 368 return m_sign;
Chris@16 369 }
Chris@16 370 BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
Chris@16 371 {
Chris@16 372 std::swap(m_data, o.m_data);
Chris@16 373 std::swap(m_sign, o.m_sign);
Chris@16 374 std::swap(m_internal, o.m_internal);
Chris@16 375 std::swap(m_limbs, o.m_limbs);
Chris@16 376 }
Chris@16 377 };
Chris@16 378
Chris@16 379 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
Chris@16 380
Chris@16 381 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
Chris@16 382 const unsigned cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::limb_bits;
Chris@16 383 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
Chris@16 384 const limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::max_limb_value;
Chris@16 385 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
Chris@16 386 const limb_type cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::sign_bit_mask;
Chris@16 387 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
Chris@16 388 const unsigned cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::internal_limb_count;
Chris@16 389 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
Chris@16 390 const bool cpp_int_base<MinBits, MaxBits, signed_magnitude, Checked, Allocator, false>::variable;
Chris@16 391
Chris@16 392 #endif
Chris@16 393
Chris@16 394 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
Chris@16 395 struct cpp_int_base<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator, false> : private Allocator::template rebind<limb_type>::other
Chris@16 396 {
Chris@16 397 //
Chris@16 398 // There is currently no support for unsigned arbitrary precision arithmetic, largely
Chris@16 399 // because it's not clear what subtraction should do:
Chris@16 400 //
Chris@16 401 BOOST_STATIC_ASSERT_MSG(((sizeof(Allocator) == 0) && !is_void<Allocator>::value), "There is curently no support for unsigned arbitrary precision integers.");
Chris@16 402 };
Chris@16 403 //
Chris@16 404 // Fixed precision (i.e. no allocator), signed-magnitude type with limb-usage count:
Chris@16 405 //
Chris@16 406 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 407 struct cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>
Chris@16 408 {
Chris@16 409 typedef limb_type* limb_pointer;
Chris@16 410 typedef const limb_type* const_limb_pointer;
Chris@16 411 typedef mpl::int_<Checked> checked_type;
Chris@16 412
Chris@16 413 //
Chris@16 414 // Interface invariants:
Chris@16 415 //
Chris@16 416 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 417
Chris@16 418 public:
Chris@16 419 BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
Chris@16 420 BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
Chris@16 421 BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1));
Chris@16 422 BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + (MinBits % limb_bits ? 1 : 0));
Chris@16 423 BOOST_STATIC_CONSTANT(bool, variable = false);
Chris@16 424 BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = MinBits % limb_bits ? (limb_type(1) << (MinBits % limb_bits)) -1 : (~limb_type(0)));
Chris@16 425 BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs");
Chris@16 426
Chris@16 427 private:
Chris@16 428 union data_type{
Chris@16 429 limb_type m_data[internal_limb_count];
Chris@16 430 limb_type m_first_limb;
Chris@16 431 double_limb_type m_double_first_limb;
Chris@16 432
Chris@16 433 BOOST_CONSTEXPR data_type() : m_first_limb(0) {}
Chris@16 434 BOOST_CONSTEXPR data_type(limb_type i) : m_first_limb(i) {}
Chris@16 435 BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i) {}
Chris@16 436 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
Chris@16 437 template <limb_type...VALUES>
Chris@16 438 BOOST_CONSTEXPR data_type(literals::detail::value_pack<VALUES...>) : m_data{ VALUES... } {}
Chris@16 439 #endif
Chris@16 440 } m_wrapper;
Chris@16 441 boost::uint16_t m_limbs;
Chris@16 442 bool m_sign;
Chris@16 443
Chris@16 444 public:
Chris@16 445 //
Chris@16 446 // Direct construction:
Chris@16 447 //
Chris@16 448 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT
Chris@16 449 : m_wrapper(i), m_limbs(1), m_sign(false) {}
Chris@16 450 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT
Chris@16 451 : m_wrapper(limb_type(i < 0 ? -i : i)), m_limbs(1), m_sign(i < 0) {}
Chris@16 452 #if defined(BOOST_LITTLE_ENDIAN)
Chris@16 453 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT
Chris@16 454 : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false) {}
Chris@16 455 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT
Chris@16 456 : m_wrapper(double_limb_type(i < 0 ? -i : i)),
Chris@16 457 m_limbs(i < 0 ? (static_cast<double_limb_type>(-i) > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)),
Chris@16 458 m_sign(i < 0) {}
Chris@16 459 #endif
Chris@16 460 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
Chris@16 461 template <limb_type...VALUES>
Chris@16 462 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<VALUES...> i)
Chris@16 463 : m_wrapper(i), m_limbs(sizeof...(VALUES)), m_sign(false) {}
Chris@16 464 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<> i)
Chris@16 465 : m_wrapper(i), m_limbs(1), m_sign(false) {}
Chris@16 466 BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& a, const literals::detail::negate_tag&)
Chris@16 467 : 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 468 #endif
Chris@16 469 //
Chris@16 470 // Helper functions for getting at our internal data, and manipulating storage:
Chris@16 471 //
Chris@16 472 BOOST_MP_FORCEINLINE unsigned size()const BOOST_NOEXCEPT { return m_limbs; }
Chris@16 473 BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return m_wrapper.m_data; }
Chris@16 474 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return m_wrapper.m_data; }
Chris@16 475 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign()const BOOST_NOEXCEPT { return m_sign; }
Chris@16 476 BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT
Chris@16 477 {
Chris@16 478 m_sign = b;
Chris@16 479 // Check for zero value:
Chris@16 480 if(m_sign && (m_limbs == 1))
Chris@16 481 {
Chris@16 482 if(limbs()[0] == 0)
Chris@16 483 m_sign = false;
Chris@16 484 }
Chris@16 485 }
Chris@16 486 BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 487 {
Chris@16 488 m_limbs = static_cast<boost::uint16_t>((std::min)(new_size, internal_limb_count));
Chris@16 489 detail::verify_new_size(m_limbs, min_size, checked_type());
Chris@16 490 }
Chris@16 491 BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 492 {
Chris@16 493 limb_pointer p = limbs();
Chris@16 494 detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count-1], upper_limb_mask, checked_type());
Chris@16 495 p[internal_limb_count-1] &= upper_limb_mask;
Chris@16 496 while((m_limbs-1) && !p[m_limbs - 1])--m_limbs;
Chris@16 497 if((m_limbs == 1) && (!*p)) m_sign = false; // zero is always unsigned
Chris@16 498 }
Chris@16 499
Chris@16 500 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() : m_wrapper(limb_type(0u)), m_limbs(1), m_sign(false) {}
Chris@16 501 // Defaulted functions:
Chris@16 502 //BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& i)BOOST_NOEXCEPT;
Chris@16 503 //~cpp_int_base() BOOST_NOEXCEPT {}
Chris@16 504
Chris@16 505 void assign(const cpp_int_base& o) BOOST_NOEXCEPT
Chris@16 506 {
Chris@16 507 if(this != &o)
Chris@16 508 {
Chris@16 509 resize(o.size(), o.size());
Chris@16 510 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 511 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size()));
Chris@16 512 #else
Chris@16 513 std::copy(o.limbs(), o.limbs() + o.size(), limbs());
Chris@16 514 #endif
Chris@16 515 m_sign = o.m_sign;
Chris@16 516 }
Chris@16 517 }
Chris@16 518 BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT
Chris@16 519 {
Chris@16 520 m_sign = !m_sign;
Chris@16 521 // Check for zero value:
Chris@16 522 if(m_sign && (m_limbs == 1))
Chris@16 523 {
Chris@16 524 if(limbs()[0] == 0)
Chris@16 525 m_sign = false;
Chris@16 526 }
Chris@16 527 }
Chris@16 528 BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT
Chris@16 529 {
Chris@16 530 return m_sign;
Chris@16 531 }
Chris@16 532 BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
Chris@16 533 {
Chris@16 534 for(unsigned i = 0; i < (std::max)(size(), o.size()); ++i)
Chris@16 535 std::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]);
Chris@16 536 std::swap(m_sign, o.m_sign);
Chris@16 537 std::swap(m_limbs, o.m_limbs);
Chris@16 538 }
Chris@16 539 };
Chris@16 540 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
Chris@16 541
Chris@16 542 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 543 const unsigned cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::limb_bits;
Chris@16 544 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 545 const limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::max_limb_value;
Chris@16 546 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 547 const limb_type cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::sign_bit_mask;
Chris@16 548 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 549 const unsigned cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::internal_limb_count;
Chris@16 550 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 551 const bool cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>::variable;
Chris@16 552
Chris@16 553 #endif
Chris@16 554 //
Chris@16 555 // Fixed precision (i.e. no allocator), unsigned type with limb-usage count:
Chris@16 556 //
Chris@16 557 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 558 struct cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>
Chris@16 559 {
Chris@16 560 typedef limb_type* limb_pointer;
Chris@16 561 typedef const limb_type* const_limb_pointer;
Chris@16 562 typedef mpl::int_<Checked> checked_type;
Chris@16 563
Chris@16 564 //
Chris@16 565 // Interface invariants:
Chris@16 566 //
Chris@16 567 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 568
Chris@16 569 public:
Chris@16 570 BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
Chris@16 571 BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
Chris@16 572 BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1));
Chris@16 573 BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + (MinBits % limb_bits ? 1 : 0));
Chris@16 574 BOOST_STATIC_CONSTANT(bool, variable = false);
Chris@16 575 BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = MinBits % limb_bits ? (limb_type(1) << (MinBits % limb_bits)) -1 : (~limb_type(0)));
Chris@16 576 BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs");
Chris@16 577
Chris@16 578 private:
Chris@16 579 union data_type{
Chris@16 580 limb_type m_data[internal_limb_count];
Chris@16 581 limb_type m_first_limb;
Chris@16 582 double_limb_type m_double_first_limb;
Chris@16 583
Chris@16 584 BOOST_CONSTEXPR data_type() : m_first_limb(0) {}
Chris@16 585 BOOST_CONSTEXPR data_type(limb_type i) : m_first_limb(i) {}
Chris@16 586 BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i) {}
Chris@16 587 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
Chris@16 588 template <limb_type...VALUES>
Chris@16 589 BOOST_CONSTEXPR data_type(literals::detail::value_pack<VALUES...>) : m_data{ VALUES... } {}
Chris@16 590 #endif
Chris@16 591 } m_wrapper;
Chris@16 592 limb_type m_limbs;
Chris@16 593
Chris@16 594 public:
Chris@16 595 //
Chris@16 596 // Direct construction:
Chris@16 597 //
Chris@16 598 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT
Chris@16 599 : m_wrapper(i), m_limbs(1) {}
Chris@16 600 BOOST_MP_FORCEINLINE cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 601 : m_wrapper(limb_type(i < 0 ? -i : i)), m_limbs(1) { if(i < 0) negate(); }
Chris@16 602 #ifdef BOOST_LITTLE_ENDIAN
Chris@16 603 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT
Chris@16 604 : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1) {}
Chris@16 605 BOOST_MP_FORCEINLINE cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 606 : m_wrapper(double_limb_type(i < 0 ? -i : i)), m_limbs(i < 0 ? (-i > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)) { if(i < 0) negate(); }
Chris@16 607 #endif
Chris@16 608 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
Chris@16 609 template <limb_type...VALUES>
Chris@16 610 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<VALUES...> i)
Chris@16 611 : m_wrapper(i), m_limbs(sizeof...(VALUES)) {}
Chris@16 612 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>)
Chris@16 613 : m_wrapper(static_cast<limb_type>(0u)), m_limbs(1) {}
Chris@16 614 #endif
Chris@16 615 //
Chris@16 616 // Helper functions for getting at our internal data, and manipulating storage:
Chris@16 617 //
Chris@16 618 BOOST_MP_FORCEINLINE unsigned size()const BOOST_NOEXCEPT { return m_limbs; }
Chris@16 619 BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return m_wrapper.m_data; }
Chris@16 620 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return m_wrapper.m_data; }
Chris@16 621 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign()const BOOST_NOEXCEPT { return false; }
Chris@16 622 BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT_IF((Checked == unchecked)) { if(b) negate(); }
Chris@16 623 BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size) BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 624 {
Chris@16 625 m_limbs = (std::min)(new_size, internal_limb_count);
Chris@16 626 detail::verify_new_size(m_limbs, min_size, checked_type());
Chris@16 627 }
Chris@16 628 BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 629 {
Chris@16 630 limb_pointer p = limbs();
Chris@16 631 detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count-1], upper_limb_mask, checked_type());
Chris@16 632 p[internal_limb_count-1] &= upper_limb_mask;
Chris@16 633 while((m_limbs-1) && !p[m_limbs - 1])--m_limbs;
Chris@16 634 }
Chris@16 635
Chris@16 636 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT
Chris@16 637 : m_wrapper(limb_type(0u)), m_limbs(1) {}
Chris@16 638 // Defaulted functions:
Chris@16 639 //BOOST_MP_FORCEINLINE cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT;
Chris@16 640 //~cpp_int_base() BOOST_NOEXCEPT {}
Chris@16 641
Chris@16 642 BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT
Chris@16 643 {
Chris@16 644 if(this != &o)
Chris@16 645 {
Chris@16 646 resize(o.size(), o.size());
Chris@16 647 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 648 std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size()));
Chris@16 649 #else
Chris@16 650 std::copy(o.limbs(), o.limbs() + o.size(), limbs());
Chris@16 651 #endif
Chris@16 652 }
Chris@16 653 }
Chris@16 654 private:
Chris@16 655 void check_negate(const mpl::int_<checked>&)
Chris@16 656 {
Chris@16 657 BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned number."));
Chris@16 658 }
Chris@16 659 void check_negate(const mpl::int_<unchecked>&){}
Chris@16 660 public:
Chris@16 661 void negate() BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 662 {
Chris@16 663 // Not so much a negate as a complement - this gets called when subtraction
Chris@16 664 // would result in a "negative" number:
Chris@16 665 unsigned i;
Chris@16 666 if((m_limbs == 1) && (m_wrapper.m_data[0] == 0))
Chris@16 667 return; // negating zero is always zero, and always OK.
Chris@16 668 check_negate(checked_type());
Chris@16 669 for(i = m_limbs; i < internal_limb_count; ++i)
Chris@16 670 m_wrapper.m_data[i] = 0;
Chris@16 671 m_limbs = internal_limb_count;
Chris@16 672 for(i = 0; i < internal_limb_count; ++i)
Chris@16 673 m_wrapper.m_data[i] = ~m_wrapper.m_data[i];
Chris@16 674 normalize();
Chris@16 675 eval_increment(static_cast<cpp_int_backend<MinBits, MinBits, unsigned_magnitude, Checked, void>& >(*this));
Chris@16 676 }
Chris@16 677 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool isneg()const BOOST_NOEXCEPT
Chris@16 678 {
Chris@16 679 return false;
Chris@16 680 }
Chris@16 681 BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
Chris@16 682 {
Chris@16 683 for(unsigned i = 0; i < (std::max)(size(), o.size()); ++i)
Chris@16 684 std::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]);
Chris@16 685 std::swap(m_limbs, o.m_limbs);
Chris@16 686 }
Chris@16 687 };
Chris@16 688 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
Chris@16 689
Chris@16 690 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 691 const unsigned cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::limb_bits;
Chris@16 692 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 693 const limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::max_limb_value;
Chris@16 694 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 695 const limb_type cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::sign_bit_mask;
Chris@16 696 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 697 const unsigned cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::internal_limb_count;
Chris@16 698 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 699 const bool cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>::variable;
Chris@16 700
Chris@16 701 #endif
Chris@16 702 //
Chris@16 703 // Traits classes to figure out a native type with N bits, these vary from boost::uint_t<N> only
Chris@16 704 // because some platforms have native integer types longer than long long, "really long long" anyone??
Chris@16 705 //
Chris@16 706 template <unsigned N, bool s>
Chris@16 707 struct trivial_limb_type_imp
Chris@16 708 {
Chris@16 709 typedef double_limb_type type;
Chris@16 710 };
Chris@16 711
Chris@16 712 template <unsigned N>
Chris@16 713 struct trivial_limb_type_imp<N, true>
Chris@16 714 {
Chris@16 715 typedef typename boost::uint_t<N>::least type;
Chris@16 716 };
Chris@16 717
Chris@16 718 template <unsigned N>
Chris@16 719 struct trivial_limb_type : public trivial_limb_type_imp<N, N <= sizeof(long long) * CHAR_BIT> {};
Chris@16 720 //
Chris@16 721 // Backend for fixed precision signed-magnitude type which will fit entirely inside a "double_limb_type":
Chris@16 722 //
Chris@16 723 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 724 struct cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, true>
Chris@16 725 {
Chris@16 726 typedef typename trivial_limb_type<MinBits>::type local_limb_type;
Chris@16 727 typedef local_limb_type* limb_pointer;
Chris@16 728 typedef const local_limb_type* const_limb_pointer;
Chris@16 729 typedef mpl::int_<Checked> checked_type;
Chris@16 730 protected:
Chris@16 731 BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT);
Chris@16 732 BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = (MinBits < limb_bits) ? local_limb_type((local_limb_type(~local_limb_type(0))) >> (limb_bits - MinBits)) : local_limb_type(~local_limb_type(0)));
Chris@16 733 private:
Chris@16 734 local_limb_type m_data;
Chris@16 735 bool m_sign;
Chris@16 736
Chris@16 737 //
Chris@16 738 // Interface invariants:
Chris@16 739 //
Chris@16 740 BOOST_STATIC_ASSERT_MSG(MinBits <= sizeof(double_limb_type) * CHAR_BIT, "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?");
Chris@16 741 protected:
Chris@16 742 template <class T>
Chris@16 743 typename boost::disable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= (int)MinBits)>::type
Chris@16 744 check_in_range(T val, const mpl::int_<checked>&)
Chris@16 745 {
Chris@16 746 BOOST_MP_USING_ABS
Chris@16 747 typedef typename common_type<T, local_limb_type>::type common_type;
Chris@16 748
Chris@16 749 if(static_cast<common_type>(abs(val)) > static_cast<common_type>(limb_mask))
Chris@16 750 BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
Chris@16 751 }
Chris@16 752 template <class T, int C>
Chris@16 753 void check_in_range(T, const mpl::int_<C>&){}
Chris@16 754
Chris@16 755 template <class T>
Chris@16 756 void check_in_range(T val)
Chris@16 757 {
Chris@16 758 check_in_range(val, checked_type());
Chris@16 759 }
Chris@16 760
Chris@16 761 public:
Chris@16 762 //
Chris@16 763 // Direct construction:
Chris@16 764 //
Chris@16 765 template <class SI>
Chris@16 766 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((Checked == unchecked))
Chris@16 767 : m_data(i < 0 ? static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(-i)) & limb_mask : static_cast<local_limb_type>(i) & limb_mask), m_sign(i < 0) {}
Chris@16 768 template <class SI>
Chris@16 769 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((Checked == unchecked))
Chris@16 770 : m_data(i < 0 ? static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(-i) & limb_mask) : static_cast<local_limb_type>(i) & limb_mask), m_sign(i < 0) { check_in_range(i); }
Chris@16 771 template <class UI>
Chris@16 772 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_IF((Checked == unchecked))
Chris@16 773 : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) {}
Chris@16 774 template <class UI>
Chris@16 775 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((Checked == unchecked))
Chris@16 776 : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) { check_in_range(i); }
Chris@16 777 template <class F>
Chris@16 778 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_IF((Checked == unchecked))
Chris@16 779 : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask), m_sign(i < 0) {}
Chris@16 780 template <class F>
Chris@16 781 BOOST_MP_FORCEINLINE cpp_int_base(F i, typename boost::enable_if_c<is_floating_point<F>::value && (Checked == checked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 782 : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask), m_sign(i < 0) { check_in_range(i); }
Chris@16 783 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
Chris@16 784 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>)
Chris@16 785 : m_data(static_cast<local_limb_type>(0u)), m_sign(false) {}
Chris@16 786 template <limb_type a>
Chris@16 787 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a>)
Chris@16 788 : m_data(static_cast<local_limb_type>(a)), m_sign(false) {}
Chris@16 789 template <limb_type a, limb_type b>
Chris@16 790 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a, b>)
Chris@16 791 : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)), m_sign(false) {}
Chris@16 792 BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& a, const literals::detail::negate_tag&)
Chris@16 793 : m_data(a.m_data), m_sign(a.m_data ? !a.m_sign : false) {}
Chris@16 794 #endif
Chris@16 795 //
Chris@16 796 // Helper functions for getting at our internal data, and manipulating storage:
Chris@16 797 //
Chris@16 798 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned size()const BOOST_NOEXCEPT { return 1; }
Chris@16 799 BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return &m_data; }
Chris@16 800 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return &m_data; }
Chris@16 801 BOOST_MP_FORCEINLINE bool sign()const BOOST_NOEXCEPT { return m_sign; }
Chris@16 802 BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT
Chris@16 803 {
Chris@16 804 m_sign = b;
Chris@16 805 // Check for zero value:
Chris@16 806 if(m_sign && !m_data)
Chris@16 807 {
Chris@16 808 m_sign = false;
Chris@16 809 }
Chris@16 810 }
Chris@16 811 BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size)
Chris@16 812 {
Chris@16 813 detail::verify_new_size(2, min_size, checked_type());
Chris@16 814 }
Chris@16 815 BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 816 {
Chris@16 817 if(!m_data)
Chris@16 818 m_sign = false; // zero is always unsigned
Chris@16 819 detail::verify_limb_mask(true, m_data, limb_mask, checked_type());
Chris@16 820 m_data &= limb_mask;
Chris@16 821 }
Chris@16 822
Chris@16 823 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() : m_data(0), m_sign(false) {}
Chris@16 824 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
Chris@16 825 : m_data(o.m_data), m_sign(o.m_sign) {}
Chris@16 826 //~cpp_int_base() BOOST_NOEXCEPT {}
Chris@16 827 BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT
Chris@16 828 {
Chris@16 829 m_data = o.m_data;
Chris@16 830 m_sign = o.m_sign;
Chris@16 831 }
Chris@16 832 BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT
Chris@16 833 {
Chris@16 834 m_sign = !m_sign;
Chris@16 835 // Check for zero value:
Chris@16 836 if(m_data == 0)
Chris@16 837 {
Chris@16 838 m_sign = false;
Chris@16 839 }
Chris@16 840 }
Chris@16 841 BOOST_MP_FORCEINLINE bool isneg()const BOOST_NOEXCEPT
Chris@16 842 {
Chris@16 843 return m_sign;
Chris@16 844 }
Chris@16 845 BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
Chris@16 846 {
Chris@16 847 std::swap(m_sign, o.m_sign);
Chris@16 848 std::swap(m_data, o.m_data);
Chris@16 849 }
Chris@16 850 };
Chris@16 851 //
Chris@16 852 // Backend for unsigned fixed precision (i.e. no allocator) type which will fit entirely inside a "double_limb_type":
Chris@16 853 //
Chris@16 854 template <unsigned MinBits, cpp_int_check_type Checked>
Chris@16 855 struct cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, true>
Chris@16 856 {
Chris@16 857 typedef typename trivial_limb_type<MinBits>::type local_limb_type;
Chris@16 858 typedef local_limb_type* limb_pointer;
Chris@16 859 typedef const local_limb_type* const_limb_pointer;
Chris@16 860 private:
Chris@16 861 BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT);
Chris@16 862 BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = limb_bits != MinBits ?
Chris@16 863 static_cast<local_limb_type>(static_cast<local_limb_type>(~local_limb_type(0)) >> (limb_bits - MinBits))
Chris@16 864 : static_cast<local_limb_type>(~local_limb_type(0)));
Chris@16 865
Chris@16 866 local_limb_type m_data;
Chris@16 867
Chris@16 868 typedef mpl::int_<Checked> checked_type;
Chris@16 869
Chris@16 870 //
Chris@16 871 // Interface invariants:
Chris@16 872 //
Chris@16 873 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 874 protected:
Chris@16 875 template <class T>
Chris@16 876 typename boost::disable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::digits <= (int)MinBits)>::type
Chris@16 877 check_in_range(T val, const mpl::int_<checked>&, const mpl::false_&)
Chris@16 878 {
Chris@16 879 typedef typename common_type<T, local_limb_type>::type common_type;
Chris@16 880
Chris@16 881 if(static_cast<common_type>(val) > limb_mask)
Chris@16 882 BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
Chris@16 883 }
Chris@16 884 template <class T>
Chris@16 885 void check_in_range(T val, const mpl::int_<checked>&, const mpl::true_&)
Chris@16 886 {
Chris@16 887 typedef typename common_type<T, local_limb_type>::type common_type;
Chris@16 888
Chris@16 889 if(static_cast<common_type>(val) > limb_mask)
Chris@16 890 BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
Chris@16 891 if(val < 0)
Chris@16 892 BOOST_THROW_EXCEPTION(std::range_error("The argument to an unsigned cpp_int constructor was negative."));
Chris@16 893 }
Chris@16 894 template <class T, int C, bool B>
Chris@16 895 BOOST_MP_FORCEINLINE void check_in_range(T, const mpl::int_<C>&, const mpl::bool_<B>&){}
Chris@16 896
Chris@16 897 template <class T>
Chris@16 898 BOOST_MP_FORCEINLINE void check_in_range(T val)
Chris@16 899 {
Chris@16 900 check_in_range(val, checked_type(), is_signed<T>());
Chris@16 901 }
Chris@16 902
Chris@16 903 public:
Chris@16 904 //
Chris@16 905 // Direct construction:
Chris@16 906 //
Chris@16 907 template <class SI>
Chris@16 908 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((Checked == unchecked))
Chris@16 909 : m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i)) & limb_mask : static_cast<local_limb_type>(i) & limb_mask) {}
Chris@16 910 template <class SI>
Chris@16 911 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((Checked == unchecked))
Chris@16 912 : m_data(i < 0 ? 1 + ~static_cast<local_limb_type>(-i) : static_cast<local_limb_type>(i)) { check_in_range(i); }
Chris@16 913 template <class UI>
Chris@16 914 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_IF((Checked == unchecked))
Chris@16 915 : m_data(static_cast<local_limb_type>(i) & limb_mask) {}
Chris@16 916 template <class UI>
Chris@16 917 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((Checked == unchecked))
Chris@16 918 : m_data(static_cast<local_limb_type>(i)) { check_in_range(i); }
Chris@16 919 template <class F>
Chris@16 920 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 921 : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask)
Chris@16 922 {
Chris@16 923 check_in_range(i);
Chris@16 924 if(i < 0)
Chris@16 925 negate();
Chris@16 926 }
Chris@16 927 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
Chris@16 928 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>)
Chris@16 929 : m_data(static_cast<local_limb_type>(0u)) {}
Chris@16 930 template <limb_type a>
Chris@16 931 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a>)
Chris@16 932 : m_data(static_cast<local_limb_type>(a)) {}
Chris@16 933 template <limb_type a, limb_type b>
Chris@16 934 BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<a, b>)
Chris@16 935 : m_data(static_cast<local_limb_type>(a) | (static_cast<local_limb_type>(b) << bits_per_limb)) {}
Chris@16 936 #endif
Chris@16 937 //
Chris@16 938 // Helper functions for getting at our internal data, and manipulating storage:
Chris@16 939 //
Chris@16 940 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR unsigned size()const BOOST_NOEXCEPT { return 1; }
Chris@16 941 BOOST_MP_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return &m_data; }
Chris@16 942 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const_limb_pointer limbs()const BOOST_NOEXCEPT { return &m_data; }
Chris@16 943 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool sign()const BOOST_NOEXCEPT { return false; }
Chris@16 944 BOOST_MP_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 945 {
Chris@16 946 if(b)
Chris@16 947 negate();
Chris@16 948 }
Chris@16 949 BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size)
Chris@16 950 {
Chris@16 951 detail::verify_new_size(2, min_size, checked_type());
Chris@16 952 }
Chris@16 953 BOOST_MP_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 954 {
Chris@16 955 detail::verify_limb_mask(true, m_data, limb_mask, checked_type());
Chris@16 956 m_data &= limb_mask;
Chris@16 957 }
Chris@16 958
Chris@16 959 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() : m_data(0) {}
Chris@16 960 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT
Chris@16 961 : m_data(o.m_data) {}
Chris@16 962 //~cpp_int_base() BOOST_NOEXCEPT {}
Chris@16 963 BOOST_MP_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT
Chris@16 964 {
Chris@16 965 m_data = o.m_data;
Chris@16 966 }
Chris@16 967 BOOST_MP_FORCEINLINE void negate() BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 968 {
Chris@16 969 if(Checked == checked)
Chris@16 970 {
Chris@16 971 BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned type."));
Chris@16 972 }
Chris@16 973 m_data = ~m_data;
Chris@16 974 ++m_data;
Chris@16 975 }
Chris@16 976 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool isneg()const BOOST_NOEXCEPT
Chris@16 977 {
Chris@16 978 return false;
Chris@16 979 }
Chris@16 980 BOOST_MP_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT
Chris@16 981 {
Chris@16 982 std::swap(m_data, o.m_data);
Chris@16 983 }
Chris@16 984 };
Chris@16 985 //
Chris@16 986 // Traits class, lets us know whether type T can be directly converted to the base type,
Chris@16 987 // used to enable/disable constructors etc:
Chris@16 988 //
Chris@16 989 template <class Arg, class Base>
Chris@16 990 struct is_allowed_cpp_int_base_conversion : public mpl::if_c<
Chris@16 991 is_same<Arg, limb_type>::value || is_same<Arg, signed_limb_type>::value
Chris@16 992 #ifdef BOOST_LITTLE_ENDIAN
Chris@16 993 || is_same<Arg, double_limb_type>::value || is_same<Arg, signed_double_limb_type>::value
Chris@16 994 #endif
Chris@16 995 #if defined(BOOST_MP_USER_DEFINED_LITERALS)
Chris@16 996 || literals::detail::is_value_pack<Arg>::value
Chris@16 997 #endif
Chris@16 998 || (is_trivial_cpp_int<Base>::value && is_arithmetic<Arg>::value),
Chris@16 999 mpl::true_,
Chris@16 1000 mpl::false_
Chris@16 1001 >::type
Chris@16 1002 {};
Chris@16 1003 //
Chris@16 1004 // Now the actual backend, normalising parameters passed to the base class:
Chris@16 1005 //
Chris@16 1006 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
Chris@16 1007 struct cpp_int_backend
Chris@16 1008 : public cpp_int_base<
Chris@16 1009 min_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
Chris@16 1010 max_precision<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
Chris@16 1011 SignType,
Chris@16 1012 Checked,
Chris@16 1013 Allocator,
Chris@16 1014 is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value>
Chris@16 1015 {
Chris@16 1016 typedef cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> self_type;
Chris@16 1017 typedef cpp_int_base<
Chris@16 1018 min_precision<self_type>::value,
Chris@16 1019 max_precision<self_type>::value,
Chris@16 1020 SignType,
Chris@16 1021 Checked,
Chris@16 1022 Allocator,
Chris@16 1023 is_trivial_cpp_int<self_type>::value> base_type;
Chris@16 1024 typedef mpl::bool_<is_trivial_cpp_int<self_type>::value> trivial_tag;
Chris@16 1025 public:
Chris@16 1026 typedef typename mpl::if_<
Chris@16 1027 trivial_tag,
Chris@16 1028 mpl::list<
Chris@16 1029 signed char, short, int, long,
Chris@16 1030 long long, signed_double_limb_type>,
Chris@16 1031 mpl::list<signed_limb_type, signed_double_limb_type>
Chris@16 1032 >::type signed_types;
Chris@16 1033 typedef typename mpl::if_<
Chris@16 1034 trivial_tag,
Chris@16 1035 mpl::list<unsigned char, unsigned short, unsigned,
Chris@16 1036 unsigned long long, double_limb_type>,
Chris@16 1037 mpl::list<limb_type, double_limb_type>
Chris@16 1038 >::type unsigned_types;
Chris@16 1039 typedef typename mpl::if_<
Chris@16 1040 trivial_tag,
Chris@16 1041 mpl::list<float, double, long double>,
Chris@16 1042 mpl::list<long double>
Chris@16 1043 >::type float_types;
Chris@16 1044 typedef mpl::int_<Checked> checked_type;
Chris@16 1045
Chris@16 1046 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend() BOOST_NOEXCEPT{}
Chris@16 1047 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 1048 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 1049 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(cpp_int_backend&& o) BOOST_NOEXCEPT
Chris@16 1050 : base_type(static_cast<base_type&&>(o)) {}
Chris@16 1051 #endif
Chris@16 1052 //
Chris@16 1053 // Direct construction from arithmetic type:
Chris@16 1054 //
Chris@16 1055 template <class Arg>
Chris@16 1056 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((Checked == unchecked) && boost::is_void<Allocator>::value)
Chris@16 1057 : base_type(i) {}
Chris@16 1058
Chris@16 1059 private:
Chris@16 1060 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
Chris@16 1061 void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::true_ const&, mpl::true_ const &)
Chris@16 1062 {
Chris@16 1063 // Assigning trivial type to trivial type:
Chris@16 1064 this->check_in_range(*other.limbs());
Chris@16 1065 *this->limbs() = static_cast<typename self_type::local_limb_type>(*other.limbs());
Chris@16 1066 this->sign(other.sign());
Chris@16 1067 this->normalize();
Chris@16 1068 }
Chris@16 1069 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
Chris@16 1070 void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::true_ const&, mpl::false_ const &)
Chris@16 1071 {
Chris@16 1072 // non-trivial to trivial narrowing conversion:
Chris@16 1073 double_limb_type v = *other.limbs();
Chris@16 1074 if(other.size() > 1)
Chris@16 1075 {
Chris@16 1076 v |= static_cast<double_limb_type>(other.limbs()[1]) << bits_per_limb;
Chris@16 1077 if((Checked == checked) && (other.size() > 2))
Chris@16 1078 {
Chris@16 1079 BOOST_THROW_EXCEPTION(std::range_error("Assignment of a cpp_int that is out of range for the target type."));
Chris@16 1080 }
Chris@16 1081 }
Chris@16 1082 *this = v;
Chris@16 1083 this->sign(other.sign());
Chris@16 1084 this->normalize();
Chris@16 1085 }
Chris@16 1086 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
Chris@16 1087 void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::false_ const&, mpl::true_ const &)
Chris@16 1088 {
Chris@16 1089 // trivial to non-trivial, treat the trivial argument as if it were an unsigned arithmetic type, then set the sign afterwards:
Chris@16 1090 *this = static_cast<
Chris@16 1091 typename boost::multiprecision::detail::canonical<
Chris@16 1092 typename cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::local_limb_type,
Chris@16 1093 cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>
Chris@16 1094 >::type
Chris@16 1095 >(*other.limbs());
Chris@16 1096 this->sign(other.sign());
Chris@16 1097 }
Chris@16 1098 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
Chris@16 1099 void do_assign(const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other, mpl::false_ const&, mpl::false_ const &)
Chris@16 1100 {
Chris@16 1101 // regular non-trivial to non-trivial assign:
Chris@16 1102 this->resize(other.size(), other.size());
Chris@16 1103 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
Chris@16 1104 std::copy(other.limbs(), other.limbs() + (std::min)(other.size(), this->size()), stdext::checked_array_iterator<limb_pointer>(this->limbs(), this->size()));
Chris@16 1105 #else
Chris@16 1106 std::copy(other.limbs(), other.limbs() + (std::min)(other.size(), this->size()), this->limbs());
Chris@16 1107 #endif
Chris@16 1108 this->sign(other.sign());
Chris@16 1109 this->normalize();
Chris@16 1110 }
Chris@16 1111 public:
Chris@16 1112 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
Chris@16 1113 cpp_int_backend(
Chris@16 1114 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other,
Chris@16 1115 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 1116 : base_type()
Chris@16 1117 {
Chris@16 1118 do_assign(
Chris@16 1119 other,
Chris@16 1120 mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
Chris@16 1121 mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
Chris@16 1122 }
Chris@16 1123 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
Chris@16 1124 explicit cpp_int_backend(
Chris@16 1125 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other,
Chris@16 1126 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 1127 : base_type()
Chris@16 1128 {
Chris@16 1129 do_assign(
Chris@16 1130 other,
Chris@16 1131 mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
Chris@16 1132 mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
Chris@16 1133 }
Chris@16 1134 template <unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
Chris@16 1135 cpp_int_backend& operator=(
Chris@16 1136 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& other)
Chris@16 1137 {
Chris@16 1138 do_assign(
Chris@16 1139 other,
Chris@16 1140 mpl::bool_<is_trivial_cpp_int<self_type>::value>(),
Chris@16 1141 mpl::bool_<is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>());
Chris@16 1142 return *this;
Chris@16 1143 }
Chris@16 1144 #ifdef BOOST_MP_USER_DEFINED_LITERALS
Chris@16 1145 BOOST_CONSTEXPR cpp_int_backend(const cpp_int_backend& a, const literals::detail::negate_tag& tag)
Chris@16 1146 : base_type(static_cast<const base_type&>(a), tag){}
Chris@16 1147 #endif
Chris@16 1148
Chris@16 1149 BOOST_MP_FORCEINLINE cpp_int_backend& operator = (const cpp_int_backend& o) BOOST_NOEXCEPT_IF((Checked == unchecked) && boost::is_void<Allocator>::value)
Chris@16 1150 {
Chris@16 1151 this->assign(o);
Chris@16 1152 return *this;
Chris@16 1153 }
Chris@16 1154 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 1155 BOOST_MP_FORCEINLINE cpp_int_backend& operator = (cpp_int_backend&& o) BOOST_NOEXCEPT_IF(boost::is_void<Allocator>::value)
Chris@16 1156 {
Chris@16 1157 *static_cast<base_type*>(this) = static_cast<base_type&&>(o);
Chris@16 1158 return *this;
Chris@16 1159 }
Chris@16 1160 #endif
Chris@16 1161 private:
Chris@16 1162 template <class A>
Chris@16 1163 typename boost::enable_if<is_unsigned<A> >::type do_assign_arithmetic(A val, const mpl::true_&)
Chris@16 1164 {
Chris@16 1165 this->check_in_range(val);
Chris@16 1166 *this->limbs() = static_cast<typename self_type::local_limb_type>(val);
Chris@16 1167 this->normalize();
Chris@16 1168 }
Chris@16 1169 template <class A>
Chris@16 1170 typename boost::disable_if<is_unsigned<A> >::type do_assign_arithmetic(A val, const mpl::true_&)
Chris@16 1171 {
Chris@16 1172 typedef typename make_signed<typename self_type::local_limb_type>::type signed_limb_type;
Chris@16 1173 this->check_in_range(val);
Chris@16 1174 *this->limbs() = (val < 0) ? static_cast<typename self_type::local_limb_type>(-static_cast<signed_limb_type>(val)) : static_cast<typename self_type::local_limb_type>(val);
Chris@16 1175 this->sign(val < 0);
Chris@16 1176 this->normalize();
Chris@16 1177 }
Chris@16 1178 BOOST_MP_FORCEINLINE void do_assign_arithmetic(limb_type i, const mpl::false_&) BOOST_NOEXCEPT
Chris@16 1179 {
Chris@16 1180 this->resize(1, 1);
Chris@16 1181 *this->limbs() = i;
Chris@16 1182 this->sign(false);
Chris@16 1183 }
Chris@16 1184 BOOST_MP_FORCEINLINE void do_assign_arithmetic(signed_limb_type i, const mpl::false_&) BOOST_NOEXCEPT_IF((Checked == unchecked))
Chris@16 1185 {
Chris@16 1186 this->resize(1, 1);
Chris@16 1187 *this->limbs() = static_cast<limb_type>(std::abs(i));
Chris@16 1188 this->sign(i < 0);
Chris@16 1189 }
Chris@16 1190 void do_assign_arithmetic(double_limb_type i, const mpl::false_&)
Chris@16 1191 {
Chris@16 1192 BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type));
Chris@16 1193 BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2);
Chris@16 1194 typename base_type::limb_pointer p = this->limbs();
Chris@16 1195 *p = static_cast<limb_type>(i);
Chris@16 1196 p[1] = static_cast<limb_type>(i >> base_type::limb_bits);
Chris@16 1197 this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1);
Chris@16 1198 this->sign(false);
Chris@16 1199 }
Chris@16 1200 void do_assign_arithmetic(signed_double_limb_type i, const mpl::false_&)
Chris@16 1201 {
Chris@16 1202 BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type));
Chris@16 1203 BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2);
Chris@16 1204 bool s = false;
Chris@16 1205 if(i < 0)
Chris@16 1206 {
Chris@16 1207 s = true;
Chris@16 1208 i = -i;
Chris@16 1209 }
Chris@16 1210 else
Chris@16 1211 this->sign(false);
Chris@16 1212 typename base_type::limb_pointer p = this->limbs();
Chris@16 1213 *p = static_cast<limb_type>(i);
Chris@16 1214 p[1] = static_cast<limb_type>(i >> 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@16 1266 BOOST_MP_FORCEINLINE cpp_int_backend& operator = (Arithmetic val)
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@16 1275 *this->limbs() = 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@16 1433 typedef typename mpl::if_c<sizeof(*this->limbs()) == 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@16 1494 result.insert(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@16 1518 result.insert(0, 1, '-');
Chris@16 1519 else if(f & std::ios_base::showpos)
Chris@16 1520 result.insert(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@16 1579 result.insert(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@16 1623 result.insert(0, 1, '-');
Chris@16 1624 else if(f & std::ios_base::showpos)
Chris@16 1625 result.insert(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@16 1766 typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_int;
Chris@16 1767 typedef rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_rational_backend;
Chris@16 1768 typedef number<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