File indexing completed on 2025-01-18 09:42:14
0001
0002
0003
0004
0005
0006 #ifndef BOOST_MP_CPP_INT_LITERALS_HPP
0007 #define BOOST_MP_CPP_INT_LITERALS_HPP
0008
0009 #include <boost/multiprecision/cpp_int/cpp_int_config.hpp>
0010
0011 namespace boost { namespace multiprecision {
0012
0013 namespace literals {
0014 namespace detail {
0015
0016 template <char>
0017 struct hex_value;
0018 template <>
0019 struct hex_value<'0'>
0020 {
0021 static constexpr limb_type value = 0;
0022 };
0023 template <>
0024 struct hex_value<'1'>
0025 {
0026 static constexpr limb_type value = 1;
0027 };
0028 template <>
0029 struct hex_value<'2'>
0030 {
0031 static constexpr limb_type value = 2;
0032 };
0033 template <>
0034 struct hex_value<'3'>
0035 {
0036 static constexpr limb_type value = 3;
0037 };
0038 template <>
0039 struct hex_value<'4'>
0040 {
0041 static constexpr limb_type value = 4;
0042 };
0043 template <>
0044 struct hex_value<'5'>
0045 {
0046 static constexpr limb_type value = 5;
0047 };
0048 template <>
0049 struct hex_value<'6'>
0050 {
0051 static constexpr limb_type value = 6;
0052 };
0053 template <>
0054 struct hex_value<'7'>
0055 {
0056 static constexpr limb_type value = 7;
0057 };
0058 template <>
0059 struct hex_value<'8'>
0060 {
0061 static constexpr limb_type value = 8;
0062 };
0063 template <>
0064 struct hex_value<'9'>
0065 {
0066 static constexpr limb_type value = 9;
0067 };
0068 template <>
0069 struct hex_value<'a'>
0070 {
0071 static constexpr limb_type value = 10;
0072 };
0073 template <>
0074 struct hex_value<'b'>
0075 {
0076 static constexpr limb_type value = 11;
0077 };
0078 template <>
0079 struct hex_value<'c'>
0080 {
0081 static constexpr limb_type value = 12;
0082 };
0083 template <>
0084 struct hex_value<'d'>
0085 {
0086 static constexpr limb_type value = 13;
0087 };
0088 template <>
0089 struct hex_value<'e'>
0090 {
0091 static constexpr limb_type value = 14;
0092 };
0093 template <>
0094 struct hex_value<'f'>
0095 {
0096 static constexpr limb_type value = 15;
0097 };
0098 template <>
0099 struct hex_value<'A'>
0100 {
0101 static constexpr limb_type value = 10;
0102 };
0103 template <>
0104 struct hex_value<'B'>
0105 {
0106 static constexpr limb_type value = 11;
0107 };
0108 template <>
0109 struct hex_value<'C'>
0110 {
0111 static constexpr limb_type value = 12;
0112 };
0113 template <>
0114 struct hex_value<'D'>
0115 {
0116 static constexpr limb_type value = 13;
0117 };
0118 template <>
0119 struct hex_value<'E'>
0120 {
0121 static constexpr limb_type value = 14;
0122 };
0123 template <>
0124 struct hex_value<'F'>
0125 {
0126 static constexpr limb_type value = 15;
0127 };
0128
0129 template <class Pack, limb_type value>
0130 struct combine_value_to_pack;
0131 template <limb_type first, limb_type... ARGS, limb_type value>
0132 struct combine_value_to_pack<value_pack<first, ARGS...>, value>
0133 {
0134 using type = value_pack<first | value, ARGS...>;
0135 };
0136
0137 template <char NextChar, char... CHARS>
0138 struct pack_values
0139 {
0140 static constexpr std::size_t chars_per_limb = sizeof(limb_type) * CHAR_BIT / 4;
0141 static constexpr std::size_t shift = ((sizeof...(CHARS)) % chars_per_limb) * 4;
0142 static constexpr limb_type value_to_add = shift ? hex_value<NextChar>::value << shift : hex_value<NextChar>::value;
0143
0144 using recursive_packed_type = typename pack_values<CHARS...>::type ;
0145 using pack_type = typename std::conditional<shift == 0,
0146 typename recursive_packed_type::next_type,
0147 recursive_packed_type>::type;
0148 using type = typename combine_value_to_pack<pack_type, value_to_add>::type;
0149 };
0150 template <char NextChar>
0151 struct pack_values<NextChar>
0152 {
0153 static constexpr limb_type value_to_add = hex_value<NextChar>::value;
0154
0155 using type = value_pack<value_to_add>;
0156 };
0157
0158 template <class T>
0159 struct strip_leading_zeros_from_pack;
0160 template <limb_type... PACK>
0161 struct strip_leading_zeros_from_pack<value_pack<PACK...> >
0162 {
0163 using type = value_pack<PACK...>;
0164 };
0165 template <limb_type... PACK>
0166 struct strip_leading_zeros_from_pack<value_pack<0u, PACK...> >
0167 {
0168 using type = typename strip_leading_zeros_from_pack<value_pack<PACK...> >::type;
0169 };
0170
0171 template <limb_type v, class PACK>
0172 struct append_value_to_pack;
0173 template <limb_type v, limb_type... PACK>
0174 struct append_value_to_pack<v, value_pack<PACK...> >
0175 {
0176 using type = value_pack<PACK..., v>;
0177 };
0178
0179 template <class T>
0180 struct reverse_value_pack;
0181 template <limb_type v, limb_type... VALUES>
0182 struct reverse_value_pack<value_pack<v, VALUES...> >
0183 {
0184 using lead_values = typename reverse_value_pack<value_pack<VALUES...> >::type;
0185 using type = typename append_value_to_pack<v, lead_values>::type ;
0186 };
0187 template <limb_type v>
0188 struct reverse_value_pack<value_pack<v> >
0189 {
0190 using type = value_pack<v>;
0191 };
0192 template <>
0193 struct reverse_value_pack<value_pack<> >
0194 {
0195 using type = value_pack<>;
0196 };
0197
0198 template <char l1, char l2, char... STR>
0199 struct make_packed_value_from_str
0200 {
0201 static_assert(l1 == '0', "Multi-precision integer literals must be in hexadecimal notation.");
0202 static_assert((l2 == 'X') || (l2 == 'x'), "Multi-precision integer literals must be in hexadecimal notation.");
0203 using packed_type = typename pack_values<STR...>::type ;
0204 using stripped_type = typename strip_leading_zeros_from_pack<packed_type>::type;
0205 using type = typename reverse_value_pack<stripped_type>::type ;
0206 };
0207
0208 template <class Pack, class B>
0209 struct make_backend_from_pack
0210 {
0211 static constexpr Pack p = {};
0212 static constexpr B value = p;
0213 };
0214
0215 #if !defined(__cpp_inline_variables)
0216 template <class Pack, class B>
0217 constexpr B make_backend_from_pack<Pack, B>::value;
0218 #endif
0219
0220 template <unsigned Digits>
0221 struct signed_cpp_int_literal_result_type
0222 {
0223 static constexpr unsigned bits = Digits * 4;
0224 using backend_type = boost::multiprecision::backends::cpp_int_backend<bits, bits, signed_magnitude, unchecked, void>;
0225 using number_type = number<backend_type, et_off> ;
0226 };
0227
0228 template <unsigned Digits>
0229 struct unsigned_cpp_int_literal_result_type
0230 {
0231 static constexpr unsigned bits = Digits * 4;
0232 using backend_type = boost::multiprecision::backends::cpp_int_backend<bits, bits, unsigned_magnitude, unchecked, void>;
0233 using number_type = number<backend_type, et_off> ;
0234 };
0235
0236 }
0237
0238 template <char... STR>
0239 constexpr typename boost::multiprecision::literals::detail::signed_cpp_int_literal_result_type<static_cast<unsigned>((sizeof...(STR)) - 2u)>::number_type operator"" _cppi()
0240 {
0241 using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type;
0242 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;
0243 }
0244
0245 template <char... STR>
0246 constexpr typename boost::multiprecision::literals::detail::unsigned_cpp_int_literal_result_type<static_cast<unsigned>((sizeof...(STR)) - 2u)>::number_type operator"" _cppui()
0247 {
0248 using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type;
0249 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;
0250 }
0251
0252 #define BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(Bits) \
0253 template <char... STR> \
0254 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)() \
0255 { \
0256 using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type; \
0257 return boost::multiprecision::literals::detail::make_backend_from_pack< \
0258 pt, \
0259 boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> >::value; \
0260 } \
0261 template <char... STR> \
0262 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)() \
0263 { \
0264 using pt = typename boost::multiprecision::literals::detail::make_packed_value_from_str<STR...>::type; \
0265 return boost::multiprecision::literals::detail::make_backend_from_pack< \
0266 pt, \
0267 boost::multiprecision::backends::cpp_int_backend<Bits, Bits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void> >::value; \
0268 }
0269
0270 BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(128)
0271 BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(256)
0272 BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(512)
0273 BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(1024)
0274
0275 }
0276
0277
0278
0279
0280 template <std::size_t MinBits, cpp_int_check_type Checked>
0281 constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
0282 operator-(const number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>& a)
0283 {
0284 return cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>(a.backend(), boost::multiprecision::literals::detail::make_negate_tag());
0285 }
0286 template <std::size_t MinBits, cpp_int_check_type Checked>
0287 constexpr number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>
0288 operator-(number<cpp_int_backend<MinBits, MinBits, signed_magnitude, Checked, void>, et_off>&& a)
0289 {
0290 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());
0291 }
0292
0293 }}
0294
0295 #endif