summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-16 07:49:44 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-16 07:49:44 +0000
commit165e075e714fdeaf93b5b4bedb4edcfbe69a0880 (patch)
tree1b6375e7bd44767f55789648d3b70c55178559b2
parent65bfb61c032e78f7315a971223fd5aa942e4da99 (diff)
downloadchromium_src-165e075e714fdeaf93b5b4bedb4edcfbe69a0880.zip
chromium_src-165e075e714fdeaf93b5b4bedb4edcfbe69a0880.tar.gz
chromium_src-165e075e714fdeaf93b5b4bedb4edcfbe69a0880.tar.bz2
Add real support for uint128. These files originated with google internally, and since they are shared, the style is a bit different. Removed SWIG support and references to other internal classes.
Review URL: https://chromiumcodereview.appspot.com/11299023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@168161 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/base/int128.cc16
-rw-r--r--net/base/int128.h330
-rw-r--r--net/base/int128_unittest.cc265
-rw-r--r--net/net.gyp3
-rw-r--r--net/quic/crypto/null_decrypter_test.cc6
-rw-r--r--net/quic/crypto/null_encrypter_test.cc6
-rw-r--r--net/quic/quic_data_reader.h2
-rw-r--r--net/quic/quic_data_writer.cc8
-rw-r--r--net/quic/quic_data_writer.h2
-rw-r--r--net/quic/quic_protocol.h2
-rw-r--r--net/quic/quic_utils.h2
-rw-r--r--net/quic/uint128.h39
12 files changed, 623 insertions, 58 deletions
diff --git a/net/base/int128.cc b/net/base/int128.cc
new file mode 100644
index 0000000..745d8ed
--- /dev/null
+++ b/net/base/int128.cc
@@ -0,0 +1,16 @@
+// 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 <iostream>
+#include "base/basictypes.h"
+#include "net/base/int128.h"
+
+const uint128_pod kuint128max = {
+ static_cast<uint64>(GG_LONGLONG(0xFFFFFFFFFFFFFFFF)),
+ static_cast<uint64>(GG_LONGLONG(0xFFFFFFFFFFFFFFFF))
+};
+
+std::ostream& operator<<(std::ostream& o, const uint128& b) {
+ return (o << b.hi_ << "::" << b.lo_);
+}
diff --git a/net/base/int128.h b/net/base/int128.h
new file mode 100644
index 0000000..b17801be
--- /dev/null
+++ b/net/base/int128.h
@@ -0,0 +1,330 @@
+// 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 <iosfwd>
+#include "base/basictypes.h"
+#include "net/base/net_export.h"
+
+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 top, uint64 bottom);
+ uint128(int bottom);
+ uint128(uint32 bottom); // Top 96 bits = 0
+ uint128(uint64 bottom); // hi_ = 0
+ uint128(const uint128 &val);
+ uint128(const uint128_pod &val);
+
+ void Initialize(uint64 top, uint64 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 Uint128Low64(const uint128& v);
+ friend uint64 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 lo_;
+ uint64 hi_;
+
+ // Not implemented, just declared for catching automatic type conversions.
+ uint128(uint8);
+ uint128(uint16);
+ uint128(float v);
+ uint128(double v);
+};
+
+// 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 hi;
+ uint64 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 Uint128Low64(const uint128& v) { return v.lo_; }
+inline uint64 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 top, uint64 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 bottom) : lo_(bottom), hi_(0) { }
+inline uint128::uint128(uint32 bottom) : lo_(bottom), hi_(0) { }
+inline uint128::uint128(int bottom) : lo_(bottom), hi_(0) {
+ if (bottom < 0) {
+ --hi_;
+ }
+}
+inline void uint128::Initialize(uint64 top, uint64 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 hi_flip = ~Uint128High64(val);
+ const uint64 lo_flip = ~Uint128Low64(val);
+ const uint64 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 shifts of >= 64 are undefined, so we will need some special-casing.
+ if (amount < 64) {
+ if (amount == 0) {
+ return val;
+ }
+ uint64 new_hi = (Uint128High64(val) << amount) |
+ (Uint128Low64(val) >> (64 - amount));
+ uint64 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 shifts of >= 64 are undefined, so we will need some special-casing.
+ if (amount < 64) {
+ if (amount == 0) {
+ return val;
+ }
+ uint64 new_hi = Uint128High64(val) >> amount;
+ uint64 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 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 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 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 a96 = hi_ >> 32;
+ uint64 a64 = hi_ & 0xffffffffu;
+ uint64 a32 = lo_ >> 32;
+ uint64 a00 = lo_ & 0xffffffffu;
+ uint64 b96 = b.hi_ >> 32;
+ uint64 b64 = b.hi_ & 0xffffffffu;
+ uint64 b32 = b.lo_ >> 32;
+ uint64 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 c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96;
+ uint64 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;
+}
+
+#endif // NET_BASE_INT128_H_
diff --git a/net/base/int128_unittest.cc b/net/base/int128_unittest.cc
new file mode 100644
index 0000000..78790e7
--- /dev/null
+++ b/net/base/int128_unittest.cc
@@ -0,0 +1,265 @@
+// 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 "base/basictypes.h"
+#include "base/logging.h"
+#include "net/base/int128.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+
+TEST(Int128, AllTests) {
+ uint128 zero(0);
+ uint128 one(1);
+ uint128 one_2arg(0, 1);
+ uint128 two(0, 2);
+ uint128 three(0, 3);
+ uint128 big(2000, 2);
+ uint128 big_minus_one(2000, 1);
+ uint128 bigger(2001, 1);
+ uint128 biggest(kuint128max);
+ uint128 high_low(1, 0);
+ uint128 low_high(0, kuint64max);
+ EXPECT_LT(one, two);
+ EXPECT_GT(two, one);
+ EXPECT_LT(one, big);
+ EXPECT_LT(one, big);
+ EXPECT_EQ(one, one_2arg);
+ EXPECT_NE(one, two);
+ EXPECT_GT(big, one);
+ EXPECT_GE(big, two);
+ EXPECT_GE(big, big_minus_one);
+ EXPECT_GT(big, big_minus_one);
+ EXPECT_LT(big_minus_one, big);
+ EXPECT_LE(big_minus_one, big);
+ EXPECT_NE(big_minus_one, big);
+ EXPECT_LT(big, biggest);
+ EXPECT_LE(big, biggest);
+ EXPECT_GT(biggest, big);
+ EXPECT_GE(biggest, big);
+ EXPECT_EQ(big, ~~big);
+ EXPECT_EQ(one, one | one);
+ EXPECT_EQ(big, big | big);
+ EXPECT_EQ(one, one | zero);
+ EXPECT_EQ(one, one & one);
+ EXPECT_EQ(big, big & big);
+ EXPECT_EQ(zero, one & zero);
+ EXPECT_EQ(zero, big & ~big);
+ EXPECT_EQ(zero, one ^ one);
+ EXPECT_EQ(zero, big ^ big);
+ EXPECT_EQ(one, one ^ zero);
+ EXPECT_EQ(big, big << 0);
+ EXPECT_EQ(big, big >> 0);
+ EXPECT_GT(big << 1, big);
+ EXPECT_LT(big >> 1, big);
+ EXPECT_EQ(big, (big << 10) >> 10);
+ EXPECT_EQ(big, (big >> 1) << 1);
+ EXPECT_EQ(one, (one << 80) >> 80);
+ EXPECT_EQ(zero, (one >> 80) << 80);
+ EXPECT_EQ(zero, big >> 128);
+ EXPECT_EQ(zero, big << 128);
+ EXPECT_EQ(Uint128High64(biggest), kuint64max);
+ EXPECT_EQ(Uint128Low64(biggest), kuint64max);
+ EXPECT_EQ(zero + one, one);
+ EXPECT_EQ(one + one, two);
+ EXPECT_EQ(big_minus_one + one, big);
+ EXPECT_EQ(one - one, zero);
+ EXPECT_EQ(one - zero, one);
+ EXPECT_EQ(zero - one, biggest);
+ EXPECT_EQ(big - big, zero);
+ EXPECT_EQ(big - one, big_minus_one);
+ EXPECT_EQ(big + kuint64max, bigger);
+ EXPECT_EQ(biggest + 1, zero);
+ EXPECT_EQ(zero - 1, biggest);
+ EXPECT_EQ(high_low - one, low_high);
+ EXPECT_EQ(low_high + one, high_low);
+ EXPECT_EQ(Uint128High64((uint128(1) << 64) - 1), 0u);
+ EXPECT_EQ(Uint128Low64((uint128(1) << 64) - 1), kuint64max);
+ EXPECT_TRUE(!!one);
+ EXPECT_TRUE(!!high_low);
+ EXPECT_FALSE(!!zero);
+ EXPECT_FALSE(!one);
+ EXPECT_FALSE(!high_low);
+ EXPECT_TRUE(!zero);
+ EXPECT_TRUE(zero == 0);
+ EXPECT_FALSE(zero != 0);
+ EXPECT_FALSE(one == 0);
+ EXPECT_TRUE(one != 0);
+
+ uint128 test = zero;
+ EXPECT_EQ(++test, one);
+ EXPECT_EQ(test, one);
+ EXPECT_EQ(test++, one);
+ EXPECT_EQ(test, two);
+ EXPECT_EQ(test -= 2, zero);
+ EXPECT_EQ(test, zero);
+ EXPECT_EQ(test += 2, two);
+ EXPECT_EQ(test, two);
+ EXPECT_EQ(--test, one);
+ EXPECT_EQ(test, one);
+ EXPECT_EQ(test--, one);
+ EXPECT_EQ(test, zero);
+ EXPECT_EQ(test |= three, three);
+ EXPECT_EQ(test &= one, one);
+ EXPECT_EQ(test ^= three, two);
+ EXPECT_EQ(test >>= 1, one);
+ EXPECT_EQ(test <<= 1, two);
+
+ EXPECT_EQ(big, -(-big));
+ EXPECT_EQ(two, -((-one) - 1));
+ EXPECT_EQ(kuint128max, -one);
+ 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) {
+ uint128 v(1);
+ (v += 4) -= 3;
+ EXPECT_EQ(2, v);
+}
+
+TEST(Int128, Multiply) {
+ uint128 a, b, c;
+
+ // Zero test.
+ a = 0;
+ b = 0;
+ c = a * b;
+ EXPECT_EQ(0, c);
+
+ // Max carries.
+ a = uint128(0) - 1;
+ b = uint128(0) - 1;
+ c = a * b;
+ EXPECT_EQ(1, c);
+
+ // Self-operation with max carries.
+ c = uint128(0) - 1;
+ c *= c;
+ EXPECT_EQ(1, c);
+
+ // 1-bit x 1-bit.
+ for (int i = 0; i < 64; ++i) {
+ for (int j = 0; j < 64; ++j) {
+ a = uint128(1) << i;
+ b = uint128(1) << j;
+ c = a * b;
+ EXPECT_EQ(uint128(1) << (i+j), c);
+ }
+ }
+
+ // Verified with dc.
+ a = uint128(GG_ULONGLONG(0xffffeeeeddddcccc),
+ GG_ULONGLONG(0xbbbbaaaa99998888));
+ b = uint128(GG_ULONGLONG(0x7777666655554444),
+ GG_ULONGLONG(0x3333222211110000));
+ c = a * b;
+ EXPECT_EQ(uint128(GG_ULONGLONG(0x530EDA741C71D4C3),
+ GG_ULONGLONG(0xBF25975319080000)), c);
+ EXPECT_EQ(0, c - b * a);
+ EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
+
+ // Verified with dc.
+ a = uint128(GG_ULONGLONG(0x0123456789abcdef),
+ GG_ULONGLONG(0xfedcba9876543210));
+ b = uint128(GG_ULONGLONG(0x02468ace13579bdf),
+ GG_ULONGLONG(0xfdb97531eca86420));
+ c = a * b;
+ EXPECT_EQ(uint128(GG_ULONGLONG(0x97a87f4f261ba3f2),
+ GG_ULONGLONG(0x342d0bbf48948200)), c);
+ EXPECT_EQ(0, c - b * a);
+ EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
+}
+
+TEST(Int128, AliasTests) {
+ uint128 x1(1, 2);
+ uint128 x2(2, 4);
+ x1 += x1;
+ EXPECT_EQ(x2, x1);
+
+ uint128 x3(1, 1ull << 63);
+ uint128 x4(3, 0);
+ x3 += x3;
+ EXPECT_EQ(x4, x3);
+}
diff --git a/net/net.gyp b/net/net.gyp
index 1f67e52..9877ae0 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -143,6 +143,8 @@
'base/file_stream_whence.h',
'base/filter.cc',
'base/filter.h',
+ 'base/int128.cc',
+ 'base/int128.h',
'base/gzip_filter.cc',
'base/gzip_filter.h',
'base/gzip_header.cc',
@@ -1269,6 +1271,7 @@
'base/expiring_cache_unittest.cc',
'base/file_stream_unittest.cc',
'base/filter_unittest.cc',
+ 'base/int128_unittest.cc',
'base/gzip_filter_unittest.cc',
'base/host_cache_unittest.cc',
'base/host_mapping_rules_unittest.cc',
diff --git a/net/quic/crypto/null_decrypter_test.cc b/net/quic/crypto/null_decrypter_test.cc
index 6c914d7..71f1970 100644
--- a/net/quic/crypto/null_decrypter_test.cc
+++ b/net/quic/crypto/null_decrypter_test.cc
@@ -14,16 +14,10 @@ namespace test {
TEST(NullDecrypterTest, Decrypt) {
unsigned char expected[] = {
// fnv hash
- 0x07, 0x2d, 0x42, 0xf0,
- 0xbe, 0x69, 0x12, 0x3d,
- 0x20, 0x80, 0x5f, 0x9a,
- 0x84, 0x9d, 0xd6, 0x0a,
- /* TODO(rch): replace this when uint128 multiplication is implemented.
0x47, 0x11, 0xea, 0x5f,
0xcf, 0x1d, 0x66, 0x5b,
0xba, 0xf0, 0xbc, 0xfd,
0x88, 0x79, 0xca, 0x37,
- */
// payload
'g', 'o', 'o', 'd',
'b', 'y', 'e', '!',
diff --git a/net/quic/crypto/null_encrypter_test.cc b/net/quic/crypto/null_encrypter_test.cc
index a71ee34..f027af4 100644
--- a/net/quic/crypto/null_encrypter_test.cc
+++ b/net/quic/crypto/null_encrypter_test.cc
@@ -14,16 +14,10 @@ namespace test {
TEST(NullEncrypterTest, Encrypt) {
unsigned char expected[] = {
// fnv hash
- 0x07, 0x2d, 0x42, 0xf0,
- 0xbe, 0x69, 0x12, 0x3d,
- 0x20, 0x80, 0x5f, 0x9a,
- 0x84, 0x9d, 0xd6, 0x0a,
- /* TODO(rch): use this when uint128 multiplication is implemented.
0x47, 0x11, 0xea, 0x5f,
0xcf, 0x1d, 0x66, 0x5b,
0xba, 0xf0, 0xbc, 0xfd,
0x88, 0x79, 0xca, 0x37,
- */
// payload
'g', 'o', 'o', 'd',
'b', 'y', 'e', '!',
diff --git a/net/quic/quic_data_reader.h b/net/quic/quic_data_reader.h
index c03c0a9..46f37bf 100644
--- a/net/quic/quic_data_reader.h
+++ b/net/quic/quic_data_reader.h
@@ -7,8 +7,8 @@
#include "base/basictypes.h"
#include "base/string_piece.h"
+#include "net/base/int128.h"
#include "net/base/net_export.h"
-#include "net/quic/uint128.h"
namespace net {
diff --git a/net/quic/quic_data_writer.cc b/net/quic/quic_data_writer.cc
index 1db9f30..42b5dc4 100644
--- a/net/quic/quic_data_writer.cc
+++ b/net/quic/quic_data_writer.cc
@@ -56,7 +56,7 @@ bool QuicDataWriter::WriteUInt64(uint64 value) {
}
bool QuicDataWriter::WriteUInt128(uint128 value) {
- return WriteUInt64(value.lo) && WriteUInt64(value.hi);
+ return WriteUInt64(Uint128Low64(value)) && WriteUInt64(Uint128High64(value));
}
bool QuicDataWriter::WriteStringPiece16(StringPiece val) {
@@ -117,8 +117,10 @@ void QuicDataWriter::WriteUint64ToBuffer(uint64 value, char* buffer) {
}
void QuicDataWriter::WriteUint128ToBuffer(uint128 value, char* buffer) {
- WriteUint64ToBuffer(value.lo, buffer);
- WriteUint64ToBuffer(value.hi, buffer + sizeof(value.lo));
+ uint64 high = Uint128High64(value);
+ uint64 low = Uint128Low64(value);
+ WriteUint64ToBuffer(low, buffer);
+ WriteUint64ToBuffer(high, buffer + sizeof(low));
}
} // namespace net
diff --git a/net/quic/quic_data_writer.h b/net/quic/quic_data_writer.h
index 0171e52..e03bb83 100644
--- a/net/quic/quic_data_writer.h
+++ b/net/quic/quic_data_writer.h
@@ -11,9 +11,9 @@
#include "base/logging.h"
#include "base/port.h"
#include "base/string_piece.h"
+#include "net/base/int128.h"
#include "net/base/net_export.h"
#include "net/quic/quic_protocol.h"
-#include "net/quic/uint128.h"
namespace net {
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index fb45cf0..25759aa 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -14,9 +14,9 @@
#include "base/hash_tables.h"
#include "base/logging.h"
#include "base/string_piece.h"
+#include "net/base/int128.h"
#include "net/base/net_export.h"
#include "net/quic/quic_time.h"
-#include "net/quic/uint128.h"
namespace net {
diff --git a/net/quic/quic_utils.h b/net/quic/quic_utils.h
index 8a49de2..4aab06f 100644
--- a/net/quic/quic_utils.h
+++ b/net/quic/quic_utils.h
@@ -7,9 +7,9 @@
#ifndef NET_QUIC_QUIC_UTILS_H_
#define NET_QUIC_QUIC_UTILS_H_
+#include "net/base/int128.h"
#include "net/base/net_export.h"
#include "net/quic/quic_protocol.h"
-#include "net/quic/uint128.h"
class IPAddress;
class IPEndPoint;
diff --git a/net/quic/uint128.h b/net/quic/uint128.h
deleted file mode 100644
index ce44b55..0000000
--- a/net/quic/uint128.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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_QUIC_UINT128_H_
-#define NET_QUIC_UINT128_H_
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-
-namespace net {
-
-struct uint128 {
- uint128() : hi(0), lo(0) {}
- uint128(uint64 hi, uint64 lo) : hi(hi), lo(lo) {}
- uint64 hi;
- uint64 lo;
-};
-
-inline uint128 operator ^(const uint128& lhs, const uint128& rhs) {
- return uint128(lhs.hi ^ rhs.hi, lhs.lo ^ rhs.lo);
-}
-
-inline uint128 operator *(const uint128& lhs, const uint128& rhs) {
- // TODO(rch): correctly implement uint128 multiplication.
- return lhs ^ rhs;
-}
-
-inline bool operator ==(const uint128& lhs, const uint128& rhs) {
- return lhs.hi == rhs.hi && lhs.lo == rhs.lo;
-}
-
-inline bool operator !=(const uint128& lhs, const uint128& rhs) {
- return !(lhs == rhs);
-}
-
-} // namespace net
-
-#endif // NET_QUIC_UINT128_H_