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. using type = value_pack<first | value, ARGS...>;
  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. using recursive_packed_type = typename pack_values<CHARS...>::type ;
  137. using pack_type = typename std::conditional<shift == 0,
  138. typename recursive_packed_type::next_type,
  139. recursive_packed_type>::type;
  140. using type = typename combine_value_to_pack<pack_type, value_to_add>::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. using type = value_pack<value_to_add>;
  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. using type = value_pack<PACK...>;
  154. };
  155. template <limb_type... PACK>
  156. struct strip_leading_zeros_from_pack<value_pack<0u, PACK...> >
  157. {
  158. using type = typename strip_leading_zeros_from_pack<value_pack<PACK...> >::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. using type = value_pack<PACK..., v>;
  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. using lead_values = typename reverse_value_pack<value_pack<VALUES...> >::type;
  173. using type = typename append_value_to_pack<v, lead_values>::type ;
  174. };
  175. template <limb_type v>
  176. struct reverse_value_pack<value_pack<v> >
  177. {
  178. using type = value_pack<v>;
  179. };
  180. template <>
  181. struct reverse_value_pack<value_pack<> >
  182. {
  183. using type = value_pack<>;
  184. };
  185. template <char l1, char l2, char... STR>
  186. struct make_packed_value_from_str
  187. {
  188. static_assert(l1 == '0', "Multi-precision integer literals must be in hexadecimal notation.");
  189. static_assert((l2 == 'X') || (l2 == 'x'), "Multi-precision integer literals must be in hexadecimal notation.");
  190. using packed_type = typename pack_values<STR...>::type ;
  191. using stripped_type = typename strip_leading_zeros_from_pack<packed_type>::type;
  192. using type = typename reverse_value_pack<stripped_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. using backend_type = boost::multiprecision::backends::cpp_int_backend<bits, bits, signed_magnitude, unchecked, void>;
  207. using number_type = number<backend_type, et_off> ;
  208. };
  209. template <unsigned Digits>
  210. struct unsigned_cpp_int_literal_result_type
  211. {
  212. static constexpr unsigned bits = Digits * 4;
  213. using backend_type = boost::multiprecision::backends::cpp_int_backend<bits, bits, unsigned_magnitude, unchecked, void>;
  214. using number_type = number<backend_type, et_off> ;
  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. using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type;
  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. using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type;
  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. using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type; \
  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. using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type; \
  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