literals.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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 https://www.boost.org/LICENSE_1_0.txt
  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 {
  10. namespace detail {
  11. template <char>
  12. struct hex_value;
  13. template <>
  14. struct hex_value<'0'>
  15. {
  16. static constexpr limb_type value = 0;
  17. };
  18. template <>
  19. struct hex_value<'1'>
  20. {
  21. static constexpr limb_type value = 1;
  22. };
  23. template <>
  24. struct hex_value<'2'>
  25. {
  26. static constexpr limb_type value = 2;
  27. };
  28. template <>
  29. struct hex_value<'3'>
  30. {
  31. static constexpr limb_type value = 3;
  32. };
  33. template <>
  34. struct hex_value<'4'>
  35. {
  36. static constexpr limb_type value = 4;
  37. };
  38. template <>
  39. struct hex_value<'5'>
  40. {
  41. static constexpr limb_type value = 5;
  42. };
  43. template <>
  44. struct hex_value<'6'>
  45. {
  46. static constexpr limb_type value = 6;
  47. };
  48. template <>
  49. struct hex_value<'7'>
  50. {
  51. static constexpr limb_type value = 7;
  52. };
  53. template <>
  54. struct hex_value<'8'>
  55. {
  56. static constexpr limb_type value = 8;
  57. };
  58. template <>
  59. struct hex_value<'9'>
  60. {
  61. static constexpr limb_type value = 9;
  62. };
  63. template <>
  64. struct hex_value<'a'>
  65. {
  66. static constexpr limb_type value = 10;
  67. };
  68. template <>
  69. struct hex_value<'b'>
  70. {
  71. static constexpr limb_type value = 11;
  72. };
  73. template <>
  74. struct hex_value<'c'>
  75. {
  76. static constexpr limb_type value = 12;
  77. };
  78. template <>
  79. struct hex_value<'d'>
  80. {
  81. static constexpr limb_type value = 13;
  82. };
  83. template <>
  84. struct hex_value<'e'>
  85. {
  86. static constexpr limb_type value = 14;
  87. };
  88. template <>
  89. struct hex_value<'f'>
  90. {
  91. static constexpr limb_type value = 15;
  92. };
  93. template <>
  94. struct hex_value<'A'>
  95. {
  96. static constexpr limb_type value = 10;
  97. };
  98. template <>
  99. struct hex_value<'B'>
  100. {
  101. static constexpr limb_type value = 11;
  102. };
  103. template <>
  104. struct hex_value<'C'>
  105. {
  106. static constexpr limb_type value = 12;
  107. };
  108. template <>
  109. struct hex_value<'D'>
  110. {
  111. static constexpr limb_type value = 13;
  112. };
  113. template <>
  114. struct hex_value<'E'>
  115. {
  116. static constexpr limb_type value = 14;
  117. };
  118. template <>
  119. struct hex_value<'F'>
  120. {
  121. static constexpr limb_type value = 15;
  122. };
  123. template <class Pack, limb_type value>
  124. struct combine_value_to_pack;
  125. template <limb_type first, limb_type... ARGS, limb_type value>
  126. struct combine_value_to_pack<value_pack<first, ARGS...>, value>
  127. {
  128. typedef value_pack<first | value, ARGS...> type;
  129. };
  130. template <char NextChar, char... CHARS>
  131. struct pack_values
  132. {
  133. static constexpr unsigned chars_per_limb = sizeof(limb_type) * CHAR_BIT / 4;
  134. static constexpr unsigned shift = ((sizeof...(CHARS)) % chars_per_limb) * 4;
  135. static constexpr limb_type value_to_add = shift ? hex_value<NextChar>::value << shift : hex_value<NextChar>::value;
  136. typedef typename pack_values<CHARS...>::type recursive_packed_type;
  137. typedef typename boost::mpl::if_c<shift == 0,
  138. typename recursive_packed_type::next_type,
  139. recursive_packed_type>::type pack_type;
  140. typedef typename combine_value_to_pack<pack_type, value_to_add>::type type;
  141. };
  142. template <char NextChar>
  143. struct pack_values<NextChar>
  144. {
  145. static constexpr limb_type value_to_add = hex_value<NextChar>::value;
  146. typedef value_pack<value_to_add> type;
  147. };
  148. template <class T>
  149. struct strip_leading_zeros_from_pack;
  150. template <limb_type... PACK>
  151. struct strip_leading_zeros_from_pack<value_pack<PACK...> >
  152. {
  153. typedef value_pack<PACK...> type;
  154. };
  155. template <limb_type... PACK>
  156. struct strip_leading_zeros_from_pack<value_pack<0u, PACK...> >
  157. {
  158. typedef typename strip_leading_zeros_from_pack<value_pack<PACK...> >::type type;
  159. };
  160. template <limb_type v, class PACK>
  161. struct append_value_to_pack;
  162. template <limb_type v, limb_type... PACK>
  163. struct append_value_to_pack<v, value_pack<PACK...> >
  164. {
  165. typedef value_pack<PACK..., v> type;
  166. };
  167. template <class T>
  168. struct reverse_value_pack;
  169. template <limb_type v, limb_type... VALUES>
  170. struct reverse_value_pack<value_pack<v, VALUES...> >
  171. {
  172. typedef typename reverse_value_pack<value_pack<VALUES...> >::type lead_values;
  173. typedef typename append_value_to_pack<v, lead_values>::type type;
  174. };
  175. template <limb_type v>
  176. struct reverse_value_pack<value_pack<v> >
  177. {
  178. typedef value_pack<v> type;
  179. };
  180. template <>
  181. struct reverse_value_pack<value_pack<> >
  182. {
  183. typedef value_pack<> type;
  184. };
  185. template <char l1, char l2, char... STR>
  186. struct make_packed_value_from_str
  187. {
  188. BOOST_STATIC_ASSERT_MSG(l1 == '0', "Multi-precision integer literals must be in hexadecimal notation.");
  189. BOOST_STATIC_ASSERT_MSG((l2 == 'X') || (l2 == 'x'), "Multi-precision integer literals must be in hexadecimal notation.");
  190. typedef typename pack_values<STR...>::type packed_type;
  191. typedef typename strip_leading_zeros_from_pack<packed_type>::type stripped_type;
  192. typedef typename reverse_value_pack<stripped_type>::type type;
  193. };
  194. template <class Pack, class B>
  195. struct make_backend_from_pack
  196. {
  197. static constexpr Pack p = {};
  198. static constexpr B value = p;
  199. };
  200. template <class Pack, class B>
  201. constexpr B make_backend_from_pack<Pack, B>::value;
  202. template <unsigned Digits>
  203. struct signed_cpp_int_literal_result_type
  204. {
  205. static constexpr unsigned bits = Digits * 4;
  206. typedef boost::multiprecision::backends::cpp_int_backend<bits, bits, signed_magnitude, unchecked, void> backend_type;
  207. typedef number<backend_type, et_off> number_type;
  208. };
  209. template <unsigned Digits>
  210. struct unsigned_cpp_int_literal_result_type
  211. {
  212. static constexpr unsigned bits = Digits * 4;
  213. typedef boost::multiprecision::backends::cpp_int_backend<bits, bits, unsigned_magnitude, unchecked, void> backend_type;
  214. typedef number<backend_type, et_off> number_type;
  215. };
  216. } // namespace detail
  217. template <char... STR>
  218. constexpr typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::number_type operator"" _cppi()
  219. {
  220. typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;
  221. 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;
  222. }
  223. template <char... STR>
  224. constexpr typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::number_type operator"" _cppui()
  225. {
  226. typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;
  227. 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;
  228. }
  229. #define BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(Bits) \
  230. template <char... STR> \
  231. 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)() \
  232. { \
  233. typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt; \
  234. return boost::multiprecision::literals::detail::make_backend_from_pack< \
  235. pt, \
  236. boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> >::value; \
  237. } \
  238. template <char... STR> \
  239. 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)() \
  240. { \
  241. typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt; \
  242. return boost::multiprecision::literals::detail::make_backend_from_pack< \
  243. pt, \
  244. boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void> >::value; \
  245. }
  246. BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(128)
  247. BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(256)
  248. BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(512)
  249. BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(1024)
  250. } // namespace literals
  251. //
  252. // Overload unary minus operator for constexpr use:
  253. //
  254. template <unsigned MinBits, cpp_int_check_type Checked>
  255. constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
  256. operator-(const number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>& a)
  257. {
  258. return cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>(a.backend(), boost::multiprecision::literals::detail::make_negate_tag());
  259. }
  260. template <unsigned MinBits, cpp_int_check_type Checked>
  261. constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
  262. operator-(number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>&& a)
  263. {
  264. 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());
  265. }
  266. }} // namespace boost::multiprecision
  267. #endif // BOOST_MP_CPP_INT_CORE_HPP