annotate DEPENDENCIES/generic/include/boost/multiprecision/cpp_int.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
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