19 #ifndef PSTORE_SUPPORT_UINT128_HPP 20 #define PSTORE_SUPPORT_UINT128_HPP 40 struct is_unsigned<
pstore::uint128> : true_type {};
42 struct is_signed<pstore::uint128> : false_type {};
46 #if defined(PSTORE_HAVE_UINT128_T) && !defined(PSTORE_HAVE_UINT128_TRAITS_SUPPORT) 48 struct is_unsigned<__uint128_t> : true_type {};
50 struct is_signed<__uint128_t> : false_type {};
51 #endif // PSTORE_HAVE_UINT128_T && !PSTORE_HAVE_UINT128_TRAITS_SUPPORT 61 template <
typename T,
typename Enable =
void>
64 constexpr std::uint64_t operator() (T
const t)
const noexcept {
75 class high<T, typename
std::enable_if<(sizeof (T) > sizeof (std::uint64_t))>::type> {
77 constexpr std::uint64_t operator() (T v)
const noexcept {
78 return (v >> 64U) & ((T{1} << 64) - 1U);
87 constexpr
uint128 () noexcept =
default;
88 constexpr
uint128 (std::nullptr_t) noexcept =
delete;
89 #ifdef PSTORE_HAVE_UINT128_T 90 constexpr
uint128 (std::uint64_t
const high, std::uint64_t
const low) noexcept
91 : v_{__uint128_t{high} << 64U | __uint128_t{low}} {}
94 template <
typename IntType,
95 typename =
typename std::enable_if<std::is_unsigned<IntType>::value>::type>
96 constexpr
uint128 (IntType v) noexcept
101 explicit constexpr
uint128 (std::uint8_t
const *
const bytes) noexcept
102 : v_{bytes_to_uint128 (bytes)} {}
104 constexpr
uint128 (std::uint64_t
const high, std::uint64_t
const low) noexcept
109 template <
typename IntType,
110 typename =
typename std::enable_if<std::is_unsigned<IntType>::value>::type>
116 explicit constexpr
uint128 (std::uint8_t
const *
const bytes) noexcept
117 : low_{bytes_to_uint64 (&bytes[8])}
118 , high_{bytes_to_uint64 (&bytes[0])} {}
119 #endif // PSTORE_HAVE_UINT128_T 121 explicit uint128 (std::array<std::uint8_t, 16>
const & bytes) noexcept
126 ~
uint128 () noexcept =
default;
131 template <
typename T>
132 constexpr
bool operator== (T rhs)
const noexcept;
133 template <
typename T>
134 constexpr
bool operator!= (T rhs)
const noexcept {
135 return !operator== (rhs);
138 #ifdef PSTORE_HAVE_UINT128_T 139 constexpr std::uint64_t high ()
const noexcept {
140 return static_cast<std::uint64_t
> (v_ >> 64U);
142 constexpr std::uint64_t low ()
const noexcept {
143 return static_cast<std::uint64_t
> (v_ & max64);
146 constexpr std::uint64_t high ()
const noexcept {
return high_; }
147 constexpr std::uint64_t low ()
const noexcept {
return low_; }
148 #endif // PSTORE_HAVE_UINT128_T 150 uint128 operator- ()
const noexcept;
151 constexpr
bool operator! ()
const noexcept;
152 uint128 operator~ ()
const noexcept;
154 uint128 & operator++ () noexcept;
155 uint128 operator++ (
int) noexcept;
156 uint128 & operator-- () noexcept;
157 uint128 operator-- (
int) noexcept;
160 uint128 & operator-= (
uint128 const b) noexcept {
return *
this += -b; }
162 template <
typename T>
163 constexpr
uint128 operator& (T rhs)
const noexcept;
164 template <
typename T>
165 constexpr
uint128 operator| (T rhs)
const noexcept;
167 template <
typename T>
168 uint128 operator<< (T n)
const noexcept;
169 uint128 & operator>>= (
unsigned n) noexcept;
171 static constexpr std::size_t hex_string_length = std::size_t{32};
173 template <
typename OutputIterator>
174 OutputIterator to_hex (OutputIterator out)
const noexcept;
175 std::string to_hex_string ()
const;
180 static constexpr std::uint64_t max64 = std::numeric_limits<std::uint64_t>::max ();
181 #ifdef PSTORE_HAVE_UINT128_T 183 static constexpr __uint128_t bytes_to_uint128 (std::uint8_t
const * bytes) noexcept;
185 std::uint64_t low_ = 0U;
186 std::uint64_t high_ = 0U;
187 static constexpr std::uint64_t bytes_to_uint64 (std::uint8_t
const * bytes) noexcept;
188 #endif // PSTORE_HAVE_UINT128_T 190 static constexpr
char digit_to_hex (
unsigned const v) noexcept {
191 PSTORE_ASSERT (v < 0x10);
192 return static_cast<char> (v + ((v < 10) ?
'0' :
'a' - 10));
196 PSTORE_STATIC_ASSERT (
sizeof (
uint128) == 16);
197 PSTORE_STATIC_ASSERT (
alignof (
uint128) == 16);
198 PSTORE_STATIC_ASSERT (std::is_standard_layout<uint128>::value);
202 template <
typename T>
203 constexpr
bool uint128::operator== (T rhs)
const noexcept {
204 #ifdef PSTORE_HAVE_UINT128_T 207 return this->high () ==
details::high<T>{}(rhs) && this->low () == (rhs & max64);
212 constexpr
bool uint128::operator==<
uint128> (
uint128 const rhs)
const noexcept {
213 #ifdef PSTORE_HAVE_UINT128_T 216 return this->high () == rhs.high () && this->low () == rhs.low ();
222 inline uint128 & uint128::operator++ () noexcept {
223 #ifdef PSTORE_HAVE_UINT128_T 232 inline uint128 uint128::operator++ (
int) noexcept {
233 auto const prev = *
this;
240 inline uint128 & uint128::operator-- () noexcept {
241 #ifdef PSTORE_HAVE_UINT128_T 254 inline uint128 uint128::operator-- (
int) noexcept {
255 auto const prev = *
this;
262 inline uint128 & uint128::operator+= (
uint128 const rhs) noexcept {
263 #ifdef PSTORE_HAVE_UINT128_T 266 auto const old_low = low_;
269 if (low_ < old_low) {
278 inline uint128 uint128::operator- ()
const noexcept {
279 #ifdef PSTORE_HAVE_UINT128_T 289 constexpr
bool uint128::operator! ()
const noexcept {
290 #ifdef PSTORE_HAVE_UINT128_T 293 return !(high_ != 0 || low_ != 0);
299 inline uint128 uint128::operator~ ()
const noexcept {
300 #ifdef PSTORE_HAVE_UINT128_T 312 template <
typename T>
313 constexpr
uint128 uint128::operator& (T
const rhs)
const noexcept {
314 #ifdef PSTORE_HAVE_UINT128_T 317 return {0U, low () & rhs};
323 #ifdef PSTORE_HAVE_UINT128_T 324 return {v_ & rhs.v_};
326 return {high () & rhs.high (), low () & rhs.low ()};
332 template <
typename T>
333 constexpr
uint128 uint128::operator| (T
const rhs)
const noexcept {
334 #ifdef PSTORE_HAVE_UINT128_T 337 return {0U, low () | rhs};
343 #ifdef PSTORE_HAVE_UINT128_T 344 return {v_ | rhs.v_};
346 return {high () | rhs.high (), low () | rhs.low ()};
352 template <
typename Other>
353 uint128 uint128::operator<< (Other
const n)
const noexcept {
354 PSTORE_ASSERT (n <= 128);
355 #ifdef PSTORE_HAVE_UINT128_T 359 return {low () << (n - 64U), 0U};
364 std::uint64_t
const mask = (std::uint64_t{1} << n) - 1U;
365 auto const dist = 64U - n;
366 std::uint64_t
const top_of_low_mask = mask << dist;
367 std::uint64_t
const bottom_of_high = (low () & top_of_low_mask) >> dist;
368 return {(high () << n) | bottom_of_high, low () << n};
369 #endif // PSTORE_HAVE_UINT128_T 374 inline uint128 & uint128::operator>>= (
unsigned const n) noexcept {
375 PSTORE_ASSERT (n <= 128);
376 #ifdef PSTORE_HAVE_UINT128_T 380 low_ = high_ >> (n - 64U);
383 std::uint64_t
const mask = (std::uint64_t{1} << n) - 1U;
384 low_ = (low_ >> n) | ((high_ & mask) << (64U - n));
387 #endif // PSTORE_HAVE_UINT128_T 393 #ifdef PSTORE_HAVE_UINT128_T 394 constexpr __uint128_t uint128::bytes_to_uint128 (std::uint8_t
const *
const bytes) noexcept {
395 return __uint128_t{bytes[0]} << 120U | __uint128_t{bytes[1]} << 112U |
396 __uint128_t{bytes[2]} << 104U | __uint128_t{bytes[3]} << 96U |
397 __uint128_t{bytes[4]} << 88U | __uint128_t{bytes[5]} << 80U |
398 __uint128_t{bytes[6]} << 72U | __uint128_t{bytes[7]} << 64U |
399 __uint128_t{bytes[8]} << 56U | __uint128_t{bytes[9]} << 48U |
400 __uint128_t{bytes[10]} << 40U | __uint128_t{bytes[11]} << 32U |
401 __uint128_t{bytes[12]} << 24U | __uint128_t{bytes[13]} << 16U |
402 __uint128_t{bytes[14]} << 8U | __uint128_t{bytes[15]};
405 constexpr std::uint64_t uint128::bytes_to_uint64 (std::uint8_t
const *
const bytes) noexcept {
406 return std::uint64_t{bytes[0]} << 56 | std::uint64_t{bytes[1]} << 48 |
407 std::uint64_t{bytes[2]} << 40 | std::uint64_t{bytes[3]} << 32 |
408 std::uint64_t{bytes[4]} << 24 | std::uint64_t{bytes[5]} << 16 |
409 std::uint64_t{bytes[6]} << 8 | std::uint64_t{bytes[7]};
411 #endif // PSTORE_HAVE_UINT128_T 413 template <
typename OutputIterator>
414 OutputIterator uint128::to_hex (OutputIterator out)
const noexcept {
418 #ifdef PSTORE_HAVE_UINT128_T 419 for (
auto shift = 4U; shift <= 128U; shift += 4U) {
420 *(out++) = digit_to_hex ((v_ >> (128U - shift)) & 0x0FU);
426 for (
auto shift = 4U; shift <= 64; shift += 4U) {
427 *(out++) = digit_to_hex ((high_ >> (64U - shift)) & 0x0FU);
432 for (
auto shift = 4U; shift <= 64; shift += 4U) {
433 *(out++) = digit_to_hex ((low_ >> (64U - shift)) & 0x0FU);
439 PSTORE_ASSERT (emitted == hex_string_length);
443 inline std::ostream & operator<< (std::ostream & os,
uint128 const & value) {
444 return os <<
'{' << value.high () <<
',' << value.low () <<
'}';
447 constexpr
bool operator== (
uint128 const & lhs,
uint128 const & rhs) noexcept {
448 return lhs.operator== (rhs);
450 constexpr
bool operator!= (
uint128 const & lhs,
uint128 const & rhs) noexcept {
451 return lhs.operator!= (rhs);
454 constexpr
bool operator< (
uint128 const & lhs,
uint128 const & rhs) noexcept {
455 return lhs.high () < rhs.high () ||
456 (!(rhs.high () < lhs.high ()) && lhs.low () < rhs.low ());
458 constexpr
bool operator> (
uint128 const & lhs,
uint128 const & rhs) noexcept {
461 constexpr
bool operator>= (
uint128 const & lhs,
uint128 const & rhs) noexcept {
464 constexpr
bool operator<= (
uint128 const & lhs,
uint128 const & rhs) noexcept {
474 using result_type = size_t;
476 result_type operator() (argument_type
const & s)
const {
477 return std::hash<std::uint64_t>{}(s.low ()) ^ std::hash<std::uint64_t>{}(s.high ());
486 static constexpr
bool is_specialized =
true;
487 static constexpr
bool is_signed =
false;
489 static constexpr type min () noexcept {
return {0U}; }
490 static constexpr type max () noexcept {
491 return {std::numeric_limits<std::uint64_t>::max (),
492 std::numeric_limits<std::uint64_t>::max ()};
494 static constexpr type lowest () noexcept {
return type{0U}; }
496 static constexpr
const int digits = 128;
497 static constexpr
const int digits10 = 38;
498 static constexpr
const int max_digits10 = 0;
499 static constexpr
const bool is_integer =
true;
500 static constexpr
const bool is_exact =
true;
501 static constexpr
const int radix = 2;
502 static constexpr type epsilon () noexcept {
return {0U}; }
503 static constexpr type round_error () noexcept {
return {0U}; }
505 static constexpr
const int min_exponent = 0;
506 static constexpr
const int min_exponent10 = 0;
507 static constexpr
const int max_exponent = 0;
508 static constexpr
const int max_exponent10 = 0;
510 static constexpr
const bool has_infinity =
false;
511 static constexpr
const bool has_quiet_NaN =
false;
513 static constexpr
const bool has_signaling_NaN =
false;
514 static constexpr
const float_denorm_style has_denorm = denorm_absent;
515 static constexpr
const bool has_denorm_loss =
false;
516 static constexpr type infinity () noexcept {
return {0U}; }
518 static constexpr type quiet_NaN () noexcept {
return {0U}; }
520 static constexpr type signaling_NaN () noexcept {
return {0U}; }
521 static constexpr type denorm_min () noexcept {
return {0U}; }
523 static constexpr
const bool is_iec559 =
false;
524 static constexpr
const bool is_bounded =
true;
525 static constexpr
const bool is_modulo =
true;
527 static constexpr
const bool traps =
true;
528 static constexpr
const bool tinyness_before =
false;
529 static constexpr
const float_round_style round_style = std::round_toward_zero;
534 #endif // PSTORE_SUPPORT_UINT128_HPP Definition: uint128.hpp:85
Definition: chunked_sequence.hpp:607
An implementation of the Haskell Maybe type.
constexpr uint128(std::uint8_t const *const bytes) noexcept
Definition: uint128.hpp:116
Definition: nonpod2.cpp:40
A function object which can extract the high 64-bits from an integer type.
Definition: uint128.hpp:62
constexpr uint128(IntType const v) noexcept
Construct from an unsigned integer that's 64-bits wide or fewer.
Definition: uint128.hpp:111