]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////// |
2 | // Copyright 2013 John Maddock. Distributed under the Boost | |
3 | // Software License, Version 1.0. (See accompanying file | |
92f5a8d4 | 4 | // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt |
7c673cae FG |
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 | ||
92f5a8d4 TL |
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 | }; | |
7c673cae FG |
128 | |
129 | template <class Pack, limb_type value> | |
130 | struct combine_value_to_pack; | |
92f5a8d4 | 131 | template <limb_type first, limb_type... ARGS, limb_type value> |
7c673cae FG |
132 | struct combine_value_to_pack<value_pack<first, ARGS...>, value> |
133 | { | |
1e59de90 | 134 | using type = value_pack<first | value, ARGS...>; |
7c673cae FG |
135 | }; |
136 | ||
92f5a8d4 | 137 | template <char NextChar, char... CHARS> |
7c673cae FG |
138 | struct pack_values |
139 | { | |
1e59de90 TL |
140 | static constexpr std::size_t chars_per_limb = sizeof(limb_type) * CHAR_BIT / 4; |
141 | static constexpr std::size_t shift = ((sizeof...(CHARS)) % chars_per_limb) * 4; | |
92f5a8d4 | 142 | static constexpr limb_type value_to_add = shift ? hex_value<NextChar>::value << shift : hex_value<NextChar>::value; |
7c673cae | 143 | |
1e59de90 TL |
144 | using recursive_packed_type = typename pack_values<CHARS...>::type ; |
145 | using pack_type = typename std::conditional<shift == 0, | |
92f5a8d4 | 146 | typename recursive_packed_type::next_type, |
1e59de90 TL |
147 | recursive_packed_type>::type; |
148 | using type = typename combine_value_to_pack<pack_type, value_to_add>::type; | |
7c673cae FG |
149 | }; |
150 | template <char NextChar> | |
151 | struct pack_values<NextChar> | |
152 | { | |
153 | static constexpr limb_type value_to_add = hex_value<NextChar>::value; | |
154 | ||
1e59de90 | 155 | using type = value_pack<value_to_add>; |
7c673cae FG |
156 | }; |
157 | ||
158 | template <class T> | |
159 | struct strip_leading_zeros_from_pack; | |
92f5a8d4 | 160 | template <limb_type... PACK> |
7c673cae FG |
161 | struct strip_leading_zeros_from_pack<value_pack<PACK...> > |
162 | { | |
1e59de90 | 163 | using type = value_pack<PACK...>; |
7c673cae | 164 | }; |
92f5a8d4 | 165 | template <limb_type... PACK> |
7c673cae FG |
166 | struct strip_leading_zeros_from_pack<value_pack<0u, PACK...> > |
167 | { | |
1e59de90 | 168 | using type = typename strip_leading_zeros_from_pack<value_pack<PACK...> >::type; |
7c673cae FG |
169 | }; |
170 | ||
171 | template <limb_type v, class PACK> | |
172 | struct append_value_to_pack; | |
92f5a8d4 | 173 | template <limb_type v, limb_type... PACK> |
7c673cae FG |
174 | struct append_value_to_pack<v, value_pack<PACK...> > |
175 | { | |
1e59de90 | 176 | using type = value_pack<PACK..., v>; |
7c673cae FG |
177 | }; |
178 | ||
179 | template <class T> | |
180 | struct reverse_value_pack; | |
92f5a8d4 | 181 | template <limb_type v, limb_type... VALUES> |
7c673cae FG |
182 | struct reverse_value_pack<value_pack<v, VALUES...> > |
183 | { | |
1e59de90 TL |
184 | using lead_values = typename reverse_value_pack<value_pack<VALUES...> >::type; |
185 | using type = typename append_value_to_pack<v, lead_values>::type ; | |
7c673cae FG |
186 | }; |
187 | template <limb_type v> | |
188 | struct reverse_value_pack<value_pack<v> > | |
189 | { | |
1e59de90 | 190 | using type = value_pack<v>; |
7c673cae FG |
191 | }; |
192 | template <> | |
193 | struct reverse_value_pack<value_pack<> > | |
194 | { | |
1e59de90 | 195 | using type = value_pack<>; |
7c673cae FG |
196 | }; |
197 | ||
92f5a8d4 | 198 | template <char l1, char l2, char... STR> |
7c673cae FG |
199 | struct make_packed_value_from_str |
200 | { | |
1e59de90 TL |
201 | static_assert(l1 == '0', "Multi-precision integer literals must be in hexadecimal notation."); |
202 | static_assert((l2 == 'X') || (l2 == 'x'), "Multi-precision integer literals must be in hexadecimal notation."); | |
203 | using packed_type = typename pack_values<STR...>::type ; | |
204 | using stripped_type = typename strip_leading_zeros_from_pack<packed_type>::type; | |
205 | using type = typename reverse_value_pack<stripped_type>::type ; | |
7c673cae FG |
206 | }; |
207 | ||
208 | template <class Pack, class B> | |
209 | struct make_backend_from_pack | |
210 | { | |
92f5a8d4 | 211 | static constexpr Pack p = {}; |
7c673cae FG |
212 | static constexpr B value = p; |
213 | }; | |
214 | ||
f51cf556 | 215 | #if !defined(__cpp_inline_variables) |
7c673cae FG |
216 | template <class Pack, class B> |
217 | constexpr B make_backend_from_pack<Pack, B>::value; | |
f51cf556 | 218 | #endif |
7c673cae FG |
219 | |
220 | template <unsigned Digits> | |
221 | struct signed_cpp_int_literal_result_type | |
222 | { | |
92f5a8d4 | 223 | static constexpr unsigned bits = Digits * 4; |
1e59de90 TL |
224 | using backend_type = boost::multiprecision::backends::cpp_int_backend<bits, bits, signed_magnitude, unchecked, void>; |
225 | using number_type = number<backend_type, et_off> ; | |
7c673cae FG |
226 | }; |
227 | ||
228 | template <unsigned Digits> | |
229 | struct unsigned_cpp_int_literal_result_type | |
230 | { | |
92f5a8d4 | 231 | static constexpr unsigned bits = Digits * 4; |
1e59de90 TL |
232 | using backend_type = boost::multiprecision::backends::cpp_int_backend<bits, bits, unsigned_magnitude, unchecked, void>; |
233 | using number_type = number<backend_type, et_off> ; | |
7c673cae FG |
234 | }; |
235 | ||
92f5a8d4 | 236 | } // namespace detail |
7c673cae FG |
237 | |
238 | template <char... STR> | |
f51cf556 | 239 | constexpr typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<static_cast<unsigned>((sizeof...(STR)) - 2u)>::number_type operator"" _cppi() |
7c673cae | 240 | { |
1e59de90 | 241 | using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type; |
f51cf556 | 242 | return boost::multiprecision::literals::detail::make_backend_from_pack<pt, typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<static_cast<unsigned>((sizeof...(STR)) - 2u)>::backend_type>::value; |
7c673cae FG |
243 | } |
244 | ||
245 | template <char... STR> | |
f51cf556 | 246 | constexpr typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<static_cast<unsigned>((sizeof...(STR)) - 2u)>::number_type operator"" _cppui() |
7c673cae | 247 | { |
1e59de90 | 248 | using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type; |
f51cf556 | 249 | return boost::multiprecision::literals::detail::make_backend_from_pack<pt, typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<static_cast<unsigned>((sizeof...(STR)) - 2u)>::backend_type>::value; |
7c673cae FG |
250 | } |
251 | ||
92f5a8d4 TL |
252 | #define BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(Bits) \ |
253 | template <char... STR> \ | |
254 | 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)() \ | |
255 | { \ | |
1e59de90 | 256 | using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type; \ |
92f5a8d4 TL |
257 | return boost::multiprecision::literals::detail::make_backend_from_pack< \ |
258 | pt, \ | |
259 | boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> >::value; \ | |
260 | } \ | |
261 | template <char... STR> \ | |
262 | 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)() \ | |
263 | { \ | |
1e59de90 | 264 | using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type; \ |
92f5a8d4 TL |
265 | return boost::multiprecision::literals::detail::make_backend_from_pack< \ |
266 | pt, \ | |
267 | boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void> >::value; \ | |
268 | } | |
7c673cae FG |
269 | |
270 | BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(128) | |
271 | BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(256) | |
272 | BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(512) | |
273 | BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(1024) | |
274 | ||
92f5a8d4 | 275 | } // namespace literals |
7c673cae FG |
276 | |
277 | // | |
278 | // Overload unary minus operator for constexpr use: | |
279 | // | |
1e59de90 | 280 | template <std::size_t MinBits, cpp_int_check_type Checked> |
7c673cae | 281 | constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off> |
92f5a8d4 | 282 | operator-(const number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>& a) |
7c673cae FG |
283 | { |
284 | return cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>(a.backend(), boost::multiprecision::literals::detail::make_negate_tag()); | |
285 | } | |
1e59de90 | 286 | template <std::size_t MinBits, cpp_int_check_type Checked> |
7c673cae | 287 | constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off> |
92f5a8d4 | 288 | operator-(number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>&& a) |
7c673cae FG |
289 | { |
290 | 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 | } | |
292 | ||
92f5a8d4 | 293 | }} // namespace boost::multiprecision |
7c673cae FG |
294 | |
295 | #endif // BOOST_MP_CPP_INT_CORE_HPP |