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 
6 #ifndef BOOST_MP_CPP_INT_LITERALS_HPP
7 #define BOOST_MP_CPP_INT_LITERALS_HPP
8 
9 #include <boost/multiprecision/cpp_int/cpp_int_config.hpp>
10 
11 namespace boost { namespace multiprecision {
12 
13 namespace literals {
14 namespace detail {
15 
16 template <char>
17 struct hex_value;
18 template <>
19 struct hex_value<'0'>
20 {
21    static constexpr limb_type value = 0;
22 };
23 template <>
24 struct hex_value<'1'>
25 {
26    static constexpr limb_type value = 1;
27 };
28 template <>
29 struct hex_value<'2'>
30 {
31    static constexpr limb_type value = 2;
32 };
33 template <>
34 struct hex_value<'3'>
35 {
36    static constexpr limb_type value = 3;
37 };
38 template <>
39 struct hex_value<'4'>
40 {
41    static constexpr limb_type value = 4;
42 };
43 template <>
44 struct hex_value<'5'>
45 {
46    static constexpr limb_type value = 5;
47 };
48 template <>
49 struct hex_value<'6'>
50 {
51    static constexpr limb_type value = 6;
52 };
53 template <>
54 struct hex_value<'7'>
55 {
56    static constexpr limb_type value = 7;
57 };
58 template <>
59 struct hex_value<'8'>
60 {
61    static constexpr limb_type value = 8;
62 };
63 template <>
64 struct hex_value<'9'>
65 {
66    static constexpr limb_type value = 9;
67 };
68 template <>
69 struct hex_value<'a'>
70 {
71    static constexpr limb_type value = 10;
72 };
73 template <>
74 struct hex_value<'b'>
75 {
76    static constexpr limb_type value = 11;
77 };
78 template <>
79 struct hex_value<'c'>
80 {
81    static constexpr limb_type value = 12;
82 };
83 template <>
84 struct hex_value<'d'>
85 {
86    static constexpr limb_type value = 13;
87 };
88 template <>
89 struct hex_value<'e'>
90 {
91    static constexpr limb_type value = 14;
92 };
93 template <>
94 struct hex_value<'f'>
95 {
96    static constexpr limb_type value = 15;
97 };
98 template <>
99 struct hex_value<'A'>
100 {
101    static constexpr limb_type value = 10;
102 };
103 template <>
104 struct hex_value<'B'>
105 {
106    static constexpr limb_type value = 11;
107 };
108 template <>
109 struct hex_value<'C'>
110 {
111    static constexpr limb_type value = 12;
112 };
113 template <>
114 struct hex_value<'D'>
115 {
116    static constexpr limb_type value = 13;
117 };
118 template <>
119 struct hex_value<'E'>
120 {
121    static constexpr limb_type value = 14;
122 };
123 template <>
124 struct hex_value<'F'>
125 {
126    static constexpr limb_type value = 15;
127 };
128 
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>
133 {
134    typedef value_pack<first | value, ARGS...> type;
135 };
136 
137 template <char NextChar, char... CHARS>
138 struct pack_values
139 {
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;
143 
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;
149 };
150 template <char NextChar>
151 struct pack_values<NextChar>
152 {
153    static constexpr limb_type value_to_add = hex_value<NextChar>::value;
154 
155    typedef value_pack<value_to_add> type;
156 };
157 
158 template <class T>
159 struct strip_leading_zeros_from_pack;
160 template <limb_type... PACK>
161 struct strip_leading_zeros_from_pack<value_pack<PACK...> >
162 {
163    typedef value_pack<PACK...> type;
164 };
165 template <limb_type... PACK>
166 struct strip_leading_zeros_from_pack<value_pack<0u, PACK...> >
167 {
168    typedef typename strip_leading_zeros_from_pack<value_pack<PACK...> >::type type;
169 };
170 
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...> >
175 {
176    typedef value_pack<PACK..., v> type;
177 };
178 
179 template <class T>
180 struct reverse_value_pack;
181 template <limb_type v, limb_type... VALUES>
182 struct reverse_value_pack<value_pack<v, VALUES...> >
183 {
184    typedef typename reverse_value_pack<value_pack<VALUES...> >::type lead_values;
185    typedef typename append_value_to_pack<v, lead_values>::type       type;
186 };
187 template <limb_type v>
188 struct reverse_value_pack<value_pack<v> >
189 {
190    typedef value_pack<v> type;
191 };
192 template <>
193 struct reverse_value_pack<value_pack<> >
194 {
195    typedef value_pack<> type;
196 };
197 
198 template <char l1, char l2, char... STR>
199 struct make_packed_value_from_str
200 {
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;
206 };
207 
208 template <class Pack, class B>
209 struct make_backend_from_pack
210 {
211    static constexpr Pack p  = {};
212    static constexpr B value = p;
213 };
214 
215 template <class Pack, class B>
216 constexpr B make_backend_from_pack<Pack, B>::value;
217 
218 template <unsigned Digits>
219 struct signed_cpp_int_literal_result_type
220 {
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;
224 };
225 
226 template <unsigned Digits>
227 struct unsigned_cpp_int_literal_result_type
228 {
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;
232 };
233 
234 } // namespace detail
235 
236 template <char... STR>
operator ""_cppi()237 constexpr typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::number_type operator"" _cppi()
238 {
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;
241 }
242 
243 template <char... STR>
operator ""_cppui()244 constexpr typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<(sizeof...(STR)) - 2>::number_type operator"" _cppui()
245 {
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;
248 }
249 
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)()    \
253    {                                                                                                                                                                                                                               \
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<                                                                                                                                                      \
256           pt,                                                                                                                                                                                                                      \
257           boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> >::value;                                                                  \
258    }                                                                                                                                                                                                                               \
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)() \
261    {                                                                                                                                                                                                                               \
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<                                                                                                                                                      \
264           pt,                                                                                                                                                                                                                      \
265           boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void> >::value;                                                                \
266    }
267 
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)
272 
273 } // namespace literals
274 
275 //
276 // Overload unary minus operator for constexpr use:
277 //
278 template <unsigned MinBits, cpp_int_check_type Checked>
279 constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
operator -(const number<cpp_int_backend<MinBits,MinBits,signed_magnitude,Checked,void>,et_off> & a)280 operator-(const number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>& a)
281 {
282    return cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>(a.backend(), boost::multiprecision::literals::detail::make_negate_tag());
283 }
284 template <unsigned MinBits, cpp_int_check_type Checked>
285 constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
operator -(number<cpp_int_backend<MinBits,MinBits,signed_magnitude,Checked,void>,et_off> && a)286 operator-(number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>&& a)
287 {
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());
289 }
290 
291 }} // namespace boost::multiprecision
292 
293 #endif // BOOST_MP_CPP_INT_CORE_HPP
294