literals.hpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright 2013 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_LITERALS_HPP
  6. #define BOOST_MP_CPP_INT_LITERALS_HPP
  7. #include <boost/multiprecision/cpp_int/cpp_int_config.hpp>
  8. namespace boost{ namespace multiprecision{
  9. namespace literals{ namespace detail{
  10. template <char> struct hex_value;
  11. template <> struct hex_value<'0'> { static constexpr limb_type value = 0; };
  12. template <> struct hex_value<'1'> { static constexpr limb_type value = 1; };
  13. template <> struct hex_value<'2'> { static constexpr limb_type value = 2; };
  14. template <> struct hex_value<'3'> { static constexpr limb_type value = 3; };
  15. template <> struct hex_value<'4'> { static constexpr limb_type value = 4; };
  16. template <> struct hex_value<'5'> { static constexpr limb_type value = 5; };
  17. template <> struct hex_value<'6'> { static constexpr limb_type value = 6; };
  18. template <> struct hex_value<'7'> { static constexpr limb_type value = 7; };
  19. template <> struct hex_value<'8'> { static constexpr limb_type value = 8; };
  20. template <> struct hex_value<'9'> { static constexpr limb_type value = 9; };
  21. template <> struct hex_value<'a'> { static constexpr limb_type value = 10; };
  22. template <> struct hex_value<'b'> { static constexpr limb_type value = 11; };
  23. template <> struct hex_value<'c'> { static constexpr limb_type value = 12; };
  24. template <> struct hex_value<'d'> { static constexpr limb_type value = 13; };
  25. template <> struct hex_value<'e'> { static constexpr limb_type value = 14; };
  26. template <> struct hex_value<'f'> { static constexpr limb_type value = 15; };
  27. template <> struct hex_value<'A'> { static constexpr limb_type value = 10; };
  28. template <> struct hex_value<'B'> { static constexpr limb_type value = 11; };
  29. template <> struct hex_value<'C'> { static constexpr limb_type value = 12; };
  30. template <> struct hex_value<'D'> { static constexpr limb_type value = 13; };
  31. template <> struct hex_value<'E'> { static constexpr limb_type value = 14; };
  32. template <> struct hex_value<'F'> { static constexpr limb_type value = 15; };
  33. template <class Pack, limb_type value>
  34. struct combine_value_to_pack;
  35. template <limb_type first, limb_type...ARGS, limb_type value>
  36. struct combine_value_to_pack<value_pack<first, ARGS...>, value>
  37. {
  38. typedef value_pack<first | value, ARGS...> type;
  39. };
  40. template <char NextChar, char...CHARS>
  41. struct pack_values
  42. {
  43. static constexpr unsigned chars_per_limb = sizeof(limb_type) * CHAR_BIT / 4;
  44. static constexpr unsigned shift = ((sizeof...(CHARS)) % chars_per_limb) * 4;
  45. static constexpr limb_type value_to_add = shift ? hex_value<NextChar>::value << shift : hex_value<NextChar>::value;
  46. typedef typename pack_values<CHARS...>::type recursive_packed_type;
  47. typedef typename boost::mpl::if_c<shift == 0,
  48. typename recursive_packed_type::next_type,
  49. recursive_packed_type>::type pack_type;
  50. typedef typename combine_value_to_pack<pack_type, value_to_add>::type type;
  51. };
  52. template <char NextChar>
  53. struct pack_values<NextChar>
  54. {
  55. static constexpr limb_type value_to_add = hex_value<NextChar>::value;
  56. typedef value_pack<value_to_add> type;
  57. };
  58. template <class T>
  59. struct strip_leading_zeros_from_pack;
  60. template <limb_type...PACK>
  61. struct strip_leading_zeros_from_pack<value_pack<PACK...> >
  62. {
  63. typedef value_pack<PACK...> type;
  64. };
  65. template <limb_type...PACK>
  66. struct strip_leading_zeros_from_pack<value_pack<0u, PACK...> >
  67. {
  68. typedef typename strip_leading_zeros_from_pack<value_pack<PACK...> >::type type;
  69. };
  70. template <limb_type v, class PACK>
  71. struct append_value_to_pack;
  72. template <limb_type v, limb_type...PACK>
  73. struct append_value_to_pack<v, value_pack<PACK...> >
  74. {
  75. typedef value_pack<PACK..., v> type;
  76. };
  77. template <class T>
  78. struct reverse_value_pack;
  79. template <limb_type v, limb_type...VALUES>
  80. struct reverse_value_pack<value_pack<v, VALUES...> >
  81. {
  82. typedef typename reverse_value_pack<value_pack<VALUES...> >::type lead_values;
  83. typedef typename append_value_to_pack<v, lead_values>::type type;
  84. };
  85. template <limb_type v>
  86. struct reverse_value_pack<value_pack<v> >
  87. {
  88. typedef value_pack<v> type;
  89. };
  90. template <>
  91. struct reverse_value_pack<value_pack<> >
  92. {
  93. typedef value_pack<> type;
  94. };
  95. template <char l1, char l2, char...STR>
  96. struct make_packed_value_from_str
  97. {
  98. BOOST_STATIC_ASSERT_MSG(l1 == '0', "Multi-precision integer literals must be in hexadecimal notation.");
  99. BOOST_STATIC_ASSERT_MSG((l2 == 'X') || (l2 == 'x'), "Multi-precision integer literals must be in hexadecimal notation.");
  100. typedef typename pack_values<STR...>::type packed_type;
  101. typedef typename strip_leading_zeros_from_pack<packed_type>::type stripped_type;
  102. typedef typename reverse_value_pack<stripped_type>::type type;
  103. };
  104. template <class Pack, class B>
  105. struct make_backend_from_pack
  106. {
  107. static constexpr Pack p = {};
  108. static constexpr B value = p;
  109. };
  110. template <class Pack, class B>
  111. constexpr B make_backend_from_pack<Pack, B>::value;
  112. template <unsigned Digits>
  113. struct signed_cpp_int_literal_result_type
  114. {
  115. static constexpr unsigned bits = Digits * 4;
  116. typedef boost::multiprecision::backends::cpp_int_backend<bits, bits, signed_magnitude, unchecked, void> backend_type;
  117. typedef number<backend_type, et_off> number_type;
  118. };
  119. template <unsigned Digits>
  120. struct unsigned_cpp_int_literal_result_type
  121. {
  122. static constexpr unsigned bits = Digits * 4;
  123. typedef boost::multiprecision::backends::cpp_int_backend<bits, bits, unsigned_magnitude, unchecked, void> backend_type;
  124. typedef number<backend_type, et_off> number_type;
  125. };
  126. }
  127. template <char... STR>
  128. constexpr typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::number_type operator "" _cppi()
  129. {
  130. typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;
  131. return boost::multiprecision::literals::detail::make_backend_from_pack<pt, typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::backend_type>::value;
  132. }
  133. template <char... STR>
  134. constexpr typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::number_type operator "" _cppui()
  135. {
  136. typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;
  137. return boost::multiprecision::literals::detail::make_backend_from_pack<pt, typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::backend_type>::value;
  138. }
  139. #define BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(Bits)\
  140. template <char... STR> \
  141. constexpr boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> > operator "" BOOST_JOIN(_cppi, Bits)()\
  142. {\
  143. typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;\
  144. return boost::multiprecision::literals::detail::make_backend_from_pack<\
  145. pt, \
  146. boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> \
  147. >::value;\
  148. }\
  149. template <char... STR> \
  150. constexpr boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void> > operator "" BOOST_JOIN(_cppui, Bits)()\
  151. {\
  152. typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;\
  153. return boost::multiprecision::literals::detail::make_backend_from_pack<\
  154. pt, \
  155. boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>\
  156. >::value;\
  157. }\
  158. BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(128)
  159. BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(256)
  160. BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(512)
  161. BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(1024)
  162. }
  163. //
  164. // Overload unary minus operator for constexpr use:
  165. //
  166. template <unsigned MinBits, cpp_int_check_type Checked>
  167. constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
  168. operator - (const number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>& a)
  169. {
  170. return cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>(a.backend(), boost::multiprecision::literals::detail::make_negate_tag());
  171. }
  172. template <unsigned MinBits, cpp_int_check_type Checked>
  173. constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
  174. operator - (number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>&& a)
  175. {
  176. return cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>(static_cast<const number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>&>(a).backend(), boost::multiprecision::literals::detail::make_negate_tag());
  177. }
  178. }} // namespaces
  179. #endif // BOOST_MP_CPP_INT_CORE_HPP