Commit 82b25c4b authored by Victor Vasiliev's avatar Victor Vasiliev Committed by Commit Bot

Move net::int128 into QUIC code.

It's not used anywhere else in the code.

R=bnc@chromium.org

Change-Id: I0c6a71b161c7cd3823700b522be3a09e33369685
Reviewed-on: https://chromium-review.googlesource.com/c/1262896Reviewed-by: default avatarBence Béky <bnc@chromium.org>
Commit-Queue: Victor Vasiliev <vasilvv@chromium.org>
Cr-Commit-Position: refs/heads/master@{#597312}
parent 81a44efd
...@@ -451,8 +451,6 @@ component("net") { ...@@ -451,8 +451,6 @@ component("net") {
"base/hex_utils.h", "base/hex_utils.h",
"base/host_mapping_rules.cc", "base/host_mapping_rules.cc",
"base/host_mapping_rules.h", "base/host_mapping_rules.h",
"base/int128.cc",
"base/int128.h",
"base/iovec.h", "base/iovec.h",
"base/ip_pattern.cc", "base/ip_pattern.cc",
"base/ip_pattern.h", "base/ip_pattern.h",
...@@ -4635,7 +4633,6 @@ test("net_unittests") { ...@@ -4635,7 +4633,6 @@ test("net_unittests") {
"base/hex_utils_test.cc", "base/hex_utils_test.cc",
"base/host_mapping_rules_unittest.cc", "base/host_mapping_rules_unittest.cc",
"base/host_port_pair_unittest.cc", "base/host_port_pair_unittest.cc",
"base/int128_unittest.cc",
"base/interval_set_test.cc", "base/interval_set_test.cc",
"base/interval_test.cc", "base/interval_test.cc",
"base/ip_address_unittest.cc", "base/ip_address_unittest.cc",
...@@ -5148,6 +5145,7 @@ test("net_unittests") { ...@@ -5148,6 +5145,7 @@ test("net_unittests") {
"third_party/quic/platform/api/quic_text_utils_test.cc", "third_party/quic/platform/api/quic_text_utils_test.cc",
"third_party/quic/platform/api/quic_url_test.cc", "third_party/quic/platform/api/quic_url_test.cc",
"third_party/quic/platform/impl/quic_chromium_clock_test.cc", "third_party/quic/platform/impl/quic_chromium_clock_test.cc",
"third_party/quic/platform/impl/quic_uint128_impl_unittest.cc",
"third_party/quic/quartc/quartc_session_test.cc", "third_party/quic/quartc/quartc_session_test.cc",
"third_party/quic/quartc/quartc_stream_test.cc", "third_party/quic/quartc/quartc_stream_test.cc",
"third_party/quic/quartc/simulated_packet_transport.cc", "third_party/quic/quartc/simulated_packet_transport.cc",
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/base/int128.h"
#include <ostream>
namespace net {
const uint128_pod kuint128max = {static_cast<uint64_t>(0xFFFFFFFFFFFFFFFFULL),
static_cast<uint64_t>(0xFFFFFFFFFFFFFFFFULL)};
std::ostream& operator<<(std::ostream& o, const uint128& b) {
return (o << b.hi_ << "::" << b.lo_);
}
} // namespace net
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_BASE_INT128_H_
#define NET_BASE_INT128_H_
#include <stdint.h>
#include <iosfwd>
#include "net/base/net_export.h"
namespace net {
struct uint128_pod;
// An unsigned 128-bit integer type. Thread-compatible.
class uint128 {
public:
uint128(); // Sets to 0, but don't trust on this behavior.
uint128(uint64_t top, uint64_t bottom);
uint128(int bottom);
uint128(uint32_t bottom); // Top 96 bits = 0
uint128(uint64_t bottom); // hi_ = 0
uint128(const uint128 &val);
uint128(const uint128_pod &val);
void Initialize(uint64_t top, uint64_t bottom);
uint128& operator=(const uint128& b);
// Arithmetic operators.
// TODO: division, etc.
uint128& operator+=(const uint128& b);
uint128& operator-=(const uint128& b);
uint128& operator*=(const uint128& b);
uint128 operator++(int);
uint128 operator--(int);
uint128& operator<<=(int);
uint128& operator>>=(int);
uint128& operator&=(const uint128& b);
uint128& operator|=(const uint128& b);
uint128& operator^=(const uint128& b);
uint128& operator++();
uint128& operator--();
friend uint64_t Uint128Low64(const uint128& v);
friend uint64_t Uint128High64(const uint128& v);
// We add "std::" to avoid including all of port.h.
friend NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& o,
const uint128& 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(uint8_t);
uint128(uint16_t);
uint128(float v);
uint128(double v);
};
inline uint128 MakeUint128(uint64_t top, uint64_t bottom) {
return uint128(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_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_pod kuint128max;
// allow uint128 to be logged
NET_EXPORT_PRIVATE extern std::ostream& operator<<(std::ostream& o,
const uint128& 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& v) {
return v.lo_;
}
inline uint64_t Uint128High64(const uint128& 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& lhs, const uint128& rhs) {
return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
Uint128High64(lhs) == Uint128High64(rhs));
}
inline bool operator!=(const uint128& lhs, const uint128& rhs) {
return !(lhs == rhs);
}
inline uint128& uint128::operator=(const uint128& b) {
lo_ = b.lo_;
hi_ = b.hi_;
return *this;
}
inline uint128::uint128(): lo_(0), hi_(0) { }
inline uint128::uint128(uint64_t top, uint64_t bottom)
: lo_(bottom), hi_(top) {}
inline uint128::uint128(const uint128 &v) : lo_(v.lo_), hi_(v.hi_) { }
inline uint128::uint128(const uint128_pod &v) : lo_(v.lo), hi_(v.hi) { }
inline uint128::uint128(uint64_t bottom) : lo_(bottom), hi_(0) {}
inline uint128::uint128(uint32_t bottom) : lo_(bottom), hi_(0) {}
inline uint128::uint128(int bottom) : lo_(bottom), hi_(0) {
if (bottom < 0) {
--hi_;
}
}
inline void uint128::Initialize(uint64_t top, uint64_t bottom) {
hi_ = top;
lo_ = bottom;
}
// Comparison operators.
#define CMP128(op) \
inline bool operator op(const uint128& lhs, const uint128& 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 operator-(const uint128& 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(hi_flip + 1, lo_add);
}
return uint128(hi_flip, lo_add);
}
inline bool operator!(const uint128& val) {
return !Uint128High64(val) && !Uint128Low64(val);
}
// Logical operators.
inline uint128 operator~(const uint128& val) {
return uint128(~Uint128High64(val), ~Uint128Low64(val));
}
#define LOGIC128(op) \
inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \
return uint128(Uint128High64(lhs) op Uint128High64(rhs), \
Uint128Low64(lhs) op Uint128Low64(rhs)); \
}
LOGIC128(|)
LOGIC128(&)
LOGIC128(^)
#undef LOGIC128
#define LOGICASSIGN128(op) \
inline uint128& uint128::operator op(const uint128& other) { \
hi_ op other.hi_; \
lo_ op other.lo_; \
return *this; \
}
LOGICASSIGN128(|=)
LOGICASSIGN128(&=)
LOGICASSIGN128(^=)
#undef LOGICASSIGN128
// Shift operators.
inline uint128 operator<<(const uint128& 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(new_hi, new_lo);
} else if (amount < 128) {
return uint128(Uint128Low64(val) << (amount - 64), 0);
} else {
return uint128(0, 0);
}
}
inline uint128 operator>>(const uint128& 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(new_hi, new_lo);
} else if (amount < 128) {
return uint128(0, Uint128High64(val) >> (amount - 64));
} else {
return uint128(0, 0);
}
}
inline uint128& uint128::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& uint128::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 operator+(const uint128& lhs, const uint128& rhs) {
return uint128(lhs) += rhs;
}
inline uint128 operator-(const uint128& lhs, const uint128& rhs) {
return uint128(lhs) -= rhs;
}
inline uint128 operator*(const uint128& lhs, const uint128& rhs) {
return uint128(lhs) *= rhs;
}
inline uint128& uint128::operator+=(const uint128& b) {
hi_ += b.hi_;
uint64_t lolo = lo_ + b.lo_;
if (lolo < lo_)
++hi_;
lo_ = lolo;
return *this;
}
inline uint128& uint128::operator-=(const uint128& b) {
hi_ -= b.hi_;
if (b.lo_ > lo_)
--hi_;
lo_ -= b.lo_;
return *this;
}
inline uint128& uint128::operator*=(const uint128& 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(a32 * b00) << 32;
*this += uint128(a00 * b32) << 32;
*this += a00 * b00;
return *this;
}
inline uint128 uint128::operator++(int) {
uint128 tmp(*this);
*this += 1;
return tmp;
}
inline uint128 uint128::operator--(int) {
uint128 tmp(*this);
*this -= 1;
return tmp;
}
inline uint128& uint128::operator++() {
*this += 1;
return *this;
}
inline uint128& uint128::operator--() {
*this -= 1;
return *this;
}
} // namespace net
#endif // NET_BASE_INT128_H_
...@@ -6,26 +6,28 @@ ...@@ -6,26 +6,28 @@
#include <limits> #include <limits>
#include "base/logging.h" #include "net/third_party/quic/platform/impl/quic_uint128_impl.h"
#include "net/base/int128.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace net { namespace quic {
namespace test { namespace test {
constexpr QuicUint128Impl kuint128max(std::numeric_limits<uint64_t>::max(),
std::numeric_limits<uint64_t>::max());
TEST(Int128, AllTests) { TEST(Int128, AllTests) {
uint128 zero(0); QuicUint128Impl zero(0);
uint128 one(1); QuicUint128Impl one(1);
uint128 one_2arg(0, 1); QuicUint128Impl one_2arg(0, 1);
uint128 two(0, 2); QuicUint128Impl two(0, 2);
uint128 three(0, 3); QuicUint128Impl three(0, 3);
uint128 big(2000, 2); QuicUint128Impl big(2000, 2);
uint128 big_minus_one(2000, 1); QuicUint128Impl big_minus_one(2000, 1);
uint128 bigger(2001, 1); QuicUint128Impl bigger(2001, 1);
uint128 biggest(kuint128max); QuicUint128Impl biggest(kuint128max);
uint128 high_low(1, 0); QuicUint128Impl high_low(1, 0);
uint128 low_high(0, std::numeric_limits<uint64_t>::max()); QuicUint128Impl low_high(0, std::numeric_limits<uint64_t>::max());
EXPECT_LT(one, two); EXPECT_LT(one, two);
EXPECT_GT(two, one); EXPECT_GT(two, one);
EXPECT_LT(one, big); EXPECT_LT(one, big);
...@@ -64,8 +66,10 @@ TEST(Int128, AllTests) { ...@@ -64,8 +66,10 @@ TEST(Int128, AllTests) {
EXPECT_EQ(zero, (one >> 80) << 80); EXPECT_EQ(zero, (one >> 80) << 80);
EXPECT_EQ(zero, big >> 128); EXPECT_EQ(zero, big >> 128);
EXPECT_EQ(zero, big << 128); EXPECT_EQ(zero, big << 128);
EXPECT_EQ(Uint128High64(biggest), std::numeric_limits<uint64_t>::max()); EXPECT_EQ(QuicUint128High64Impl(biggest),
EXPECT_EQ(Uint128Low64(biggest), std::numeric_limits<uint64_t>::max()); std::numeric_limits<uint64_t>::max());
EXPECT_EQ(QuicUint128Low64Impl(biggest),
std::numeric_limits<uint64_t>::max());
EXPECT_EQ(zero + one, one); EXPECT_EQ(zero + one, one);
EXPECT_EQ(one + one, two); EXPECT_EQ(one + one, two);
EXPECT_EQ(big_minus_one + one, big); EXPECT_EQ(big_minus_one + one, big);
...@@ -79,8 +83,8 @@ TEST(Int128, AllTests) { ...@@ -79,8 +83,8 @@ TEST(Int128, AllTests) {
EXPECT_EQ(zero - 1, biggest); EXPECT_EQ(zero - 1, biggest);
EXPECT_EQ(high_low - one, low_high); EXPECT_EQ(high_low - one, low_high);
EXPECT_EQ(low_high + one, high_low); EXPECT_EQ(low_high + one, high_low);
EXPECT_EQ(Uint128High64((uint128(1) << 64) - 1), 0u); EXPECT_EQ(QuicUint128High64Impl((QuicUint128Impl(1) << 64) - 1), 0u);
EXPECT_EQ(Uint128Low64((uint128(1) << 64) - 1), EXPECT_EQ(QuicUint128Low64Impl((QuicUint128Impl(1) << 64) - 1),
std::numeric_limits<uint64_t>::max()); std::numeric_limits<uint64_t>::max());
EXPECT_TRUE(!!one); EXPECT_TRUE(!!one);
EXPECT_TRUE(!!high_low); EXPECT_TRUE(!!high_low);
...@@ -93,7 +97,7 @@ TEST(Int128, AllTests) { ...@@ -93,7 +97,7 @@ TEST(Int128, AllTests) {
EXPECT_FALSE(one == 0); EXPECT_FALSE(one == 0);
EXPECT_TRUE(one != 0); EXPECT_TRUE(one != 0);
uint128 test = zero; QuicUint128Impl test = zero;
EXPECT_EQ(++test, one); EXPECT_EQ(++test, one);
EXPECT_EQ(test, one); EXPECT_EQ(test, one);
EXPECT_EQ(test++, one); EXPECT_EQ(test++, one);
...@@ -116,98 +120,16 @@ TEST(Int128, AllTests) { ...@@ -116,98 +120,16 @@ TEST(Int128, AllTests) {
EXPECT_EQ(two, -((-one) - 1)); EXPECT_EQ(two, -((-one) - 1));
EXPECT_EQ(kuint128max, -one); EXPECT_EQ(kuint128max, -one);
EXPECT_EQ(zero, -zero); EXPECT_EQ(zero, -zero);
LOG(INFO) << one;
LOG(INFO) << big_minus_one;
}
TEST(Int128, PodTests) {
uint128_pod pod = { 12345, 67890 };
uint128 from_pod(pod);
EXPECT_EQ(12345u, Uint128High64(from_pod));
EXPECT_EQ(67890u, Uint128Low64(from_pod));
uint128 zero(0);
uint128_pod zero_pod = {0, 0};
uint128 one(1);
uint128_pod one_pod = {0, 1};
uint128 two(2);
uint128_pod two_pod = {0, 2};
uint128 three(3);
uint128_pod three_pod = {0, 3};
uint128 big(1, 0);
uint128_pod big_pod = {1, 0};
EXPECT_EQ(zero, zero_pod);
EXPECT_EQ(zero_pod, zero);
EXPECT_EQ(zero_pod, zero_pod);
EXPECT_EQ(one, one_pod);
EXPECT_EQ(one_pod, one);
EXPECT_EQ(one_pod, one_pod);
EXPECT_EQ(two, two_pod);
EXPECT_EQ(two_pod, two);
EXPECT_EQ(two_pod, two_pod);
EXPECT_NE(one, two_pod);
EXPECT_NE(one_pod, two);
EXPECT_NE(one_pod, two_pod);
EXPECT_LT(one, two_pod);
EXPECT_LT(one_pod, two);
EXPECT_LT(one_pod, two_pod);
EXPECT_LE(one, one_pod);
EXPECT_LE(one_pod, one);
EXPECT_LE(one_pod, one_pod);
EXPECT_LE(one, two_pod);
EXPECT_LE(one_pod, two);
EXPECT_LE(one_pod, two_pod);
EXPECT_GT(two, one_pod);
EXPECT_GT(two_pod, one);
EXPECT_GT(two_pod, one_pod);
EXPECT_GE(two, two_pod);
EXPECT_GE(two_pod, two);
EXPECT_GE(two_pod, two_pod);
EXPECT_GE(two, one_pod);
EXPECT_GE(two_pod, one);
EXPECT_GE(two_pod, one_pod);
EXPECT_EQ(three, one | two_pod);
EXPECT_EQ(three, one_pod | two);
EXPECT_EQ(three, one_pod | two_pod);
EXPECT_EQ(one, three & one_pod);
EXPECT_EQ(one, three_pod & one);
EXPECT_EQ(one, three_pod & one_pod);
EXPECT_EQ(two, three ^ one_pod);
EXPECT_EQ(two, three_pod ^ one);
EXPECT_EQ(two, three_pod ^ one_pod);
EXPECT_EQ(two, three & (~one));
EXPECT_EQ(three, ~~three);
EXPECT_EQ(two, two_pod << 0);
EXPECT_EQ(two, one_pod << 1);
EXPECT_EQ(big, one_pod << 64);
EXPECT_EQ(zero, one_pod << 128);
EXPECT_EQ(two, two_pod >> 0);
EXPECT_EQ(one, two_pod >> 1);
EXPECT_EQ(one, big_pod >> 64);
EXPECT_EQ(one, zero + one_pod);
EXPECT_EQ(one, zero_pod + one);
EXPECT_EQ(one, zero_pod + one_pod);
EXPECT_EQ(one, two - one_pod);
EXPECT_EQ(one, two_pod - one);
EXPECT_EQ(one, two_pod - one_pod);
} }
TEST(Int128, OperatorAssignReturnRef) { TEST(Int128, OperatorAssignReturnRef) {
uint128 v(1); QuicUint128Impl v(1);
(v += 4) -= 3; (v += 4) -= 3;
EXPECT_EQ(2, v); EXPECT_EQ(2, v);
} }
TEST(Int128, Multiply) { TEST(Int128, Multiply) {
uint128 a, b, c; QuicUint128Impl a, b, c;
// Zero test. // Zero test.
a = 0; a = 0;
...@@ -216,55 +138,55 @@ TEST(Int128, Multiply) { ...@@ -216,55 +138,55 @@ TEST(Int128, Multiply) {
EXPECT_EQ(0, c); EXPECT_EQ(0, c);
// Max carries. // Max carries.
a = uint128(0) - 1; a = QuicUint128Impl(0) - 1;
b = uint128(0) - 1; b = QuicUint128Impl(0) - 1;
c = a * b; c = a * b;
EXPECT_EQ(1, c); EXPECT_EQ(1, c);
// Self-operation with max carries. // Self-operation with max carries.
c = uint128(0) - 1; c = QuicUint128Impl(0) - 1;
c *= c; c *= c;
EXPECT_EQ(1, c); EXPECT_EQ(1, c);
// 1-bit x 1-bit. // 1-bit x 1-bit.
for (int i = 0; i < 64; ++i) { for (int i = 0; i < 64; ++i) {
for (int j = 0; j < 64; ++j) { for (int j = 0; j < 64; ++j) {
a = uint128(1) << i; a = QuicUint128Impl(1) << i;
b = uint128(1) << j; b = QuicUint128Impl(1) << j;
c = a * b; c = a * b;
EXPECT_EQ(uint128(1) << (i+j), c); EXPECT_EQ(QuicUint128Impl(1) << (i + j), c);
} }
} }
// Verified with dc. // Verified with dc.
a = uint128(0xffffeeeeddddccccULL, 0xbbbbaaaa99998888ULL); a = QuicUint128Impl(0xffffeeeeddddccccULL, 0xbbbbaaaa99998888ULL);
b = uint128(0x7777666655554444ULL, 0x3333222211110000ULL); b = QuicUint128Impl(0x7777666655554444ULL, 0x3333222211110000ULL);
c = a * b; c = a * b;
EXPECT_EQ(uint128(0x530EDA741C71D4C3ULL, 0xBF25975319080000ULL), c); EXPECT_EQ(QuicUint128Impl(0x530EDA741C71D4C3ULL, 0xBF25975319080000ULL), c);
EXPECT_EQ(0, c - b * a); EXPECT_EQ(0, c - b * a);
EXPECT_EQ(a*a - b*b, (a+b) * (a-b)); EXPECT_EQ(a * a - b * b, (a + b) * (a - b));
// Verified with dc. // Verified with dc.
a = uint128(0x0123456789abcdefULL, 0xfedcba9876543210ULL); a = QuicUint128Impl(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
b = uint128(0x02468ace13579bdfULL, 0xfdb97531eca86420ULL); b = QuicUint128Impl(0x02468ace13579bdfULL, 0xfdb97531eca86420ULL);
c = a * b; c = a * b;
EXPECT_EQ(uint128(0x97a87f4f261ba3f2ULL, 0x342d0bbf48948200ULL), c); EXPECT_EQ(QuicUint128Impl(0x97a87f4f261ba3f2ULL, 0x342d0bbf48948200ULL), c);
EXPECT_EQ(0, c - b * a); EXPECT_EQ(0, c - b * a);
EXPECT_EQ(a*a - b*b, (a+b) * (a-b)); EXPECT_EQ(a * a - b * b, (a + b) * (a - b));
} }
TEST(Int128, AliasTests) { TEST(Int128, AliasTests) {
uint128 x1(1, 2); QuicUint128Impl x1(1, 2);
uint128 x2(2, 4); QuicUint128Impl x2(2, 4);
x1 += x1; x1 += x1;
EXPECT_EQ(x2, x1); EXPECT_EQ(x2, x1);
uint128 x3(1, 1ull << 63); QuicUint128Impl x3(1, 1ull << 63);
uint128 x4(3, 0); QuicUint128Impl x4(3, 0);
x3 += x3; x3 += x3;
EXPECT_EQ(x4, x3); EXPECT_EQ(x4, x3);
} }
} // namespace test } // namespace test
} // namespace net } // namespace quic
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment