|  | @@ -262,21 +262,50 @@ inline uint128& uint128::operator=(unsigned __int128 v) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  #endif  // ABSL_HAVE_INTRINSIC_INT128
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// Shift and arithmetic operators.
 | 
	
		
			
				|  |  | +// Arithmetic operators.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128 operator<<(uint128 lhs, int amount) { return lhs <<= amount; }
 | 
	
		
			
				|  |  | +uint128 operator<<(uint128 lhs, int amount);
 | 
	
		
			
				|  |  | +uint128 operator>>(uint128 lhs, int amount);
 | 
	
		
			
				|  |  | +uint128 operator+(uint128 lhs, uint128 rhs);
 | 
	
		
			
				|  |  | +uint128 operator-(uint128 lhs, uint128 rhs);
 | 
	
		
			
				|  |  | +uint128 operator*(uint128 lhs, uint128 rhs);
 | 
	
		
			
				|  |  | +uint128 operator/(uint128 lhs, uint128 rhs);
 | 
	
		
			
				|  |  | +uint128 operator%(uint128 lhs, uint128 rhs);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128 operator>>(uint128 lhs, int amount) { return lhs >>= amount; }
 | 
	
		
			
				|  |  | +inline uint128& uint128::operator<<=(int amount) {
 | 
	
		
			
				|  |  | +  *this = *this << amount;
 | 
	
		
			
				|  |  | +  return *this;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128 operator+(uint128 lhs, uint128 rhs) { return lhs += rhs; }
 | 
	
		
			
				|  |  | +inline uint128& uint128::operator>>=(int amount) {
 | 
	
		
			
				|  |  | +  *this = *this >> amount;
 | 
	
		
			
				|  |  | +  return *this;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128 operator-(uint128 lhs, uint128 rhs) { return lhs -= rhs; }
 | 
	
		
			
				|  |  | +inline uint128& uint128::operator+=(uint128 other) {
 | 
	
		
			
				|  |  | +  *this = *this + other;
 | 
	
		
			
				|  |  | +  return *this;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128 operator*(uint128 lhs, uint128 rhs) { return lhs *= rhs; }
 | 
	
		
			
				|  |  | +inline uint128& uint128::operator-=(uint128 other) {
 | 
	
		
			
				|  |  | +  *this = *this - other;
 | 
	
		
			
				|  |  | +  return *this;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128 operator/(uint128 lhs, uint128 rhs) { return lhs /= rhs; }
 | 
	
		
			
				|  |  | +inline uint128& uint128::operator*=(uint128 other) {
 | 
	
		
			
				|  |  | +  *this = *this * other;
 | 
	
		
			
				|  |  | +  return *this;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128 operator%(uint128 lhs, uint128 rhs) { return lhs %= rhs; }
 | 
	
		
			
				|  |  | +inline uint128& uint128::operator/=(uint128 other) {
 | 
	
		
			
				|  |  | +  *this = *this / other;
 | 
	
		
			
				|  |  | +  return *this;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +inline uint128& uint128::operator%=(uint128 other) {
 | 
	
		
			
				|  |  | +  *this = *this % other;
 | 
	
		
			
				|  |  | +  return *this;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  constexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -514,9 +543,9 @@ inline uint128& uint128::operator^=(uint128 other) {
 | 
	
		
			
				|  |  |    return *this;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// Shift and arithmetic assign operators.
 | 
	
		
			
				|  |  | +// Arithmetic operators.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128& uint128::operator<<=(int amount) {
 | 
	
		
			
				|  |  | +inline uint128 operator<<(uint128 lhs, int amount) {
 | 
	
		
			
				|  |  |    assert(amount >= 0);   // Negative shifts are undefined.
 | 
	
		
			
				|  |  |    assert(amount < 128);  // Shifts of >= 128 are undefined.
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -524,17 +553,16 @@ inline uint128& uint128::operator<<=(int amount) {
 | 
	
		
			
				|  |  |    // special-casing.
 | 
	
		
			
				|  |  |    if (amount < 64) {
 | 
	
		
			
				|  |  |      if (amount != 0) {
 | 
	
		
			
				|  |  | -      hi_ = (hi_ << amount) | (lo_ >> (64 - amount));
 | 
	
		
			
				|  |  | -      lo_ = lo_ << amount;
 | 
	
		
			
				|  |  | +      return MakeUint128(
 | 
	
		
			
				|  |  | +          (Uint128High64(lhs) << amount) | (Uint128Low64(lhs) >> (64 - amount)),
 | 
	
		
			
				|  |  | +          Uint128Low64(lhs) << amount);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    hi_ = lo_ << (amount - 64);
 | 
	
		
			
				|  |  | -    lo_ = 0;
 | 
	
		
			
				|  |  | +    return lhs;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return *this;
 | 
	
		
			
				|  |  | +  return MakeUint128(Uint128Low64(lhs) << (amount - 64), 0);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128& uint128::operator>>=(int amount) {
 | 
	
		
			
				|  |  | +inline uint128 operator>>(uint128 lhs, int amount) {
 | 
	
		
			
				|  |  |    assert(amount >= 0);   // Negative shifts are undefined.
 | 
	
		
			
				|  |  |    assert(amount < 128);  // Shifts of >= 128 are undefined.
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -542,49 +570,51 @@ inline uint128& uint128::operator>>=(int amount) {
 | 
	
		
			
				|  |  |    // special-casing.
 | 
	
		
			
				|  |  |    if (amount < 64) {
 | 
	
		
			
				|  |  |      if (amount != 0) {
 | 
	
		
			
				|  |  | -      lo_ = (lo_ >> amount) | (hi_ << (64 - amount));
 | 
	
		
			
				|  |  | -      hi_ = hi_ >> amount;
 | 
	
		
			
				|  |  | +      return MakeUint128(Uint128High64(lhs) >> amount,
 | 
	
		
			
				|  |  | +                         (Uint128Low64(lhs) >> amount) |
 | 
	
		
			
				|  |  | +                             (Uint128High64(lhs) << (64 - amount)));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    lo_ = hi_ >> (amount - 64);
 | 
	
		
			
				|  |  | -    hi_ = 0;
 | 
	
		
			
				|  |  | +    return lhs;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return *this;
 | 
	
		
			
				|  |  | +  return MakeUint128(0, Uint128High64(lhs) >> (amount - 64));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128& uint128::operator+=(uint128 other) {
 | 
	
		
			
				|  |  | -  hi_ += other.hi_;
 | 
	
		
			
				|  |  | -  uint64_t lolo = lo_ + other.lo_;
 | 
	
		
			
				|  |  | -  if (lolo < lo_)
 | 
	
		
			
				|  |  | -    ++hi_;
 | 
	
		
			
				|  |  | -  lo_ = lolo;
 | 
	
		
			
				|  |  | -  return *this;
 | 
	
		
			
				|  |  | +inline uint128 operator+(uint128 lhs, uint128 rhs) {
 | 
	
		
			
				|  |  | +  uint128 result = MakeUint128(Uint128High64(lhs) + Uint128High64(rhs),
 | 
	
		
			
				|  |  | +                               Uint128Low64(lhs) + Uint128Low64(rhs));
 | 
	
		
			
				|  |  | +  if (Uint128Low64(result) < Uint128Low64(lhs)) {  // check for carry
 | 
	
		
			
				|  |  | +    return MakeUint128(Uint128High64(result) + 1, Uint128Low64(result));
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return result;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128& uint128::operator-=(uint128 other) {
 | 
	
		
			
				|  |  | -  hi_ -= other.hi_;
 | 
	
		
			
				|  |  | -  if (other.lo_ > lo_) --hi_;
 | 
	
		
			
				|  |  | -  lo_ -= other.lo_;
 | 
	
		
			
				|  |  | -  return *this;
 | 
	
		
			
				|  |  | +inline uint128 operator-(uint128 lhs, uint128 rhs) {
 | 
	
		
			
				|  |  | +  uint128 result = MakeUint128(Uint128High64(lhs) - Uint128High64(rhs),
 | 
	
		
			
				|  |  | +                               Uint128Low64(lhs) - Uint128Low64(rhs));
 | 
	
		
			
				|  |  | +  if (Uint128Low64(lhs) < Uint128Low64(rhs)) {  // check for carry
 | 
	
		
			
				|  |  | +    return MakeUint128(Uint128High64(result) - 1, Uint128Low64(result));
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return result;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -inline uint128& uint128::operator*=(uint128 other) {
 | 
	
		
			
				|  |  | +inline uint128 operator*(uint128 lhs, uint128 rhs) {
 | 
	
		
			
				|  |  |  #if defined(ABSL_HAVE_INTRINSIC_INT128)
 | 
	
		
			
				|  |  |    // TODO(strel) Remove once alignment issues are resolved and unsigned __int128
 | 
	
		
			
				|  |  |    // can be used for uint128 storage.
 | 
	
		
			
				|  |  | -  *this = static_cast<unsigned __int128>(*this) *
 | 
	
		
			
				|  |  | -          static_cast<unsigned __int128>(other);
 | 
	
		
			
				|  |  | -  return *this;
 | 
	
		
			
				|  |  | +  return static_cast<unsigned __int128>(lhs) *
 | 
	
		
			
				|  |  | +         static_cast<unsigned __int128>(rhs);
 | 
	
		
			
				|  |  |  #else   // ABSL_HAVE_INTRINSIC128
 | 
	
		
			
				|  |  | -  uint64_t a32 = lo_ >> 32;
 | 
	
		
			
				|  |  | -  uint64_t a00 = lo_ & 0xffffffff;
 | 
	
		
			
				|  |  | -  uint64_t b32 = other.lo_ >> 32;
 | 
	
		
			
				|  |  | -  uint64_t b00 = other.lo_ & 0xffffffff;
 | 
	
		
			
				|  |  | -  hi_ = hi_ * other.lo_ + lo_ * other.hi_ + a32 * b32;
 | 
	
		
			
				|  |  | -  lo_ = a00 * b00;
 | 
	
		
			
				|  |  | -  *this += uint128(a32 * b00) << 32;
 | 
	
		
			
				|  |  | -  *this += uint128(a00 * b32) << 32;
 | 
	
		
			
				|  |  | -  return *this;
 | 
	
		
			
				|  |  | +  uint64_t a32 = Uint128Low64(lhs) >> 32;
 | 
	
		
			
				|  |  | +  uint64_t a00 = Uint128Low64(lhs) & 0xffffffff;
 | 
	
		
			
				|  |  | +  uint64_t b32 = Uint128Low64(rhs) >> 32;
 | 
	
		
			
				|  |  | +  uint64_t b00 = Uint128Low64(rhs) & 0xffffffff;
 | 
	
		
			
				|  |  | +  uint128 result =
 | 
	
		
			
				|  |  | +      MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) +
 | 
	
		
			
				|  |  | +                      Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32,
 | 
	
		
			
				|  |  | +                  a00 * b00);
 | 
	
		
			
				|  |  | +  result += uint128(a32 * b00) << 32;
 | 
	
		
			
				|  |  | +  result += uint128(a00 * b32) << 32;
 | 
	
		
			
				|  |  | +  return result;
 | 
	
		
			
				|  |  |  #endif  // ABSL_HAVE_INTRINSIC128
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |