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