cpp_int_config.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright 2012 John Maddock. Distributed under the Boost
  3. // Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
  5. #ifndef BOOST_MP_CPP_INT_CORE_HPP
  6. #define BOOST_MP_CPP_INT_CORE_HPP
  7. #include <boost/integer.hpp>
  8. #include <boost/integer_traits.hpp>
  9. #include <boost/mpl/if.hpp>
  10. #include <boost/mpl/int.hpp>
  11. #include <boost/static_assert.hpp>
  12. #include <boost/assert.hpp>
  13. namespace boost{ namespace multiprecision{
  14. namespace detail{
  15. //
  16. // These traits calculate the largest type in the list
  17. // [unsigned] long long, long, int, which has the specified number
  18. // of bits. Note that intN_t and boost::int_t<N> find the first
  19. // member of the above list, not the last. We want the last in the
  20. // list to ensure that mixed arithmetic operations are as efficient
  21. // as possible.
  22. //
  23. template <unsigned N>
  24. struct largest_signed_type
  25. {
  26. typedef typename mpl::if_c<
  27. 1 + std::numeric_limits<long long>::digits == N,
  28. long long,
  29. typename mpl::if_c<
  30. 1 + std::numeric_limits<long>::digits == N,
  31. long,
  32. typename mpl::if_c<
  33. 1 + std::numeric_limits<int>::digits == N,
  34. int,
  35. typename boost::int_t<N>::exact
  36. >::type
  37. >::type
  38. >::type type;
  39. };
  40. template <unsigned N>
  41. struct largest_unsigned_type
  42. {
  43. typedef typename mpl::if_c<
  44. std::numeric_limits<unsigned long long>::digits == N,
  45. unsigned long long,
  46. typename mpl::if_c<
  47. std::numeric_limits<unsigned long>::digits == N,
  48. unsigned long,
  49. typename mpl::if_c<
  50. std::numeric_limits<unsigned int>::digits == N,
  51. unsigned int,
  52. typename boost::uint_t<N>::exact
  53. >::type
  54. >::type
  55. >::type type;
  56. };
  57. } // namespace detail
  58. #if defined(BOOST_HAS_INT128)
  59. typedef detail::largest_unsigned_type<64>::type limb_type;
  60. typedef detail::largest_signed_type<64>::type signed_limb_type;
  61. typedef boost::uint128_type double_limb_type;
  62. typedef boost::int128_type signed_double_limb_type;
  63. static const limb_type max_block_10 = 1000000000000000000uLL;
  64. static const limb_type digits_per_block_10 = 18;
  65. inline limb_type block_multiplier(unsigned count)
  66. {
  67. static const limb_type values[digits_per_block_10]
  68. = { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000 };
  69. BOOST_ASSERT(count < digits_per_block_10);
  70. return values[count];
  71. }
  72. // Can't do formatted IO on an __int128
  73. #define BOOST_MP_NO_DOUBLE_LIMB_TYPE_IO
  74. // Need to specialise integer_traits for __int128 as it's not a normal native type:
  75. } // namespace multiprecision
  76. template<>
  77. class integer_traits<multiprecision::double_limb_type>
  78. : public std::numeric_limits<multiprecision::double_limb_type>,
  79. public detail::integer_traits_base<multiprecision::double_limb_type, 0, ~static_cast<multiprecision::double_limb_type>(0)>
  80. { };
  81. template<>
  82. class integer_traits<multiprecision::signed_double_limb_type>
  83. : public std::numeric_limits<multiprecision::signed_double_limb_type>,
  84. public detail::integer_traits_base<multiprecision::signed_double_limb_type, static_cast<multiprecision::signed_double_limb_type>((static_cast<multiprecision::double_limb_type>(1) << 127)), static_cast<multiprecision::signed_double_limb_type>(((~static_cast<multiprecision::double_limb_type>(0)) >> 1))>
  85. { };
  86. namespace multiprecision{
  87. #else
  88. typedef detail::largest_unsigned_type<32>::type limb_type;
  89. typedef detail::largest_signed_type<32>::type signed_limb_type;
  90. typedef boost::uint64_t double_limb_type;
  91. typedef boost::int64_t signed_double_limb_type;
  92. static const limb_type max_block_10 = 1000000000;
  93. static const limb_type digits_per_block_10 = 9;
  94. inline limb_type block_multiplier(unsigned count)
  95. {
  96. static const limb_type values[digits_per_block_10]
  97. = { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
  98. BOOST_ASSERT(count < digits_per_block_10);
  99. return values[count];
  100. }
  101. #endif
  102. static const unsigned bits_per_limb = sizeof(limb_type) * CHAR_BIT;
  103. template <class T>
  104. inline void minmax(const T& a, const T& b, T& aa, T& bb)
  105. {
  106. if(a < b)
  107. {
  108. aa = a;
  109. bb = b;
  110. }
  111. else
  112. {
  113. aa = b;
  114. bb = a;
  115. }
  116. }
  117. enum cpp_integer_type
  118. {
  119. signed_magnitude = 1,
  120. unsigned_magnitude = 0,
  121. signed_packed = 3,
  122. unsigned_packed = 2
  123. };
  124. enum cpp_int_check_type
  125. {
  126. checked = 1,
  127. unchecked = 0
  128. };
  129. }}
  130. //
  131. // Figure out whether to support user-defined-literals or not:
  132. //
  133. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_USER_DEFINED_LITERALS) \
  134. && !defined(BOOST_NO_CXX11_CONSTEXPR)
  135. # define BOOST_MP_USER_DEFINED_LITERALS
  136. #endif
  137. #endif // BOOST_MP_CPP_INT_CORE_HPP