OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Protocol Buffers - Google's data interchange format |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // found in the LICENSE file. | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // |
| 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are |
| 7 // met: |
| 8 // |
| 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. |
| 11 // * Redistributions in binary form must reproduce the above |
| 12 // copyright notice, this list of conditions and the following disclaimer |
| 13 // in the documentation and/or other materials provided with the |
| 14 // distribution. |
| 15 // * Neither the name of Google Inc. nor the names of its |
| 16 // contributors may be used to endorse or promote products derived from |
| 17 // this software without specific prior written permission. |
| 18 // |
| 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 #ifndef GOOGLE_PROTOBUF_STUBS_INT128_H_ |
| 31 #define GOOGLE_PROTOBUF_STUBS_INT128_H_ |
4 | 32 |
5 #ifndef NET_BASE_INT128_H_ | 33 #include <google/protobuf/stubs/common.h> |
6 #define NET_BASE_INT128_H_ | |
7 | |
8 #include <stdint.h> | |
9 | 34 |
10 #include <iosfwd> | 35 #include <iosfwd> |
11 | 36 |
12 #include "net/base/net_export.h" | 37 namespace google { |
| 38 namespace protobuf { |
13 | 39 |
14 struct uint128_pod; | 40 struct uint128_pod; |
15 | 41 |
| 42 // TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is |
| 43 // available. |
| 44 #ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR |
| 45 # define UINT128_CONSTEXPR constexpr |
| 46 #else |
| 47 # define UINT128_CONSTEXPR |
| 48 #endif |
| 49 |
16 // An unsigned 128-bit integer type. Thread-compatible. | 50 // An unsigned 128-bit integer type. Thread-compatible. |
17 class uint128 { | 51 class LIBPROTOBUF_EXPORT uint128 { |
18 public: | 52 public: |
19 uint128(); // Sets to 0, but don't trust on this behavior. | 53 UINT128_CONSTEXPR uint128(); // Sets to 0, but don't trust on this behavior. |
20 uint128(uint64_t top, uint64_t bottom); | 54 UINT128_CONSTEXPR uint128(uint64 top, uint64 bottom); |
21 uint128(int bottom); | 55 #ifndef SWIG |
22 uint128(uint32_t bottom); // Top 96 bits = 0 | 56 UINT128_CONSTEXPR uint128(int bottom); |
23 uint128(uint64_t bottom); // hi_ = 0 | 57 UINT128_CONSTEXPR uint128(uint32 bottom); // Top 96 bits = 0 |
24 uint128(const uint128 &val); | 58 #endif |
25 uint128(const uint128_pod &val); | 59 UINT128_CONSTEXPR uint128(uint64 bottom); // hi_ = 0 |
| 60 UINT128_CONSTEXPR uint128(const uint128_pod &val); |
26 | 61 |
27 void Initialize(uint64_t top, uint64_t bottom); | 62 // Trivial copy constructor, assignment operator and destructor. |
28 | 63 |
29 uint128& operator=(const uint128& b); | 64 void Initialize(uint64 top, uint64 bottom); |
30 | 65 |
31 // Arithmetic operators. | 66 // Arithmetic operators. |
32 // TODO: division, etc. | |
33 uint128& operator+=(const uint128& b); | 67 uint128& operator+=(const uint128& b); |
34 uint128& operator-=(const uint128& b); | 68 uint128& operator-=(const uint128& b); |
35 uint128& operator*=(const uint128& b); | 69 uint128& operator*=(const uint128& b); |
| 70 // Long division/modulo for uint128. |
| 71 uint128& operator/=(const uint128& b); |
| 72 uint128& operator%=(const uint128& b); |
36 uint128 operator++(int); | 73 uint128 operator++(int); |
37 uint128 operator--(int); | 74 uint128 operator--(int); |
38 uint128& operator<<=(int); | 75 uint128& operator<<=(int); |
39 uint128& operator>>=(int); | 76 uint128& operator>>=(int); |
40 uint128& operator&=(const uint128& b); | 77 uint128& operator&=(const uint128& b); |
41 uint128& operator|=(const uint128& b); | 78 uint128& operator|=(const uint128& b); |
42 uint128& operator^=(const uint128& b); | 79 uint128& operator^=(const uint128& b); |
43 uint128& operator++(); | 80 uint128& operator++(); |
44 uint128& operator--(); | 81 uint128& operator--(); |
45 | 82 |
46 friend uint64_t Uint128Low64(const uint128& v); | 83 friend uint64 Uint128Low64(const uint128& v); |
47 friend uint64_t Uint128High64(const uint128& v); | 84 friend uint64 Uint128High64(const uint128& v); |
48 | 85 |
49 // We add "std::" to avoid including all of port.h. | 86 // We add "std::" to avoid including all of port.h. |
50 friend NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& o, | 87 LIBPROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o, |
51 const uint128& b); | 88 const uint128& b); |
52 | 89 |
53 private: | 90 private: |
| 91 static void DivModImpl(uint128 dividend, uint128 divisor, |
| 92 uint128* quotient_ret, uint128* remainder_ret); |
| 93 |
54 // Little-endian memory order optimizations can benefit from | 94 // Little-endian memory order optimizations can benefit from |
55 // having lo_ first, hi_ last. | 95 // having lo_ first, hi_ last. |
56 // See util/endian/endian.h and Load128/Store128 for storing a uint128. | 96 // See util/endian/endian.h and Load128/Store128 for storing a uint128. |
57 uint64_t lo_; | 97 uint64 lo_; |
58 uint64_t hi_; | 98 uint64 hi_; |
59 | 99 |
60 // Not implemented, just declared for catching automatic type conversions. | 100 // Not implemented, just declared for catching automatic type conversions. |
61 uint128(uint8_t); | 101 uint128(uint8); |
62 uint128(uint16_t); | 102 uint128(uint16); |
63 uint128(float v); | 103 uint128(float v); |
64 uint128(double v); | 104 uint128(double v); |
65 }; | 105 }; |
66 | 106 |
67 // This is a POD form of uint128 which can be used for static variables which | 107 // This is a POD form of uint128 which can be used for static variables which |
68 // need to be operated on as uint128. | 108 // need to be operated on as uint128. |
69 struct uint128_pod { | 109 struct uint128_pod { |
70 // Note: The ordering of fields is different than 'class uint128' but the | 110 // Note: The ordering of fields is different than 'class uint128' but the |
71 // same as its 2-arg constructor. This enables more obvious initialization | 111 // same as its 2-arg constructor. This enables more obvious initialization |
72 // of static instances, which is the primary reason for this struct in the | 112 // of static instances, which is the primary reason for this struct in the |
73 // first place. This does not seem to defeat any optimizations wrt | 113 // first place. This does not seem to defeat any optimizations wrt |
74 // operations involving this struct. | 114 // operations involving this struct. |
75 uint64_t hi; | 115 uint64 hi; |
76 uint64_t lo; | 116 uint64 lo; |
77 }; | 117 }; |
78 | 118 |
79 NET_EXPORT_PRIVATE extern const uint128_pod kuint128max; | 119 LIBPROTOBUF_EXPORT extern const uint128_pod kuint128max; |
80 | 120 |
81 // allow uint128 to be logged | 121 // allow uint128 to be logged |
82 NET_EXPORT_PRIVATE extern std::ostream& operator<<(std::ostream& o, | 122 LIBPROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o, |
83 const uint128& b); | 123 const uint128& b); |
84 | 124 |
85 // Methods to access low and high pieces of 128-bit value. | 125 // Methods to access low and high pieces of 128-bit value. |
86 // Defined externally from uint128 to facilitate conversion | 126 // Defined externally from uint128 to facilitate conversion |
87 // to native 128-bit types when compilers support them. | 127 // to native 128-bit types when compilers support them. |
88 inline uint64_t Uint128Low64(const uint128& v) { | 128 inline uint64 Uint128Low64(const uint128& v) { return v.lo_; } |
89 return v.lo_; | 129 inline uint64 Uint128High64(const uint128& v) { return v.hi_; } |
90 } | |
91 inline uint64_t Uint128High64(const uint128& v) { | |
92 return v.hi_; | |
93 } | |
94 | 130 |
95 // TODO: perhaps it would be nice to have int128, a signed 128-bit type? | 131 // TODO: perhaps it would be nice to have int128, a signed 128-bit type? |
96 | 132 |
97 // -------------------------------------------------------------------------- | 133 // -------------------------------------------------------------------------- |
98 // Implementation details follow | 134 // Implementation details follow |
99 // -------------------------------------------------------------------------- | 135 // -------------------------------------------------------------------------- |
100 inline bool operator==(const uint128& lhs, const uint128& rhs) { | 136 inline bool operator==(const uint128& lhs, const uint128& rhs) { |
101 return (Uint128Low64(lhs) == Uint128Low64(rhs) && | 137 return (Uint128Low64(lhs) == Uint128Low64(rhs) && |
102 Uint128High64(lhs) == Uint128High64(rhs)); | 138 Uint128High64(lhs) == Uint128High64(rhs)); |
103 } | 139 } |
104 inline bool operator!=(const uint128& lhs, const uint128& rhs) { | 140 inline bool operator!=(const uint128& lhs, const uint128& rhs) { |
105 return !(lhs == rhs); | 141 return !(lhs == rhs); |
106 } | 142 } |
107 inline uint128& uint128::operator=(const uint128& b) { | |
108 lo_ = b.lo_; | |
109 hi_ = b.hi_; | |
110 return *this; | |
111 } | |
112 | 143 |
113 inline uint128::uint128(): lo_(0), hi_(0) { } | 144 inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {} |
114 inline uint128::uint128(uint64_t top, uint64_t bottom) | 145 inline UINT128_CONSTEXPR uint128::uint128(uint64 top, uint64 bottom) |
115 : lo_(bottom), hi_(top) {} | 146 : lo_(bottom), hi_(top) {} |
116 inline uint128::uint128(const uint128 &v) : lo_(v.lo_), hi_(v.hi_) { } | 147 inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v) |
117 inline uint128::uint128(const uint128_pod &v) : lo_(v.lo), hi_(v.hi) { } | 148 : lo_(v.lo), hi_(v.hi) {} |
118 inline uint128::uint128(uint64_t bottom) : lo_(bottom), hi_(0) {} | 149 inline UINT128_CONSTEXPR uint128::uint128(uint64 bottom) |
119 inline uint128::uint128(uint32_t bottom) : lo_(bottom), hi_(0) {} | 150 : lo_(bottom), hi_(0) {} |
120 inline uint128::uint128(int bottom) : lo_(bottom), hi_(0) { | 151 #ifndef SWIG |
121 if (bottom < 0) { | 152 inline UINT128_CONSTEXPR uint128::uint128(uint32 bottom) |
122 --hi_; | 153 : lo_(bottom), hi_(0) {} |
123 } | 154 inline UINT128_CONSTEXPR uint128::uint128(int bottom) |
124 } | 155 : lo_(bottom), hi_(static_cast<int64>((bottom < 0) ? -1 : 0)) {} |
125 inline void uint128::Initialize(uint64_t top, uint64_t bottom) { | 156 #endif |
| 157 |
| 158 #undef UINT128_CONSTEXPR |
| 159 |
| 160 inline void uint128::Initialize(uint64 top, uint64 bottom) { |
126 hi_ = top; | 161 hi_ = top; |
127 lo_ = bottom; | 162 lo_ = bottom; |
128 } | 163 } |
129 | 164 |
130 // Comparison operators. | 165 // Comparison operators. |
131 | 166 |
132 #define CMP128(op) \ | 167 #define CMP128(op) \ |
133 inline bool operator op(const uint128& lhs, const uint128& rhs) { \ | 168 inline bool operator op(const uint128& lhs, const uint128& rhs) { \ |
134 return (Uint128High64(lhs) == Uint128High64(rhs)) ? \ | 169 return (Uint128High64(lhs) == Uint128High64(rhs)) ? \ |
135 (Uint128Low64(lhs) op Uint128Low64(rhs)) : \ | 170 (Uint128Low64(lhs) op Uint128Low64(rhs)) : \ |
136 (Uint128High64(lhs) op Uint128High64(rhs)); \ | 171 (Uint128High64(lhs) op Uint128High64(rhs)); \ |
137 } | 172 } |
138 | 173 |
139 CMP128(<) | 174 CMP128(<) |
140 CMP128(>) | 175 CMP128(>) |
141 CMP128(>=) | 176 CMP128(>=) |
142 CMP128(<=) | 177 CMP128(<=) |
143 | 178 |
144 #undef CMP128 | 179 #undef CMP128 |
145 | 180 |
146 // Unary operators | 181 // Unary operators |
147 | 182 |
148 inline uint128 operator-(const uint128& val) { | 183 inline uint128 operator-(const uint128& val) { |
149 const uint64_t hi_flip = ~Uint128High64(val); | 184 const uint64 hi_flip = ~Uint128High64(val); |
150 const uint64_t lo_flip = ~Uint128Low64(val); | 185 const uint64 lo_flip = ~Uint128Low64(val); |
151 const uint64_t lo_add = lo_flip + 1; | 186 const uint64 lo_add = lo_flip + 1; |
152 if (lo_add < lo_flip) { | 187 if (lo_add < lo_flip) { |
153 return uint128(hi_flip + 1, lo_add); | 188 return uint128(hi_flip + 1, lo_add); |
154 } | 189 } |
155 return uint128(hi_flip, lo_add); | 190 return uint128(hi_flip, lo_add); |
156 } | 191 } |
157 | 192 |
158 inline bool operator!(const uint128& val) { | 193 inline bool operator!(const uint128& val) { |
159 return !Uint128High64(val) && !Uint128Low64(val); | 194 return !Uint128High64(val) && !Uint128Low64(val); |
160 } | 195 } |
161 | 196 |
(...skipping 24 matching lines...) Expand all Loading... |
186 | 221 |
187 LOGICASSIGN128(|=) | 222 LOGICASSIGN128(|=) |
188 LOGICASSIGN128(&=) | 223 LOGICASSIGN128(&=) |
189 LOGICASSIGN128(^=) | 224 LOGICASSIGN128(^=) |
190 | 225 |
191 #undef LOGICASSIGN128 | 226 #undef LOGICASSIGN128 |
192 | 227 |
193 // Shift operators. | 228 // Shift operators. |
194 | 229 |
195 inline uint128 operator<<(const uint128& val, int amount) { | 230 inline uint128 operator<<(const uint128& val, int amount) { |
196 // uint64_t shifts of >= 64 are undefined, so we will need some | 231 // uint64 shifts of >= 64 are undefined, so we will need some special-casing. |
197 // special-casing. | |
198 if (amount < 64) { | 232 if (amount < 64) { |
199 if (amount == 0) { | 233 if (amount == 0) { |
200 return val; | 234 return val; |
201 } | 235 } |
202 uint64_t new_hi = | 236 uint64 new_hi = (Uint128High64(val) << amount) | |
203 (Uint128High64(val) << amount) | (Uint128Low64(val) >> (64 - amount)); | 237 (Uint128Low64(val) >> (64 - amount)); |
204 uint64_t new_lo = Uint128Low64(val) << amount; | 238 uint64 new_lo = Uint128Low64(val) << amount; |
205 return uint128(new_hi, new_lo); | 239 return uint128(new_hi, new_lo); |
206 } else if (amount < 128) { | 240 } else if (amount < 128) { |
207 return uint128(Uint128Low64(val) << (amount - 64), 0); | 241 return uint128(Uint128Low64(val) << (amount - 64), 0); |
208 } else { | 242 } else { |
209 return uint128(0, 0); | 243 return uint128(0, 0); |
210 } | 244 } |
211 } | 245 } |
212 | 246 |
213 inline uint128 operator>>(const uint128& val, int amount) { | 247 inline uint128 operator>>(const uint128& val, int amount) { |
214 // uint64_t shifts of >= 64 are undefined, so we will need some | 248 // uint64 shifts of >= 64 are undefined, so we will need some special-casing. |
215 // special-casing. | |
216 if (amount < 64) { | 249 if (amount < 64) { |
217 if (amount == 0) { | 250 if (amount == 0) { |
218 return val; | 251 return val; |
219 } | 252 } |
220 uint64_t new_hi = Uint128High64(val) >> amount; | 253 uint64 new_hi = Uint128High64(val) >> amount; |
221 uint64_t new_lo = | 254 uint64 new_lo = (Uint128Low64(val) >> amount) | |
222 (Uint128Low64(val) >> amount) | (Uint128High64(val) << (64 - amount)); | 255 (Uint128High64(val) << (64 - amount)); |
223 return uint128(new_hi, new_lo); | 256 return uint128(new_hi, new_lo); |
224 } else if (amount < 128) { | 257 } else if (amount < 128) { |
225 return uint128(0, Uint128High64(val) >> (amount - 64)); | 258 return uint128(0, Uint128High64(val) >> (amount - 64)); |
226 } else { | 259 } else { |
227 return uint128(0, 0); | 260 return uint128(0, 0); |
228 } | 261 } |
229 } | 262 } |
230 | 263 |
231 inline uint128& uint128::operator<<=(int amount) { | 264 inline uint128& uint128::operator<<=(int amount) { |
232 // uint64_t shifts of >= 64 are undefined, so we will need some | 265 // uint64 shifts of >= 64 are undefined, so we will need some special-casing. |
233 // special-casing. | |
234 if (amount < 64) { | 266 if (amount < 64) { |
235 if (amount != 0) { | 267 if (amount != 0) { |
236 hi_ = (hi_ << amount) | (lo_ >> (64 - amount)); | 268 hi_ = (hi_ << amount) | (lo_ >> (64 - amount)); |
237 lo_ = lo_ << amount; | 269 lo_ = lo_ << amount; |
238 } | 270 } |
239 } else if (amount < 128) { | 271 } else if (amount < 128) { |
240 hi_ = lo_ << (amount - 64); | 272 hi_ = lo_ << (amount - 64); |
241 lo_ = 0; | 273 lo_ = 0; |
242 } else { | 274 } else { |
243 hi_ = 0; | 275 hi_ = 0; |
244 lo_ = 0; | 276 lo_ = 0; |
245 } | 277 } |
246 return *this; | 278 return *this; |
247 } | 279 } |
248 | 280 |
249 inline uint128& uint128::operator>>=(int amount) { | 281 inline uint128& uint128::operator>>=(int amount) { |
250 // uint64_t shifts of >= 64 are undefined, so we will need some | 282 // uint64 shifts of >= 64 are undefined, so we will need some special-casing. |
251 // special-casing. | |
252 if (amount < 64) { | 283 if (amount < 64) { |
253 if (amount != 0) { | 284 if (amount != 0) { |
254 lo_ = (lo_ >> amount) | (hi_ << (64 - amount)); | 285 lo_ = (lo_ >> amount) | (hi_ << (64 - amount)); |
255 hi_ = hi_ >> amount; | 286 hi_ = hi_ >> amount; |
256 } | 287 } |
257 } else if (amount < 128) { | 288 } else if (amount < 128) { |
| 289 lo_ = hi_ >> (amount - 64); |
258 hi_ = 0; | 290 hi_ = 0; |
259 lo_ = hi_ >> (amount - 64); | |
260 } else { | 291 } else { |
| 292 lo_ = 0; |
261 hi_ = 0; | 293 hi_ = 0; |
262 lo_ = 0; | |
263 } | 294 } |
264 return *this; | 295 return *this; |
265 } | 296 } |
266 | 297 |
267 inline uint128 operator+(const uint128& lhs, const uint128& rhs) { | 298 inline uint128 operator+(const uint128& lhs, const uint128& rhs) { |
268 return uint128(lhs) += rhs; | 299 return uint128(lhs) += rhs; |
269 } | 300 } |
270 | 301 |
271 inline uint128 operator-(const uint128& lhs, const uint128& rhs) { | 302 inline uint128 operator-(const uint128& lhs, const uint128& rhs) { |
272 return uint128(lhs) -= rhs; | 303 return uint128(lhs) -= rhs; |
273 } | 304 } |
274 | 305 |
275 inline uint128 operator*(const uint128& lhs, const uint128& rhs) { | 306 inline uint128 operator*(const uint128& lhs, const uint128& rhs) { |
276 return uint128(lhs) *= rhs; | 307 return uint128(lhs) *= rhs; |
277 } | 308 } |
278 | 309 |
| 310 inline uint128 operator/(const uint128& lhs, const uint128& rhs) { |
| 311 return uint128(lhs) /= rhs; |
| 312 } |
| 313 |
| 314 inline uint128 operator%(const uint128& lhs, const uint128& rhs) { |
| 315 return uint128(lhs) %= rhs; |
| 316 } |
| 317 |
279 inline uint128& uint128::operator+=(const uint128& b) { | 318 inline uint128& uint128::operator+=(const uint128& b) { |
280 hi_ += b.hi_; | 319 hi_ += b.hi_; |
281 uint64_t lolo = lo_ + b.lo_; | 320 uint64 lolo = lo_ + b.lo_; |
282 if (lolo < lo_) | 321 if (lolo < lo_) |
283 ++hi_; | 322 ++hi_; |
284 lo_ = lolo; | 323 lo_ = lolo; |
285 return *this; | 324 return *this; |
286 } | 325 } |
287 | 326 |
288 inline uint128& uint128::operator-=(const uint128& b) { | 327 inline uint128& uint128::operator-=(const uint128& b) { |
289 hi_ -= b.hi_; | 328 hi_ -= b.hi_; |
290 if (b.lo_ > lo_) | 329 if (b.lo_ > lo_) |
291 --hi_; | 330 --hi_; |
292 lo_ -= b.lo_; | 331 lo_ -= b.lo_; |
293 return *this; | 332 return *this; |
294 } | 333 } |
295 | 334 |
296 inline uint128& uint128::operator*=(const uint128& b) { | 335 inline uint128& uint128::operator*=(const uint128& b) { |
297 uint64_t a96 = hi_ >> 32; | 336 uint64 a96 = hi_ >> 32; |
298 uint64_t a64 = hi_ & 0xffffffffu; | 337 uint64 a64 = hi_ & 0xffffffffu; |
299 uint64_t a32 = lo_ >> 32; | 338 uint64 a32 = lo_ >> 32; |
300 uint64_t a00 = lo_ & 0xffffffffu; | 339 uint64 a00 = lo_ & 0xffffffffu; |
301 uint64_t b96 = b.hi_ >> 32; | 340 uint64 b96 = b.hi_ >> 32; |
302 uint64_t b64 = b.hi_ & 0xffffffffu; | 341 uint64 b64 = b.hi_ & 0xffffffffu; |
303 uint64_t b32 = b.lo_ >> 32; | 342 uint64 b32 = b.lo_ >> 32; |
304 uint64_t b00 = b.lo_ & 0xffffffffu; | 343 uint64 b00 = b.lo_ & 0xffffffffu; |
305 // multiply [a96 .. a00] x [b96 .. b00] | 344 // multiply [a96 .. a00] x [b96 .. b00] |
306 // terms higher than c96 disappear off the high side | 345 // terms higher than c96 disappear off the high side |
307 // terms c96 and c64 are safe to ignore carry bit | 346 // terms c96 and c64 are safe to ignore carry bit |
308 uint64_t c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96; | 347 uint64 c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96; |
309 uint64_t c64 = a64 * b00 + a32 * b32 + a00 * b64; | 348 uint64 c64 = a64 * b00 + a32 * b32 + a00 * b64; |
310 this->hi_ = (c96 << 32) + c64; | 349 this->hi_ = (c96 << 32) + c64; |
311 this->lo_ = 0; | 350 this->lo_ = 0; |
312 // add terms after this one at a time to capture carry | 351 // add terms after this one at a time to capture carry |
313 *this += uint128(a32 * b00) << 32; | 352 *this += uint128(a32 * b00) << 32; |
314 *this += uint128(a00 * b32) << 32; | 353 *this += uint128(a00 * b32) << 32; |
315 *this += a00 * b00; | 354 *this += a00 * b00; |
316 return *this; | 355 return *this; |
317 } | 356 } |
318 | 357 |
319 inline uint128 uint128::operator++(int) { | 358 inline uint128 uint128::operator++(int) { |
(...skipping 11 matching lines...) Expand all Loading... |
331 inline uint128& uint128::operator++() { | 370 inline uint128& uint128::operator++() { |
332 *this += 1; | 371 *this += 1; |
333 return *this; | 372 return *this; |
334 } | 373 } |
335 | 374 |
336 inline uint128& uint128::operator--() { | 375 inline uint128& uint128::operator--() { |
337 *this -= 1; | 376 *this -= 1; |
338 return *this; | 377 return *this; |
339 } | 378 } |
340 | 379 |
341 #endif // NET_BASE_INT128_H_ | 380 } // namespace protobuf |
| 381 } // namespace google |
| 382 |
| 383 #endif // GOOGLE_PROTOBUF_STUBS_INT128_H_ |
OLD | NEW |