如果有对位操作的须要,可以参考 变量操作位操作数据结构
/*
* 128 位数据,文件源于chromium中,但关联有多个C文件,为方便使用重新修改和定义为一个文件,
* 128位数据类中没有除法,
* 2022-02-26 63744457@qq.com
*
* */
#ifndef _LONG_LONG_INTEGER_128_BITS_H_
#define _LONG_LONG_INTEGER_128_BITS_H_
#include <stdint.h>
#include <iosfwd>
#include <ostream>
#define NET_EXPORT
#define NET_EXPORT_PRIVATE
struct __uint128_type_pod;
// An unsigned 128-bit integer type. Thread-compatible.
class __uint128_type {
public:
__uint128_type(); // Sets to 0, but don't trust on this behavior.
__uint128_type(uint64_t top, uint64_t bottom);
__uint128_type(int bottom);
__uint128_type(uint32_t bottom); // Top 96 bits = 0
__uint128_type(uint64_t bottom); // hi_ = 0
__uint128_type(const __uint128_type &val);
__uint128_type(const __uint128_type_pod &val);
void Initialize(uint64_t top, uint64_t bottom);
__uint128_type& operator=(const __uint128_type& b);
// Arithmetic operators.
// TODO: division, etc.
__uint128_type& operator+=(const __uint128_type& b);
__uint128_type& operator-=(const __uint128_type& b);
__uint128_type& operator*=(const __uint128_type& b);
__uint128_type operator++(int);
__uint128_type operator--(int);
__uint128_type& operator<<=(int);
__uint128_type& operator>>=(int);
__uint128_type& operator&=(const __uint128_type& b);
__uint128_type& operator|=(const __uint128_type& b);
__uint128_type& operator^=(const __uint128_type& b);
__uint128_type& operator++();
__uint128_type& operator--();
friend uint64_t Uint128Low64(const __uint128_type& v);
friend uint64_t Uint128High64(const __uint128_type& v);
// We add "std::" to avoid including all of port.h.
friend NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& o,
const __uint128_type& b);
private:
// Little-endian memory order optimizations can benefit from
// having lo_ first, hi_ last.
// See util/endian/endian.h and Load128/Store128 for storing a uint128.
uint64_t lo_;
uint64_t hi_;
// Not implemented, just declared for catching automatic type conversions.
__uint128_type(uint8_t);
__uint128_type(uint16_t);
__uint128_type(float v);
__uint128_type(double v);
};
inline __uint128_type MakeUint128(uint64_t top, uint64_t bottom) {
return __uint128_type(top, bottom);
}
// This is a POD form of uint128 which can be used for static variables which
// need to be operated on as uint128.
struct __uint128_type_pod {
// Note: The ordering of fields is different than 'class uint128' but the
// same as its 2-arg constructor. This enables more obvious initialization
// of static instances, which is the primary reason for this struct in the
// first place. This does not seem to defeat any optimizations wrt
// operations involving this struct.
uint64_t hi;
uint64_t lo;
};
NET_EXPORT_PRIVATE extern const __uint128_type_pod kuint128max;
// allow uint128 to be logged
NET_EXPORT_PRIVATE extern std::ostream& operator<<(std::ostream& o,
const __uint128_type& b);
// Methods to access low and high pieces of 128-bit value.
// Defined externally from uint128 to facilitate conversion
// to native 128-bit types when compilers support them.
inline uint64_t Uint128Low64(const __uint128_type& v) {
return v.lo_;
}
inline uint64_t Uint128High64(const __uint128_type& v) {
return v.hi_;
}
// TODO: perhaps it would be nice to have int128, a signed 128-bit type?
// --------------------------------------------------------------------------
// Implementation details follow
// --------------------------------------------------------------------------
inline bool operator==(const __uint128_type& lhs, const __uint128_type& rhs) {
return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
Uint128High64(lhs) == Uint128High64(rhs));
}
inline bool operator!=(const __uint128_type& lhs, const __uint128_type& rhs) {
return !(lhs == rhs);
}
inline __uint128_type& __uint128_type::operator=(const __uint128_type& b) {
lo_ = b.lo_;
hi_ = b.hi_;
return *this;
}
inline __uint128_type::__uint128_type(): lo_(0), hi_(0) { }
inline __uint128_type::__uint128_type(uint64_t top, uint64_t bottom)
: lo_(bottom), hi_(top) {}
inline __uint128_type::__uint128_type(const __uint128_type &v) : lo_(v.lo_), hi_(v.hi_) { }
inline __uint128_type::__uint128_type(const __uint128_type_pod &v) : lo_(v.lo), hi_(v.hi) { }
inline __uint128_type::__uint128_type(uint64_t bottom) : lo_(bottom), hi_(0) {}
inline __uint128_type::__uint128_type(uint32_t bottom) : lo_(bottom), hi_(0) {}
inline __uint128_type::__uint128_type(int bottom) : lo_(bottom), hi_(0) {
if (bottom < 0) {
--hi_;
}
}
inline void __uint128_type::Initialize(uint64_t top, uint64_t bottom) {
hi_ = top;
lo_ = bottom;
}
// Comparison operators.
#define CMP128(op) \
inline bool operator op(const __uint128_type& lhs, const __uint128_type& rhs) { \
return (Uint128High64(lhs) == Uint128High64(rhs)) ? \
(Uint128Low64(lhs) op Uint128Low64(rhs)) : \
(Uint128High64(lhs) op Uint128High64(rhs)); \
}
CMP128(<)
CMP128(>)
CMP128(>=)
CMP128(<=)
#undef CMP128
// Unary operators
inline __uint128_type operator-(const __uint128_type& val) {
const uint64_t hi_flip = ~Uint128High64(val);
const uint64_t lo_flip = ~Uint128Low64(val);
const uint64_t lo_add = lo_flip + 1;
if (lo_add < lo_flip) {
return __uint128_type(hi_flip + 1, lo_add);
}
return __uint128_type(hi_flip, lo_add);
}
inline bool operator!(const __uint128_type& val) {
return !Uint128High64(val) && !Uint128Low64(val);
}
// Logical operators.
inline __uint128_type operator~(const __uint128_type& val) {
return __uint128_type(~Uint128High64(val), ~Uint128Low64(val));
}
#define LOGIC128(op) \
inline __uint128_type operator op(const __uint128_type& lhs, const __uint128_type& rhs) { \
return __uint128_type(Uint128High64(lhs) op Uint128High64(rhs), \
Uint128Low64(lhs) op Uint128Low64(rhs)); \
}
LOGIC128(|)
LOGIC128(&)
LOGIC128(^)
#undef LOGIC128
#define LOGICASSIGN128(op) \
inline __uint128_type& __uint128_type::operator op(const __uint128_type& other) { \
hi_ op other.hi_; \
lo_ op other.lo_; \
return *this; \
}
LOGICASSIGN128(|=)
LOGICASSIGN128(&=)
LOGICASSIGN128(^=)
#undef LOGICASSIGN128
;
// Shift operators.
inline __uint128_type operator<<(const __uint128_type& val, int amount)
{
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
if (amount < 64) {
if (amount == 0) {
return val;
}
uint64_t new_hi =
(Uint128High64(val) << amount) | (Uint128Low64(val) >> (64 - amount));
uint64_t new_lo = Uint128Low64(val) << amount;
return __uint128_type(new_hi, new_lo);
} else if (amount < 128) {
return __uint128_type(Uint128Low64(val) << (amount - 64), 0);
} else {
return __uint128_type(0, 0);
}
}
inline __uint128_type operator>>(const __uint128_type& val, int amount) {
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
if (amount < 64) {
if (amount == 0) {
return val;
}
uint64_t new_hi = Uint128High64(val) >> amount;
uint64_t new_lo =
(Uint128Low64(val) >> amount) | (Uint128High64(val) << (64 - amount));
return __uint128_type(new_hi, new_lo);
} else if (amount < 128) {
return __uint128_type(0, Uint128High64(val) >> (amount - 64));
} else {
return __uint128_type(0, 0);
}
}
inline __uint128_type& __uint128_type::operator<<=(int amount) {
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
if (amount < 64) {
if (amount != 0) {
hi_ = (hi_ << amount) | (lo_ >> (64 - amount));
lo_ = lo_ << amount;
}
} else if (amount < 128) {
hi_ = lo_ << (amount - 64);
lo_ = 0;
} else {
hi_ = 0;
lo_ = 0;
}
return *this;
}
inline __uint128_type& __uint128_type::operator>>=(int amount) {
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
if (amount < 64) {
if (amount != 0) {
lo_ = (lo_ >> amount) | (hi_ << (64 - amount));
hi_ = hi_ >> amount;
}
} else if (amount < 128) {
hi_ = 0;
lo_ = hi_ >> (amount - 64);
} else {
hi_ = 0;
lo_ = 0;
}
return *this;
}
inline __uint128_type operator+(const __uint128_type& lhs, const __uint128_type& rhs) {
return __uint128_type(lhs) += rhs;
}
inline __uint128_type operator-(const __uint128_type& lhs, const __uint128_type& rhs) {
return __uint128_type(lhs) -= rhs;
}
inline __uint128_type operator*(const __uint128_type& lhs, const __uint128_type& rhs) {
return __uint128_type(lhs) *= rhs;
}
inline __uint128_type& __uint128_type::operator+=(const __uint128_type& b) {
hi_ += b.hi_;
uint64_t lolo = lo_ + b.lo_;
if (lolo < lo_)
++hi_;
lo_ = lolo;
return *this;
}
inline __uint128_type& __uint128_type::operator-=(const __uint128_type& b) {
hi_ -= b.hi_;
if (b.lo_ > lo_)
--hi_;
lo_ -= b.lo_;
return *this;
}
inline __uint128_type& __uint128_type::operator*=(const __uint128_type& b) {
uint64_t a96 = hi_ >> 32;
uint64_t a64 = hi_ & 0xffffffffu;
uint64_t a32 = lo_ >> 32;
uint64_t a00 = lo_ & 0xffffffffu;
uint64_t b96 = b.hi_ >> 32;
uint64_t b64 = b.hi_ & 0xffffffffu;
uint64_t b32 = b.lo_ >> 32;
uint64_t b00 = b.lo_ & 0xffffffffu;
// multiply [a96 .. a00] x [b96 .. b00]
// terms higher than c96 disappear off the high side
// terms c96 and c64 are safe to ignore carry bit
uint64_t c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96;
uint64_t c64 = a64 * b00 + a32 * b32 + a00 * b64;
this->hi_ = (c96 << 32) + c64;
this->lo_ = 0;
// add terms after this one at a time to capture carry
*this += __uint128_type(a32 * b00) << 32;
*this += __uint128_type(a00 * b32) << 32;
*this += a00 * b00;
return *this;
}
inline __uint128_type __uint128_type::operator++(int) {
__uint128_type tmp(*this);
*this += 1;
return tmp;
}
inline __uint128_type __uint128_type::operator--(int) {
__uint128_type tmp(*this);
*this -= 1;
return tmp;
}
inline __uint128_type& __uint128_type::operator++() {
*this += 1;
return *this;
}
inline __uint128_type& __uint128_type::operator--() {
*this -= 1;
return *this;
}
#define kuint128max (const __uint128_type_pod ){ \
static_cast<uint64_t>(0xFFFFFFFFFFFFFFFFULL),\
static_cast<uint64_t>(0xFFFFFFFFFFFFFFFFULL)\
}
inline std::ostream& operator<<(std::ostream& o, const __uint128_type& b)
{
return (o << b.hi_ << "::" << b.lo_);
}
#endif // NET_BASE_INT128_H_