File indexing completed on 2025-04-19 08:19:40
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_CHARCONV_DETAIL_EMULATED128_HPP
0009 #define BOOST_CHARCONV_DETAIL_EMULATED128_HPP
0010
0011 #include <boost/charconv/detail/config.hpp>
0012 #include <boost/charconv/config.hpp>
0013 #include <boost/core/bit.hpp>
0014 #include <type_traits>
0015 #include <limits>
0016 #include <cstdint>
0017 #include <cassert>
0018 #include <cmath>
0019
0020 namespace boost { namespace charconv { namespace detail {
0021
0022
0023
0024
0025
0026
0027
0028 struct trivial_uint128
0029 {
0030 #if BOOST_CHARCONV_ENDIAN_LITTLE_BYTE
0031 std::uint64_t low;
0032 std::uint64_t high;
0033 #else
0034 std::uint64_t high;
0035 std::uint64_t low;
0036 #endif
0037 };
0038
0039
0040 struct uint128
0041 {
0042 std::uint64_t high;
0043 std::uint64_t low;
0044
0045
0046 constexpr uint128() noexcept : high {}, low {} {}
0047
0048 constexpr uint128(const uint128& v) noexcept = default;
0049
0050 constexpr uint128(uint128&& v) noexcept = default;
0051
0052 constexpr uint128(std::uint64_t high_, std::uint64_t low_) noexcept : high {high_}, low {low_} {}
0053
0054 constexpr uint128(const trivial_uint128& v) noexcept : high {v.high}, low {v.low} {}
0055
0056 constexpr uint128(trivial_uint128&& v) noexcept : high {v.high}, low {v.low} {}
0057
0058 #define SIGNED_CONSTRUCTOR(expr) constexpr uint128(expr v) noexcept : high {v < 0 ? UINT64_MAX : UINT64_C(0)}, low {static_cast<std::uint64_t>(v)} {}
0059 #define UNSIGNED_CONSTRUCTOR(expr) constexpr uint128(expr v) noexcept : high {}, low {static_cast<std::uint64_t>(v)} {}
0060
0061 SIGNED_CONSTRUCTOR(char)
0062 SIGNED_CONSTRUCTOR(signed char)
0063 SIGNED_CONSTRUCTOR(short)
0064 SIGNED_CONSTRUCTOR(int)
0065 SIGNED_CONSTRUCTOR(long)
0066 SIGNED_CONSTRUCTOR(long long)
0067
0068 UNSIGNED_CONSTRUCTOR(unsigned char)
0069 UNSIGNED_CONSTRUCTOR(unsigned short)
0070 UNSIGNED_CONSTRUCTOR(unsigned)
0071 UNSIGNED_CONSTRUCTOR(unsigned long)
0072 UNSIGNED_CONSTRUCTOR(unsigned long long)
0073
0074 #ifdef BOOST_CHARCONV_HAS_INT128
0075 constexpr uint128(boost::int128_type v) noexcept :
0076 high {static_cast<std::uint64_t>(v >> 64)},
0077 low {static_cast<std::uint64_t>(static_cast<boost::uint128_type>(v) & ~UINT64_C(0))} {}
0078
0079 constexpr uint128(boost::uint128_type v) noexcept :
0080 high {static_cast<std::uint64_t>(v >> 64)},
0081 low {static_cast<std::uint64_t>(v & ~UINT64_C(0))} {}
0082 #endif
0083
0084 #undef SIGNED_CONSTRUCTOR
0085 #undef UNSIGNED_CONSTRUCTOR
0086
0087
0088 #define SIGNED_ASSIGNMENT_OPERATOR(expr) BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const expr& v) noexcept { high = v < 0 ? UINT64_MAX : UINT64_C(0); low = static_cast<std::uint64_t>(v); return *this; }
0089 #define UNSIGNED_ASSIGNMENT_OPERATOR(expr) BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const expr& v) noexcept { high = 0U; low = static_cast<std::uint64_t>(v); return *this; }
0090
0091 SIGNED_ASSIGNMENT_OPERATOR(char)
0092 SIGNED_ASSIGNMENT_OPERATOR(signed char)
0093 SIGNED_ASSIGNMENT_OPERATOR(short)
0094 SIGNED_ASSIGNMENT_OPERATOR(int)
0095 SIGNED_ASSIGNMENT_OPERATOR(long)
0096 SIGNED_ASSIGNMENT_OPERATOR(long long)
0097
0098 UNSIGNED_ASSIGNMENT_OPERATOR(unsigned char)
0099 UNSIGNED_ASSIGNMENT_OPERATOR(unsigned short)
0100 UNSIGNED_ASSIGNMENT_OPERATOR(unsigned)
0101 UNSIGNED_ASSIGNMENT_OPERATOR(unsigned long)
0102 UNSIGNED_ASSIGNMENT_OPERATOR(unsigned long long)
0103
0104 #ifdef BOOST_CHARCONV_HAS_INT128
0105 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const boost::int128_type& v) noexcept { *this = uint128(v); return *this; }
0106 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const boost::uint128_type& v) noexcept { *this = uint128(v); return *this; }
0107 #endif
0108
0109 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const trivial_uint128& v) noexcept { this->low = v.low; this->high = v.high; return *this; }
0110
0111 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator=(const uint128&) noexcept;
0112
0113 #undef SIGNED_ASSIGNMENT_OPERATOR
0114 #undef UNSIGNED_ASSIGNMENT_OPERATOR
0115
0116
0117 #define INTEGER_CONVERSION_OPERATOR(expr) explicit constexpr operator expr() const noexcept { return static_cast<expr>(low); }
0118 #define FLOAT_CONVERSION_OPERATOR(expr) explicit operator expr() const noexcept { return std::ldexp(static_cast<expr>(high), 64) + static_cast<expr>(low); }
0119
0120 INTEGER_CONVERSION_OPERATOR(char)
0121 INTEGER_CONVERSION_OPERATOR(signed char)
0122 INTEGER_CONVERSION_OPERATOR(short)
0123 INTEGER_CONVERSION_OPERATOR(int)
0124 INTEGER_CONVERSION_OPERATOR(long)
0125 INTEGER_CONVERSION_OPERATOR(long long)
0126 INTEGER_CONVERSION_OPERATOR(unsigned char)
0127 INTEGER_CONVERSION_OPERATOR(unsigned short)
0128 INTEGER_CONVERSION_OPERATOR(unsigned)
0129 INTEGER_CONVERSION_OPERATOR(unsigned long)
0130 INTEGER_CONVERSION_OPERATOR(unsigned long long)
0131
0132 explicit constexpr operator bool() const noexcept { return high || low; }
0133
0134 #ifdef BOOST_CHARCONV_HAS_INT128
0135 explicit constexpr operator boost::int128_type() const noexcept { return (static_cast<boost::int128_type>(high) << 64) + low; }
0136 explicit constexpr operator boost::uint128_type() const noexcept { return (static_cast<boost::uint128_type>(high) << 64) + low; }
0137 #endif
0138
0139 FLOAT_CONVERSION_OPERATOR(float)
0140 FLOAT_CONVERSION_OPERATOR(double)
0141 FLOAT_CONVERSION_OPERATOR(long double)
0142
0143 #undef INTEGER_CONVERSION_OPERATOR
0144 #undef FLOAT_CONVERSION_OPERATOR
0145
0146
0147 constexpr friend uint128 operator-(uint128 val) noexcept;
0148 constexpr friend uint128 operator+(uint128 val) noexcept;
0149
0150
0151
0152
0153 #define INTEGER_OPERATOR_EQUAL(expr) constexpr friend bool operator==(uint128 lhs, expr rhs) noexcept { return lhs.high == 0 && rhs >= 0 && lhs.low == static_cast<std::uint64_t>(rhs); }
0154 #define UNSIGNED_INTEGER_OPERATOR_EQUAL(expr) constexpr friend bool operator==(uint128 lhs, expr rhs) noexcept { return lhs.high == 0 && lhs.low == static_cast<std::uint64_t>(rhs); }
0155
0156 INTEGER_OPERATOR_EQUAL(char)
0157 INTEGER_OPERATOR_EQUAL(signed char)
0158 INTEGER_OPERATOR_EQUAL(short)
0159 INTEGER_OPERATOR_EQUAL(int)
0160 INTEGER_OPERATOR_EQUAL(long)
0161 INTEGER_OPERATOR_EQUAL(long long)
0162 UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned char)
0163 UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned short)
0164 UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned)
0165 UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned long)
0166 UNSIGNED_INTEGER_OPERATOR_EQUAL(unsigned long long)
0167
0168 #ifdef BOOST_CHARCONV_HAS_INT128
0169 constexpr friend bool operator==(uint128 lhs, boost::int128_type rhs) noexcept { return lhs == uint128(rhs); }
0170 constexpr friend bool operator==(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs == uint128(rhs); }
0171 #endif
0172
0173 constexpr friend bool operator==(uint128 lhs, uint128 rhs) noexcept;
0174
0175 #undef INTEGER_OPERATOR_EQUAL
0176 #undef UNSIGNED_INTEGER_OPERATOR_EQUAL
0177
0178
0179 #define INTEGER_OPERATOR_NOTEQUAL(expr) constexpr friend bool operator!=(uint128 lhs, expr rhs) noexcept { return !(lhs == rhs); }
0180
0181 INTEGER_OPERATOR_NOTEQUAL(char)
0182 INTEGER_OPERATOR_NOTEQUAL(signed char)
0183 INTEGER_OPERATOR_NOTEQUAL(short)
0184 INTEGER_OPERATOR_NOTEQUAL(int)
0185 INTEGER_OPERATOR_NOTEQUAL(long)
0186 INTEGER_OPERATOR_NOTEQUAL(long long)
0187 INTEGER_OPERATOR_NOTEQUAL(unsigned char)
0188 INTEGER_OPERATOR_NOTEQUAL(unsigned short)
0189 INTEGER_OPERATOR_NOTEQUAL(unsigned)
0190 INTEGER_OPERATOR_NOTEQUAL(unsigned long)
0191 INTEGER_OPERATOR_NOTEQUAL(unsigned long long)
0192
0193 #ifdef BOOST_CHARCONV_HAS_INT128
0194 constexpr friend bool operator!=(uint128 lhs, boost::int128_type rhs) noexcept { return !(lhs == rhs); }
0195 constexpr friend bool operator!=(uint128 lhs, boost::uint128_type rhs) noexcept { return !(lhs == rhs); }
0196 #endif
0197
0198 constexpr friend bool operator!=(uint128 lhs, uint128 rhs) noexcept;
0199
0200 #undef INTEGER_OPERATOR_NOTEQUAL
0201
0202
0203 #define INTEGER_OPERATOR_LESS_THAN(expr) constexpr friend bool operator<(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && rhs > 0 && lhs.low < static_cast<std::uint64_t>(rhs); }
0204 #define UNSIGNED_INTEGER_OPERATOR_LESS_THAN(expr) constexpr friend bool operator<(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && lhs.low < static_cast<std::uint64_t>(rhs); }
0205
0206 INTEGER_OPERATOR_LESS_THAN(char)
0207 INTEGER_OPERATOR_LESS_THAN(signed char)
0208 INTEGER_OPERATOR_LESS_THAN(short)
0209 INTEGER_OPERATOR_LESS_THAN(int)
0210 INTEGER_OPERATOR_LESS_THAN(long)
0211 INTEGER_OPERATOR_LESS_THAN(long long)
0212 UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned char)
0213 UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned short)
0214 UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned)
0215 UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned long)
0216 UNSIGNED_INTEGER_OPERATOR_LESS_THAN(unsigned long long)
0217
0218 #ifdef BOOST_CHARCONV_HAS_INT128
0219 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, boost::int128_type rhs) noexcept { return lhs < uint128(rhs); }
0220 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs < uint128(rhs); }
0221 #endif
0222
0223 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<(uint128 lhs, uint128 rhs) noexcept;
0224
0225 #undef INTEGER_OPERATOR_LESS_THAN
0226 #undef UNSIGNED_INTEGER_OPERATOR_LESS_THAN
0227
0228
0229 #define INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator<=(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && rhs >= 0 && lhs.low <= static_cast<std::uint64_t>(rhs); }
0230 #define UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator<=(uint128 lhs, expr rhs) noexcept { return lhs.high == 0U && lhs.low <= static_cast<std::uint64_t>(rhs); }
0231
0232 INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(char)
0233 INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(signed char)
0234 INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(short)
0235 INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(int)
0236 INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(long)
0237 INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(long long)
0238 UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned char)
0239 UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned short)
0240 UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned)
0241 UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned long)
0242 UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO(unsigned long long)
0243
0244 #ifdef BOOST_CHARCONV_HAS_INT128
0245 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, boost::int128_type rhs) noexcept { return lhs <= uint128(rhs); }
0246 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs <= uint128(rhs); }
0247 #endif
0248
0249 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator<=(uint128 lhs, uint128 rhs) noexcept;
0250
0251 #undef INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO
0252 #undef UNSIGNED_INTEGER_OPERATOR_LESS_THAN_OR_EQUAL_TO
0253
0254
0255 #define INTEGER_OPERATOR_GREATER_THAN(expr) constexpr friend bool operator>(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || rhs < 0 || lhs.low > static_cast<std::uint64_t>(rhs); }
0256 #define UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(expr) constexpr friend bool operator>(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || lhs.low > static_cast<std::uint64_t>(rhs); }
0257
0258 INTEGER_OPERATOR_GREATER_THAN(char)
0259 INTEGER_OPERATOR_GREATER_THAN(signed char)
0260 INTEGER_OPERATOR_GREATER_THAN(short)
0261 INTEGER_OPERATOR_GREATER_THAN(int)
0262 INTEGER_OPERATOR_GREATER_THAN(long)
0263 INTEGER_OPERATOR_GREATER_THAN(long long)
0264 UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned char)
0265 UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned short)
0266 UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned)
0267 UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned long)
0268 UNSIGNED_INTEGER_OPERATOR_GREATER_THAN(unsigned long long)
0269
0270 #ifdef BOOST_CHARCONV_HAS_INT128
0271 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, boost::int128_type rhs) noexcept { return lhs > uint128(rhs); }
0272 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs > uint128(rhs); }
0273 #endif
0274
0275 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>(uint128 lhs, uint128 rhs) noexcept;
0276
0277 #undef INTEGER_OPERATOR_GREATER_THAN
0278 #undef UNSIGNED_INTEGER_OPERATOR_GREATER_THAN
0279
0280
0281 #define INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator>=(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || rhs < 0 || lhs.low >= static_cast<std::uint64_t>(rhs); }
0282 #define UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(expr) constexpr friend bool operator>=(uint128 lhs, expr rhs) noexcept { return lhs.high > 0U || lhs.low >= static_cast<std::uint64_t>(rhs); }
0283
0284 INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(char)
0285 INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(signed char)
0286 INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(short)
0287 INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(int)
0288 INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(long)
0289 INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(long long)
0290 UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned char)
0291 UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned short)
0292 UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned)
0293 UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned long)
0294 UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO(unsigned long long)
0295
0296 #ifdef BOOST_CHARCONV_HAS_INT128
0297 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, boost::int128_type rhs) noexcept { return lhs >= uint128(rhs); }
0298 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs >= uint128(rhs); }
0299 #endif
0300
0301 BOOST_CHARCONV_CXX14_CONSTEXPR friend bool operator>=(uint128 lhs, uint128 rhs) noexcept;
0302
0303 #undef INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO
0304 #undef UNSIGNED_INTEGER_OPERATOR_GREATER_THAN_OR_EQUAL_TO
0305
0306
0307
0308
0309 constexpr friend uint128 operator~(uint128 v) noexcept;
0310
0311
0312 #define INTEGER_BINARY_OPERATOR_OR(expr) constexpr friend uint128 operator|(uint128 lhs, expr rhs) noexcept { return {lhs.high, lhs.low | static_cast<std::uint64_t>(rhs)}; }
0313
0314 INTEGER_BINARY_OPERATOR_OR(char)
0315 INTEGER_BINARY_OPERATOR_OR(signed char)
0316 INTEGER_BINARY_OPERATOR_OR(short)
0317 INTEGER_BINARY_OPERATOR_OR(int)
0318 INTEGER_BINARY_OPERATOR_OR(long)
0319 INTEGER_BINARY_OPERATOR_OR(long long)
0320 INTEGER_BINARY_OPERATOR_OR(unsigned char)
0321 INTEGER_BINARY_OPERATOR_OR(unsigned short)
0322 INTEGER_BINARY_OPERATOR_OR(unsigned)
0323 INTEGER_BINARY_OPERATOR_OR(unsigned long)
0324 INTEGER_BINARY_OPERATOR_OR(unsigned long long)
0325
0326 #ifdef BOOST_CHARCONV_HAS_INT128
0327 constexpr friend uint128 operator|(uint128 lhs, boost::int128_type rhs) noexcept { return lhs | uint128(rhs); }
0328 constexpr friend uint128 operator|(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs | uint128(rhs); }
0329 #endif
0330
0331 constexpr friend uint128 operator|(uint128 lhs, uint128 rhs) noexcept;
0332
0333 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator|=(uint128 v) noexcept;
0334
0335 #undef INTEGER_BINARY_OPERATOR_OR
0336
0337
0338 #define INTEGER_BINARY_OPERATOR_AND(expr) constexpr friend uint128 operator&(uint128 lhs, expr rhs) noexcept { return {lhs.high, lhs.low & static_cast<std::uint64_t>(rhs)}; }
0339
0340 INTEGER_BINARY_OPERATOR_AND(char)
0341 INTEGER_BINARY_OPERATOR_AND(signed char)
0342 INTEGER_BINARY_OPERATOR_AND(short)
0343 INTEGER_BINARY_OPERATOR_AND(int)
0344 INTEGER_BINARY_OPERATOR_AND(long)
0345 INTEGER_BINARY_OPERATOR_AND(long long)
0346 INTEGER_BINARY_OPERATOR_AND(unsigned char)
0347 INTEGER_BINARY_OPERATOR_AND(unsigned short)
0348 INTEGER_BINARY_OPERATOR_AND(unsigned)
0349 INTEGER_BINARY_OPERATOR_AND(unsigned long)
0350 INTEGER_BINARY_OPERATOR_AND(unsigned long long)
0351
0352 #ifdef BOOST_CHARCONV_HAS_INT128
0353 constexpr friend uint128 operator&(uint128 lhs, boost::int128_type rhs) noexcept { return lhs & uint128(rhs); }
0354 constexpr friend uint128 operator&(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs & uint128(rhs); }
0355 #endif
0356
0357 constexpr friend uint128 operator&(uint128 lhs, uint128 rhs) noexcept;
0358
0359 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator&=(uint128 v) noexcept;
0360
0361 #undef INTEGER_BINARY_OPERATOR_AND
0362
0363
0364 #define INTEGER_BINARY_OPERATOR_XOR(expr) constexpr friend uint128 operator^(uint128 lhs, expr rhs) noexcept { return {lhs.high, lhs.low ^ static_cast<std::uint64_t>(rhs)}; }
0365
0366 INTEGER_BINARY_OPERATOR_XOR(char)
0367 INTEGER_BINARY_OPERATOR_XOR(signed char)
0368 INTEGER_BINARY_OPERATOR_XOR(short)
0369 INTEGER_BINARY_OPERATOR_XOR(int)
0370 INTEGER_BINARY_OPERATOR_XOR(long)
0371 INTEGER_BINARY_OPERATOR_XOR(long long)
0372 INTEGER_BINARY_OPERATOR_XOR(unsigned char)
0373 INTEGER_BINARY_OPERATOR_XOR(unsigned short)
0374 INTEGER_BINARY_OPERATOR_XOR(unsigned)
0375 INTEGER_BINARY_OPERATOR_XOR(unsigned long)
0376 INTEGER_BINARY_OPERATOR_XOR(unsigned long long)
0377
0378 #ifdef BOOST_CHARCONV_HAS_INT128
0379 constexpr friend uint128 operator^(uint128 lhs, boost::int128_type rhs) noexcept { return lhs ^ uint128(rhs); }
0380 constexpr friend uint128 operator^(uint128 lhs, boost::uint128_type rhs) noexcept { return lhs ^ uint128(rhs); }
0381 #endif
0382
0383 constexpr friend uint128 operator^(uint128 lhs, uint128 rhs) noexcept;
0384
0385 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator^=(uint128 v) noexcept;
0386
0387 #undef INTEGER_BINARY_OPERATOR_XOR
0388
0389
0390 #define INTEGER_BINARY_OPERATOR_LEFT_SHIFT(expr) \
0391 BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator<<(uint128 lhs, expr rhs) noexcept \
0392 { \
0393 if (rhs >= 64) \
0394 { \
0395 return {lhs.low << (rhs - 64), 0}; \
0396 } \
0397 else if (rhs == 0) \
0398 { \
0399 return lhs; \
0400 } \
0401 \
0402 return {(lhs.high << rhs) | (lhs.low >> (64 - rhs)), lhs.low << rhs}; \
0403 }
0404
0405 INTEGER_BINARY_OPERATOR_LEFT_SHIFT(char)
0406 INTEGER_BINARY_OPERATOR_LEFT_SHIFT(signed char)
0407 INTEGER_BINARY_OPERATOR_LEFT_SHIFT(short)
0408 INTEGER_BINARY_OPERATOR_LEFT_SHIFT(int)
0409 INTEGER_BINARY_OPERATOR_LEFT_SHIFT(long)
0410 INTEGER_BINARY_OPERATOR_LEFT_SHIFT(long long)
0411 INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned char)
0412 INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned short)
0413 INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned)
0414 INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned long)
0415 INTEGER_BINARY_OPERATOR_LEFT_SHIFT(unsigned long long)
0416
0417 #define INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(expr) \
0418 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator<<=(expr amount) noexcept \
0419 { \
0420 *this = *this << amount; \
0421 return *this; \
0422 }
0423
0424 INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(char)
0425 INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(signed char)
0426 INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(short)
0427 INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(int)
0428 INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(long)
0429 INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(long long)
0430 INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned char)
0431 INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned short)
0432 INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned)
0433 INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned long)
0434 INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT(unsigned long long)
0435
0436 #undef INTEGER_BINARY_OPERATOR_LEFT_SHIFT
0437 #undef INTEGER_BINARY_OPERATOR_EQUALS_LEFT_SHIFT
0438
0439
0440 #define INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(expr) \
0441 BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator>>(uint128 lhs, expr amount) noexcept \
0442 { \
0443 if (amount >= 64) \
0444 { \
0445 return {0, lhs.high >> (amount - 64)}; \
0446 } \
0447 else if (amount == 0) \
0448 { \
0449 return lhs; \
0450 } \
0451 \
0452 return {lhs.high >> amount, (lhs.low >> amount) | (lhs.high << (64 - amount))}; \
0453 }
0454
0455 INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(char)
0456 INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(signed char)
0457 INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(short)
0458 INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(int)
0459 INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(long)
0460 INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(long long)
0461 INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned char)
0462 INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned short)
0463 INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned)
0464 INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned long)
0465 INTEGER_BINARY_OPERATOR_RIGHT_SHIFT(unsigned long long)
0466
0467 #define INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(expr) \
0468 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator>>=(expr amount) noexcept \
0469 { \
0470 *this = *this >> amount; \
0471 return *this; \
0472 }
0473
0474 INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(char)
0475 INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(signed char)
0476 INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(short)
0477 INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(int)
0478 INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(long)
0479 INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(long long)
0480 INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned char)
0481 INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned short)
0482 INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned)
0483 INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned long)
0484 INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT(unsigned long long)
0485
0486 #undef INTEGER_BINARY_OPERATOR_RIGHT_SHIFT
0487 #undef INTEGER_BINARY_OPERATOR_EQUALS_RIGHT_SHIFT
0488
0489
0490 inline uint128 &operator+=(std::uint64_t n) noexcept;
0491
0492 BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator+(uint128 lhs, uint128 rhs) noexcept;
0493
0494 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator+=(uint128 v) noexcept;
0495
0496 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator++() noexcept;
0497
0498 BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 operator++(int) noexcept;
0499
0500 BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator-(uint128 lhs, uint128 rhs) noexcept;
0501
0502 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator-=(uint128 v) noexcept;
0503
0504 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator--() noexcept;
0505
0506 BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 operator--(int) noexcept;
0507
0508 BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator*(uint128 lhs, uint128 rhs) noexcept;
0509
0510 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator*=(uint128 v) noexcept;
0511
0512 BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator/(uint128 lhs, uint128 rhs) noexcept;
0513
0514 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator/=(uint128 v) noexcept;
0515
0516 BOOST_CHARCONV_CXX14_CONSTEXPR friend uint128 operator%(uint128 lhs, uint128 rhs) noexcept;
0517
0518 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &operator%=(uint128 v) noexcept;
0519
0520 private:
0521 BOOST_CHARCONV_CXX14_CONSTEXPR friend int high_bit(uint128 v) noexcept;
0522
0523 BOOST_CHARCONV_CXX14_CONSTEXPR friend void
0524 div_impl(uint128 lhs, uint128 rhs, uint128 "ient, uint128 &remainder) noexcept;
0525 };
0526
0527 constexpr uint128 operator-(uint128 val) noexcept
0528 {
0529 return {~val.high + static_cast<std::uint64_t>(val.low == 0), ~val.low + 1};
0530 }
0531
0532 constexpr uint128 operator+(uint128 val) noexcept
0533 {
0534 return val;
0535 }
0536
0537 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator=(const uint128& v) noexcept
0538 {
0539 low = v.low;
0540 high = v.high;
0541 return *this;
0542 }
0543
0544 constexpr bool operator==(uint128 lhs, uint128 rhs) noexcept
0545 {
0546 return lhs.high == rhs.high && lhs.low == rhs.low;
0547 }
0548
0549 constexpr bool operator!=(uint128 lhs, uint128 rhs) noexcept
0550 {
0551 return !(lhs == rhs);
0552 }
0553
0554 BOOST_CHARCONV_CXX14_CONSTEXPR bool operator<(uint128 lhs, uint128 rhs) noexcept
0555 {
0556 if (lhs.high == rhs.high)
0557 {
0558 return lhs.low < rhs.low;
0559 }
0560
0561 return lhs.high < rhs.high;
0562 }
0563
0564 BOOST_CHARCONV_CXX14_CONSTEXPR bool operator<=(uint128 lhs, uint128 rhs) noexcept
0565 {
0566 return !(rhs < lhs);
0567 }
0568
0569 BOOST_CHARCONV_CXX14_CONSTEXPR bool operator>(uint128 lhs, uint128 rhs) noexcept
0570 {
0571 return rhs < lhs;
0572 }
0573
0574 BOOST_CHARCONV_CXX14_CONSTEXPR bool operator>=(uint128 lhs, uint128 rhs) noexcept
0575 {
0576 return !(lhs < rhs);
0577 }
0578
0579 constexpr uint128 operator~(uint128 v) noexcept
0580 {
0581 return {~v.high, ~v.low};
0582 }
0583
0584 constexpr uint128 operator|(uint128 lhs, uint128 rhs) noexcept
0585 {
0586 return {lhs.high | rhs.high, lhs.low | rhs.low};
0587 }
0588
0589 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator|=(uint128 v) noexcept
0590 {
0591 *this = *this | v;
0592 return *this;
0593 }
0594
0595 constexpr uint128 operator&(uint128 lhs, uint128 rhs) noexcept
0596 {
0597 return {lhs.high & rhs.high, lhs.low & rhs.low};
0598 }
0599
0600 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator&=(uint128 v) noexcept
0601 {
0602 *this = *this & v;
0603 return *this;
0604 }
0605
0606 constexpr uint128 operator^(uint128 lhs, uint128 rhs) noexcept
0607 {
0608 return {lhs.high ^ rhs.high, lhs.low ^ rhs.low};
0609 }
0610
0611 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator^=(uint128 v) noexcept
0612 {
0613 *this = *this ^ v;
0614 return *this;
0615 }
0616
0617 inline uint128 &uint128::operator+=(std::uint64_t n) noexcept
0618 {
0619 #if BOOST_CHARCONV_HAS_BUILTIN(__builtin_addcll)
0620
0621 unsigned long long carry {};
0622 low = __builtin_addcll(low, n, 0, &carry);
0623 high = __builtin_addcll(high, 0, carry, &carry);
0624
0625 #elif BOOST_CHARCONV_HAS_BUILTIN(__builtin_ia32_addcarryx_u64)
0626
0627 unsigned long long result {};
0628 auto carry = __builtin_ia32_addcarryx_u64(0, low, n, &result);
0629 low = result;
0630 __builtin_ia32_addcarryx_u64(carry, high, 0, &result);
0631 high = result;
0632
0633 #elif defined(BOOST_MSVC) && defined(_M_X64)
0634
0635 auto carry = _addcarry_u64(0, low, n, &low);
0636 _addcarry_u64(carry, high, 0, &high);
0637
0638 #else
0639
0640 auto sum = low + n;
0641 high += (sum < low ? 1 : 0);
0642 low = sum;
0643
0644 #endif
0645 return *this;
0646 }
0647
0648 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator+(uint128 lhs, uint128 rhs) noexcept
0649 {
0650 const uint128 temp = {lhs.high + rhs.high, lhs.low + rhs.low};
0651
0652
0653 if (temp.low < lhs.low)
0654 {
0655 return {temp.high + 1, temp.low};
0656 }
0657
0658 return temp;
0659 }
0660
0661 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator+=(uint128 v) noexcept
0662 {
0663 *this = *this + v;
0664 return *this;
0665 }
0666
0667 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator++() noexcept
0668 {
0669 if (this->low == UINT64_MAX)
0670 {
0671 this->low = 0;
0672 ++this->high;
0673 }
0674 else
0675 {
0676 ++this->low;
0677 }
0678
0679 return *this;
0680 }
0681
0682 BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 uint128::operator++(int) noexcept
0683 {
0684 return ++(*this);
0685 }
0686
0687 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator-(uint128 lhs, uint128 rhs) noexcept
0688 {
0689 const uint128 temp {lhs.high - rhs.high, lhs.low - rhs.low};
0690
0691
0692 if (lhs.low < rhs.low)
0693 {
0694 return {temp.high - 1, temp.low};
0695 }
0696
0697 return temp;
0698 }
0699
0700 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator-=(uint128 v) noexcept
0701 {
0702 *this = *this - v;
0703 return *this;
0704 }
0705
0706 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator--() noexcept
0707 {
0708 if (this->low == 0)
0709 {
0710 this->low = UINT64_MAX;
0711 --this->high;
0712 }
0713 else
0714 {
0715 --this->low;
0716 }
0717
0718 return *this;
0719 }
0720
0721 BOOST_CHARCONV_CXX14_CONSTEXPR const uint128 uint128::operator--(int) noexcept
0722 {
0723 return --(*this);
0724 }
0725 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator*(uint128 lhs, uint128 rhs) noexcept
0726 {
0727 const auto a = static_cast<std::uint64_t>(lhs.low >> 32);
0728 const auto b = static_cast<std::uint64_t>(lhs.low & UINT32_MAX);
0729 const auto c = static_cast<std::uint64_t>(rhs.low >> 32);
0730 const auto d = static_cast<std::uint64_t>(rhs.low & UINT32_MAX);
0731
0732 uint128 result { lhs.high * rhs.low + lhs.low * rhs.high + a * c, b * d };
0733 result += uint128(a * d) << 32;
0734 result += uint128(b * c) << 32;
0735 return result;
0736 }
0737
0738 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator*=(uint128 v) noexcept
0739 {
0740 *this = *this * v;
0741 return *this;
0742 }
0743
0744 BOOST_CHARCONV_CXX14_CONSTEXPR int high_bit(uint128 v) noexcept
0745 {
0746 if (v.high != 0)
0747 {
0748 return 127 - boost::core::countl_zero(v.high);
0749 }
0750 else if (v.low != 0)
0751 {
0752 return 63 - boost::core::countl_zero(v.low);
0753 }
0754
0755 return 0;
0756 }
0757
0758
0759 BOOST_CHARCONV_CXX14_CONSTEXPR void div_impl(uint128 lhs, uint128 rhs, uint128& quotient, uint128& remainder) noexcept
0760 {
0761 constexpr uint128 one {0, 1};
0762
0763 if (rhs > lhs)
0764 {
0765 quotient = 0U;
0766 remainder = 0U;
0767 }
0768 else if (lhs == rhs)
0769 {
0770 quotient = 1U;
0771 remainder = 0U;
0772 }
0773
0774 uint128 denom = rhs;
0775 quotient = 0U;
0776
0777 std::int32_t shift = high_bit(lhs) - high_bit(rhs);
0778 if (shift < 0)
0779 {
0780 shift = 32 - shift;
0781 }
0782 denom <<= shift;
0783
0784 for (int i = 0; i <= shift; ++i)
0785 {
0786 quotient <<= 1;
0787 if (lhs >= denom)
0788 {
0789 lhs -= denom;
0790 quotient |= one;
0791 }
0792 denom >>= 1;
0793 }
0794
0795 remainder = lhs;
0796 }
0797
0798 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator/(uint128 lhs, uint128 rhs) noexcept
0799 {
0800 uint128 quotient {0, 0};
0801 uint128 remainder {0, 0};
0802 div_impl(lhs, rhs, quotient, remainder);
0803
0804 return quotient;
0805 }
0806
0807 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator/=(uint128 v) noexcept
0808 {
0809 *this = *this / v;
0810 return *this;
0811 }
0812
0813 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 operator%(uint128 lhs, uint128 rhs) noexcept
0814 {
0815 uint128 quotient {0, 0};
0816 uint128 remainder {0, 0};
0817 div_impl(lhs, rhs, quotient, remainder);
0818
0819 return remainder;
0820 }
0821
0822 BOOST_CHARCONV_CXX14_CONSTEXPR uint128 &uint128::operator%=(uint128 v) noexcept
0823 {
0824 *this = *this % v;
0825 return *this;
0826 }
0827
0828 static inline std::uint64_t umul64(std::uint32_t x, std::uint32_t y) noexcept
0829 {
0830
0831 #if defined(BOOST_CHARCONV_HAS_MSVC_32BIT_INTRINSICS) && !defined(_M_ARM)
0832
0833 return __emulu(x, y);
0834
0835 #else
0836
0837 return x * static_cast<std::uint64_t>(y);
0838
0839 #endif
0840 }
0841
0842
0843 BOOST_CHARCONV_SAFEBUFFERS inline uint128 umul128(std::uint64_t x, std::uint64_t y) noexcept
0844 {
0845 #if defined(BOOST_CHARCONV_HAS_INT128)
0846
0847 auto result = static_cast<boost::uint128_type>(x) * static_cast<boost::uint128_type>(y);
0848 return {static_cast<std::uint64_t>(result >> 64), static_cast<std::uint64_t>(result)};
0849
0850
0851 #elif defined(BOOST_CHARCONV_HAS_MSVC_64BIT_INTRINSICS) && !defined(_M_ARM64)
0852
0853 unsigned long long high;
0854 std::uint64_t low = _umul128(x, y, &high);
0855 return {static_cast<std::uint64_t>(high), low};
0856
0857
0858 #elif defined(_M_ARM64) && !defined(__MINGW32__)
0859
0860 std::uint64_t high = __umulh(x, y);
0861 std::uint64_t low = x * y;
0862 return {high, low};
0863
0864 #else
0865
0866 auto a = static_cast<std::uint32_t>(x >> 32);
0867 auto b = static_cast<std::uint32_t>(x);
0868 auto c = static_cast<std::uint32_t>(y >> 32);
0869 auto d = static_cast<std::uint32_t>(y);
0870
0871 auto ac = umul64(a, c);
0872 auto bc = umul64(b, c);
0873 auto ad = umul64(a, d);
0874 auto bd = umul64(b, d);
0875
0876 auto intermediate = (bd >> 32) + static_cast<std::uint32_t>(ad) + static_cast<std::uint32_t>(bc);
0877
0878 return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
0879 (intermediate << 32) + static_cast<std::uint32_t>(bd)};
0880
0881 #endif
0882 }
0883
0884 BOOST_CHARCONV_SAFEBUFFERS inline std::uint64_t umul128_upper64(std::uint64_t x, std::uint64_t y) noexcept
0885 {
0886 #if defined(BOOST_CHARCONV_HAS_INT128)
0887
0888 auto result = static_cast<boost::uint128_type>(x) * static_cast<boost::uint128_type>(y);
0889 return static_cast<std::uint64_t>(result >> 64);
0890
0891 #elif defined(BOOST_CHARCONV_HAS_MSVC_64BIT_INTRINSICS)
0892
0893 return __umulh(x, y);
0894
0895 #else
0896
0897 auto a = static_cast<std::uint32_t>(x >> 32);
0898 auto b = static_cast<std::uint32_t>(x);
0899 auto c = static_cast<std::uint32_t>(y >> 32);
0900 auto d = static_cast<std::uint32_t>(y);
0901
0902 auto ac = umul64(a, c);
0903 auto bc = umul64(b, c);
0904 auto ad = umul64(a, d);
0905 auto bd = umul64(b, d);
0906
0907 auto intermediate = (bd >> 32) + static_cast<std::uint32_t>(ad) + static_cast<std::uint32_t>(bc);
0908
0909 return ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32);
0910
0911 #endif
0912 }
0913
0914
0915
0916 BOOST_CHARCONV_SAFEBUFFERS inline uint128 umul192_upper128(std::uint64_t x, uint128 y) noexcept
0917 {
0918 auto r = umul128(x, y.high);
0919 r += umul128_upper64(x, y.low);
0920 return r;
0921 }
0922
0923
0924
0925 inline std::uint64_t umul96_upper64(std::uint32_t x, std::uint64_t y) noexcept
0926 {
0927 #if defined(BOOST_CHARCONV_HAS_INT128) || defined(BOOST_CHARCONV_HAS_MSVC_64BIT_INTRINSICS)
0928
0929 return umul128_upper64(static_cast<std::uint64_t>(x) << 32, y);
0930
0931 #else
0932
0933 auto yh = static_cast<std::uint32_t>(y >> 32);
0934 auto yl = static_cast<std::uint32_t>(y);
0935
0936 auto xyh = umul64(x, yh);
0937 auto xyl = umul64(x, yl);
0938
0939 return xyh + (xyl >> 32);
0940
0941 #endif
0942 }
0943
0944
0945
0946 BOOST_CHARCONV_SAFEBUFFERS inline uint128 umul192_lower128(std::uint64_t x, uint128 y) noexcept
0947 {
0948 auto high = x * y.high;
0949 auto highlow = umul128(x, y.low);
0950 return {high + highlow.high, highlow.low};
0951 }
0952
0953
0954
0955 inline std::uint64_t umul96_lower64(std::uint32_t x, std::uint64_t y) noexcept
0956 {
0957 return x * y;
0958 }
0959
0960 }}}
0961
0962
0963 namespace std {
0964
0965 template <>
0966 struct numeric_limits<boost::charconv::detail::uint128>
0967 {
0968
0969 BOOST_ATTRIBUTE_UNUSED static constexpr bool is_specialized = true;
0970 BOOST_ATTRIBUTE_UNUSED static constexpr bool is_signed = false;
0971 BOOST_ATTRIBUTE_UNUSED static constexpr bool is_integer = true;
0972 BOOST_ATTRIBUTE_UNUSED static constexpr bool is_exact = true;
0973 BOOST_ATTRIBUTE_UNUSED static constexpr bool has_infinity = false;
0974 BOOST_ATTRIBUTE_UNUSED static constexpr bool has_quiet_NaN = false;
0975 BOOST_ATTRIBUTE_UNUSED static constexpr bool has_signaling_NaN = false;
0976 BOOST_ATTRIBUTE_UNUSED static constexpr std::float_round_style round_style = std::round_toward_zero;
0977 BOOST_ATTRIBUTE_UNUSED static constexpr bool is_iec559 = false;
0978 BOOST_ATTRIBUTE_UNUSED static constexpr bool is_bounded = true;
0979 BOOST_ATTRIBUTE_UNUSED static constexpr bool is_modulo = true;
0980 BOOST_ATTRIBUTE_UNUSED static constexpr int digits = 128;
0981 BOOST_ATTRIBUTE_UNUSED static constexpr int digits10 = 38;
0982 BOOST_ATTRIBUTE_UNUSED static constexpr int max_digits10 = 0;
0983 BOOST_ATTRIBUTE_UNUSED static constexpr int radix = 2;
0984 BOOST_ATTRIBUTE_UNUSED static constexpr int min_exponent = 0;
0985 BOOST_ATTRIBUTE_UNUSED static constexpr int min_exponent10 = 0;
0986 BOOST_ATTRIBUTE_UNUSED static constexpr int max_exponent = 0;
0987 BOOST_ATTRIBUTE_UNUSED static constexpr int max_exponent10 = 0;
0988 BOOST_ATTRIBUTE_UNUSED static constexpr bool traps = std::numeric_limits<std::uint64_t>::traps;
0989 BOOST_ATTRIBUTE_UNUSED static constexpr bool tinyness_before = false;
0990
0991
0992 BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 (min)() { return 0; }
0993 BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 lowest() { return 0; }
0994 BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 (max)() { return {UINT64_MAX, UINT64_MAX}; }
0995 BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 epsilon() { return 0; }
0996 BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 round_error() { return 0; }
0997 BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 infinity() { return 0; }
0998 BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 quiet_NaN() { return 0; }
0999 BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 signaling_NaN() { return 0; }
1000 BOOST_ATTRIBUTE_UNUSED static constexpr boost::charconv::detail::uint128 denorm_min() { return 0; }
1001 };
1002
1003 }
1004
1005 #endif