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
6 #ifndef BOOST_MP_CPP_INT_LITERALS_HPP
7 #define BOOST_MP_CPP_INT_LITERALS_HPP
9 #include <boost/multiprecision/cpp_int/cpp_int_config.hpp>
11 namespace boost { namespace multiprecision {
21 static constexpr limb_type value = 0;
26 static constexpr limb_type value = 1;
31 static constexpr limb_type value = 2;
36 static constexpr limb_type value = 3;
41 static constexpr limb_type value = 4;
46 static constexpr limb_type value = 5;
51 static constexpr limb_type value = 6;
56 static constexpr limb_type value = 7;
61 static constexpr limb_type value = 8;
66 static constexpr limb_type value = 9;
71 static constexpr limb_type value = 10;
76 static constexpr limb_type value = 11;
81 static constexpr limb_type value = 12;
86 static constexpr limb_type value = 13;
91 static constexpr limb_type value = 14;
96 static constexpr limb_type value = 15;
101 static constexpr limb_type value = 10;
104 struct hex_value<'B'>
106 static constexpr limb_type value = 11;
109 struct hex_value<'C'>
111 static constexpr limb_type value = 12;
114 struct hex_value<'D'>
116 static constexpr limb_type value = 13;
119 struct hex_value<'E'>
121 static constexpr limb_type value = 14;
124 struct hex_value<'F'>
126 static constexpr limb_type value = 15;
129 template <class Pack, limb_type value>
130 struct combine_value_to_pack;
131 template <limb_type first, limb_type... ARGS, limb_type value>
132 struct combine_value_to_pack<value_pack<first, ARGS...>, value>
134 typedef value_pack<first | value, ARGS...> type;
137 template <char NextChar, char... CHARS>
140 static constexpr unsigned chars_per_limb = sizeof(limb_type) * CHAR_BIT / 4;
141 static constexpr unsigned shift = ((sizeof...(CHARS)) % chars_per_limb) * 4;
142 static constexpr limb_type value_to_add = shift ? hex_value<NextChar>::value << shift : hex_value<NextChar>::value;
144 typedef typename pack_values<CHARS...>::type recursive_packed_type;
145 typedef typename boost::mpl::if_c<shift == 0,
146 typename recursive_packed_type::next_type,
147 recursive_packed_type>::type pack_type;
148 typedef typename combine_value_to_pack<pack_type, value_to_add>::type type;
150 template <char NextChar>
151 struct pack_values<NextChar>
153 static constexpr limb_type value_to_add = hex_value<NextChar>::value;
155 typedef value_pack<value_to_add> type;
159 struct strip_leading_zeros_from_pack;
160 template <limb_type... PACK>
161 struct strip_leading_zeros_from_pack<value_pack<PACK...> >
163 typedef value_pack<PACK...> type;
165 template <limb_type... PACK>
166 struct strip_leading_zeros_from_pack<value_pack<0u, PACK...> >
168 typedef typename strip_leading_zeros_from_pack<value_pack<PACK...> >::type type;
171 template <limb_type v, class PACK>
172 struct append_value_to_pack;
173 template <limb_type v, limb_type... PACK>
174 struct append_value_to_pack<v, value_pack<PACK...> >
176 typedef value_pack<PACK..., v> type;
180 struct reverse_value_pack;
181 template <limb_type v, limb_type... VALUES>
182 struct reverse_value_pack<value_pack<v, VALUES...> >
184 typedef typename reverse_value_pack<value_pack<VALUES...> >::type lead_values;
185 typedef typename append_value_to_pack<v, lead_values>::type type;
187 template <limb_type v>
188 struct reverse_value_pack<value_pack<v> >
190 typedef value_pack<v> type;
193 struct reverse_value_pack<value_pack<> >
195 typedef value_pack<> type;
198 template <char l1, char l2, char... STR>
199 struct make_packed_value_from_str
201 BOOST_STATIC_ASSERT_MSG(l1 == '0', "Multi-precision integer literals must be in hexadecimal notation.");
202 BOOST_STATIC_ASSERT_MSG((l2 == 'X') || (l2 == 'x'), "Multi-precision integer literals must be in hexadecimal notation.");
203 typedef typename pack_values<STR...>::type packed_type;
204 typedef typename strip_leading_zeros_from_pack<packed_type>::type stripped_type;
205 typedef typename reverse_value_pack<stripped_type>::type type;
208 template <class Pack, class B>
209 struct make_backend_from_pack
211 static constexpr Pack p = {};
212 static constexpr B value = p;
215 template <class Pack, class B>
216 constexpr B make_backend_from_pack<Pack, B>::value;
218 template <unsigned Digits>
219 struct signed_cpp_int_literal_result_type
221 static constexpr unsigned bits = Digits * 4;
222 typedef boost::multiprecision::backends::cpp_int_backend<bits, bits, signed_magnitude, unchecked, void> backend_type;
223 typedef number<backend_type, et_off> number_type;
226 template <unsigned Digits>
227 struct unsigned_cpp_int_literal_result_type
229 static constexpr unsigned bits = Digits * 4;
230 typedef boost::multiprecision::backends::cpp_int_backend<bits, bits, unsigned_magnitude, unchecked, void> backend_type;
231 typedef number<backend_type, et_off> number_type;
234 } // namespace detail
236 template <char... STR>
237 constexpr typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::number_type operator"" _cppi()
239 typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;
240 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;
243 template <char... STR>
244 constexpr typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::number_type operator"" _cppui()
246 typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt;
247 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;
250 #define BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(Bits) \
251 template <char... STR> \
252 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)() \
254 typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt; \
255 return boost::multiprecision::literals::detail::make_backend_from_pack< \
257 boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> >::value; \
259 template <char... STR> \
260 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)() \
262 typedef typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type pt; \
263 return boost::multiprecision::literals::detail::make_backend_from_pack< \
265 boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void> >::value; \
268 BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(128)
269 BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(256)
270 BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(512)
271 BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(1024)
273 } // namespace literals
276 // Overload unary minus operator for constexpr use:
278 template <unsigned MinBits, cpp_int_check_type Checked>
279 constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
280 operator-(const number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>& a)
282 return cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>(a.backend(), boost::multiprecision::literals::detail::make_negate_tag());
284 template <unsigned MinBits, cpp_int_check_type Checked>
285 constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
286 operator-(number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>&& a)
288 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());
291 }} // namespace boost::multiprecision
293 #endif // BOOST_MP_CPP_INT_CORE_HPP